Привет, Хабр! На связи C#-разработчик компании SimbirSoft Георгий. В этой статье поговорим о том, как с помощью комментариев кода можно ускорить погружение новых разработчиков в проект, упростить написание документации и найти общий язык с коллегами-разработчиками. Отмечу, что это рекомендации, основанные на собственном опыте, и вы можете быть с ними не согласны.

Материал будет интересен как начинающим IT-специалистам, кто только учится писать чистый и красивый код, так и тем, кто отвечает за формирование кодстайла проектов. Подкреплять свои рассуждения буду примерами из личного опыта и опыта коллег. Сначала быстро пройдемся по основам, а потом откроем этот ящик Пандоры и уйдем в рассуждения.

База

Обзорно начнем с базы. Рассматривать все будем в VisualStudio 2022 (разницы особо нет, но лучше уточнить). 

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

Рассмотрим простой пример бесполезного метода:

        /// <summary>
        /// Описание метода.
        /// </summary>
        /// <param name="parameter">Входной параметр.</param>
        /// <returns>Возвращаемые данные.</returns>
        /// <exception cref="NotImplementedException">Ошибки.</exception>
        public static string GetBase(int parameter)
        {
            throw new NotImplementedException();
        } 

Для описания используются следующие теги:

        /// <summary>
        /// Описание метода.
        /// </summary>

Непосредственно описание того, что метод делает:

/// <param name="parameter">Входной параметр.</param>

Описание входных параметров метода:

/// <returns>Возвращаемые данные.</returns>

Описание возвращаемого значения, если такое есть:

/// <exception cref="NotImplementedException">Ошибки.</exception>

Ошибки, которые могут возникнуть в результате его выполнения.

Также достаточно часто используется тег

/// <inheritdoc/>

Он применяется в связке «интерфейс – реализация» и навешивается на методы реализации, если у интерфейсных методов есть описание. Позволяет более явно указать, что у метода есть комментарий, но он будет взят из соответствующего метода интерфейса (или базового класса).

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

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

Чтобы самому приходилось меньше писать руками, в Visual Studio (как, наверняка, и в любой другой IDE) существуют сниппеты, которые позволяют генерировать шаблоны для таких комментариев. В той же Visual Studio можно ввести 

///

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

А теперь перейдем к основной части с примерами.

Проблема и возможный путь ее решения 

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

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

Разработчик устраивается на новую работу. Так получилось, что его новый проект – легаси десяти лет от роду, документация которого была утеряна во времена наполеоновских войн, а кор-команда разработчиков пропала без вести на необитаемом острове. Глоссарий собирался разными специалистами в разные моменты существования проекта и очень неполный. Комментариев в коде нет, а аналитик с лидом в рабстве постоянных созвонов.

Перспективы быстро вникнуть весьма удручающие, но что делать — оффер уже подписан, надо разбираться. Можно смело заявить, что разработчику потребуется немало времени, чтобы глубоко погрузиться в проект. Естественно, что он будет обращаться к своей команде за помощью, чтобы понять, что вообще должно происходить в системе. Это всё время, а время – это деньги. Чем быстрее новый сотрудник освоится, тем быстрее он начнет работать в полную силу. 

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

Пример утрированный, но весьма показательный. Если проект большой и существует уже долгое время, то скорее всего что-то забылось, что-то потерялось, кто-то где-то прикрутил «велосипед без колес». Комментарии помогут в понимании разработчиков друг друга и объяснят, почему в коде есть велосипед и зачем он горит.

Если проект уже какое-то время развивается, на его рефакторинг не дадут ни времени, ни денег, поэтому самое быстрое и не затратное решение – написать комментарии там, где довелось поработать. Потратить 10-15 минут на написание развернутых комментариев для каждой новой фичи звучит, как душное занудство, но эти 10-15 минут сейчас экономят часы в будущем. Речь идет не о комментировании каждой строчки кода, а о добавлении документирующих комментариев к методам, классам и так далее, которые будут отражать общую суть выполняемых действий.  

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

Коротко по делу: когда комментарии могут упростить разработку

1. Предсказуемость методов в случае сбоев

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

Очень удобно, если используется какой-либо хелпер/парсер или что угодно другое без интерфейса. Тогда из клиентского кода можно понять, что может пойти не так, завернуть это в try catch и уже тут разбираться, что мы хотим делать с ошибкой. Не то чтобы мне часто доводилось этим пользоваться, но была пара случаев, когда такого рода комментария не хватало.

