Не пишите комментарии к коду!

    Вступление


    Доброго времени суток, Хабражитель. Сразу хочу оговорится, что название не означает, что я буду призывать не писать комментарии никогда, любая крайность в этом мире скорее всего ущербна. Я лишь хочу сказать, что желание написать комментарий в каком-либо месте почти всегда свидетельствует о более важной проблеме в коде, разобравшись с которой необходимость в комментировании пропадет.

    Перед началом еще хочу сказать, что примеры буду приводить с использованием Java, а небольшой отрывок кода (с маленьким дополнением) взят из проекта описанного тут.

    Для понимания проблемы обратимся к Вики, а после перейдем к примерам:

    Коммента́рии — пояснения к исходному тексту программы, находящиеся непосредственно внутри комментируемого кода.


    Пример комментариев к коду



    public static void main(String[] args) throws IOException {
        // "ua.in.link.rest.server" - name of package with classes for Jersey server
        ResourceConfig rc = new PackagesResourceConfig("ua.in.link.rest.server");
        // creating httpServer for url "http://localhost:8080"
        HttpServer httpServer = GrizzlyServerFactory.createHttpServer("http://localhost:8080", rc);    
        InetSocketAddress socketAddres = httpServer.getAddress();    
        doSomethisWithSocket(socketAddres);        // waiting for Enter before stoping the server
        System.in.read();
        httpServer.stop();
    }
    


    Константы



    Давайте поглядим на данный пример. Начнем с таких строк:
        // "ua.in.link.rest.server" - name of package with classes for Jersey server
        ResourceConfig rc = new PackagesResourceConfig("ua.in.link.rest.server");
    

    Для человека, который не работал с локальным сервером Jersey, может быть действительно неочевидно, что за строка передается в конструкторе («ua.in.link.rest.server»). И автор, наверняка, хотел сделать данную часть более понятной. Однако, теперь, если по каким-либо причинам имя пакета в конструкторе будет изменено существует вероятность того, что комментарий останется старый, а, как известно, устаревший комментарий хуже отсутствующего. Более того, как уже говорил ранее, желание вставить комментарий в код свидетельствует (почти всегда) об проблемах с кодом. В данном примере думаю понятно, что проблемой является «захардкоденная» строка пакета(«ua.in.link.rest.server»). И если ее вынести в отдельную сущность, мы будем вынуждены именовать ее, для связки ее с данным кодом. Например, мы вынесли ее как константу:

    private static final String JERSEY_CLASSES_PACKAGE_NAME = "ua.in.link.rest.server";
     
    public static void main(String[] args) throws IOException {
        ResourceConfig rc = new PackagesResourceConfig(JERSEY_CLASSES_PACKAGE_NAME);
        // creating httpServer for url "http://localhost:8080"
        HttpServer httpServer = GrizzlyServerFactory.createHttpServer("http://localhost:8080", rc);    
        InetSocketAddress socketAddres = httpServer.getAddress();    
        doSomethisWithSocket(socketAddres);    
        // waiting for Enter before stoping the server
        System.in.read();
        httpServer.stop();
    }
    


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

    Разделяй и властвуй



    Идем далее… Обратим внимание на вот эти строки:

        // creating httpServer for url "http://localhost:8080"
        HttpServer httpServer = GrizzlyServerFactory.createHttpServer("http://localhost:8080", rc);    
        InetSocketAddress socketAddres = httpServer.getAddress();    
        doSomethisWithSocket(socketAddres);
    


    И тут комментарий наносит непоправимую пользу=). Вроде и так понятно, что делаю строки, комментарий дописан, так как метод в данном примере решает более чем одну задачу и нужно разграничить код, очень часто это делают комментариями, как тут. Что мы в итоге имеем. Допустим, что сервер стартует в каком-либо другом месте и из данного места старт сервера необходимо убрать. Нам нужно точно знать какой код отвечает за его старт. И вот проблема. Отвечает за старт только эта строка:

        HttpServer httpServer = GrizzlyServerFactory.createHttpServer("http://localhost:8080", rc);    
    


    А две другие были добавлены только потому, что для корректности программы нужно выполнить еще пару строк кода, или же рабочий сервер можно получить только и исключительно этими тремя строками кода:

        HttpServer httpServer = GrizzlyServerFactory.createHttpServer("http://localhost:8080", rc);    
        InetSocketAddress socketAddres = httpServer.getAddress();    
        doSomethisWithSocket(socketAddres);
    


    Непонятно, какие строки необходимо убрать в случаи, если сервер запускается где-то на стороне. Более того, при модификации кода очень легко оставить строку:
        ResourceConfig rc = new PackagesResourceConfig(JERSEY_CLASSES_PACKAGE_NAME);
    

    Не заметив что она так же относится к блоку создания сервера.

    Давайте теперь отрефакторим данный код.

    private static final String JERSEY_CLASSES_PACKAGE_NAME = "ua.in.link.rest.server";
     
    private static final String SERVER_URL = "http://localhost:8080";
     
    public static void main(String[] args) throws IOException {    
        HttpServer httpServer = startServer();    
        
        InetSocketAddress socketAddres = httpServer.getAddress();    
        prepareSocket(socketAddres); 
        
        // waiting for Enter before stoping the server
        System.in.read();
        httpServer.stop();
    }
     
    private static HttpServer startServer() {
        ResourceConfig rc = new PackagesResourceConfig(JERSEY_CLASSES_PACKAGE_NAME);
        return GrizzlyServerFactory.createHttpServer(SERVER_URL, rc);    
    }
     
    private static void prepareSocket(InetSocketAddress socketAddres){
        doSomethisWithSocket(socketAddres);       
    }
    


    Теперь очевидно, что операции с Socket не касаются факта запуска сервера, иначе они бы выполнялись в методе старта сервера, как-то так:

    private static HttpServer startServer() {
        ResourceConfig rc = new PackagesResourceConfig(JERSEY_CLASSES_PACKAGE_NAME);
        HttpServer httpServer = GrizzlyServerFactory.createHttpServer(SERVER_URL, rc);    
        InetSocketAddress socketAddres = httpServer.getAddress();    
        prepareSocket(socketAddres); 
        return httpServer;
    }
    


    Теперь ясно, что именно отвечает за запуск сервера. Более того, если более точно представляешь какой код за что отвечает, то более просто локализовтаь баг.

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

    private static final String JERSEY_CLASSES_PACKAGE_NAME = "ua.in.link.rest.server";
     
    private static final String SERVER_URL = "http://localhost:8080";
    
    private static final String PRESS_ENTER__TO_STOP_STRING = "Press Enter to stop server";
     
    public static void main(String[] args) throws IOException {    
        HttpServer httpServer = startServer();    
        
        InetSocketAddress socketAddres = httpServer.getAddress();    
        prepareSocket(socketAddres); 
        
        userStopsServer(httpServer);
    }
     
    private static HttpServer startServer() {
        ResourceConfig rc = new PackagesResourceConfig(JERSEY_CLASSES_PACKAGE_NAME);
        return GrizzlyServerFactory.createHttpServer(SERVER_URL, rc);    
    }
     
    private static void prepareSocket(InetSocketAddress socketAddres){
        doSomethisWithSocket(socketAddres);       
    }
     
    private static void userStopsServer(HttpServer httpServer){
        System.out.println(PRESS_ENTER__TO_STOP_STRING + httpServer.toString());
        System.in.read();
        httpServer.stop();
    }
    


    А где нужны комментарии?



    Очень удачно по поводу тестов сказано в Вики, которую я и процитирую:

    Большинство специалистов сходятся во мнении, что комментарии должны объяснять намерения программиста, а не код; то, что можно выразить на языке программирования, не должно выноситься в комментарии — в частности, надо использовать говорящие названия переменных, функций, классов, методов и пр., разбивать программу на лёгкие для понимания части, стремиться к тому, чтобы структура классов и структура баз данных были максимально понятными и прозрачными и т. д. Есть даже мнение (его придерживаются в экстремальном программировании и некоторых других гибких методологиях программирования), что если для понимания программы требуются комментарии — значит, она плохо написана.


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

    И все же, иногда нету иного пути, кроме как прибегнуть к неочевидному решению. Пример этому — использование более старой версии библиотеки или @Depricated методов. Но все эти случаи на практике встречаются куда реже, чем кажется.

    JavaDoc



    Множество проектов, уже на пред-релизном этапе, изобилуют стандартными комментариями вида:
    /**
    * Имя или краткое описание объекта
    * 
    * Развернутое описание
    * 
    * @имя_дескриптора значение
    * @return тип_данных
    */
    


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

    Вместо выводов



    Само собой комментарии — это весьма холиварная тема. Много, кто может полезть в открытые проекты, которыми я заведую и, указав на какой -то код, сказать — «без комментариев он не очевиден» и будет абсолютно прав. Однако, если у меня будет время заняться этой частью кода, я потрачу это время на рефакторинг а не на написание комментариев, и лишь будучи загнан в угол и не придумав как применить принцип KISS, покорно напишу комментарий, но не ранее. Так же хочется сказать, что о комментариях часто напоминают молодые программисты, которым на самом деле банально не хватает практики, что бы увидеть в том или ином коде всем известный паттерн, подход или незнание работы каких-либо библиотек. Но это не проблема (и точно не необходимость) комментариев, а просто отсутствие должного опыта.
    Поделиться публикацией

    Похожие публикации

    Комментарии 325
      –14
      Ещё чего.
        +23
        Пост не читай — комментарий к посту пиши? Зато вы первый, ага.
          –19
          Пост читал. Не согласен. Комментарии нужны почти везде, кроме геттеров, сеттеров и getItemByID.
            +13
            Зачем они нужны? Аргументируйте, пожалуйста, свои высказывания.
              +11
              После таких вот XP техник без комментариев я потрачу до 5 раз больше времени на разбор действий кода, чем с комментариями. До 10% функций кода рискуют быть непонятыми вследствие их костыльности или неочевидности.
                +5
                И это позволяет быстро локализовтаь эти 10% костыльных и не очивидных мест в коде, которыми необходимо занятся в первую очередь. Там и коментарий можно поставить с пометкой // TODO…
                  –17
                  Комментарии todo не нужны, поскольку их специально практически никто не do.
                    +22
                    Не надо говорить за всех, пожалуйста.
                    Я, например, вообще предпочитаю сначала написать общую структуру программы в виде комментариев todo, а потом уже реализовывать. Какие-то todo остаются «на потом», конечно.
                      +1
                      Я тоже так раньше делал, вот только потом понял что таким образом очень плохо контролируется что уже реализовано, а что случайно осталось «на потом». Намного лучше писать костяк будущего кода сразу вызовами несуществующих пока функций — таким образом сохраняется принцип «сначала написать общую структуру» и никогда не забудется написать что-то важное (код просто не скомпилируется).
                        +1
                        Вот хочется, чтобы он скопиллировался;)

                        Критичные TODO можно написать так:
                        #error TODO! implement this feature
                        


                        Менее критичные так:
                        #warning TODO! implement this feature
                        


                        А совсем «на потом» так:
                        // TODO! implement this feature
                        
                          –1
                          Если то, что Вы отметили как "#error" должно препятствовать компиляции — то какой смысл такое писать? Не лучше ли сразу написать вызов будущего метода — и меньше писанины, и задел на будущее.

                          По поводу "#warning" — согласен, до этого вполне могут дойти руки, потому что «надо сделать чтобы проект собирался без ворнингов!» — этим руководствуются многие.

                          А "// TODO" — полностью бесполезная вещь — забудете и не сделаете никогда (ну разве что ваша IDE эти штуки умеет собирать и показывать в одном месте — но даже в этом случае вряд ли до них дойдут руки).
                            +1
                            >>Если то, что Вы отметили как "#error" должно препятствовать компиляции — то какой смысл такое писать?
                            Это может быть субъективно, но сознание более свободно, когда описываешь программу, а не пишешь ее, если Вы меня понимаете:) Это как на доске сначала нарисовать, а потом уже начать делать.
                        +4
                        В моей среде разработки TODO и FIXME подсвечиваются особым цветом.
                        Для того чтобы не помнить о всех TODO есть специальная владка где задания разделены на проект, текущий файл и скоп:

                        image
                        0
                        www.rau.su/observer/N07_96/7_14.HTM

                        TL;DR: Если вы вместо TODO занимались чем-то другим, есть немалая вероятность, что это что-то другое оказалось важнее.
                          0
                          В проектах, которые я видел, метка todo являлась чем-то вроде overengineering-а. Так что что-то другое само собой оказывалось намного важнее.
                      +18
                      Лучше называть методы нормально и код писать понятно, а тотальное комментирование приводит к наплевательскому отношению к их написанию.
                      В итоге получаем уродцев с автогенерированными комментариями типа

                      //Builds the Ext
                      public void BuildExt()

                      и так постоянно
                      Зато блин покрытие комментариями 100%, только это блин мусор. А натыкаясь на мусор перестаёшь видеть действительно стоящие комментарии.
                        +10
                        Лучший комментарий — это тест.
                          –1
                          Function InitClient(someArguments, &error=Null) {
                          //Логика работы: 1. Старт сокета, 2. соединение, 3. хендшейк
                          //Входящие параметры: тратата
                          //Возврат: Объект типа ClientConnection; Null в случае какой-то ошибки, error содержит описание ошибки
                          // 1. Старт сокета
                          Code Code Code
                          // 2. Соединение
                          Code Code Code
                          // 3. Хендшейк
                          Code Code Code
                          } //Конец InitClient

                          В таком случае я могу понять логику в 1 строке, пропуская весь код функции. Если всё грамотно сделано, то сокращает анализ кода
                            +9
                            Сколько строчек кода в функции? Можно отрефакторить и вынести код в три метода с понятными названиями.
                              +1
                              Иногда рефакторить вредно — когда операция идет на неявно связанных объектах единожды в программе, но при этом используется весьма много параметров, у вас получится еще большая каша.
                              А иногда просто функция сложная и состоит из этапов. Удобно вам иметь одну функцию, которая делает что надо и разбита по пунктам, или лучше иметь InitClient(Arg){return InitClient_Step3(InitClient_Step2(InitClient_Step1(Arg)))}
                                +3
                                Мне второй вариант нравится больше, но разумеется не в таком виде.

                                Connection InitClient(args) {
                                    var socket = CreateSocket(args);
                                    var connection = CreateConnection(socket);
                                    connection.StartHandshake();
                                }


                                Хотя целесообразность наличия такого метода с именно такой функциональностью под вопросом, но для этого нужно контекст знать.
                                  +4
                                  А если вам надо ещё и ошибки обрабатывать? Ваш код превратится в nested hell. Такие случаи лучше разбивать на отдельные фунции и связывать через одну цепочку вызовов с Either. На Scala это будет как-то так
                                  def startServer(): Either[String, Server] = {
                                    for {
                                      conf <- loadConfig().right
                                      sever <- startServer(conf).right
                                      _ <- addListeners(server).right
                                      _ <- addHooks(server).right
                                      _ <- logServerSetup(server).right
                                      _ <- verifyServer(server).right
                                  } yield server
                                  


                                  А каждая из функций будет что-то типа
                                    def startServer(conf: ServerConfig) = {
                                     try {
                                        val server = new Server(conf)
                                        server.start()
                                        Right(server)
                                    } catch {
                                      case e: ServerException => Left("Failed to start server " + e)
                                    }
                                  


                                  При таком подходе чётко видно какие функции в каком порядке выполняются, каждая функция отвечает за одну задачу и ошибки удобно обрабатывать. Исполнение остановится на первой встреченной ошибке и вернёт сообщение об этом.
                                    +5
                                    [off]«Какой кошмар ваш Scala»[/off]
                                    Именно по этой причине я и ввожу переменную по ссылке &error — для возврата ошибки
                                      –1
                                      Э… то есть если сервер не стартовал, то приложение ругается в код, но продолжает доблестно работать?
                                        0
                                        Нет, если сервер не стартовал, то функции addListeners, addHooks и т.п. не запускаются вообще, а вызывающему возвращается ошибка в виде Left(error). Вызывающий уже обработает это, в соответствии с бизнес-логикой.

                                        Преимущество в том, что нормальный процесс весь в одном месте, а обработка ошибок вся в одном, но другом, месте. Примерно того же можно добиться бросая некрасивые исключения отовсюду и только ловя их в одном месте. Но это просто некрасиво.
                                      +1
                                      Почему бы такие функции не вынести в объект?
                                        +2
                                        Скажем так, в куче языков просто объект с функциями — весьма нетривиально и\или весьма нестандартно. Этим вы внесете еще большую путаницу. Ну а необходимость выделять под одноразовую «не-reusable» задачу класс — это известный холивар. Я сторонник не городить ООП там, где можно и проще обойтись функциональным программированием.

                                        В добавок, 99% моей текущей деятельности на PoSH, в котором весьма геморройно выглядят любые введения ООП от имени пользователя
                                          0
                                          Ну согласитесь, если набор функция оперирует множеством переменных, на 2-3 экрана, ее нужно разбить на методы. Потом оказывается, что эти функции будут работать каждая с 3+ переменными. Безусловно удобнее будет выделить подобное в класс, или переменные вынести в существующий класс.
                                          Это все, если конечно пишешь в ООП стиле, не процедурном
                                            0
                                            Полностью согласен, если язык предусматривает введение классов.
                                            Если же это скриптовый язык типа PoSH, то сама операция создания класса и его объекта вызовет лютый баттхерт, а коллеги не смогут прочитать код, так как введение класса в языке, который в большинстве своем используется для маленьих простых програм — очень редкое и невиданное явление
                                +14
                                Видимо, вы никогда не разбирались в больших проектах. Встретить комментарий — большая радость, уменьшает количество работы и времени для добавления фичи ил правки бага.
                                  +1
                                  Мы говорим о комментировании кода. Нет никакой разницы большой проект или маленький, это уже вопрос проектирования.

                                  Ну а вообще, я только лишь хотел аргументированное мнение от Lamaster, он уже второй комментарий делает пустые заявления.
                                    +10
                                    Оо да. На моём веку было много случаев, когда именно в больших проектах комментарии не соответствовали действительности. Потому что код изменился, а комментарий остался.

                                    Так что есть комментарий или нет — а в код смотреть надо. Особенно в больших и старых проектах.
                                      +3
                                      Помню в большом проекте долго разбирался с куском кода, и увидел комментарий, уже обрадовался, как прочитал что там было написано: /* Refactoring this shit */
                                      +1
                                      Ваше утверждение ничуть не потиворечит созержанию поста. Автор предлагает решение взамен комментариев, которое работает даже лучше них. Понятное дело, что если никто не трудился над понятностью и чистотой кода, то встретить хотя бы комментарий — это просто счастье. Вопрос в том, как писать код сейчас, чтобы при его поддержке не приходилось так же «радоваться».
                                    0
                                    Ну вот видите, прочитали пост и после этого написали комментарий по делу. Более того, я с вами даже в чем-то согласен. Сам стараюсь писать предельно понятный код(очевидные имена переменных, методов и классов, лаконичные методы, выполняющие одну задачу), но при этом стараюсь еще и дополнять код комментариями. Тем более, что пишу на C# и XML комментарии помогают при использовании методов из других классов.
                                +4
                                Всеми руками за! Сам работаю с проектом (livestreet), для примера есть файлы, где на 110 строк только 20 строк кода. Поэтому работа начинается с удаления комментариев — тогда становится возможным читать код, а не комментарий что $sCurrentAction это переменная, которая хранит текущий экшн, и принимает строковые значения.
                                  +4
                                  Ну в публичных CMS это оправдано, тут уровень понимания пользователя может весьма варьироваться.
                                    +2
                                    в публичных CMS есть документация. Не нужно запихивать её в файлы с кодом (пример комментария выше — реален).

                                    Серьёзно, я в первый раз столкнулся с Livestreet и обилие комментариев только мешает разбираться с кодом. Тем более большинство комментариев просто копирует название функций/переменных.
                                      +7
                                      Не знаю как livestreet, но многие решения генерируют техническую документацию именно из комментариев к коду.

                                      Некоторые IDE могут сворачивать комментарии.
                                        –2
                                        >>многие решения генерируют техническую документацию именно из комментариев к коду.
                                        И это очень плохо. В результате получается документация, которая «как бы есть».

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

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


                                          С какого перепугу «как бы есть»? Если разработчик ленивый и не документировал как следует код — это его проблемы и проблемы его квалификации. Если уж смог написать прототип метода, потрать еще 2-3 минуты и напиши к нему коментарий, из которого сгенерируется документация. Эти коменарии и есть по сути написание документации.
                                          Плохой разработчик и код напишет, который «как бы есть».

                                          Вот вам пару примеров «как бы есть», AFNetworking, Facebook iOS SDK. Да вооще любая зрелая и уважающая себя open source библиотека для iOS подробно документирует в коде все свои API, чего уже говорить про код самой Apple.

                                          И понятие «читаемости» у вас какое-то специфическое, даже «забитая строка» ее ухудшает…
                                            –6
                                            Обьясняю
                                            /**
                                            * Абстрактный класс экшена.
                                            *
                                            * От этого класса наследуются все экшены в движке.
                                            * Предоставляет базовые метода для работы с параметрами и шаблоном при запросе страницы в браузере.
                                            *
                                            * @package engine
                                            * since 1.0
                                            */
                                            abstract class Action extends LsObject {
                                            /**
                                            * Список зарегистрированных евентов
                                            *
                                            * var array
                                            */
                                            protected $aRegisterEvent=array();
                                            /**
                                            * Список параметров из URL
                                            * /action/event/param0/param1/../paramN/
                                            *
                                            * var array
                                            */
                                            protected $aParams=array();
                                            /**
                                            * Список совпадений по регулярному выражению для евента
                                            *
                                            * var array
                                            */
                                            protected $aParamsEventMatch=array('event'=>array(),'params'=>array());
                                            /**
                                            * Объект ядра
                                            *
                                            * var Engine|null
                                            */
                                            protected $oEngine=null;
                                            /**
                                            * Шаблон экшена
                                            * see SetTemplate
                                            * see SetTemplateAction
                                            *
                                            * var string|null
                                            */
                                            protected $sActionTemplate=null;
                                            /**
                                            * Дефолтный евент
                                            * see SetDefaultEvent
                                            *
                                            * var string|null
                                            */
                                            protected $sDefaultEvent=null;
                                            /**
                                            * Текущий евент
                                            *
                                            * var string|null
                                            */
                                            protected $sCurrentEvent=null;
                                            /**
                                            * Имя текущий евента
                                            * Позволяет именовать экшены на основе регулярных выражений
                                            *
                                            * var string|null
                                            */
                                            protected $sCurrentEventName=null;
                                            /**
                                            * Текущий экшен
                                            *
                                            * var null|string
                                            */
                                            protected $sCurrentAction=null;

                                            /**
                                            * Конструктор
                                            *
                                            * param Engine $oEngine Объект ядра
                                            * param string $sAction Название экшена
                                            */
                                              +9
                                              Ну это явно написано под автокомплит любимой IDE разработчика или под генерирование документации, как я и говорил.

                                              Используйте IDE вроде PHPStorm и вы по-другому будете смотреть на такие комментарии(аннотации).
                                                +3
                                                Поддерживаю. Раз. Два.

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

                                                Любой более-менее продвинутый текстовый редактор (sublime text 2, например), имеет кучу средств навигации по коду «в обход» этих коментариев.

                                                Могу только придумать одну ситуацию, когда это тяжело читать — в текстовом редакторе типа Notepad'а, без какой-либо подсветки синтаксиса, и когда код, по какой-то необъяснимой причине, нужно читать от корки до корки, как страницы в книге, как роман. Тогда да, ваши аргументы уместны.
                                                0
                                                Бедный хабрапользователи от икоты поди уже отчаялись. В следующий раз форматируйте код перед размещением в комментариях.
                                                0
                                                Эти библиотеки (AFNetworking, FB SDK) скорее комментируют свой API чтобы собрать из этого appledoc'и.
                                                +5
                                                Свернуть комментарии — идея хорошая — но это доп действия ручками.
                                                Зачастую в IDE есть и автоматическое сворачивание регионов определённого типа.
                                        +2
                                        Полностью согласен, лучше уделить время понятному коду.

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

                                        Так же насчет doc комментирования, его очень хорошо использовать в классах, которые по определению реюзабельны, эти комментарии подхватывают многие IDE и выдают понятный пользователю автокомплит.
                                          +6
                                          Создавайте отдельную функцию на каждую неявную формулу/регулярное выражение. Это значительно улучшит понимание кода.

                                          Согласитесь, checkMail($mail) читается гараздо лучше, чем
                                          preg_match('/^([0-9a-zA-Z]([-.w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-w]*[0-9a-zA-Z].)+[a-zA-Z]{2,9})$/si', $subject, $regs)
                                            +3
                                            Ну тут можно функцию то не городить. А сохранить сам регехп в переменную с именем checkMailRegExp и уже его проверить. А вообще регехп бы статической константой вынести глобально. Чтоб в проекте не было 10 разных валидаций. Я больше люблю разруливать такие вещи говорящими переменными нежели функциями. Если нужна будет какая то более сложная обработка то уже функция отдельная, опять же лучше в каком то паке утилов завести что консистентность проверок поддержать.
                                              +1
                                              Можно и так — суть в том что можно обойтись без комментария.

                                              Единственная проблема в вашем решении в том, что если регекспа станет не хватать, то прийдётся во всём коде переделывать на функцию.
                                                +2
                                                Да, и не так уж это и сложно. Я пришёл к выводу что бритва Оккама работает очень хорошо. Делать надо минимум. Если вы точно знаете что такая более сложная чем регехп обработка будет, то можно сразу функцию заводить. В противном случае нет. Не так уж и долго найти все ссылки на константу и во всех местах на функцию заменить, совсем не сложно. Зато не будет ненужных уровней абстракции. За последние пару лет разработки я понял что всего на перёд всё равно не предусмотришь, а в 10-15 местах заменить одно на другое не проблема, особенно когда ide рефакторинг хорошо поддерживает.
                                              +2
                                              Это проблему решает лишь отчасти. Тут, имхо, нужен комментарий, указывающий как проверяется адрес почты и почему именно так. И если «как» кому-то может показаться избыточным (типа, ты что не впитал навык чтения PCRE с молоком матери?), то «почему так» тут явно напрашивается.
                                            +6
                                            Вообще придерживаюсь принципа: комментируй как это сделано, а не что с.делано.
                                            Ещё недавно видел вот такую штуку и мне прям понравилось:
                                            if (equation > 0) { doSmth(); } else if (equation < 0) { doSmthElse(); } else { // комментарий о том что случай с равенством нулю не забыт, // обработка не требуется. }
                                            Сразу понятно что и как.

                                            //fallthrough всегда пишу когда применяю.
                                            Иногда вместо обновления приватной переменной изнутри класса дёргаю внешний сеттер, тогда тоже пишу коммент что сеттер дёрнут намеренно. Или геттер с ленивой инициализацией. Этидва случая конечно попахивают, но иногда для простоты и балланса между горой ненужного кода и простотой применяю.
                                            Т.е. если код может быть прочтён двояко, и может быть заподозрена ошибка то пишем коммент.

                                            А вообще с постом согласен, тупы хоменнтариев дублирующих написанное быть не должно.
                                              0
                                              Подождите, вы пишите код, которым описываете, как вы это сделали. А потом описываете в комментарии как это сделали?

                                              Серьезно, имя функции, переменных, класса, анотации — неужто этого не достаточно? Нет, было время, мне нравилось писать хитросделанные фунции и формулы, которые не с первого получаса поймёшь — но блин, мы же продукт делаем, а не заковыристостью кода хвастаемся!
                                                0
                                                Подождите, вы пишите код, которым описываете, как вы это сделали

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

                                                Блин, тег code херню какую то делает. source надо использовать

                                                if (equation > 0) {
                                                	doSmth();
                                                } else if (equation < 0) {
                                                	doSmthElse();
                                                } else {
                                                	// комментарий о том что случай с равенством нулю не забыт,
                                                	// обработка не требуется.
                                                }
                                                  0
                                                  >>Вообще придерживаюсь принципа: комментируй как это сделано, а не что с.делано.

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

                                                  К тому же очень часто такой комент должен звучать как
                                                  //Тут надо вроде ещё проверку сделать, но этот случай маловероятен, PM сказал забить.
                                                    +1
                                                    //Тут надо вроде ещё проверку сделать, но этот случай маловероятен, PM сказал забить.
                                                    Вот такой зло как раз. У нас, слава всем богам, есть время разработчиков когда они выполняют поддержание кода и инструментов в порядке, и не отчитываются за это время ни перед кем. В такое время это и делается. А мой вариант показывает что не забыли это обработать. Он не маловероятен, он вполне вероятен, только действие не требуется. И не сразу это очевидно. Когда придумывал, думал что понадобится действие. Написал последний елс. Потом попробовал внести в один из ифов также равенство, тоже не круто. Вот и выделил отдельно. И всегда понятно будет почему так, и при чтении руки ни у кого не зачешутся поправить.
                                                      –2
                                                      Ок, давайте рассмотрим

                                                      b = $('.someDiv');
                                                      if (b.html() == "")
                                                      b.html(«Привет»);

                                                      *тут код продолжается*
                                                      — Ваш вариант:
                                                      b = $('.someDiv');
                                                      if (b.html() == "")
                                                      b.html(«Привет»);
                                                      else {
                                                      /*тут ничего делать не надо, просто так конструкцию написал*/
                                                      }

                                                      *тут код продолжается*

                                                      Может быть лучше просто не писать конструкции, если их не нужно использовать?
                                                      Если же код неочевиден — то очевидно нужно его изменить.
                                                        +5
                                                        Да пишите, кто же против то. Вам же код поддерживать. Я говорил о случае когда мы по некому условию разбиваем всё доступное пространство входных данный на некоторые большие области и их специфично обрабатываем. Классической ошибкой в таких штуках является потерять границы. И часто при дебаге и чтении кода на таких местах заостряется внимание. Тут просто сразу дана подсказка что это не ошибочно забыто а сознательно не обработано. Мне это помогает. И, если вы не заметили, не рекомендую всегда так писать. Но в некоторых местах такая штука бывает полезна. Мы код пишем чтоб писать его и поддерживать.
                                                          –5
                                                          >>Мы код пишем чтоб писать его и поддерживать.
                                                          А мы — чтоб он работал :)

                                                          Если без шуток — каждый комментарий — это напоминание о том, что код попахивает (например — каждая область if содержит по сотне строк). И тут есть два пути:
                                                          1) оставить комментарий
                                                          2) исправить код

                                                          Естественно это всё не про анотации.
                                                            +1
                                                            Вовсе не каждый. Как минимум комментарии нужны, чтобы объяснять почему выбран конкретный вариант в рамках предметной области. Скажем «используем ньютоновскую механику, релятивистскими эффектами можно пренебречь — это эмулятор морского корабля, а не космического :)» или «проверяем валидность мыла „интуитивно“, извращенцы, знающие RFC наизусть — не наша ЦА»
                                                              0
                                                              Вам не кажется, что в код стоит лезть с некой определённой целью? Скажем — определить откуда растут ноги у ошибки, провести рефакторинг и так далее. Т.е., грубо говоря «какую формулы мы выбрали» — должна рассказывать спецификация к проекту (юзер стори, сценарии поведения пользователя и так далее). А код — должен просто это реализовывать. Так зачем спецификацию запихивать в код?
                                                                0
                                                                Ошибка может быть из-за того, что релятивистские эффекты не учитываем или учитываем их криво. Вот чтобы разобраться в «или» нужна документация к коду.

                                                                И далеко не все проекты достаются с отдельной документацией, даже если она когда-то была. Зачем плодить сущности сверх необходимого, если можно документировать код прямо в коде комментариями?
                                                                  0
                                                                  Потому что это:
                                                                  1) Экранирует принципы реализации от не-программистов (например от физиков и математиков, маркетологов и так далее)

                                                                  2) Мешает разбераться в коде (честно — я ту формулу не с первого раза пойму, даже если будет приписано что это за формула. Так что просто так копаться точно не буду)

                                                                  3) комментарий не изменяется вместе с кодом. Точнее должен — но часто о нём забывают. В результате Вы офигиваете от того, что релятивистские эффекты не учитываются на скоростях близких к С, потом офигиваете от того, что они таки учитываются (вопреки комментарию).
                                                +3
                                                Жесть какая-то. Тогда надо к каждому IF писать ELSE с комментарием «не, я не забыл про этот случай — просто ничего не надо делать». Ну чтобы уже наверняка! А то мало ли кто заподозрит…
                                                  +8
                                                  Кому-то жесть, а кому-то… Согласен, что нужна «золотая середина».

                                                  Лично я не вижу ничего плохого прописать явно какую-то пустую или тупиковую ветку алгоритма с комментарием "//do nothing", чтобы потом вспомнить, что там действительно «nothing to do». Естественно, делать так повсеместно не призываю:)

                                                  Одно время я параноил и расставлял return без параметров в функциях, которые не должны ничего возвращать. Тем самым я подчеркивал, что функция действительно дописана, а я не просто отвлекся от кода и забыл дописать:). Сейчас от этого отошел, но это и есть — поиск «золотой середины»:)
                                                    –2
                                                    В упор не понимаю зачем сама ветка ELSE существует. Самый нормальный способ — добавить юнит тест наподобие ifEquationIsZeroDoNothingBecause… Но если так и прет дописать комментарий, то можно сделать его перед первым IF. Сама ветка ELSE вообще ни к селу ни к городу. По поводу вашего return без параметров — вы просто набрались опыта и поняли, что это бесполезная практика. А другие разработчики, которые с вами работали, одобряли эту практику?
                                                      +7
                                                      Я не понимаю, почему тесты так упорно противопоставляются комментариям в коде. Одно другому не мешает!

                                                      Что касается «избыточной ветки ELSE».

                                                      Case1. Программист дочитал до этого ELSE и подумал (как Вы, например) «нафига здесь эта пустую ничего не означающая ветка?» — это мысль на доли секунды, такой риторический вопрос, ответ на который дан в комментарии; код читается дальше с мимолетным ощущением собственной крутости «а я и так все понял бы, без этой тупиковой ветки!»:)

                                                      Case2. Программист в поисках ошибки добирается до IF и не видит обработки ветки ELSE. Задумывается, начинает смотреть, а что означает эта другая отсутствующая ветка с точки зрения входных данных, даже находит заботливо подготовленный старшим товарищем unit-тест, запустив который, убеждается, что зря параноил. 5 минут тоже не так много в масштабе вселенной, но… против долей секунды в Case1 — неприлично много.

                                                      Имхо,
                                                      тесты отвечают на вопрос «оно все еще работает?», а комментарии отвечают на вопрос «почему оно работает?».

                                                      Это лишь мое скромное мнение, сформированное за 20 лет программирования:)
                                                        0
                                                        Вы так увлеклись выдумыванием странных кейсов, что забыли про мой основной вопрос: «Зачем ветка ELSE, если комментарий можно поставить перед первым или последним IF?».

                                                        Почему оно работает вам должны говорить имена классов, переменных, методов и комментарии в том случае, когда вы не в силах выразить сложность задумки простым и понятным кодом.
                                                          +1
                                                          Николай,
                                                          я не призываю в каждом случае фанатично ставить пустые ветки ELSE:)
                                                          На самом деле, наличие такой ветки больше вписываются в Ваше мировоззрение — все-таки «else {}» — это код, который «говорит сам за себя»;)
                                                          Я говорю лишь то, что не вижу ничего зазорного в том, чтобы использовать такую конструкцию, если по смыслу окружения могут закрасться сомнения — вот и все!

                                                          p.s. Я реально не вижу смысла в продолжении этой ветки дискуссии, чтобы не превращать обсуждение в балаган, что настойчиво пытаются сделать два товарища далее по тексту:). Предмета для спора просто нет:)
                                                            0
                                                            На самом деле действительно вставка ветки else выглядит несколько сомнительным приемом. Его хотя бы нужно было тоже закомментировать с фразой типа «вдруг когда нибудь придется обрабатывать и ноль». Информативность в плане того, что обработка ноля не баг, а фича не уменьшается, но эффективность кода может понизиться в некоторых трансляторах.
                                                    +3
                                                    Не так. В коде из примера любой новый программист вначале будет считать, что он обнаружил ошибку («да тут же не обрабатывается случай, когда equation == 0 !»). Именно для этого и написан комментарий.
                                                      +3
                                                      «Programs must be written for people to read, and only incidentally for machines to execute», воистину :)
                                                  0
                                                  А во, ещё практика. Иногда я в коде закладки делаю своеобразные, // guid
                                                  И в отдельном файле что помечено какими гуидами. Удобно задумать например какой то рефакторинг, держать его в голове пару недель и расставлять в коде такие метки с местами которым стоит уделить внимание. Потом банальным поиском по проекту элементарно находится. Гуит у меня в ide одним хоткеем ставится.
                                                  Пришёл к выводу что это лучше чем всякие системы закладок на код. Потому что команда у нас работает с разными ide + элементарн работать с такими метками даже в блокноте, никогда не рассинхронизируются. В общем счастье одно.
                                                    +2
                                                    На мой взгляд, комментарии как намерения обязательно должны присутствовать, в коде или в документации. Если их нет, то ошибочный код будет неотличим. Затем, идею прочитать легче в тексте, чем разбирать в не очень приспособленном для этого языке. Пример идеи: поставить перед текстом "#", если это hex-строка и реализация; что прочитать легче?
                                                    var color = $("#color").val().toUpperCase(), cL = color.length;
                                                    for(var i in cL)
                                                        if(cL[i] < '0' && cL[i] > 'F') //найден не hex-символ
                                                            break;
                                                    document.body.style.backgroundColor = (color.charAt[0] !='#' && i < cL ?'':'#') + color;
                                                    
                                                      0
                                                      Имхо в идеале- вынести в отдельный метод с соответствующим названием. А уже этот метод нормально прокомментировать.
                                                      Но суть в том что комментарии придётся читать только если нужно выяснить как он там работает, а не просто в момент когда встречаешь его вызов.
                                                      Т.е. что-то типа «PrepareColorValue»(название можно придумать и получше чем у меня), а что там внутри нужно будет смотреть только когда надо действительно разобраться что там такое
                                                        +1
                                                        Вот видите, какую вы ужастную реализацию сделали, что её и понять то с первого раза сложно.
                                                        Вынесите код в функции, избавтесь от неочевидных конструкций типа color.charAt[0] !='#' && i < cL ?'':'#' и комментарии станут не нужны.

                                                        Самая большая проблема коментов в том, что после изменения кода — комментарии автоматически не меняются
                                                          +5
                                                          if(cL[i] < '0' && cL[i] > 'F') //найден не hex-символ

                                                          Какой смешной код. Между '0' и 'F' ещё много чего находится.
                                                            0
                                                            Это и есть иллюстрация того, что идея описывается цельнее, чем код, который имеет допуски, которые в данном случае работают — нужно лишь отличать hex-коды от слов, в которых не встречается ни тех 7 знаков, ни многих других (если подробнее, то наличие ошибочного знака с тем же успехом не даст результата, что и отсутствие "#").
                                                            +2
                                                            Правильное решение — вынести проверку в отдельный метод: скажем,
                                                            CharIsHexSymbol(c) {
                                                              return c > '0' && c < 'F';
                                                            }
                                                            

                                                            Код сам себя успешно комментирует, и это допустимо почти в любой ситуации. Ну все примеры, которые народ приводил, все поголовно используют комментарии там, где можно использовать инкапсуляцию.
                                                            Согласен, что иногда комментариев не избежать, но уж, имхо, точно не в случае с пустым ELSE. Тудухи — в тудухи, если вы на своих проектах забиваете на тудухи, то это проблема не тудух, а ваших проектов.
                                                              0
                                                              Хоть и плюсанул ваш коммент, но, имхо, тут всё же необходим комментарий, объясняющий почему столь странная (по крайней мере для ASCII-based кодировок) проверка выбрана. Зачастую комментарии служат лишь средством записи контракта (это понятие несколько шире чем сигнатура обычно). В данном случае либо в комментарии а-ля *doc напрашивается описание для функции типа «Argument MUST not to match to PCRE /[:-@]/» или «надеюсь, не найдется идиота, который в поле для ввода шестнадцатиричного числа будет набирать некоторые знаки препинания и прочей типографики» (типичный случай, почему у меня в коде присутсвуют комментарии на двух языках :( )для самой проверки. Во втором случае функцию можно было бы называть CharIsNeralytHexDigit, но опять же для понимания того, что значит «nearly» нужно будет в код заглядывать, а название CharIsBetween0AndF выглядит совсем тупо — типичный случай, когда код лучше инкапсуляции.

                                                              Или ещё пример, когда комментарии крайне желательны: Реализуем функцию сортировки. С точки зрения вызывающего кода всё равно как мы её реализуем, потому именуем её тупо sort(array) — что делает функция определено. Решаем реализовать её пузырьковым методом — как нам донести это для читателей кода без комментариев? Переименовать именно в «пузырьковую сортировку»? Так могут возникнуть мысли, что в использовании именно её есть некий сакральный смысл, что мы ограничены, скажем, в памяти, а не в процессоре. Оставить всё как есть? Так можем допустить ошибку в реализации и читающему код не будет понятно баг это или фича, а то он просто не опознает в ней именно пузырьковую.
                                                                0
                                                                Вы абсолютно правы, собственно, именно это и имел в виду Макконнелл, говоря про комментирование намерений. Но в данном топике народ старательно путает намерения и реализацию.

                                                                Что касается сортировки… Мне лично кажется, что если в ситуации допустимо использование нескольких сортировок, лучше воспользоваться каким-то паттерном, наподобие композита. Читающему код будет понятно, что в каждом конкретном вызове композитного сортировщика выполняется какая-то сортировка, а какая именно — будет отлично видно в названии класса-сортировщика.
                                                                В случае если мы вдруг при живом квиксорте решили воспользоваться пузырьком, конечно, комментарий следует написать, но именно как описание некоего магического знания: «Здесь мы проседаем по памяти». Потому как в противном случае (вместо названия писать суть в комментарии) придется писать комментарий на каждый вызов этой сортировки.
                                                            +19
                                                            Канонический ответ: зависит от кода и области применения. Вот сейчас как раз читаю код коллеги — реализация некого анализа на основе normalized cross-correlation на CUDA. Даже с учетом того, что я знаю идею и формулы, сложно было бы уследить за извивами мысли без комментариев.

                                                            Если работаете с каким-либо мат.аппаратом, то лучше перебдеть.
                                                              –1
                                                              Проблема черезмерного комментирования и написания все-в-одном методов очень свойственна, почему то, именно Инженерам, т.е. тем кто больше работает с мат. аппаратом а не реализацией. И часто такой код трудно поддерживать без рефакторинга, даже если он и неплохо документирован.
                                                                +4
                                                                Ну декомпозицией кода в таких решениях, можно и навредить, я уже представляю класс из 300 методов или 300 классов по одному методу, как больше нравится.
                                                                  0
                                                                  Ну, как говорится, сделай все максимально просто но не проще чем это возможно. Само собой я не говорю о тех вариантах где это навредит.
                                                                    +3
                                                                    А мне когда то пришлось работать с функцией на 2500 строк. Поверте, лучше 300 отдельных методов.

                                                                    Человек привык работать с абстрациями. Мы говорим — «дойди до остановки и сядь на автобус до стадиона» — не уточняя, как именно идти (скорость, длина шага), какой остановки(обычно это понятно в контексте) и что это вообще такое, и как выглядит стадион.
                                                                      0
                                                                      Ну просто получается такая ситуация: выносить, скажем так, «одноразовый» код в отдельные методы так же не лучшая практика.

                                                                      Нужно грамотно выдержать баланс между декомпозицией, реюзабельными методами и комментариями, но это уже дело немалого опыта.
                                                                        +1
                                                                        Если код одноразовый, то грамотный компилятор соберет все «одноразовые» методы в одну функцию. Даже без явного inline.
                                                                          0
                                                                          выносить, скажем так, «одноразовый» код в отдельные методы так же не лучшая практика.


                                                                          Вы зря считаете что код выносится в методы только для уменьшения энтропии code duplication. Это лишь одна сторона, и я бы не сказал что главная. Большинство кода (по крайней мере в моей работе) — одноразовый. Но я неустанно бью код на мелкие методы (порой по 2-3 строчки) для поддержания некого layering'а в рамках класса. Методы уровнем повыше вызывают методы уровнем пониже. А мешать вызовы высокоуровневых методов с какой нибудь низкоуровневой арифметикой (хоть и относящейся к ответственности сего класса) — не комильфо. Мозг очень медленно при чтении таких методов меняет уровень абстракции. Приходится перечитывать по несколько раз. Лучше чтобы один метод имел один уровень.

                                                                    +11
                                                                    Особенно полезны комментарии к математике в шейдерах или граф\физ движках: там ради оптимизации в пару тактов может так формула измениться, что саппортер глаза сломает, пока поймет по коду. Один только dot(a,a) вместо pow(length(a),2) чего стоит, и это далеко не сложный пример.
                                                                      +6
                                                                      Аналогичная ситуация по коду на assember-е и некоторым скриптам на bash-e. Такой недокументированный код мы между собой называем write-only:)
                                                                        +2
                                                                        Хмм, иногда целые языки программирования называют write-only… ;)
                                                                          0
                                                                          Но если вы сами работаете с ассемблером — то не проще ли научиться такой код читать? Хотя комментарии вроде «здесь мы используем флаг Carry, полученный 6 команд назад» вполне могут пригодиться: слишком большой риск, что при редактировании кто-нибудь его испортит.
                                                                            +4
                                                                            Да что уж тут! Давайте запишем в корпоративных стандартах, что в команде программистов должны быть только гении, да чтоб еще и мысли друг друга могли читать через время и расстояние. И действительно, о чем мы тут спорим?:)

                                                                            С комментариями, опять же по моей практике и по моему скромному мнению, значительно больше шансов, что никто ничего не испортит:)
                                                                              0
                                                                              Недавно на Хабре был опрос. 16% сказали, что они могут быстро разобраться в любом чужом коде. Может быть, существование write-only языков, всё-таки, несколько преувеличено?

                                                                              А чтобы с комментариями никто ничего не испортил, тут уж точно надо уметь читать мысли — причём из будущего. Чтобы понять, что придёт в голову будущему редактору, что для него будет очевидным, а что — тоже очевидным, но при этом неправильным?
                                                                              Разве что комментарий типа «у этого блока вход такой-то, выход такой-то, меняет то-то, делает то-то, других побочных эффектов не имеет. Write-only, хотите изменить поведение — переписывайте заново». Если программа разбита на подобные блоки, то шансы, что её не испортят, слегка повышаются.
                                                                                +2
                                                                                А чтобы с комментариями никто ничего не испортил, тут уж точно надо уметь читать мысли — причём из будущего. Чтобы понять, что придёт в голову будущему редактору, что для него будет очевидным, а что — тоже очевидным, но при этом неправильным?

                                                                                Решается путем чтения своих мыслей при написании кода :)
                                                                                  +1
                                                                                  Так мысли-то говорят, что вновь пришедшие программисты будут умнее нас — так что то, что очевидно мне, будет тем более очевидно и им. Зачем тогда комментарии?
                                                                                    0
                                                                                    Умнее-то они может и будут, но вот контекст совпадать совсем необязательно будет. Наверное, основная задача комментариев — это именно передача контекста. Что мы придумали видно и так в коде, но вот почему мы придумали именно так и что имели в виду на самом деле (чтобы читатель кода точно знал «это не баг, это фича») нужно документировать.
                                                                                      0
                                                                                      Тогда 80% комментариев к проекту должны жить вне кода, в большом документе сопровождения. Где перечисляются не классы с интерфейсами, а общие концепции и их взаимосвязи. Возможно, с указанием их отражения в архитектуре. Ведь это и есть контекст проекта. Только… кто ж его писать и поддерживать-то будет?
                                                                                        0
                                                                                        Вот комментарии и должны минимизировать необходимость такой документации :)
                                                                                          0
                                                                                          Я думаю, что наоборот :) Контекст — штука глобальная. Даже такие мелкие решения, как «захватывать/освобождать массивы каждый раз или повторно их использовать», не очень понятно, где описывать — их влияние может распространяться на несколько файлов. А в глобальном контексте местечко для описания найдётся сразу.
                                                                                            0
                                                                                            Извините, упустил слово «общие». А если контекст локальный? Вот выбрал я «пузырек» для сортировки — где не самое лучшее место как в самой реализации сортировки описать почему я его выбрал? Может я просто других методов не знаю, может минимизировал свои усилия, а может минимизировал потребление памяти.
                                                                          +1
                                                                          За pow(length(a),2) — выгонять из проекта, пока не исправится. Выглядит оно заметно сложнее, чем dot(a,a), а выполняется в 10 раз дольше. Любой, кто работает с компьютерной геометрией, увидит и поймёт скаляный квадрат вектора, вообще не затрачивая усилий — это же идиома!
                                                                          А более сложный пример можете привести? Если можно, без комментариев :)
                                                                            +3
                                                                            Никто в здравом уме и не пишет возведение в степень для квадрата, но ведь и руки не отвалятся если рядом с чем-то вроде dot(a,a) писать // length(a)^2, а лучше кончную цель вычисления или формулу.
                                                                            Вот простой пример с dot:
                                                                            n.z = sqrt(saturate(1.0f - dot(n.xy,n.xy)));

                                                                            Шейдерист по профилю с первого взгляда узнает восстановление третей компоненты tangent-space normal, но часто бывает, что код надо надо саппортить программисту более широкого профиля и простейший комментарий с формулой тут был пригодился.

                                                                            А вот пример показательного шейдерного кода без комментариев (© unigine):
                                                                            
                                                                            float4 q2 = q0 * (2.0f / dot(q0,q0));
                                                                            q0 *= scale;
                                                                            			
                                                                            float4 qq0 = q0 * q2 * 0.5f;
                                                                            float3 q0x = q0.xxx * q2.yzw;
                                                                            float3 q0y = q0.yyz * q2.zww;
                                                                            float3 q1x = q1.xxx * q2.wzy;
                                                                            float3 q1y = q1.yyy * q2.zwx;
                                                                            float3 q1z = q1.zzz * q2.yxw;
                                                                            float3 q1w = q1.www * q2.xyz;
                                                                            			
                                                                            float4 row_0 = float4(qq0.w + qq0.x - qq0.y - qq0.z,q0x.x - q0y.z,q0x.y + q0y.y,q1w.x + q1x.x - q1y.x + q1z.x);
                                                                            float4 row_1 = float4(q0x.x + q0y.z,qq0.w + qq0.y - qq0.x - qq0.z,q0y.x - q0x.z,q1w.y + q1x.y + q1y.y - q1z.y);
                                                                            float4 row_2 = float4(q0x.y - q0y.y,q0x.z + q0y.x,qq0.w + qq0.z - qq0.x - qq0.y,q1w.z - q1x.z + q1y.z + q1z.z);
                                                                            
                                                                              0
                                                                              Весело у вас :)
                                                                              Сначала, увидев .yzw, я подумал, что речь идёт о тензорах 4^3 (потом понял, что ошибся). Потом ещё надо было догадаться, что умножение покоординатное. В итоге получилось что-то вроде возведения в квадрат матрицы поворота на малый угол со сдвигом. Хотя, наверное, у этой формулы есть более строгий физический или геометрический смысл.
                                                                                0
                                                                                Конечно же я вырвал кусок кода из контекста, чтобы эффект был заметнее. =) На самом деле по имени файла, дефайнам и пр. видно, что это скиннинг с Dual Quaternions, q0 и q1 это кватернионы соседних двух костей, а row_* формируют результирующую Modelview матрицу для вертексов. Но, ей Богу, если будет подозрение на ошибку в этом месте, то головная боль обеспечена.
                                                                                P.S. К чести автора кода (тов. frustum из Unigine), он отлажен и работает идеально. Но все же пример показателен.
                                                                                  0
                                                                                  Не похоже, чтобы q0 и q1 были независимы (что такое «соседние кости», я не знаю). q1 попадает только в столбец сдвига, а q0 явно отвечает за поворот… вычисляется матрица для чего-то вроде (q0*v+q1)*Inverse(q0). В первый раз такое вижу. Когда писал сам, то использовал q0*v*Inverse(q0)+VShift. Надо будет посмотреть, в чём преимущество ввода вектора сдвига под скобку. А то вдруг кватернионы снова понадобятся (в своём проекте я отказался от них лет семь назад, в пользу матриц).
                                                                                +1
                                                                                А вообще, это интересный пример. Здесь самым полезным комментарием (после глобального — «преобразуем кватернионы в матрицу») будет как раз «что сделано», а не «как сделано» — явно расписанные формулы перед вычислением row_0, row_1, row_2. Тогда читатель сможет, во-первых, убедиться, что формулы соответствуют теории (а если не соответствуют — внести нужные изменения), а во-вторых — проследить, где какой член этой формулы вычисляется, и правильно ли он достаётся.
                                                                                  0
                                                                                  В принципе, явно расписывать формулы не обязательно в подобных случаях, если они широко известны в узких кругах — достаточно ссылки (желательно и библиографической, и URI) на места, где их можно найти.
                                                                          +9
                                                                          Процитирую Макконнелла:

                                                                          «Вопрос о том, стоит ли комментировать код, вполне обоснован. При плохом выполнении комментирование является пустой тратой времени и иногда причиняет вред. При грамотном применении комментирование полезно.
                                                                          Основная часть критически важной информации о программе должна содержаться в исходном коде. На протяжении жизни программы актуальности исходного кода уделяется больше внимания, чем актуальности любого другого ресурса, поэтому важную информацию полезно интегрировать в код.
                                                                          Хороший код сам является самой лучшей документацией. Если код настолько плох, что требует объемных комментариев, попытайтесь сначала улучшить его.
                                                                          Комментарии должны сообщать о коде что-то такое, чего он не может сообщить сам — на уровне резюме или уровне цели.
                                                                          Некоторые стили комментирования заставляют выполнять много нудной канцелярской работы. Используйте стиль, который было бы легко поддерживать»
                                                                            +4
                                                                            Это всё хорошо, пока вы пользуетесь чем-то вроде блокнота или vi. В нормальных IDE комментарии вроде JavaDoc помогают избежать подглядывания в код вызываемых методов, а в случае с пхп и phpDoc и вовсе единственный способ дать IDE знать, какой тип у параметров и возвращаемых значений.
                                                                              0
                                                                              Если, конечно, вести речь о аннотациях перед телом метода|класса.
                                                                              0
                                                                              www.gunsmoker.ru/2010/07/blog-post_31.html
                                                                              Весьма похожая статья бородатых годов. Вы, случаем, не ею вдохновлялись?
                                                                                0
                                                                                Благодарю за ссылку. Ранее не поподалась на глаза =(
                                                                                +8
                                                                                Допустим ситуация — кусок кода или какое-то хитросплетение методов и асинхронных колбеков, и вроде даже код написан с соблюдением всех правил, но очень тяжело понять. Или вы видите какой-то кусок кода, который на первый взгляд не нужен, но есть подозрение, что тут какой-то побочный эффект. И не нужно говорить «код говно», «код говно» это очень даже реальный случай, который нужно нередко поддерживать или рефакторить, но для начала нужно понять что хотел сделать автор.

                                                                                Так вот в такой ситуации, неужели не возникнет мысли «Автор, блин, мудила, не мог пару строк коментариев написать что ли! Без ста грамм не разобраться!»

                                                                                Коментарии нужны, хорошие коментарии нужны, не пишите больше статей с таким заголовком :)

                                                                                Ну а документация исходного кода — отдельная история.
                                                                                Пример iOS документация, сделанная с помощью коментариев в .h файлах и headerdoc. Ведь именно эта документация отображается в Xcode и на сайте iOS Developer. Или аналог headerdoc'а — appledoc. Яркие примеры проектов с такой документацией — AFNetworking и Facebook iOS SDK.

                                                                                Даже если вы пишите код для внутреннего проекта, рано или поздно в команду прийдут новые разработчики. Вы конечно можете сказать «иди читай код, он у нас говорящий», а можете снабдить все API подробной документацией (с помощью коментариев), как это принято в мире open source, да и не только.
                                                                                  +3
                                                                                  Код говорящий? — пусть новичок читает.
                                                                                  Код говорящий, новичок не умеет читать? — не умеющий читать тот язык, на котором пришел работать, не нужен проекту.
                                                                                  Код не говорящий? Переписываем код, потому что он говно.
                                                                                  Код не говорящий, но его переписать понятнее нельзя (потому как хитрая оправданная оптимизация, например) — тогда и начинаем думать о комментировании.

                                                                                  Выше цитата из Макконела где-то о том же.
                                                                                  +14
                                                                                  Автор поста, видимо, никогда не участвовал в больших проектах или не развивал один проект на протяжении длительного времени (пробовали возвращаться к своему коду через 10 лет? Не возникало вопроса «какой дурак это написал?»?)

                                                                                  Глубоко убежден, что комментарии необходимы. Особенно необходимы при написании интерфейсов (классов, библиотек). Огромный плюс, если комментарии стандартизированы, например, в формате doxygen.
                                                                                    –4
                                                                                    >Не возникало вопроса «какой дурак это написал?»?)

                                                                                    Я думаю у любого программиста всегда возникает такой вопрос по поводу своего кода :), вне зависимости от комментариев, если у него есть профессиональный рост.

                                                                                    >Глубоко убежден, что комментарии необходимы. Особенно необходимы при написании интерфейсов (классов, библиотек). Огромный плюс, если комментарии стандартизированы, например, в формате doxygen.

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

                                                                                    Лично я не могу придумать такой пример где комментарий нельзя заменить на более грамотный код. (без крайностей конечно, для исключений нужно и действовать исключительно)
                                                                                      +16
                                                                                      Практически любая оптимизация, когда проектное решение отличается от того, что 99% программистам приходит в голову сразу, требует документирования. Именно в комментарии нужно ответить на вопрос потомков: а почему он сделал так через задницу, а не просто и понятно в лоб? Предвосхитите этот вопрос и не портите себе карму в будущем:))
                                                                                        –5
                                                                                        Может быть проще и правильнее предвосхитить этот вопрос тестом? Если вы знаете о какой-то ситуации, из-за которой код написат так как написан, то воспроизведите ее в тестах. Это не даст вашим «потомкам» на скорую руку поправить «якобы баг» в вашем творении. А если вы такую ситуацию не можете воспроизвести, то может быть и не стоит так код писать. Исключительно редко на моей практике попадались такие ситуации, в основном из-за дефектов во внешнем коде. Вот тогда комментарий с линкой на проблему очень даже полезен.
                                                                                          +2
                                                                                          Я за тесты, также как и за комментарии! Надеюсь, Вы не считаете, что одно другому мешает?:)
                                                                                            +2
                                                                                            А если вы такую ситуацию не можете воспроизвести, то может быть и не стоит так код писать.

                                                                                            Тесты прежде всего фиксируют поведение, но они не объясняют почему оно такое.
                                                                                              +2
                                                                                              Это смотря как вы пишете тесты. Многие используют структуру тестов, которая полностью описывает как раз суть сценария, объясняя ПОЧЕМУ код должен себя так вести. Но естественно не описывают КАК это сделано в коде, то есть его структуру.
                                                                                                0
                                                                                                Для меня поведение кода — это его входы и выходы (включая побочные эффекты). А вот, например, сложности (как по «тактам», так и по памяти) в поведение не входит — это свойства поведения, но не его суть. Именования и тесты раскрывают суть, но не раскрывают свойства. В общем случае. Бывают, конечно, исключения типа «необходимо, чтобы на конкретной программно-аппаратной платформе время исполнения не превышало N микросекунд», но мы же не об этом говорим?
                                                                                          +1
                                                                                          Но, насколько я понял, в данном топике обсуждаются именно комментарии к коду, а не аннотации, которые несомненно полезны.


                                                                                          Многие восприняли этот топик как «нет коментариям вообще!», в том числе нет и аннотациям. Собственно у топика и заголовок такой.
                                                                                          Посмотрите пару веток выше, там как раз идет обсуждение, нужны ли аннотации (по большому счету — специализированные коментарии). Некоторые выступают даже против такого вида коментирования.

                                                                                          А примеры могут быть.
                                                                                          Допустим приходится общаться с сервером, а у его архитектуры есть какая-то необычная особенность, вот есть и все, в силу каких-то архитектурных решений она там давно поселилась и никуда деваться не собирается.

                                                                                          Из-за этой особенности в коде клиента, приходится делать какой-то вызов, который трудно понять, как правильно и красиво ты его не реализуй.
                                                                                          Простой коментарий вроде «особенности архитектуры сервера, см. вики, страница такая-то» съэкономит массу времени и нервов.
                                                                                        +1
                                                                                        Странно, что никто ещё не вспомнил про книгу «Чистый код». Про коментарии там написано достаточно подробно.
                                                                                          0
                                                                                          Ок, согласен код должен быть понятным, это просто без вариантов, но по моему в данном конкретном случае листинг увеличился раза в 3, эт норм?
                                                                                            +9
                                                                                            Посмотрел петпрожект автора на гитхабе. Быдлокодер еще тот, еще других взялся учить.
                                                                                              +3
                                                                                              Не согласен, он высказал проблему, которая совсем не однозначна, зато очевидна. Или давайте код всех кто за и против сравнивать.
                                                                                                +4
                                                                                                Простите, а для того, чтобы поднять проблему и подтолкнуть к её обсуждению в комментариях — обязательно иметь 150 идеальных проектов на Гитхабе? По-моему, каждый имеет право инициировать дискуссию.
                                                                                                +4
                                                                                                Я даже не представляю, как работал бы со многими Open Source проектам, если бы авторы не комментировали свой код.

                                                                                                Совет автора топика, по крайней мере, выглядит довольно странным.
                                                                                                  +1
                                                                                                  Может вы смешиваете, комментирование API и комментирование кода. Для многих open source проектов документация API (а не кода внутри) гораздо важнее самого кода, потому что это то, что они «продают» для конечного потребителя и оно должно выглядеть отлично. В принципе как и документация к сложному продукту. Вопрос же о комментариях внутри кода.
                                                                                                  –1
                                                                                                  Выносить поголовно единожды используемые переменные в константы… Зачем?
                                                                                                  Только засорять код. Они ведь нигде не используются, кроме как внутри метода. Если нужно получить доступ к быстрому их изменению, то достаточно объявить их в начале метода.
                                                                                                    +5
                                                                                                    Константы следует выносить на видное место хотя бы ради того, чтобы подчеркнуть, что какая-то цифирь оказалась захардкожена в программу! А в комментарии необходимо указать, почему выбрано именно такое значение, какие значения возможны еще и как программа будет работать при установке этих других значений. Поверьте, это существенно облегчит жизнь Вашим последователям.
                                                                                                      0
                                                                                                      Справедливо.
                                                                                                      Однако в данном конкретном случае, разве это не очевидно?
                                                                                                      Вот, к примеру, я работаю над Meridian. Там все константы API для VK вынесены в отдельный класс, потому что другие значения там просто неприемлемы. А тут — обычный каркас, показанный скорее для разработчика, что не желает копаться в документации.
                                                                                                      Хотя, может я и не прав.
                                                                                                        +2
                                                                                                        >> Однако в данном конкретном случае, разве это не очевидно?
                                                                                                        Предметом обсуждения, имхо, является не данный конкретный случай, все-таки, а общий подход.

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

                                                                                                        Также и «в данном конкретном случае». Если не задумываешься об этом на маленьких проектах, то в большие никто не пустит:)
                                                                                                    +6
                                                                                                    Хвала Роберту Мартину и его книге «The Clean Coder: A Code of Conduct for Professional Programmers», втолковавшей мне, что комментарии должны содержать намерения кода. С тех пор, как я стал применять это простое правило, вникать в свои же собественные листинги стало куда проще.
                                                                                                    +3
                                                                                                    На мой взгляд необходимость в комментариях серьезно зависит от языка и сути программы.
                                                                                                    Неоткомментированная логика на ассемблере и неоткомментированный UI на С# — все-таки разные вещи.
                                                                                                      +2
                                                                                                      Старенький пост в тему: habrahabr.ru/post/97320/
                                                                                                        0
                                                                                                        Был простой понятный метод с комментариями, а вы развели на ровном месте кучу методов и констант, не решающих по сути ни одну из проблем с комментариями. Что касается устаревания — название константы, комментирующее её назначение, может устареть точно так же, как и комментарий. Что касается читаемости — грамотно прокомментированный код читается как книга, как техническая статья. Просто читаются комментарии и примерно обозреваются структурные конструкции в фоне. В то время, как код без комментариев вынуждает читать именно код, вникать во все подробности тогда, когда это может быть не нужно. А неоправданное разбиение кода на функции увеличивает время понимания кода тогда, когда ты реально хочешь разобраться до тонкостей, как работает код, привнося искусственные сущности, захламляя ими оперативную память мозга.

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

                                                                                                          +2
                                                                                                          Почему не надо?
                                                                                                          Перечитайте еще раз на цитату Макконела orionll

                                                                                                          Константы, в отличие от комментариев — это код. Со всеми вытекающими. Это значит, что коду больше внимания. Это значит, что имя константы устаревает гораздо реже. Лично я вообще не помню, чтобы они устаревали, т.к. IDE прекрасно справляются по переименованию константы. Комментарии не компилируются. И не переименовываются во всех местах с помощью каких-то технических средств.

                                                                                                          Да и самое главное — язык программирования — это в первую очередь язык. Ваша задача — выразить замысел требований на языке программирования.
                                                                                                          Если код читается плохо, надо учиться что-то с кодом делать, чтобы он читался лучше. Код для программиста должен стать родным языком. Ни ЮМЛ, ни комментарии. С чего вдруг программисты когда-то решили, что комментарии так нужны? Похоже, что это были либо программисты, для которых язык программирования не родной, либо уже такой язык программирования, не позволяющий кратко/емко выражать мысли. Приходится мысли дублировать на естественном языке, разжевывая, что делает код, или даже цель/намерение кода.
                                                                                                            +2
                                                                                                            Комментарии нужны хотя бы чтобы выразить замысел требований на естественном языке. Иначе человек, читающий код, не может быть уверен, что код их реализует.
                                                                                                              –2
                                                                                                              Код надо (в идеале) писать так, чтобы он выражал требования. А не реализацию. И правильно писали, что вместо комментариев эти требования прекрасно выражаются еще и тестами, если кодом не удается.

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

                                                                                                              Чтобы немного сместить взгляд, представьте себе, что такое функция и что такое класс в другом русле. Тут где-то было и в комментариях к другим постам, что не имеет смысла выносить код в функцию, который используется один раз. Это механический способ рефакторинга, когда вы следуете DRY. Но можно кроме механики, ввести другой критерий. Допустим, вы написали довольно длинное полотно — код функции. Далее, хотите поставить комментарии на какие-то куски, объясняя, что они делают или как. Именно в этот момент, когда рука потянется комментировать, этот кусок и становится кандидатом для получения названия. И комментарий — по сути название новой функции. Тогда ваш код станет легко читать, как и комментированный. С той разницей, что смысл выражен в коде, а не в комментариях.

                                                                                                              Всё это конечно спорно и требует чувства баланса. Языки программирования к сожалению не идеальны. Или я таких не знаю. Сила выражения мыслей на языке программирования зависит от языка, очевидно. Например, на Си, где нет эксепшинов, даже маленькое действие в методе превратится в много проверок и выходов. Но в С#, на котором сейчас работаю, действительно можно неплохо выразить мысль, без никаких дополнительных комментариев.
                                                                                                                +2
                                                                                                                Во-первых, именно в идеале. Никто от ошибок не застрахован. Во-вторых, рука должна тянуться написать комментарий прежде всего, когда чувствуешь неочевидность данного подхода и/или возможные проблемы. В таких ситуациях комментарии должны быть аргументом принятого технического решения, передавать не только «что» и «как», но и «почему именно это и именно так».
                                                                                                                  +1
                                                                                                                  А вот здесь не о чем спорить. Всё так. Я и писал: это пост о том, к чему надо стремиться. Не всё можно сделать без комментариев отлично читаемым. Было бы прекрасно, если бы так получилось.

                                                                                                                  Другое дело, что часто программисты идеалом считают именно комментированный код. Т.е. стремятся не в ту сторону.
                                                                                                                    0
                                                                                                                    Я уверен, что нельзя так сделать и даже не стоит к этому стремиться. Стремиться нужно к золотой середине между самодокументируемостью кода и не «само» (не забывая про другие виды документации как проектной, так и пользовательской). «Само» в кавычках потому, что, чисто формально, комментарии — это часть кода программы… Они обрабатываются транслятором, пускай и путем игнорирования до конца комментария. Так и, например, именование функций и переменных трансляторами, как правило, на определенных этапах игнорируется.
                                                                                                                      +1
                                                                                                                      Вообще, мне кажется, не только можно, но и нужно так говорить. Хотя бы потому, что есть две точки зрения:
                                                                                                                      1. Не важно как написан код, любой код считаем идентичным, если он выполняется правильно.
                                                                                                                      2. Код от кода сильно отличаются в плане читаемости, поддержки и т.д.

                                                                                                                      Если мы принимаем второе, то «куда стремиться» — это практика улучшения кода. Формально да, и комментарии — часть кода. У нас цель — улучшить читаемость и облегчить поддержку кода. Есть разные способы улучшения кода. Так комментарии — самый последний и самый худший. Можно код, например, упростить. Я вот недавно проект переписывал. Люди потратили на него два человеко-года. Я написал заново за 2 месяца (именно заново, не брал оттуда ни одной глупейшей идеи) и в итоге кода стало в 10 раз меньше. 40 000 строк против 4000. Думаю, мой код гораздо читабельнее, хотя бы в силу того, что с меньшим объемом надо разбираться.
                                                                                                                      А можно было бы разобраться с их кодом и покрыть комментариями. На самом деле причина переписывания была в том, что тот код невозможно было развивать никак. Хотя не костыли, а весь по задумкам автора на абстракциях и паттернах. Комментарии тому коду никак бы не помогли. Ну разобрались бы другие люди как работает. А изменять код все равно не возможно.

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

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

                                                                                                                      1. Размер кода. Есть некоторая корреляция между краткостью и поддерживаемостью, читаемостью. Грубая оценка. Но если код слишком большой для небольшой задачи, должны возникать подозрения.
                                                                                                                      2. DRY. Заметил на глаз, без какого-то анализа, что что-то повторяется (дежавю), надо разбираться, почему так получилось. Есть кандидаты на вынос в отдельный метод, в базовый класс и т.д.
                                                                                                                      3. Вынос логических кусков в отдельный метод. Та самая читаемость. Если хочется кусок прокомментировать — лучше дать ему имя, сделать отдельным методом. Тут нужен баланс. Так делать не всегда нужно. Вынос куска кода, который используется один раз, не требуется по DRY. Но и не нарушает этот принцип. Но вынос отдельного куска в отдельный метод — это также создание нового имени. Нарушение бритвы Оккама. Создание новой «сущности», а значит дополнительная смысловая нагрузка на читателя кода. Комментарии, кстати, ничем не лучше. Это тоже дополнительная нагрузка. Таким образом, надо всегда смотреть, насколько выгодно будет с т.з. читаемости выносить метод. Дело в его названии. Чтобы уменьшить смысловую нагрузку, имя в идеале должно быть уже известным и понятным читателю. Чтобы ему не надо было открывать метод.
                                                                                                                      4. Всё должно выражаться по возможности средствами языка программирования. Работа программиста – это работа переводчика. Если вы переводите с китайского на английский, то нечего там оставлять куски еще и на русском, которые вы не сумели перевести. Это говорит о вас, как о плохом переводчике. При этом средства языка программирования – я подразумеваю его родную семантику и синтаксис. Например – отражение в дотнете – архиплохая вещь. Иногда нужна, но она уже выходит за пределы языка. Когда вы говорите «корова», вы передаете смысл, а не считаете количество букв «О» и в каком порядке они идут. Язык – это средство передачи смысла, а не способ в нем самом искать глубокий смысл. Если представлять язык программирования – как язык, а не как конструктор для конструкций в виде стимпанка, то станет яснее, что такое кратко, точно и без искажений выразить мысль – требование заказчика.
                                                                                                                      5. Писать нужно как можно декларативнее. Вообще, по-моему, в императивности и декларативности языков есть немного лукавство. Даже в самом декларативном языке вы описываете также и логику и задаете направлении работы программы. Известный пример с вычислением квадратного корня. Декларативно задать программу – это указать, что квадрат искомого числа будет равен исходному. Но особо никакой язык эту задачу не решит, не имея аппарата исследования функций. Далее, вы в декларативном стиле на более низком уровне абстракции уже декларируете, что такое метод Ньютона. А в совокупности, это уже императивная программа.
                                                                                                                      Также и в императивном, особенно в ООП языке – вы можете большую часть кода выразить декларативно. Методы с ветвлениями, циклами и зашитым порядком инструкций – императивные. Классы, их связи – декларативные. Сами методы, даже если они внутри императивные, являются декларацией. Т.е. название метода – это декларация того, что вы хотите сделать. Когда вы пишете вызов метода – вы декларируете, что хотите некоторое действие и вам не важно, как оно выполнится. Как – это внутри того метода. Теперь, если ваш метод, не смотря на то, что он имеет какой-то последовательный код, он частично состоит из вызовов других методов. И вот, стремиться надо в ту сторону, чтобы методы читались целиком и не было желания у читателя заглядывать еще дальше внутрь вызовов. Опять встает вопрос баланса. Не стоит код превращать в балаган названий, скрывая все его конструкции. Где-то они всё равно будут и в совокупности, код это не упростит.
                                                                                                                        0
                                                                                                                        Вынос куска кода, который используется один раз, не требуется по DRY. Но и не нарушает этот принцип.

                                                                                                                        Формально нарушает — два раза придется писать название метода.
                                                                                                                        Работа программиста – это работа переводчика.
                                                                                                                        Понравилась аналогия, но она скорее защищает комментарии. Хороший переводчик с помощью примечаний (комментариев) передает не только смысл, но и контекст, которым читатель вероятно не обладает. Культурный, философский, юридический или ещё какой — не суть. Первый пришедший в голову пример — в английском есть слово «sheriff», которого в русском нет (ну или не было пускай даже в пассивном словаре значительной части, если не большинства, русскоговорящих относительно недавно), переводчик может писать «глава полицейского управления округа в США (как правило выборная должность)» каждый раз, может слово «заимствовать», не раскрывая понятия («формально в русском языке слово давно есть кому надо посмотрят в БСЭ»), а может дополнительно дать ему один раз определение в примечаниях, да ещё желательно с фразой «здесь», поскольку у слова «шериф» несколько значений и в контексте современных США оно означает несколько другую сущность, чем в контексте средневековой Англии.
                                                                                                              +2
                                                                                                              Если у вас внимания к комментариям меньше, чем к коду, это ваш недостаток, который надо исправлять, а не обходить. Комментарии для понимания важны и рассинхронизация комментариев с кодом это не менее недопустимая ситуация, чем double PI = 4.

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

                                                                                                                0
                                                                                                                судя по минусам вообще всем людям, которые против комментариев, такое ощущение, что здесь собрались враги языков программирования )))

                                                                                                                Язык программирования — это язык. Выражая логику и смысл на нем, Вы, кроме этого, не дублируете свою работу. На нем в любом случае должна быть выражена логика, чтобы программа заработала. Кроме того, выражая на нем то, что вы задумали, полнее, вы еще и даете возможность компилятору эту логику проверять. Смысл (требования) — это всегда ограничения. Вы можете выбирать общий тип, для бОльшей гибкости и меньших ограничений, например, указатель на сырую память, передавая там число — возраст человека. И напишете комментарий, что там возраст. Это не утрирование, а доведение до крайности идеи с комментариями. А можете создать типы, точно ограничивающие данные, поведение, как и в требованиях. Последний подход — и есть выражение смысла в коде. Компилятор тогда будет с его (допустим) статической типизацией работать с высоким КПД и выдавать надежный машинный код. Смысл комментариев на этом фоне просто теряется.

                                                                                                                То, что Вы проще понимаете человеческий язык… Не совсем верно. Вы думаете кучей языков, кроме естественного. Например, математика. Представьте себе школьную задачу — бросание камня под углом к горизонту. Естественным языком решение звучало бы так: ну примерно, как кажется, метров на 20-30. Язык же формул позволяет выдать точный ответ.
                                                                                                                Естественные языки очень плохо подходят вообще для думать. Вы, когда думаете, еще и кучу всего моделируете, в том числе интуитивно используете математику.
                                                                                                                Ну это лирика. Действительно, требования чаще всего выражаются естественным языком. Поэтому я и писал, что языки программирования не идеальны. Не близки к естественному, точнее, не одинаково близки. Будем ждать будущих языков.
                                                                                                                Но из этого и не следует, что не нужно пытаться приблизить код к естественному языку, а надо писать говнокод и покрывать его комментариями, чтобы люди поняли.
                                                                                                                  +1
                                                                                                                  Это ещё и хуже для программирования, что думаем на куче языков :) То есть задача программирования, вернее подзадача документирования кода, усложняется. С кучи языков нужно перевести на один, с довольно ограниченными средствами передачи смысла, а потом читатель кода должен перевести это опять на кучу языков. Почему ему не намекнуть комментарием «здесь я думаю языком математики, а здесь языком физики» раз в ЯП для этого средств нет?
                                                                                                                    0
                                                                                                                    Понимаете, задача документирования в идеале вообще не должна стоять. Код — это язык и это же документация. Заблуждение изначально, по моему мнению, конечно, в том, что когда-то решили, что код — это материальный объект. Что-то вроде дома или автомобиля. А документация — это чертежи, по которому его делают.
                                                                                                                    А вот и не правильно. Код — это тоже чертежи. Кто-то вдалбливает в голову на уровне подсознания, наверное, в ВУЗах, что так правильно с инженерной т.з. (и все себя в касках представляют деволоперами, конструкторское бюро еще есть). Когда как это не стройка, это не создание конструкций. Это перевод. Поэтому два перевода с языка заказчика держать глупо, неправильно принципиально. Еще интересно, когда еще и делают двойной перевод. Т.е. когда вначале рисуют схемы и пишут документацию, а потом с нее делают перевод уже на язык программирования.

                                                                                                                    Ладно, напишу ка я на примере ниже. Вроде ж просто всё и примеры можно приводить, как отказываться от комментариев.
                                                                                                                      +1
                                                                                                                      Так комментарии (кроме всяческих *doc и аннотаций) не должны содержать перевод с языка заказчика. Они должны содержать оригинал на языке заказчика. Человек открывает код и видит, что хотел заказчик, а что получил. И далеко не всегда первое «что» можно выразить достаточно кратко, чтобы использовать в виде имени метода или переменной.
                                                                                                                        0
                                                                                                                        А давайте в код ещё цитаты с башорга постить. Ну чтоб веселее было читать. И фотки симпатичных сотрудниц.

                                                                                                                        Вам не кажется, что код должен содержать код? А для документации, требований и так далее — есть немного другие места?
                                                                                                                        У нас требования заказчика, даже к небольшой части функционала — это хорошая такая вики страничка с макетами. Как Вы это вообще в коде представляете? Я уж молчу, что пожелание заказчика исполняет весь код вцелом, а не некая конкретная функция
                                                                                                                          +1
                                                                                                                          Не кажется. Код должен содержать информацию, облегчающую его чтение. Комментарии — один из способов эту информацию передать. Пускай даже ссылкой на вики :)

                                                                                                                          Или вы при именовании методов или классов называете их типа p7_12 чтобы ни в коем случае не допустить просачивания смысла требований в код? А кому надо зачем-то узнать что в терминах домена код делает откроет ТЗ на пункте 7.12? «Кодировать» же почти синоним «шифровать». Если вы скажите, что я бросаюсь в крайность, то я вам отвечу тем же.
                                                                                                                            +1
                                                                                                                            Знаете, как то довелось читать «войну и мир» Там есть главы, где дворяне общаются на смеси русского и французкого. Я французкого, кстати, не знаю. Так вот, половину страницы занимали сноски-переводы. И знаете — это нифига не упрощало чтение. Книга, написанная целиком на простом и понятном языке читается напорядок лучше книги, написанной непонятным языком, но напичканной сносками/комментариями

                                                                                                                            Моя идея в том — что всю информацию можно передать кодом. По крайней мере, если мы гооврим не о машинных кодах или об ассемблере.
                                                                                                                              0
                                                                                                                              Простите, а вы термины в коде пишете по-русски?
                                                                                                                                0
                                                                                                                                А с чего вы взяли, что понятным может быть только русский язык? Как раз мешанину из транслитирации и английского языка тяжело читать
                                                                                                                                  +1
                                                                                                                                  Понятным обычно может быть только родной язык разработчика, особенно в части сложных прикладных терминов.

                                                                                                                                  Если для вас родной язык английский — вам проще, поздравляю.
                                                                                                                                    0
                                                                                                                                    Знаете, чуть меньше года назад, я пришёл в английский проект, который занимается миникридитованием. Т.е. куча прикладных терминов + устоявшиеся в команде выражения. Естественно — все документы и общение на английском (мой уровень — в районе среднего). И знаете — ничего, привык. Иногда на рабочие темы на английском было проще говорить чем на русском.

                                                                                                                                    Так что я думаю ваша теория в корне не верна.
                                                                                                                                      +1
                                                                                                                                      Я неправильно выразился, конечно, не родной язык разработчика. Я говорил о языке прикладной области.

                                                                                                                                      В DDD есть такое понятие — ubiquitous language, общий язык. Вот когда понятия из этого языка (например, lease) однозначно выразимы в коде — наступает счастье. А когда у вас общий язык составлен из понятий на русском, у вас начинаются развлечения (обременитель? залогодатель? паника!).
                                                                                                                                        –1
                                                                                                                                        Для этого существует код-ревью. Чтобы давать по ушам за неправильное именование, и приучать к правильному.
                                                                                                                                          +1
                                                                                                                                          Дело не в неправильном именовании, а в том, что разработчик, глядя в русскоязычную доменную модель и англоязычный код, не может сопоставить одно с другим без дополнительных подсказок. И дальше остается только вопрос, куда именно вносить эти подсказки.
                                                                                                                                            –1
                                                                                                                                            нет. Сколько у вас в работе часто встречающихся узко специфических терминов? 10, 15? Очень врядли больше. Сколько надо времени, чтоб их заучить? Да практически не сколько. Ну наткнётесь вы в коде на функцию getLeaseAmount — Если вы не вчера из деревни приехали, то как минимум get и Amount уже знакомы. Lease — спросите у гугла или товарища.

                                                                                                                                            Зато в разговорах с англоязычными товарищами не будет проблем.
                                                                                                                                              +1
                                                                                                                                              Во-первых, по решению — несколько сотен. Во-вторых, проблема в том, как не перепутать близкие по значению специальные термины.

                                                                                                                                              Вот есть Charge — это обременение или начисление? А если в прикладной модели есть и то, и другое?

                                                                                                                                              (не говоря уже о том, что сложнее в обратную сторону — понять, как называется класс, который реализует русскоязычный термин из прикладной модели. Вот есть юридическое лицо (в противовес физическому) — как понять, как будет называться соответствующая ему сущность в коде?)
                                                                                                                                +1
                                                                                                                                Моя идея в том — что всю информацию можно передать кодом.

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

                                                                                                                                Забавно, что я когда писал про примечания переводчика тоже вспоминал «Войну и мир», но с другими чувствами — положительными.

                                                                                                                                Кстати, насчет языка комментариев. Взаимодействуя с иностранцами мы пришли к тому, что если английский в совершенстве не знаешь, то лучше писать комментарии на родном языке, описывающие, что должна делать та или иная сущность, стараясь не использовать сленга и сокращений, сложносочиненных предложений, соблюдать правила и т. п. В общем облегчать задачу перевода (машинного или «школьного» — не суть). Потом тот, кто английский знает хорошо, сможет перевести на него без труда (изменяя комментарии в коде), и переименовать сущности если их название безграмотно на английском получилось изначально. Это удобнее чем разбирать неграмотные названия и комментарии на английском, сам его толком не зная — двойная безграмотная трансляция получается, а такой метод сводит её кк максимум одной — англофон может плохо перевести нормальный немецкий или русский в вид понятный даже тем, кто с английский не очень дружит.
                                                                                                                          0
                                                                                                                          Допустим видим такой кусок кода:
                                                                                                                          // // Далее мы ищем сумму пирожков во всех корзинках. Массив a[] содержит число пирожков в каждой корзинке
                                                                                                                          int c = a.Length();
                                                                                                                          int s = 0;
                                                                                                                          for (int i = 0; i < c; i++)
                                                                                                                          {
                                                                                                                              s += a[i];
                                                                                                                          }
                                                                                                                          

                                                                                                                          Здесь без комментария и правда не разберешься, зачем этот код. Но присмотревшись, видим, что почему-то смысл происходящего описан только в комментарии. Когда как имена переменных ни о чем не говорят. Меняем ситуацию. Также переименовываем и в комментарии, чтобы не устарел
                                                                                                                          // Далее мы ищем cумму пирожков во всех корзинках. Массив pattyCountsInBaskets[] содержит число пирожков в каждой корзинке
                                                                                                                          int pattySum = 0;
                                                                                                                          for (int i = 0; i < pattyCountsInBaskets.Length(); i++)
                                                                                                                          {
                                                                                                                              pattySum += pattyCountsInBaskets[i];
                                                                                                                          }
                                                                                                                          

                                                                                                                          Замечаем, что простое переименоваие сделало вторую фразу в комментарии бессмысленной. Убираем
                                                                                                                          // Далее мы ищем cумму пирожков во всех корзинках.
                                                                                                                          int pattySum = 0;
                                                                                                                          for (int i = 0; i < pattyCountsInBaskets.Length(); i++)
                                                                                                                          {
                                                                                                                              pattySum += pattyCountsInBaskets[i];
                                                                                                                          }
                                                                                                                          

                                                                                                                          В принципе уже можно удалять и весь комментарий. И так понятно по переменной, что мы ищем и код не слишком большой, чтобы понять смысл. Но смотрим дальше. Нам надо найти сумму. С чего вдруг у нас обход массива от первого элемента до последнего? А почему не наоборот? Похоже тут лишняя информация. Замысел у нас короче — просто найти сумму. Переделываем.
                                                                                                                          int pattySum = 0;
                                                                                                                          foreach (int puttyCount in pattyCountsInBaskets)
                                                                                                                          {
                                                                                                                              pattySum += puttyCount;
                                                                                                                          }
                                                                                                                          

                                                                                                                          Уже понятно, что мы складываем элементы (пирожки), просто. В не волнующем нас порядке. Уже лучше. Но все таки складывание — что-то лишнее. Находим метод суммы и пользуемся им:
                                                                                                                          int pattySum = pattyCountsInBaskets.Sum();
                                                                                                                          

                                                                                                                          Вот здесь уже никто не упрекнет, что строка императивная и расписывает как делать, а не говорит что. Пример, конечно, вымышленный. Но улучшение кода внутри методов, для C#, не намного отличается. Там есть еще Linq, так что не только сумму можно найти. Если же в языке, допустим, нет такого средства, то тот кусок кода точно также можно было представить:

                                                                                                                          int pattySum = Sum(pattyCountsInBaskets);
                                                                                                                          

                                                                                                                          или если массив является полем:
                                                                                                                          int pattySum = pattyCountsInBasketsSum();
                                                                                                                          
                                                                                                                            0
                                                                                                                            Еще. Реальный пример из жизни. Пришел мне код. Правда писал не профессиональный разработчик. Но вот такой код, весь зеленый, так покрыт комментариями:
                                                                                                                            for (int i = 0; i < UBOUND_1; i++) // i - Month Dimension, UBOUND_1 - Upper Bound of Month Dimension
                                                                                                                            {
                                                                                                                                for (int j = 0; j < UBOUND_2; j++) // j - ......., UBOUND_2 - .......
                                                                                                                                {
                                                                                                                                    for (int k = 0; k < UBOUND_3; k++) // k - ......, UBOUND_3 - ......
                                                                                                                                    {
                                                                                                                                        if (k > 3)
                                                                                                                                        {
                                                                                                                                            s += a[i, j, k];
                                                                                                                                        }
                                                                                                                                    }
                                                                                                                                }
                                                                                                                            }
                                                                                                                            

                                                                                                                            Разберем первую строку. Просто меняю имя переменным и комментарий сразу становится бессмысленным повторением кода:
                                                                                                                            for (int monthIndex = 0; monthIndex < monthCount; monthIndex++) // monthIndex - Month Dimension, monthCount - Upper Bound of Month Dimension
                                                                                                                            

                                                                                                                            Если еще ввести некоторые элементы языка для повышения читаемости, то:
                                                                                                                            enum Month: int
                                                                                                                            {
                                                                                                                                January = 0,
                                                                                                                                February = 1,
                                                                                                                                March 2,
                                                                                                                                .....
                                                                                                                            }
                                                                                                                            
                                                                                                                            foreach (var month in Enum.GetValues(typeof(Month))
                                                                                                                            

                                                                                                                            И т.д. Обычно комментарии всегда можно выкосить. Они показывают то, о чем должен говорить сам код.

                                                                                                                            PS. Не знаю, почему так жутко раскрашивается текст C#
                                                                                                                          +1
                                                                                                                          Кто Вам рассказал такую чушь? Давайте вы преведёте пример кода, который невозможно оставить без комментария (не анотации), а я попробую привести вам контраргумент
                                                                                                                            –1
                                                                                                                            Математические или физические расчеты по «нешкольным» (а зачастую и по школьным) формулам. При переводе «многоэтажных» формул в «функционально-линейный вид», свойственный мэйнстримовым ЯП, они теряют, как минимум, визуальную узнаваемость, а могут быть вообще неизвестны тому, кто их читает.

                                                                                                                            m1 = F / (G * (m2 / pow(R, 2)) // Используем следствие закона всеобщего тяготения Ньютона

                                                                                                                            Вариант с функцией calcM1ByConsequenceOfNewtonsLawOfUniversalGravitation чур не предлагать.
                                                                                                                              0
                                                                                                                              m1 = getMassFromForcePlanetMassAndRadius(force, planetMass, radius);

                                                                                                                              function getMassFromForcePlanetMassAndRadius(force, planetMass, radius) {
                                                                                                                              return force / (G * (planetMass / pow(Radius, 2))
                                                                                                                              }

                                                                                                                              Согласитесь, в таком виде код более читаем. Только не надо ныть на тему длины названия функции — не в блокноте чай работаем.

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

                                                                                                                              Более того, такой вариант подталкивает к различным абстракциям и уменьшению зависимостей — у вас вполне могут быть функции для расчёта массы в инерционных и неинерционных системах отсчёта, которые легко править в зависимости от принятой в ситеме точности расчётов. В вашем же случае Вы, скореее всего, получите раскиданые по коду формулы, с потерявшими актуальность коментариями.
                                                                                                                                0
                                                                                                                                Код-то читаем. Но понять из него, почему считается именно по этой формуле — невозможно.
                                                                                                                                  –1
                                                                                                                                  public class Planet
                                                                                                                                  {
                                                                                                                                      private readonly IPhysics physics;
                                                                                                                                      private readonly double mass;
                                                                                                                                      private readonly double radius;
                                                                                                                                  
                                                                                                                                      public Planet (IPhysics physics, double mass, double radius)
                                                                                                                                      {
                                                                                                                                          if (physics == null) throw new AgumentNullException ("physics");
                                                                                                                                          if (mass <= 0) ...
                                                                                                                                          if (radius <= 0) ...
                                                                                                                                  
                                                                                                                                          this.physisc = physics;
                                                                                                                                          this.mass = mass;
                                                                                                                                          this.radius = radius;
                                                                                                                                      }
                                                                                                                                      
                                                                                                                                      ...
                                                                                                                                  
                                                                                                                                      public double CalulcateImpulse (double force)
                                                                                                                                      {
                                                                                                                                          return this.physics.CalculateImpulse (force, this.mass, this.radius);
                                                                                                                                      }
                                                                                                                                  }
                                                                                                                                  
                                                                                                                                  internal class NewtonPhysics : IPhysics
                                                                                                                                  {
                                                                                                                                      ...
                                                                                                                                      public double CalulcateImpulse (double force, double mass, double radius)
                                                                                                                                      {
                                                                                                                                          return force / (G * (mass / Math.Pow(radius, 2));
                                                                                                                                      }
                                                                                                                                  }
                                                                                                                                  
                                                                                                                                    +1
                                                                                                                                    А теперь скажите мне, сколько операций вам понадобится, чтобы определить, что выдаст planet.CalculateImpulse(1).

                                                                                                                                    BTW, я из кода вообще не понимаю физический смысл расчетов. И это очень показательно.
                                                                                                                                      –1
                                                                                                                                      А скажите мне сначала зачем вам знать что выдаст planet.CalculateImpulse(1)? Мы именно для того пишем программы, чтобы за нас на подобное отвечал компьютер. Вам лишь важно знать, что при вызове planet.CalculateImpulse(1) будет возвращён импульс планеты для силы 1. Если вам нужно проверить, что CalculateImpulse считается верно, то вам нужно будет написать тест для интерисующей вас физики (IPhysics) — в данном случае у нас только одна реализация и нам нужно будет написать тест для NewtonPhysics.CalulcateImpulse. В виду того, что метод Planet.CalulcateImpulse тривиален, его вообще можно не тестировать (при условии, что тест для NewtonPhysics.CalulcateImpulse написан).
                                                                                                                                        +2
                                                                                                                                        А скажите мне сначала зачем вам знать что выдаст planet.CalculateImpulse(1)?

                                                                                                                                        Чтобы понимать, как работает программа. Не числовое значение, нет — алгоритм расчета.
                                                                                                                                          –1
                                                                                                                                          Понимать как работает программа и алгоритм расчёта это две разные задачи. Для понимая работы программы вам не нужно знать внутренние алгоритмы расчёта — достаточно видеть что рассчитывается импульс планеты и потом это значение где-то применяется.

                                                                                                                                          Для понимания алгоритма расчёта физики вам нужно будет посмотреть на класс NewtonPhysics из названия которого следует, что это реализация расчёта Ньютоновской физики. Там есть метод CalulcateImpulse, название которого говорит, что здесь происходит расчёт импульса. Смотрим — там формула. Почему именно такая? Ну вот тут уже нужно вспоминать/гуглить теорию расчёта импульса ньютоновской физики — наши названия можно использовать как ключевые слова, лезем в гугл и вбиваем слова «Расчёт импульса Ньютоновская физика».

                                                                                                                                          Ваш вариант комментария:
                                                                                                                                          Используем следствие закона всеобщего тяготения Ньютона

                                                                                                                                          Отсюда тоже непонятно почему именно такая формула — нужно точно также идти читать теорию (если не помнишь). Но только в нашем случае мы вынесли часть, которая скорее всего будет использована в других расчётах (не только планет) и разъединили классы вычислений и планеты тем самым подготовив их к тестированию и расширению другими физическими теориями.
                                                                                                                                            0
                                                                                                                                            Ваш вариант комментария:

                                                                                                                                            Это не мой вариант комментария.

                                                                                                                                            Но только в нашем случае мы вынесли часть, которая скорее всего будет использована в других расчётах (не только планет) и разъединили классы вычислений и планеты тем самым подготовив их к тестированию и расширению другими физическими теориями.

                                                                                                                                            А это было нужно?
                                                                                                                                              –1
                                                                                                                                              А это было нужно?


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

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

                                                                                                                                                  Я уже не говорю о других приемуществах DI, о которых я советую почитать в замечательной книге Dependency Injection in .NET от Mark Seemann
                                                                                                                                                    +1
                                                                                                                                                    Возможность модификации в нетривиальных программах подразумевает тестируемость.

                                                                                                                                                    Я не очень понимаю, что у вас что подразумевает.

                                                                                                                                                    Я же хочу сказать, что возможность модификации (точнее — расширения) может быть не нужна; а что касается тестируемости, то еще нужно выяснять, насколько в реальности какой из вариантов был тестируемым.

                                                                                                                                                    И спасибо, Симана я тоже читал, не ново. Вот только не надо путать преимущества DI с преимуществами IoC (оно же DIP из SOLID).
                                                                                                                                    0
                                                                                                                                    А вот тут как раз главное заблуждение. Код не должен давать понимание, почему мы реализуем именно такое решение. Вы ведь маркетинговые иследования не прикрепляете к коду, чтоб обосновать сценарии поведения пользователей?

                                                                                                                                    Задача программиста — просто воплотить в жизнь заданную модель. Воплотить её точно согласно спецификации, без дополнительных упрощений или упущений.
                                                                                                                                      0
                                                                                                                                      Часто приходится принимать решения в них не отраженные. И да, комментарий в стиле «прости тот, кто читает код — так менеджер приказал написать» вполне допустимы и даже необходимы.