Пожалуйста, прекратите комментировать код

Java
Пожалуйста, прекратите комментировать код

Оригинальный текст этой статьи здесь (medium.com/@bpnorl...

«Чистый код должен быть похож на хорошую прозу» — Роберт С. Мартин.

Распространенная проблема с плохим кодом заключается в том, что в нем много комментариев. Это самый очевидный признак беспорядочного исходного кода.

Целью каждого программиста должно быть написание чистого и выразительного кода без комментариев. Назначение каждой переменной, функции и класса должно подразумеваться в их имени и структуре.

Когда другие люди читают ваш код, им не следует читать комментарии, чтобы понять, что делает ваш код. Хорошо названные классы и функции должны вести читателей по вашему коду, как хорошо написанный роман. Когда читатели видят новый класс или функцию, их не должно смущать то, что они видят внутри.

Помните, что очень мало рабочего времени разработчик тратит на написание кода.Гораздо больше времени тратится на чтение и понимание кода.

Комментарии скрывают ошибки

Именование в коде очень важно. Вы должны приложить много усилий для точного и точного наименования каждого фрагмента кода, чтобы другие разработчики могли понять ваш код.

// 按状态查找员工
List<Employee> find(Status status) {
  ...
}

В этом примере имя find недостаточно описательно, поэтому автор этой функции должен оставить описательный комментарий, описывающий, что делает функция. Когда мы видим, что функция find вызывается из другого модуля, остается загадкой, что она делает. Что он нашел? Что именно это значит? Вернул ли он то, что нашел? Как найти то, что нашел? Как сказал дядя Боб в своей книге «Чистый код», если вам нужно написать комментарии, вы не можете выразить то, что вы на самом деле подразумеваете под кодом.

Мы не хотим проверять комментарии над каждой функцией, чтобы увидеть, что она делает.

List<Employee> getEmployeesByStatus(Status status) {
  ...
}

Теперь очевидно, что делает эта функция, что делает комментарий излишним. Это подводит меня к следующему способу плохо комментировать.

Избыточные комментарии

Они загромождают ваш код и совершенно не нужны.

//此函数发送电子邮件
void sendEmail() {
  ...
}

//此函数发送电子邮件
public class Employee {
  ...
}

/ **
* @param title CD的标题
* @param作者CD的作者
* @param track CD上的曲目数
 * /
public void addCd(String title, String author, int tracks) {
  ...
}

В большинстве случаев применяется избыточность. Многие компании требуют этого в каждой функции и категории. Если ваш начальник просит об этом, попросите его не делать этого.

неправильный уровень абстракции

Если у вас есть длинная функция или вам нужно документировать, какая часть кода что делает, то вы, вероятно, нарушаете следующие правила:

  1. Функция должна делать одну вещь.
  2. Характеристики должны быть небольшими.

Вот пример

//此函数计算价格,与销售额进行比较
//促销,检查价格是否有效,然后
//向用户发送促销电子邮件
public  void doSomeThings(){

  //计算价格
  ...
    ...
    ...
  
  //将计算出的价格与促销活动进
  ...
    ...
    ...
  
  //检查计算的价格是否有效
  ...
    ...
    ...
  
  //向用户发送促销信息
  ...
    ...
    ...
}

Когда вы успешно инкапсулируете каждую часть логики в отдельную функцию, код должен вести себя так же, как и без комментариев.

Рефакторинг следующим образом:

public  void sendPromotionEmailToUsers(){
  calculatePrices();
  compareCalculatedPricesWithSalesPromotions();
  checkIfCalculatedPricesAreValid();
  sendPromotionEmail();
}

Вместо того, чтобы комментировать каждый раздел кода, каждый блок логики должен быть красиво инкапсулирован в свою собственную функцию.

Во-первых, это улучшаетудобочитаемость. Каждый блок кода не обязательно читать построчно. Мы можем просто прочитать имя вспомогательной функции и понять, что она делает. Если мы хотим узнать больше деталей внутри каждой функции, мы можем перейти к конкретной реализации.

Во-вторых, улучшаетТестируемость. В приведенном выше примере мы можем проводить модульное тестирование каждой функции по отдельности. Без инкапсуляции этих отдельных функций было бы сложно протестировать каждую часть более крупной функции sendPromotionEmailToUsers(). Функции, выполняющие несколько функций, трудно тестировать.

Наконец, улучшаетсяреконфигурируемость. Инкапсулируя каждую часть логики в отдельную функцию, ее легче поддерживать для будущих изменений, а функция отдельной функции изолируется, чтобы изменить только поведение этой функции. Когда мы используем длинные функции с локальными переменными, которые сохраняются на протяжении всей функции, из-за тесной связи функций трудно реорганизовать функцию, не вызывая изменений в другом месте.

закомментированный код

Закомментированный код следует считать дорожным убийством. Не смотри на него, не нюхай его, не спрашивай, откуда он взялся, просто избавься от него. Чем дольше вы его храните, тем дольше будет пахнуть остальной код...

/ *
public void oldFunction(){
  noOneRemembersWhyIAmHere();
  tryToUnCommentMe();
  iWillProbablyCauseABuildFailure();
  HAHAHA();
}
* /

Даже если вы удалите его, другие не посмеют его удалить. Если вам это понадобится позже, вы всегда можете проверить систему контроля версий, потому что вы определенно используете VCS, верно? (если не тогда, когда я этого не говорил)

Примечания к TODO

Не пишите комментарии TODO, а не просто... не так ли? В большинстве случаев эти аннотации забываются и впоследствии могут стать неактуальными или ошибочными. Когда позже другой программист увидит комментарий TODO, как он узнает, нужно ли это сделать?

Тем не менее, случайные комментарии TODO вполне допустимы, если вы ждете слияния другого товарища по команде (как правило, не слишком долго). Просто делайте это, пока не сможете исправить и зафиксировать его.

«Когда вы чувствуете необходимость написать комментарии, сначала попробуйте реорганизовать код, чтобы любые комментарии стали излишними», — Мартин Фаулер.

Аннотированная ложь

Когда Джимми аннотирует новые функции, которые он пишет, он думает, что помогает любому будущему разработчику, который увидит его код. На самом деле, то, что он действительно делает, - это установка ловушки. Его заметки могли быть громадным (без каламбура), бездействующим в течение месяцев или лет нетронутыми, просто ожидающими, чтобы стать неприятной ловушкой. Затем однажды, во время одного из сотен рефакторингов и изменений требований, его комментарии были признаны недействительными из какого-то отдаленного модуля, но все же вводили в заблуждение бесчисленное количество сборщиков.

Когда вы меняете строку кода, как вы узнаете, что измененный вами код сделает комментарии в другом месте недействительными? нет способа узнать

public class User {
  ...
  //它包含用户的名字和姓氏
  String name;
  ...
}

Затем требования меняются, и они хотят разделить имя на имя и фамилию.

public class User {
  ...
  
  // 它包含用户的名字和姓氏
  String firstName;
  String lastName;
    
  ...
}

Аннотация теперь неверна. Вы можете обновить аннотации, чтобы отразить изменения, но действительно ли вы хотите поддерживать все аннотации вручную после каждого изменения? Вы разработчик, а не документация.

Но эту аннотацию легко заметить и не нужно ничего менять. Но вы вряд ли можете гарантировать, что в других местах программы вы также аннотируете это имя параметра как имя и фамилию пользователя. Изменение небольшого фрагмента кода может сделать многие комментарии кода недействительными.

Давайте посмотрим на другой пример:

//根据状态处理员工
void processEmployees(){
  ...
  List < Employee > employees = findEmployees(statusList);
  ...
}

//这会按状态列表查找Employees
List < Employee > findEmployees(List < String > statusList){
  ...
}

Затем кого-то попросили изменить функцию findEmployees, чтобы она находила сотрудников по списку имен, а не по списку статусов.

//根据状态处理员工
void processEmployees(){
  ...
  List < Employee > employees = findEmployees(statusList);
  ...
}

//这会按状态列表查找Employees
List < Employee > findEmployees(List < String > nameList){
  ...
}

Во-первых, приведенная выше аннотация findEmployees больше не существует, поэтому ее необходимо изменить. Нет проблем, верно?неправильный.

Аннотация выше processEmployees также не существует, поэтому ее также необходимо изменить. Сколько других комментариев стало недействительным в результате этого небольшого рефакторинга? Сколько ложных комментариев вызвало это изменение в исходном коде?

альтернативный план:

void processEmployees(){
  ...
  List < Employee > employees = findEmployeesByName(nameList);
  ...
}

List < Employee > findEmployeesByName(List < Name > nameList){
  ...
}

Если вы точно и точно называете свои функции, вам не нужны комментарии, и вы не распространяете ложь в своем коде.

«Код никогда не лжет, лгут комментарии», — Рон Джеффрис.

Когда вам нужны аннотации?

Я знаю многих разработчиков, которые являются стойкими сторонниками комментариев в коде, для которых я должен признать, что иногда комментарии — это нормально. Но у каждого абзаца, который вы пишете, должна быть веская причина

сложные выражения

Если у вас есть сложные операторы SQL или регулярные выражения, продолжайте писать комментарии. Может быть сложно четко выразить подобные операторы в коде. Комментарии к этим выражениям могут помочь другим разработчикам лучше понять ваш код.

// 格式匹配kk:mm:ss EEE,MMM dd,yyy
Pattern timePattern = Pattern.compile("\\d*:\\d*:\\d* \\w*, \\w*, \\d*, \\d*");

Предупреждение об аннотации

Если вам нужно предупредить других разработчиков о возможных ошибках в этом коде, вы можете оставить комментарий рядом с этим кодом. Эти комментарии могут служить предвестником таинственного поведения в вашем коде и повышать ценность вашего кода.

намерение уточнить

Если вы действительно плохо умеете называть вещи, возьмите на себя ответственность за свою неспособность писать выразительный код и пишите комментарии, чтобы показать свои намерения.

Если вы должны написать записку, убедитесь, что она местная. Неместные обзоры, далекие от их цитирований, обречены на провал и превратятся в ложь. Комментарии, ссылающиеся на функцию или переменную, должны располагаться прямо над ними. Предупреждающий комментарий может быть выше или рядом с кодом, на который он ссылается. Если ваша среда IDE поддерживает подсветку комментариев, выделите комментарии-предупреждения среди остального кода.

Наконец

Я сформировал свое отношение к комментариям кода. Я их презираю, но знаю, что иногда они нужны.

Поэтому, пожалуйста, перестаньте писать так много комментариев.

Эта статья была написана автором после просмотра в Твиттере изложения иностранного великого бога Брайана Ноланда. Я надеюсь, что в будущем мой код будет таким же элегантным, как проза.

Пополнить

Поскольку официальная учетная запись Java в Twitter была ретвитнута, за границей также была очень интенсивная дискуссия по этому вопросу, если вам интересно, вы можете прочитать это.:

Не прекращайте писать комментарии к коду

раздел комментариев на реддите

Соответствующие фрагменты:

Поскольку это перевод оригинального текста автора, я не буду изменять его, чтобы уважать содержание автора.

Моя точка зрения — сам код должен быть чистым, ясным по смыслу и точным по выражению, но это не значит, что все комментарии совсем бесполезны, это не абсолют.

Первое: мы не можем считать, что английский у всех на уровне (есть даже имена на пиньине - таких людей надо обязать писать заметки)

Во-вторых: первоначальный автор имел в виду противодействовать недействительным и бесполезным комментариям в процессе разработки, но не упомянул, что распространение версии должно предоставлять API-интерфейсы для комментариев к документам, которые используются другими. Комментарии к документации необходимы для облегчения понимания пользователем интерфейса. Поскольку документация привязана к номеру версии, вам больше не нужно поддерживать эти аннотации при последующей разработке. Однако весьма вероятно, что перед выпуском версии будет внесено много изменений в требования, если только комментарии документа не будут поддерживаться один раз для каждого изменения требования. В противном случае документ, сгенерированный непосредственно в конце, может содержать ошибки. Лучший способ — написать единые комментарии к документам для создания документации до того, как версия будет выпущена.

Третье: для внутренней ситуации лучшим предложением должно быть: код должен быть как можно более элегантным и чистым, а также соглашения об именах. В целях заботы о других разработчиках, обязательно пишите комментарии, когда это необходимо, и прикрепляйте к комментариям время и номер версии. как можно больше времени и своевременно обновлять комментарии. Но постарайтесь максимально сократить избыточные комментарии (то есть сам код можно выразить понятно, комментарии не нужны, чтобы избежать обслуживания и обновлений в будущем), чтобы не вводить в заблуждение доковщика. Автор оригинальной статьи упомянул, что каждый раз, когда он пишет комментарий, он должен сам себе объяснить причину существования этого комментария, что, вероятно, он и имел в виду.

Четвертое: Причина, по которой многие люди не могут понять, заключается в том, что они невнимательно читали.

// xxxx

вместо

/**
 * xxxx 
 * @author
 * @date
 */

OVER