Например, так это может выглядеть:

2. Простая поставка библиотек

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

3. Ускоренное погружение новых сотрудников

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

4. Упрощение код-ревью и шаринг знаний

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

5. Глоссарий в коде

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

А что комментировать-то? 

Без фанатизма. Главное, чтобы были описаны методы, классы, интерфейсы, входные параметры методов и их возвращаемые значения. Вообще прекрасно, если описаны модели, их свойства, названия. Не всем импонирует идея прописывать для свойств уровня ObjectId «идентификатор объекта», но с другой стороны, никто не гарантирует, что в будущем модель не расширят (появится еще пара айдишников), не добавят сложных и непонятных с первого взгляда свойств. В этой ситуации я рекомендую придерживаться единообразия. Если комментарий есть на одном свойстве/методе, то он должен быть везде. Так и код выглядит аккуратнее, и не будет мыслей вроде: «Так, я только что видел же описание этого свойства, а на другом оно где? А было ли первое описание вообще? А может, тут другая логика, раз описания нет?».

Что в итоге?

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

Больше авторских материалов для backend-разработчиков от моих коллег читайте в соцсетях SimbirSoft – ВКонтакте и Telegram.

Комментарии (34)


  1. SUNsung
    01.08.2024 12:18

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


    1. panzerfaust
      01.08.2024 12:18
      +7

      во многих компаниях предпочитают "выразительный код" чем требовать коментирование

      Потому что это работает. Вот такой вот сюрприз. Очень наивно думать, что у вас есть некая серебряная пуля (комментарии), а вокруг одни идиоты, которые не додумались.


  1. ganqqwerty
    01.08.2024 12:18
    +10

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

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

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


    1. TerraV
      01.08.2024 12:18
      +3

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


      1. ganqqwerty
        01.08.2024 12:18

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


    1. inkelyad
      01.08.2024 12:18

      Завтра разработчик поменял поведение функции, а на комментарий не обратил внимание.

      Или: описал нужное поведение в комментарии правильно (скопировав из ТЗ), а поведение изменил неправильно.

      Появилось два источника правды: коммент и сам код.

      Нет. Если есть противоречие - это означает, что где-то накосячили. Правду надо найти в другом месте и привести к ней и то и то.

      Есть ли у вас инструмент, не допускающий возникновения противоречий между кодом и комментариями к этому коду?

      Code Review

      Кроме того, аргумент 1-в-1 совпадает с наличием теста. Код поправили, а тест нет. Где источник правды - то, как тест говорит делать или то, что в коде?

      Однако никто же не говорит на основании такого аргумента, что тесты не нужны.


      1. ganqqwerty
        01.08.2024 12:18
        +1

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


        1. inkelyad
          01.08.2024 12:18

          Это в самом прямом смысле ручная проверка.

          Разумеется. Это - высокоуровневая проверка того, что то, что мы накодили, соответствует тому, что хочется, и прочим (трудно/не)формализуемым желаниям. А текст комментария, соответственно - почти эквивалентен высокоуровневому тесту.

          Сейчас, наверное, если напрячься, можно какой-нибудь ИИ для черновой проверки соответствия этому 'тесту' прикрутить.


          1. ganqqwerty
            01.08.2024 12:18

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

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


            1. inkelyad
              01.08.2024 12:18

              Но вы же согласны с тем, что когда возможно, ручные проверки лучше заменять машинными?

              Да. Но это не повод отказываться от ручных проверок там, где машинные невозможны. А отказ от комментариев - это оно (такой отказ) и есть.


              1. ganqqwerty
                01.08.2024 12:18

                Да как же так? Я же привел альтернативу: отказаться от большинства комментариев, но делать следующее:

                • полагаться на нормальную спецификацию типов параметров, исключений и возвращаемых значений,

                • хорошо названные функции, отвечающие давно всем понятным принципам хорошего кода

                • автоматизированные юнит и интеграционные тесты.


                1. inkelyad
                  01.08.2024 12:18

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


                  1. ganqqwerty
                    01.08.2024 12:18

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

                    В немецкоязычных проектах со швейцарскими коллегами мы в какой-то момент начали использовать немецкие названия и немецкие для сущностей предметной области в именах переменных и функций, чтобы у нас был воспетый в DDD Ubiquitous Language.

                    В русском или китайском коде это бы выглядело еще более странно.


      1. panzerfaust
        01.08.2024 12:18

        Код поправили, а тест нет.

        А это закон какой-то, что изменение кода обязательно ведет к изменению тестов?


        1. inkelyad
          01.08.2024 12:18

          А это закон какой-то, что изменение кода обязательно ведет к изменению тестов?

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


      1. ganqqwerty
        01.08.2024 12:18
        +1

        Кроме того, аргумент 1-в-1 совпадает с наличием теста. Код поправили, а тест нет. Где источник правды - то, как тест говорит делать или то, что в коде?

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


        1. inkelyad
          01.08.2024 12:18

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

          Если на Code Review происходящее вдумчиво читают (ну да, лениво) - то до билда ничего даже не дойдет. Изменения не примут.


          1. navferty
            01.08.2024 12:18
            +1

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


            1. inkelyad
              01.08.2024 12:18

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

              Правильно. Но если автоматическая проверка невозможна - нужно использовать инструмент ручной проверки. Вот комментарий - такой инструмент и есть.


              1. navferty
                01.08.2024 12:18
                +1

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

                При соблюдении этих принципов, комментарий просто дублирует логику кода, не добавляя вообще никаких преимуществ, а только вводит риск расхождений кода и комментариев.


                1. inkelyad
                  01.08.2024 12:18

                  Как именно комментарий предоставляет инструмент ручной проверки кода?

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

                  Комментарий, кстати, может и не прямо к функции, а к соответствующему автоматизированному тесту.


                  1. navferty
                    01.08.2024 12:18

                    Поиск подходящей заявки в соответствии с ТЗ номер, правила параграфа...

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


                    1. inkelyad
                      01.08.2024 12:18

                      Номер задачи - обычно там что-то довольно обширное. Комментарий что вот эта функция реализует вот конкретно эти пункты из ТЗ - сильно помогает при разборе полетов и модификации кода лет так через 10 после написания кода.

                      Когда на третию-четвертую линию поддержки приходит запрос 'а почему у нас система делает <что-то по мнению пользователя неправильное>" - и потом приходится сообщать "Вот тогда-то утвердили такое поведение, вот тут (тыкаешь пальцем в конкретный параграф) написано, что так и должно быть."

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


                      1. navferty
                        01.08.2024 12:18

                        Если в задаче что-то слишком обширное, возможно следует заняться декомпозицией, чтобы привязанный к ПР/коммиту тикет был достаточно конкретным.

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

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


                      1. inkelyad
                        01.08.2024 12:18

                        Да при чем тут Version Control с соседями. Они отлично помогают, но аргумент не про них.

                        Вот есть задача в жире (кстати, в какой жире? За 10 лет оно и умереть может - смотри что недавно произошло. После этого все подобные ссылки немного умирают) вида "Реализация сценария..."

                        В этой таске - 3-4 документа от разных лиц ну даже пусть короткие.

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

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

                        Гораздо проще, когда рядом с кодом сразу ссылка есть - что смотреть и на основании чего конкретно (а не "ищи где-то тут") оно тут написано.

                        И еще хуже - когда не ревьюверу надо, а как-нибудь гораздо позднее разбираемся, что тут у нас наделано и почему.


                      1. inkelyad
                        01.08.2024 12:18

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

                        Это вопрос простейшей небольшой занудности и аккуратности.

                        Но нет, видимо, надо дождаться момента коммита(ов), вспомнить, какое изменение по какому поводу было, закоммитить все это по отдельности, сославшись на задачу(и). (А если достаточно подробного деления нет?). Потом, в зависимости от политики разработки, еще добиться, чтобы каждый коммит собирался и тестировался. А потом, при мерже в основную ветку, всему этому squash сделают.

                        И ради чего? Чтобы комментариев в коде не видеть?


  1. ganqqwerty
    01.08.2024 12:18
    +6

    Вот вы приводите тут пример:

     /// <summary>
    /// Описание метода.
    /// </summary>
    /// <param name="parameter">Входной параметр.</param>
    /// <returns>Возвращаемые данные.</returns>
    /// <exception cref="NotImplementedException">Ошибки.</exception>
    public static string GetBase(int parameter)
    {
       throw new NotImplementedException();
    } 

    У меня на код ревью сразу к этому возникнут вопросы:

    • зачем тут нужно описание метода? У вашей функции недостаточно хорошее имя чтобы было понятно, что она делает? Переименуйте чтобы было понятно и удалите коммент. Ваша функция делает сразу миллион вещей и это все не впихнуть в название? Разбейте функцию на куски и удалите коммент.

    • зачем тут нужно описание параметра? У параметра плохое имя и не понятно, что туда передавать? Переименуйте. Тип int недостаточно хорош, и функция будет работать только с некоторыми интами? Используйте выразительные средства вашего ЯП, чтобы сузить тип. Кстати, дайте типу хорошее имя. И удалите коммент.

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

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

    • Или может быть, вы кидаете слишком общее исключение? Создайте более частное исключение с понятным именем. Коммент лучше удалить.


    1. panzerfaust
      01.08.2024 12:18
      +1

      Добавлю, что все эти детские ошибки разжевываются где-то в первой четверти "Чистого кода" Мартина и чуть более разреженно в "Рефакторинге" Фаулера. Книги написаны 12 и 25 лет назад соответственно. Видимо, некоторым и этого срока мало.


      1. ganqqwerty
        01.08.2024 12:18
        +1

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


  1. ganqqwerty
    01.08.2024 12:18

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


  1. navferty
    01.08.2024 12:18

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

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

    Возьмём приведенный пример с методом парсинга: SomeValidator.TryParseInt("3"); со списком выбрасываемых исключений в xml-документации. Хорошо, если этот метод был реализован один раз и почти никогда не меняется, но что если вдруг нужно исправить срочный баг? Например, при передаче в тексте числа, выходящего за границы int32, происходит переполнение - и при фиксе бага разработчик добавил там проверку, которая может выбрасывать ArgumentOutOfRangeException. Конечно же, документацию в xml-комментах обновить забыли. Теперь доки не просто бесполезны, а даже вредны - потому что врут.

    Альтернатива исключениям в бизнес-логике

    Даже если бы не забыли обновить доки - как в этом случае убедиться, что все кто использует этот метод, учли новый тип исключения наряду с уже описанным ранее CustomException?

    На днях пришла хорошая новость: в C# появился пропозал о добавлении Type Unions, так что теперь, надеюсь, получится написать метод так:

    public static (int or ParseError) TryParseInt(string input)
    { /*...*/ }

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

    var x = result switch
    {
        int a => x,
        ParseError err =>
        {
          Console.WriteLine(err.Message);
          throw new Exception("Parse failed: " + err.Message);
        }
    };

    И при добавлении третьей опции в сигнатуре метода этот switch просто не скомпилируется, так как не хватает третьей ветви.

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

    Я считаю, главная цель комментариев - не описывать, что делает тот или иной фрагмент кода, а для чего он предназначен, и почему он реализован именно так. Ответ на первый вопрос ("что") должен давать сам код, через понятные имена методов, классов и переменных. А информацию по другим вопросам ("для чего" и "почему") может быть намного сложнее получить из самого кода, и для них комментарии - хороший источник ответов.


  1. skovoroad
    01.08.2024 12:18
    +1

    Комментарий это экзоскелет. Здоровому человеку в обычной жизни он не нужен.

    • Он нужен, если человек (или код) нездоров

    • Он нужен, если нагрузка (или когнитивная нагрузка) чрезмерна и это принципиально невозможно устранить. Нечастая ситуация.

    • Во всех остальных (то есть во всех нормальных) случаях он не нужен

    • (ну правда бывает ещё автогенерируемая документация, тут метафора ломается)


    1. inkelyad
      01.08.2024 12:18

      • Он нужен, если нагрузка (или когнитивная нагрузка) чрезмерна и это принципиально невозможно устранить. Нечастая ситуация.

      Очень частая ситуация. Системы пишутся не для того чтобы писать, а для того, чтобы эксплуатировать. И вот есть легаси 10 летней выдержки (да даже 5 летней), которое в сумме тысячи человек много-много человеко-лет писали. И есть сейчас программисты поддержки, которых ну максимум десяток. В их мозги все весь этот код и вся это логика просто не влезет. И про починке ошибок или доработках - объяснения что тут в коде что (даже неправильные и слегка устаревшие) - сильно помогают.


      1. skovoroad
        01.08.2024 12:18

        Да, это бывает. Главное не путать такую ситуацию с первым пунктом)