В прошлом совете поделился способом быстро находить бесполезные комментарии в коде. Сегодня — о коментах‑зарубках и документирующих коментах.
Коменты‑зарубки TODO и FIXME
Зарубками помечают техдолг — то что надо сделать или починить, но сейчас не до того.
// TODO: унифицировать все модалы в единый класс
// FIXME: долго грузится в Сафари
// todo. needs refactoring
// FIXME!!!!!!!
С зарубками две проблемы: в формате комента неудобно хранить контекст задачи, а сами коменты обычно теряются, забываются и игнорируются годами.
Не поленитесь оформить техдолг в полноценную задачу: опишите проблему, варианты решения, ход мысли, спланируйте исправление, назначьте ответственного. Так вероятность исправления будет гораздо выше, чем при оставлении зарубки в коде.
Как найти время для работы с техдолгом — в совете Фёдора Борщёва.
Документирующие коменты
Документирующие коменты подробно объясняют код, описывают функции, аргументы, содержат примеры использования. Это полезно для библиотек, сервисов, АПИ — интерфейсов, с которыми будут работать другие люди. Документация ускорит работу, упростит интеграцию, поможет избежать ошибок.
/**
* Creates an object composed of keys generated from the results of running
* each element of `collection` thru `iteratee`. The corresponding value of
* each key is the number of times the key was returned by `iteratee`. The
* iteratee is invoked with one argument: (value).
*
* @static
* @memberOf _
* @since 0.5.0
* @category Collection
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} [iteratee=_.identity] The iteratee to transform keys.
* @returns {Object} Returns the composed aggregate object.
* @example
*
* _.countBy([6.1, 4.2, 6.3], Math.floor);
* // => { '4': 1, '6': 2 }
*
* // The `_.property` iteratee shorthand.
* _.countBy(['one', 'two', 'three'], 'length');
* // => { '3': 2, '5': 1 }
*/
var countBy = createAggregator(function(result, value, key) {
if (hasOwnProperty.call(result, key)) {
++result[key];
} else {
baseAssignValue(result, key, 1);
}
});
Но документация не бесплатная. Писать и поддерживать её актуальность — отдельная полноценная работа. Если не следить за документацией, она устареет, начнёт вводить в заблуждение и приведёт к проблемам.
Документация не отменяет необходимость следить за качеством кода, покрытием тестами, обменом знаниями в команде и другими хорошими программистскими практиками
Не документируйте всё подряд. Пишите документацию там, где затраты на её поддержку окупятся и она будет полезна: например, снимет частые вопросы или поможет людям избежать типовых ошибок при работе с кодом. Будьте лаконичны.
Документация не отменяет необходимость следить за качеством кода, покрытием тестами, обменом знаниями в команде и другими хорошими программистскими практиками
Многословная, но бесполезная по смыслу документация будет лишь воровать внимание разработчиков:
/**
* Документация для класса ProductCard
* Этот класс описывает карточку товара, принимает объект типа ProductData и HTMLElement куда рендерить карточку. TODO: добавить отслеживание карточки для аналитики
* Например, new ProductCard(productData, document.querySelector('.js-catalog'))
*
* @param {ProductData} данные карточки товара
* @param {HTMLElement} элемент родитель куда зарендерить
*
* by leonidovich | 18.08.2016 via WebStorm
*/
class ProductCard {
constructor(product, parent) {
this.product = product
this.root = parent
}
/**
* Функция рендера. Создаёт HTMLElement по шаблону с обработчиками событий и затем добавляет его в родителя карточки, переданного в конструктор
* Не требует передачи аргументов
*
* @returns {HTMLElement}
*/
render() {
const templateData = {
product: this.product,
onAddToCart: this.addToCard.bind(this),
onRemoveFromCart: this.removeFromCart.bind(this),
}
const HTML = useTemplate('./product-card.html', templateData)
return this.root.appendChild(HTML)
}
/**
* Добавление в корзину
* Метод добавляет товар в корзину через сервис, передаёт туда данные карточки. Если товар уже добавлен, тогда ничего не произойдёт
*
* @returns {Promise}
*/
addToCard() {
return basketService.addToCart(this.product)
}
/**
* Удаление из корзины
* Удаляет товар из корзины через сервис, возвращает промис
*
* @returns {Promise}
*/
removeFromCart() {
return basketService.removeFromCart(this.product)
}
}
P. S. Это был совет о веб‑разработке. Хотите знать всё о коде, тестах, фронтенд‑разработке, цеэсэсе, яваскрипте, рельсах и джейде? Присылайте вопросы.