Не пишите лишнего

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


    Дольше всего приходится вычитывать не хитрые алгоритмы, и не решения с алгебраическими типами данных и монадами, а огромные куски простого кода: методы на 500 строк, скрипты на 1000 строк, классы на 1500 строк. Все они доставляют индустрии проблем не меньше, чем печально известное NullPointerException.


    В классической книге “Рефакторинг” М. Фаулера приводятся всего три типа “подозрительного кода”, относящиеся к объёму: “Длинный метод”, “Большой класс”, “Длинный список параметров”. В современных реалиях этот список можно было бы пополнить, но даже эти три давно известных принципа нарушаются сплошь и рядом, а большие куски кода продолжают доставлять массу проблем.


    Первая (и главная) проблема — это потраченное время. “Много кода” — это, прежде всего, просто много текста, который нужно читать. И никакие техники быстрого чтения здесь не помогут, потому что в коде важен каждый нюанс. Прочесть его “по диагонали”, значит впустую потратить своё время и сделать ложные выводы о том, как он работает.
    Неправильно представляя, как работает кусок системы, программист обречён ошибиться при написании нового кода.


    Большие куски кода трудно тестировать. Большие методы, использующие кучу данных, практически нереально покрыть Unit тестами, а интеграционные тесты оказываются огромными и очень сложными. Наcтолько, что впору писать тесты на тесты. Впрочем, можно сделать вид, что на проекте вообще нет автоматических тестов, и всё хорошо. Тогда вам очень пригодится книга Э. Йордона “Путь Камикадзе”.


    Большие куски кода сложно ревьюить. Коллега был очень продуктивен и написал подсистему за выходные? Прекрасно, но теперь нужно потратить уйму человеко-часов на чтение этого опуса перед отправкой его в master! Дочитывая изменения в третьем десятке файлов, будет непросто удержать в голове изменения из самого начала, не говоря уж о своей собственной текущей задаче.


    Большой кусок кода практически невозможно переиспользовать. Он делает слишком много вещей одновременно, а переиспользовать обычно нужно лишь некоторые из них. Улучшить ситуацию, применяя “Выделение метода” и другие приёмы, тоже не всегда возможно, так как этот огромный кусок вряд ли хорошо покрыт тестами.


    Попробуйте вообще избежать написания кода.


    • Проверьте, не решал ли кто-то до вас в этом проекте такую же (или сильно похожую) задачу. Переиспользуйте код, выделяйте абстракции, не стесняйтесь.
    • Знайте и любите утилиты и API собственного проекта. Особенно, если ему больше полугода. Там могут найтись жемчужины, которые сэкономят вам десятки строк кода.
    • Ещё знайте и любите популярные библиотеки для вашего языка или платформы. Если говорить о java, то не поленитесь ознакомиться как минимум с Google Guava и семейством Apache Commons. Не изобретайте велосипеды.

    Когда всё-таки пишете свой код.


    • Выделяйте новые функции и методы (и структуры, классы, компоненты, файлы). Код заслуживает быть вынесенным в отдельную функцию не только тогда, когда его планируется переиспользовать, но и в целях улучшения читаемости. Не экономьте стек вызовов. В вашем блоке if { … } else { … } стало больше 20 строк кода? Вынесите его ветки в отдельные функции с хорошими именами, отражающими суть действия. Ваш метод занимает больше половины экрана (в альбомной ориентации)? Разбейте его на семантически значимые части.
    • Не увлекайтесь лямбда-выражениями и анонимными классами. Если какой-нибудь обработчик onSuccess() занимает 200 строк из 400 строк метода, то выделите его код в отдельную функцию, объект или класс. Он не должен мешать понимать, что же ещё (кроме установки onSuccess()) делает исходный метод.
    • Следите за уровнем абстракции. Не сваливайте в одну кучу бизнес-логику (например, принятие решения об отправке сообщения) и прикладной уровень (работа с сокетами для отправки).

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


    Уменьшая количество кода, вы


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

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

    Поделиться публикацией
    Ой, у вас баннер убежал!

    Ну. И что?
    Реклама
    Комментарии 180
    • +14
      Слишком простые советы для бывалых программистов и в то-же время очень мало из того, что можно посоветовать начинающим программистам. В чем суть и основной посыл?
      • +10
        Напомнить бывалым, что не написанный код содержит заведомо меньше ошибок, чем написанный.
        К сожалению, в последнее время встречаю много огромных «простыней» за авторством именно бывалых (5+ лет разработки), уверенных в себе людей
        • +7
          И действительно, если ничего не писать — никогда не допустишь ошибку.

          Но вопрос огромных простыней — все ещё открытый. Часто бывает что нужно выбрать между двумя вариантами
          1. Метод в 20 строчек, для пониманияя и дебага которого необходимо глотнуть чего-то разогревающего..
          2. Метод в 100 строчек, но который четко и ясно написан и в котормо можно легко отследить логику действий.

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

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


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


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


                  Вообще рекомендую прочитать книгу "Чистый код: создание, анализ" за авторством Роберта С. Мартина, там очень много полезного написано, в том числе и то что в статье перечислено.

                  • +2
                    Комментарий должен отвечать на вопрос «зачем» здесь этот код, какая бизнес-необходимость привела к его написанию. Тогда он не устареет вне зависимости от смены реализации. Ещё комментарий может говорить о хаках и трюках, которые (зачем то) понадобились.
                    Комментарий, который говорит «что» делает код — действительно почти бесполезен при правильной организации оного кода
                    • +2
                      Комментарий должен отвечать на вопрос «зачем» здесь этот код, какая бизнес-необходимость привела к его написанию. Тогда он не устареет вне зависимости от смены реализации.

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


                      Ещё комментарий может говорить о хаках и трюках, которые (зачем то) понадобились.

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


                      i  = 0x5f3759df - ( i >> 1 ); // what the fuck? 

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

                      • –2
                        Комментарий должен коротко передавать суть написанного. В указаном примере из квейка комментарий, собственно, передает суть :D
                        • +7
                          Встретились как-то аббревиатуры для программеров. Тоже можно в комментариях использовать.

                          image
                          • 0
                            Обычных болтающихся комментариев в коде стоит избегать, так как обычно единственное что можно понять из комментария, так это то, что у автора не получается писать достаточно выразительный код.
                            Мои комментарии часто бывают в стиле «сделано так, потому что другой способ, очевидный, является неправильным или неэффективным».

                            К примеру, если в delphi создаёшь форму через Application.CreateForm(TForm, formReference), то нужно обязательно вызвать Application.Run, даже если приложение запускается не в интерактивном режиме (можно в Run послать сразу Terminate), другого способа корректно освободить ресурсы этих форм нет.

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

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

                              На самом деле иногда поражает на сколько люди ленятся читать код без комментариев, даже если он сам себя комментирует через имена его компонентов. Даешь человеку прочитать свой код, чтобы обсудить с ним какую-то его часть — он возвращается с упрёком, мол «где комментарии». Я отвечаю: «а зачем, тут же всё достаточно хорошо расписано, и всё есть в документации», на что обычно я получаю ответ в стиле: «код без комментариев не может быть понятным», хотя на деле это просто человеческая лень, ведь очень демотивирует когда ты видишь исходник на 3 тысячи строк кода (отформатированных по стандарту, определенному проектом, написаным с максимальной выразительностью, и с функциями, тела которых не превышают 20 строк, и обладают единственной ответственностью) без единого комментария. Хотя если приглядеться и начать таки читать, всё читается как текст. Сам читал такой код не раз, сам пишу такой же код на работе.
                              • 0
                                Если в коде торчит костыль, который так и просит, чтобы его удалили, его можно либо закрепить комментарием, либо переписать всё нафиг (а ещё лучше — на другом языке), чтобы костыли не приходилось вставлять. Можно переписать, но это какой-то не реалистичный подход.
                                • 0
                                  3 тысячи строк кода с функциями, тела которых не превышают 20 строк

                                  150 функций на одном уровне вложенности, каждая из которых может потенциально вызываться из остальных? Я бы наверно тоже так сказал.

                                  • 0

                                    не, ну если в блокноте читать, то понятное дело. Никто же не запрещает использовать Ctags, встроенные в IDE фичи, такие как поиск символа и так далее (мазохизм конечно никто не отменял).


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


                                    на одном уровне вложенности

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

                                    • 0
                                      не, ну если в блокноте читать, то понятное дело

                                      Так количество функций что в блокноте что в IDE одинаковое) Чтобы понять, что тут делается, надо все их проанализировать.


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

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


                                      Что не так с одним уровнем вложенности я не понял, вы функции в глобальном пространстве видимости на разных уровнях вложенности пишете?

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

                                      • 0
                                        Так количество функций что в блокноте что в IDE одинаковое) Чтобы понять, что тут делается, надо все их проанализировать.
                                        Чаще всего достаточно прочесть название функции. Если вдруг понадобятся детали одной из десятка — лезть глубже в конкретный блок, а не пытаться искать ориентиры в простыне.
                                        • 0
                                          Я говорю о случае, когда разбивается слишком подробно. Чаще всего, если мы лезем в код, нас интересует реализация. Если в функции вынесены логически независимые части, тогда да, можно ориентироваться по названию.
                                          Куча мелких функций ничем не лучше кучи строк в одной функции. Названиями переменных тоже можно действия документировать. В данном примере 3000 строк лучше разделить на несколько классов, а не пытаться прикрыть сложность функциями.
                                          • 0
                                            Слишком подробно разбираться сразу во всём не стоит) Едва ли можно эффективно держать в памяти все тонкости реализации в таких объемах. Практика показывает, что скорее всего отдельные логические части в 3000 строках точно найдутся. И их не только можно выносить, но и нужно, ведь это основа SRP. Классы — это ведь просто форма пространства имен функций и (возможно) какое-то скрытое состояние.
                                            • 0
                                              какое-то скрытое состояние
                                              которое просто является скрытыми параметрами для этих функций, так что как раз пространством имен и является с возможностью инкапсулировать параметры для своих функций для удобства. И только.
                      • 0
                        Ни разу не встречал метода на 100 строк в котором можно легко отследить логику действий (конфиги не в счет).
                    • +1
                      «Не нужно додумывать слишком много. Так вы создаете проблемы, которых изначально не было.»

                      Фридрих Ницше
                      • +1
                        Знавал я бывалых программистов, которые на моё искреннее удивление: «Ребята, у вас тут метод на 2000+ строк, это ок вообще?» — недоумевали: «А что такого? Всё ж понятно».
                        • –2
                          Это лучше, чем тупо порезать его пополам, потому что по кодстайлу такие длинные методы запрещены.
                          • +1
                            Ага, причем с восемью вложенными блоками и с рекурсией.
                        • +8
                          Не хватает эпиграфа к статье )
                          «Совершенство достигается не тогда, когда нечего добавить, а тогда, когда нечего отнять».
                          • +6

                            Угу, любимое занятие: "фиксил багу… стёр 200 строк кода, теперь вроде работает правильно".


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

                            • +4
                              Я ничего не имею против коротких лямбд. Для того они и существуют. Но когда внутри callback-а кто-то ставит в очередь Runnable внутри которого ещё и дёргает map по коллекции, становится очень печально. Эдакий callback hell на стероидах.
                              на универсальность не претендую :)
                              • +4
                                Правило — если в лямбда-функции хочется написать императивный код, а не выражение, нужно выносить в отдельную функцию.
                                • +1

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

                                  • +1

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

                                    • +1
                                      Удобство довольно сомнительно. Локальная функция требует значительно больше места для её описания (+4 строки). Плюс это не отменяет того факта, что функция вместе с её локальными функциями должна умещаться на экране.
                                      • 0
                                        Лямбда не эквивалентнта локальной. Последняя компилируется в более производительный код, умеет работать с дженериками. Кроме того, лямбда-функции логично вписываются в рекурсивные функции, когда инициализирующий метод один, а локальная функция — такой же, но с дополнительными параметрами из инициализирующего.
                                  • +9
                                    Всё бы ничего статья, но…

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

                                    Когда слишком много структур — это ничем не лучше, чем когда слишком много кода. Когда видишь перед собой простую редко выполняющуюся задачу категоризации (а-ля «разложить общую кучу элементов по нескольким по определенному признаку»), решаемую с помощью пары интерфейсов, десятка классов, и «умно» примененных паттернов — схватиться за пистолет хочется нисколько не меньше, чем при чтении метода на 1000 строк.
                                    • +1
                                      Истина конечно же где-то посередине.
                                      • +1
                                        А она тут вообще есть? Сомневаюсь.
                                        Посудите сами, если у вас есть однородная задача на 10 000 действий, то это задача на 10 000 действий. Вы можете её разбить на 1*10000, 10*1000, 100*100, 1000*10 и тд структурных единиц, но от этого она меньше не станет. Она останется задачей на 10000. Ваши разбиения лишь добавляют в неё энтропию. Да, разбиение работает в качестве оглавления, но, в целом, оно ни лучше и не хуже простого комментирования кода.
                                        Вкусовщина. Одним людям проще кушать слона по частям. Другим проще прочесть код, как книгу, — от корки до корки. Третьи будут ныть в любом случае, а четвёртые вообще не будут читать, позвонят разработчику и вынут всю душу вместе с содержимым кишечника.

                                        Я не имею в виду программу с ГУИ, обработкой командной строки, работой с БД и расчётным блоком. Это разные задачи — структурные единицы, которые должны быть разнесены. А бывают иные задачи, разбиение которых ничего не даёт, кроме эстетического удовлетворения и проблем с передачей параметров. Стоит оно того или нет? Я не знаю.
                                        • +2
                                          Посудите сами, если у вас есть однородная задача на 10 000 действий, то это задача на 10 000 действий. Вы можете её разбить на 1*10000, 10*1000, 100*100, 1000*10 и тд структурных единиц, но от этого она меньше не станет. Она останется задачей на 10000.

                                          вот только для среднего изменения в одном случае надо будет прочитать 10-15 блоков по 10 действий, а в другом — 3-4 блока по тысяче
                                          • 0
                                            И какой из этих двух вариантов лучше? У меня вот нет однозначного ответа. С одной стороны, перемножив всё получаем 150 против 4000 действий, и первое как будто лучше, с другое — не надо недооценивать «10-15 блоков» как самостоятельную большую проблему. Возможно, это большая проблема, чем разница в 30 раз в количестве действий.
                                            • 0
                                              существует миллион причин почему разделять код на блоки лучше:
                                              1. читается код намного больше раз, чем пишется. Монолитный код приходится читать полностью, в то время как модульный — только интересующими нас кусками.
                                              2. человеческая память ограничена определенным количеством действий. Один раз прочитав метод и зная, что он вычисляет какой-нибудь f(x,y,z) и не имеет побочных эффектов, повторно можно его не анализировать. Большие методы, однако, держать в голове полностью невозможно.
                                              3. поведение маленьких модулей проще, значит проще составить модель их ожидаемого поведения, протестировать и гарантировать корректность
                                              4. маленькие методы легко переиспользовать, слишком большие — невозможно. Поэтому в плохо разделенном коде чаще встречается дублирование, которое само по себе ведет к нескольким другим проблемам.

                                              А теперь еще раз вспомните, что все эти действия над кодом надо делать каждый раз при попытке внесения изменений.
                                              • +1
                                                1) Далеко не всегда это так. Очень далеко не всегда. Есть отдельные модули, которые пишутся раз и навсегда просто потому, что их менять нет смысла. Откройте, например, OpenSSL\Crypto и посмотрите историю изменений. Половина исходников там с бородатых времён практически неизменна: менялись только лицензии и, возможно, фичи для обхода предупреждений компилятора.
                                                • 0
                                                  Работает — не трогай.
                                                  • 0
                                                    а вы не историю изменений читайте, а сам код, и учитесь на его примере
                                                    • 0
                                                      Нет уж, сами читайте код, sha1 и AES я лучше по аналитическим формулам изучу.
                                                      И, уж извините, OpenSSL не является эталоном качества ни по удобству, ни по качеству структурирования, ни по документированности, ни по надёжности, ни по тестам.
                                                    • 0
                                                      Там есть причина — максимальная производительность. Можно записать красивее, но будет медленнее. В библиотеке это очень важно.
                                                    • 0
                                                      Вы как будто комментарий не прочитали и отвечаете. Или я так непонятно написал? По вашим пунктам
                                                      1) я и писал про читаемость кода
                                                      2) а этот пункт как раз и был предметом сомнений: я совсем даже не уверен, что держать в голове 15 коротких блоков проще чем 4 длинных, и даже более того, сталкивался с ситуациями, когда эти самые короткие блоки, поделённые на отдельные функции и вложенные друг в друга, меня ужасно бесили при чтении кода — гораздо приятнее было бы прочитать одну простыню, чем ворох мелких фрагментов; если у вас такого никогда не было — это не значит что всем так же.
                                                      3) опять та же проблема: вам надо сделать кучу мелких проверок или одну большую: усложнение графа связей между функциями само по себе добавляет проблем, и, может быть, оно добавит меньше проблем, чем решит благодаря маленькому размеру модулей, а может и нет
                                                      4) ну, да, но переиспользование не везде будет требоваться; если вы пишете какое-то апи общего назначения — то да, вы не можете заранее полностью знать контекст его применения, а если вы пишете конкретный продукт под конкретную задачу — то уже можете знать, что какая-то функция, хоть она и могла бы быть переиспользованной в другом случае, но конкретно в вашем проекте она используется всего 1 раз и больше не будет; у многих есть склонность создавать абстракции и апи общего назначения там, где их «не заказывали» — это далеко не всегда хорошо.
                                                      • 0
                                                        вы выбираете какой из двух примеров плохо структурированного кода лучше не имея представления о том, как должен выглядеть хорошо структурированный код. Недавно выкладывали статью про исследование кода LLVM, в числе прочего указали процент больших (> 70 строк) функций. Их процент ничтожен

                                                        Сложность теста пропорциональна сложности метода. Проще метод — проще тест.

                                                        Проект редко (никогда не) заканчивается сразу после реализации первично обговоренного функционала. Лучше сделать код расширяемым чем рефакторить на каждую хотелку.
                                                        • 0

                                                          Я сравниваю два варианта, которые были предложены вами же выше. Причём тут код LLVM непонятно. ПРо тесты это отдельная тема но про них в начале речи тоже не шло.


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

                                                          Во-первых, это просто не так. Во-вторых, добавление функционала не означает, что из этого нового функционала может быть вызвана произвольная функция. В-третьих, такие преждевременные абстракции имеют свою цену, и если вы заранее сделаете 100 ненужных апи функций, а потом, в процессе доработки, 10 их них пригодятся — то весьма сомнительно, что вы в итоге выиграли. Я не говорю, что делать апи заранее ненужно (более того, есть места, где оно понадобится потом с вероятностью >70%), но делать его везде — определённо лишнее, и есть места, которые в вашем проекте его потребуют с вероятностью, например, не больше 5%, но вы, забыв о рабочей задаче, начинаете вместо специализированного инструмента делать софт общего назначения "для всех".

                                                      • 0
                                                        Маленьких методов много. И когда код разбит больше чем надо, при анализе надо все их держать в голове с учетом контекста.
                                                      • 0
                                                        У меня был кейс недавно однозначный. Нужно было сохранить 50 тысяч файлов с именами 1,2,3 и т.д… Можно было всё в одну директорию, можно в 5 по 10000, в 500 по 100. Я выбрал в 50 по 1000. Тогда директория [удаленно] открывается и не зависает, и можно нужный файл быстро в файл менеджере найти. Остальные варианты ощутимо хуже.
                                                        Так что всё по своей мере.
                                                    • +1
                                                      Согласен с вами. Если задача требует 10 000 действий, то от них никуда не денешься. И разбиения только увеличивают количество сущностей.
                                                      Но правильно выбраное разбиение на абстракции может разбить эту задачу на (условно) 10 * 10 * 10 * 10 структурных единиц (не только методов, но может быть и классов). В зависимости от того, на сколько глубоко нужно изучить механизм решения задачи, можно будет прочесть (условно) один метод на 10 строк. Или ещё 2-3 метода по 10 строк и так далее. Гораздо легче сфокусироваться, погружаясь в детали.

                                                      Я столкнулся с таким, казалось бы излишним, разбиением в open source проекте, к которому готовил pull request, и оно меня спасло. Оно того стоит.
                                                      • +1
                                                        А ещё бывает, что рядом с сорцами лежит маткадовский или латексовый файл, где лежат те же формулы, что реализованы в исходниках, а исходники лежат в двух вариантах: без оптимизаций и RAEP_TIEM. Внутри всё было сплошным полотном, но по соседним файлам и меткам всё было очень читаемо, на уровне методички по матану.
                                                        Я такое видел лишь единожды, и мне очень понравилось.

                                                        Я не собираюсь спорить, какой вариант лучше. Разбиение на структурные единицы — инструмент. И им тоже нужно уметь пользоваться.
                                                  • 0
                                                    Когда видишь перед собой простую редко выполняющуюся задачу категоризации (а-ля «разложить общую кучу элементов по нескольким по определенному признаку»), решаемую с помощью пары интерфейсов, десятка классов, и «умно» примененных паттернов

                                                    А если такая задача решалась бы с помощью пары интерфейсов, ДВА десятка классов, НО БЕЗ «умно» примененных паттернов — это было бы лучше 1000 строк?
                                                  • +4
                                                    Статья хорошая, но есть вопросы:
                                                    1. Это вольный пересказ нескольких глав из книг Фаулера и Йордона?
                                                    2. Статья про код, про ООП и про Java, но ни строчки кода на Java?
                                                    И маленькое дополнение: Хотелось бы увидеть как автор доказывает и показывает , что вот этот код ( здесь пример кода) был таким, а потом стал таким и что из этого вышло и к чему привело. Или так писать плохо(тут пример плохого кода), а так писать хорошо (тут пример хорошего...) Как говорится — всё познается в сравнении.
                                                    • +5
                                                      1. Нет, пересказа не было.
                                                      2. Была такая мысль. Но проиллюстрировать проблемы с большим объёмом кода можно только большим объёмом кода. Который никто не любит читать :)
                                                    • +4
                                                      есть пара оговорок. 1. зачастую написание более абстрактного кода позволяет упростить дальнейшие поддержку, тестирование и развитие, но это ценой увеличения объема. Это прямое противоречие принципу «ни строчкой больше»
                                                      2. код должен быть разделен на логические блоки, а не параграфы. Ветку if “на 20+ строк” имеет смысл выносить в отдельную функцию только если она будет являться самостоятельной логической единицей.
                                                      • 0
                                                        Спасибо, всё правда. Видимо, я плохо описал пример с if. Там речь шла о большом количестве кода внутри «веток». Пока дочитаешь до else, условие успеет уйти с экрана. В таком случае код «веток» следует вынести (функции, объекты и т. д.)
                                                        • 0
                                                          Так вот Antervis, если я правильно его понимаю, пишет полностью противоположное Вам. Что выносить ветку в отдельную функцию следует только если она будет являться самостоятельной логической единицей, а количество строчек — не аргумент (или вторичный аргумент?). Так, Antervis?
                                                          • 0
                                                            важно скорее то, что существует две трактовки комментария на естественном языке в обсуждении написания/чтения кода.
                                                      • 0
                                                        «Гладко было на бумаге...»

                                                        Хорошо работает только если нет костылей. Если есть reflection, или дыры в тестах, т.п. — любой рефакторинг выливается в рефакторинг зависимых частей, и такой «проект» растет, как снежный ком. И даже хуже — если не довести его до конца, приходится добавлять еще костылей.
                                                        • –2
                                                          В действительности количество кода косвенно влияет на количество ошибок:

                                                          а вот теперь по остальным выводам:

                                                          Сэкономите кучу времени себе (на написание) и другим (на чтение).

                                                          Есть метод XXZZ12YYu(int a)
                                                          Он вызывается во всем проекте несколько и в разных местах.
                                                          вызов занимает 1 строчку, а вот что он делает, анализ метода занимает огромное кол-во времени, плюс написание тестов (если их нет) что бы понять конкретный результат.

                                                          Уменьшите количество ошибок в системе.
                                                          Выше косвенно влияет, но только при условии, что в системе остальное работает безупречно.

                                                          Упростите поддержку и развитие системы.
                                                          Ситуация стандартная, когда не понимаешь как это работает и посмотреть негде, а есть только 2 строчки кода. Большие затраты времени на анализ «маленького» кода.

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

                                                          Код должен быть лаконичным, что не эквивалентно понятию «Короткий»,
                                                          что означает — каждый следующий элемент кода должен следовать логически из предыдущего.
                                                          • +1
                                                            Нет кода — нет проблемы, всегда так говорю своим начинающим коллегам. И Вам советую
                                                            • +1

                                                              Присоединяюсь, только у меня фраза звучит так: "Идеальный код — это не написанный".

                                                              • 0
                                                                Сгенерированный, что ли?

                                                                Или что-то из яндекс-дзен-буддизма,
                                                                • 0
                                                                  Сгенерированный тоже сойдет. Но отсутствующий — еще лучше.

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

                                                                    Это помогает:
                                                                    — сократить время разработки;
                                                                    — упростить саппорт.
                                                                    • +1
                                                                      Вы слишком экзотический пример приводите.
                                                                      Вот прихожу я к вам и говорю — «мне нужно вот с этих пяти сайтов собирать информацию об их товарах, чтоб как только что новое появляется — у меня сразу вся инфа с ценой.»
                                                                      Достаю и держу в руках пачку денег

                                                                      Давайте по своим четырем пунктам попробуйте пройтись. Начните с конфигов)
                                                                      • +1
                                                                        1. Нет ли у этих сайтов фидов с ценами? Может можно добавить продукты в избранное и получать цены о них на почту? Может уже есть сервис-агрегатор и вам нужно купить подписку на него вместо разработки своей системы?
                                                                        2. Если у меня уже есть какой-то парсер, я могу добавить ваши сайты в него и дописать только необходимую часть.
                                                                        3. Если у меня есть парсер (допустим я уже делал такие задачи) — возможно в нем есть вариант конфигурировать правила разбора разметки, пользуясь например XML или YAML.
                                                                        4. Если все с нуля — поищу какие есть готовые библиотеки для парсинга, для отправки HTTP запросов, для отправки писем.
                                                                          И только потом напишу код-склейку.
                                                                        • +1
                                                                          1. нету, естественно. вы такое вообще видели?
                                                                          2. нету, конечно
                                                                          3. см. 2
                                                                          4. О каком парсинге речь? html-парсинге? Это подножный стандартный инструмент. Всё остальное всё равно придется ручками писать. А любое готовое типа универсальное решение которое вам (или вы) будут впаривать в итоге выйдет боком и намного дороже пары сотен своих строк.
                                                                          Я даже не беру в расчет время, необходимое на изучение и настройки этих готовых решений, и их ошибки. И вообще, зависание на чужой код.
                                                                          • 0
                                                                            1. Есть функции добавления товара в избранное, когда на почту приходят уведомления о появлении товара в наличии или изменения цены. Есть фиды, которые магазины отправляют какой-нибудь яндекс-маркет, может быть есть возможность его получить.
                                                                            2. нет так нет
                                                                            3. см. 2
                                                                            4. Я подумал, что вы хотите со страницу интернет-магазина цену брать, поэтому html-парсер. Возможно, есть другие способы. Что плохого в зависимости от чужого кода, если он решает задачу? Опять же, я не имею в виду первую попавшуюся поделку с гитхаба, есть решения с большим сообществом и долгой историей. Я предпочитаю, чтобы баги фиксил кто-то другой.
                                                                            • 0
                                                                              Я просто сам писал несколько раз такое. На php вытащить со страницы нужную информацию в нужном формате — 10-20 строчек кода с какой-нибудь simple_php библиотекой (это де факто стандарт для парсинга html в php). Не преувеличиваю. Еще немного кода засунуть это себе в БД или еще куда. Ради этого зависать на чужой непонятный софт? Вы в инете времени в 5 раз больше потратите на его поиск чем сам кодинг.

                                                                              По поводу фида было — висел я на фидах, и в один момент один перестал работать. А хозяин даже не заметил — кому сейчас rss этот нужен. Пришлось аврально переписывать на парсинг сайта, который всегда должен быть онлайн

                                                                              Так что все зависит от задачи. Иногда можно и библиотеки поискать, но в большинстве несложных случаев проще самому.
                                                              • 0
                                                                А я из названия статьи подумал, что тут будет совет не писать незапрошенных фич/абстракций/совместимостей (имеющиеся планы на будущее развитие — тоже запрос, конечно). Но кажется в статье такого совета среди прочего нет.
                                                                • +1
                                                                  Переиспользуйте код, выделяйте абстракции, не стесняйтесь.
                                                                  Опасный совет.
                                                                  Зачастую, выделенные абстракции — неправильные, и приводят к серьёзному усложнению программы и большему числу багов, чем лишний раз скопипасченный кусок кода.
                                                                  Выделять абстракции можно потом, во время рефакторинга, когда очевидно что этот кусок кода используется 3 или больше раз в неизменном виде, а не на этапе написания нового функционала.
                                                                  • –1
                                                                    Зачем откладывать рефакторинг на потом, если с большой долей вероятности он будет полезен уже сейчас?
                                                                    • +4
                                                                      3 причины:
                                                                      — в зависимости от проекта бывает очень тяжело предсказать что будет дальше, хотя, в отличие от тупых продакт менеджеров разработчик уже знает
                                                                      — есть большая вероятность написать что-то лишнее, а все лишнее нужно поддерживать (об этом статья)
                                                                      — преждевременно написанный код: если написать код, который в общем виде понадобится в будущем релизе, а не текущем. такое явно нужно согласовывать, т.к. может быть приоритеты другие.
                                                                      • 0

                                                                        Преждевременно написанный код возникает при попытке выделить абстракции в момент первого написания функционала. Тут я соглашусь.


                                                                        Но когда тот же функционал используется уже во второй раз — абстракции уже стоит выделять, не доводя до рефакторинга, поскольку


                                                                        • дальше будет как обычно — нехватка времени на поддержку, исправление похожих багов в разных похожих участках кода и никто не готов выделить время на рефакторинг.
                                                                        • а не надо писать лишнее. Выделяются только те абстракциии, которые нужны. Если когда этот функционал будет использован в третий раз — абстракции можно будет доработать.
                                                                        • качество кода это не предмет согласования, а прямая обязанность программиста. А если проект планируется дольше чем на полгода — еще и головная боль.
                                                                        • 0
                                                                          нехватка времени на исправление похожих багов в разных похожих участках кода и никто не готов выделить время на рефакторинг.
                                                                          Рефакторинг проводится тогда, когда ты возвращаешься к этому коду — при исправлении багов или реализации новой функциональности. Поэтому специально выделять на него время нужно лишь в крайне редких, сложных и запущенных случаях, когда были допущены существенные ошибки в архитектуре приложения (а чаще это даже вредно, так как есть риск попасть в ловушку «рефакторинг ради рефакторинга», сжирающую любой выделенный на неё объём времени без каких-либо реальных выгод).
                                                                          а не надо писать лишнее. Выделяются только те абстракции, которые нужны
                                                                          Сложновато сделать вывод о том, нужна ли абстракция (и в такой ли форме?), если она встречается только дважды, причём второе применение — новое, для которого всегда может последовать команда «Отставить!».
                                                                          Если когда этот функционал будет использован в третий раз — абстракции можно будет доработать.
                                                                          В результате чего придётся вносить изменения (и рисковать багами) в первых двух применениях. Зацепленность не просто так считается одной из важнейших проблем при программировании.
                                                                    • –1
                                                                      С выделением в функции кода только ради именования я бы тоже поспорил, но даже единожды скопированные без изменения несколько строк кода — абсолютное зло.
                                                                      • +2
                                                                        даже единожды скопированные без изменения несколько строк кода — абсолютное зло.
                                                                        Часто встречаются ложно-одинаковые куски кода, которые ни в коем случае нельзя выделять в абстракции, потому что хоть они и «скопированы без изменения» — но изменения в них точно будут, просто не на данном этапе.
                                                                        Например, инициализация элементов UI: несколько диалогов в руках у разработчика могут быть идентичными — но стоит им попасть в руки дизайнеров, и каждый получит индивидуальный цвет, вкус и запах.
                                                                        • 0

                                                                          Кастомизация цвета/вкуса и запаха, имхо должна быть не в коде

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

                                                                                Так они есть, просто от самого кода они удалены довольно далеко.
                                                                                Критерий сиюминутного качества — это стоимость написания того, что нужно вотпрямщас. Критерий долговременного качества — стоимость поддержки и развития последующие N лет.

                                                                                В обоих случаях первичны, опять же, деньги. А не «сколько нам нужно грамотных проектировщиков, чтоб всё было красиво», и тем более не «сколько в среднем строк на метод» и прочее, имеющее непосредственное отношение к коду. А дальше кто как разумеет, тот так и идёт от денег к конкретным инструкциям для тех же джунов. Кто-то эмпирическим путем определяет, как «строки на метод» относятся к стоимости поддержки, кто-то пользуется своим (и чужим) прошлым неудачным и удачным опытом, чтоб понять, что некий набор методик и рекомендаций скорее всего позволит вписаться в сроки и бюджеты, и так далее. Путей очень много.
                                                                            • 0
                                                                              Самоконтроль нужен всем, это правда. Очень помогает, если на проекте есть инструмент code review (GitHub pull request, Gitter, Upsource etc.) в котором несложно предложить коллегам посмотреть на новый код.
                                                                            • 0
                                                                              Про Java добавлю, что в последних версиях (начиная с 7/8) разработчики языка довольно много переносят из сторонних библиотек в основную. Сейчас ту же Guava довольно редко когда приходится использовать.

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

                                                                              Да и не будут это читать «бывалые». А если прочитают, то не согласятся. Иначе бы уже давно исправились. Нужны организационные изменения. Какие — зависит от конкретной организации. Где-то достаточно обязательных code review. Где-то можно внедрить роботов, которые блокируют PR, если там слишком плохой с формальной точки зрения код. Где-то еще что-то.
                                                                              • 0
                                                                                Код заслуживает быть вынесенным в отдельную функцию не только тогда, когда его планируется переиспользовать, но и в целях улучшения читаемости.

                                                                                Маленькая проблема, называется "области видимости". В результате в вашу "отдельную функцию" постоянно придётся носить кучу параметров, а если она ещё и в цикле (вложенных циклах) вызывается — так уж вообще проще застрелиться, сколько времени сожрёт её вызов чисто на запуливание-выпуливание параметров в/из стека.


                                                                                Нет, конечно, бывают тривиальные случаи, но как правило, если написана "длинная простыня", то случай не тривиальный.

                                                                                • +3

                                                                                  Области видимости — это не проблема, а благословение, позволяющее экономить сложность.


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


                                                                                  Еще лучше с длинными простынями. Часто при распутывании таких "нетривиальных" случаев оказывается, что покрыты не все результаты ветвления и в некоторых случаях получатся странные результаты либо явные расчетные или инфраструктурные (забыли считать/модифицировать общие данные) ошибки.

                                                                                  • 0
                                                                                    Интересно, как бы можно было разбить на маленькие куски кода, например, такой код:
                                                                                    image
                                                                                    Сhart of how Slack decides to send a notification
                                                                                    • +2

                                                                                      1) Это не код, а блок-схема. Вероятно, она была нарисована, когда авторы совсем запутались в написанном коде;)
                                                                                      2) В этой блок-схеме есть два очевидно отдельных куска с разделением в "What's the user's channel notification pref for this device". При этом нижнюю часть скорее всего можно упростить, т.к. есть пересечение у channel и global notifications (например Mentions). Также если делать не единственные точки выхода (YES/NO), то из схемы пропадёт куча объединяющих стрелочек и она станет не такой страшной.
                                                                                      3) Главное, эта схема описывает реальную сложную бизнес-логику. Ее тоже не стоит переусложнять (пользователю будет непонятно), но это другой случай. Описывающий эту логику код поместится на 1-2 страницах, и с учетом хорошей документации в этом нет проблем. Но есть еще код, который вытаскивает из внутренних структур значения переменных, которые тут в if'е. Если он подмешан к коду бизнес-логики, то именно тогда и получается простыня, требующая рефакторинга.

                                                                                      • 0
                                                                                        Отлично объяснено, спасибо!
                                                                                  • 0
                                                                                    сколько времени сожрёт её вызов чисто на запуливание-выпуливание параметров в/из стека.

                                                                                    Ого! Вот с таким уровнем оптимизации я никогда не сталкивался. Простите уж Java-программисту его наивность :)

                                                                                    Что касается большого количества параметров выделяемой функции, то, если все они действительно нужны, можно задуматься о выделении структуры или класса. Но только если не приходится экономить на виртуальных вызовах и количестве параметров на стеке :)
                                                                                  • 0
                                                                                    Большие куски кода трудно тестировать. Большие методы, использующие кучу данных, практически нереально покрыть Unit тестами, а интеграционные тесты оказываются огромными и очень сложными.

                                                                                    Если код приходится "покрывать" тестами, лучше забыть про Unit-тесты, иначе и в тестировании разочаруетесь, и руководителям нервы испортите. Напишите интеграционные или приемочные тесты. Главное, чтобы они позволили без страха рефакторить и добавлять новый функционал. А новый код пишите по TDD.


                                                                                    Большие куски кода сложно ревьюить.

                                                                                    Ревью — вообще проблема и один из самых больших bottleneck'ов в процессе доставки продукта конечному пользователю. И на больших, и на маленьких кусках кода. Человек, который делает ревью, не может адекватно оценить решение, потому что он не в контексте задачи. Обычно на ревью находят всякую стилистическую шелуху, которую при наличии тестов можно поправить в любой момент.


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


                                                                                    Переиспользуйте код, выделяйте абстракции, не стесняйтесь.

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


                                                                                    Чтобы писать меньше кода, нужно:


                                                                                    • перестать реализовывать бесполезные фичи
                                                                                    • решать с помощью кода только текущие проблемы, а не мечтать "когда мы будем как Facebook, такое простое решение работать не будет"
                                                                                    • сначала написать падающий тест
                                                                                    • потом заставить тест проходить
                                                                                    • закончить рефакторингом
                                                                                    • если рефакторинг не идет — оставьте код в покое, позже все равно поймете как сделать лучше
                                                                                    • +4
                                                                                      1. Проблема не в размере кода а в его сложности и читаемости. Можно написать короткий код в стиле «смотри как я могу» в который сам автор через месяц минут 10 будет втыкать перед тем как поймет что он делает а можно написать в 2 раза длиннее но так, что любой дурак сразу поймет.

                                                                                      2. Искать библиотечки тоже не всегда нужно. Иногда проще свелосипедить чем тащить зависимость ради одной тривиальной задачи. Тоже самое с переиспользованием. Часто лучше скопипастить, если это что-то что 100% не будет меняться, чем зависеть от других классов, проектов.

                                                                                      За 10+ опыта вывел для себя следующие приоритеты:
                                                                                      1. Простота, читабельность, понятность кода;
                                                                                      2. По-меньше всяких абстракций и ООП, только тогда когда они реально нужны;
                                                                                      3. Слабая связность и изорилорваность, даже если придется копипастить (без фанатазима), так, чтобы в случае чего код можно было безопасно выкинуть или переписать не затрагивая другого функционала системы;
                                                                                      4. Линейный, императивный код, в идеале такой чтобы определенную логику можно было проанализировать прочитав один файл сверху вниз один раз а не прыгать по разным файлам в разных проектах;
                                                                                      5. Код дружелюбен к тестам и дебагингу.
                                                                                      • +1
                                                                                        Лет 25 назад читал подобные тексты, чуть ли ни слово в слово. Неужели ничего не изменилось?

                                                                                        Кодинг — это как лингвистический язык (русский, английски). Должна быть культура его разговора, его обучения. Правила, стилистика, синтаксис, орфография и всё остальное, а не феня гопника.
                                                                                        • –1
                                                                                          Раньше кодинг был искусством. Помню, еще на первом курсе давали задачки: написать код на любом языке, который в качестве вывода выдаст сам себя. Сейчас так могут?

                                                                                          А сосед написал тетрис на ассемблере, самый быстрый, который я когда либо видел — фигурки падали с ускорением свободного падения на 486. Да еще и с алгоритмом, когда он сам собирался.

                                                                                          А другой накодил сетевой 3д-шутер на VAX-VMS на псевдографике.

                                                                                          В той атмосфере код любой программы старались довести до совершенства. Это было как личная калиграфическая роспись.
                                                                                          • +1
                                                                                            Раньше кодинг был искусством. Помню, еще на первом курсе давали задачки: написать код на любом языке, который в качестве вывода выдаст сам себя. Сейчас так могут?

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

                                                                                            • 0
                                                                                              Раньше кодинг был искусством.

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

                                                                                              • 0
                                                                                                Тогда у вас будут поляроидные фотографии, но не будет рукописных портретов.
                                                                                                • 0
                                                                                                  Ну если следовать вашей аналогии, то… А вот вам на паспорт что больше подойдёт: полароид или рукописный портрет, да еще в стиле какого-нибудь Пикассо, ну если совсем повезёт? :)
                                                                                                  Конечно даже в программирование есть место для «искусства». Вот только 99% всё равно остаются «ремеслом». И тут важнее чтобы код правильно работал и легко поддерживался, а не «я художник, я так вижу» :)
                                                                                                  • +1
                                                                                                    Так-то да, но если копнуть глубже, то без доктора физических наук не будет работы у слесаря.
                                                                                                    И дело в том, что поляроид — это не сам ремесленник, а его инструмент. Нам дали полароид на время. РКН недавно заблокировал что-то, и полрунета перестало работать. Потому что полароид — ихний. Почему у нас аналогов этих гугловских сервисов нет? Свифта нет? Потому что все радостно бегают с полароидами и думают, что крутые мастера.
                                                                                                    Полароиды делают те самые художники, ремесленник его не сделает. И Гугл и Майкрософт сразу же выдергивают из России любого начинающего художника, как увидят, на 100К плюс полный соцпакет и переезд для всей семьи.

                                                                                                    Так что до поры до времени — да, полароид удобней.
                                                                                                    • 0
                                                                                                      Ну вы всё-таки немного о другом. Гугловский сервис он на 99,9999% тоже ремесло. Да, такие вещи требуют своего «гениального момента» или классной идеи или вот просто чумного алгоритма. Но всё равно потом вокруг этого «проблеска гениальности» надо написать огромный пласт «обычного» кода. И тут уж неважно гений ты, не гений, художник или нет: код должен быть легко понимаем и легок в обслуживании.

                                                                                                      П.С. И да, большие фирмы тянут «художников» отовсюду. И не только из России. И не только в информатике. Но тут уж ничего не поделать, «художники» тоже люди и тоже хотят хорошо жить.
                                                                                                      • –1
                                                                                                        Вы не правы. Когда-то давно мой друг уезжал в Микрософт. Я помню его уровень, помню, как он летал на интервью, знал о заданиях, которые ему давали, в каком отделе он работал, что делал, уровень организации труда. уровень его коллег. Потом он перешел в Гугл перед его взлетом. Так вот и там и там именно на 99.999% искусство. И даже простой гугловский сервис делают художники, хоть он и кажется элементарным.
                                                                                                        Рено логан штампуют ремесленники, но создавали его не ремесленники.
                                                                                                        • 0
                                                                                                          Ну у нас похоже немного разное понимание того что означает «искусство» в айти-области. Но насколько известно лично мне и гугл и майкрософт очень даже следят за качеством своего кода. То есть даже если у них и работают одни «художники», то им всё равно приходится писать «чистый» код :)
                                                                                                          • +1
                                                                                                            Что-то я не понял, каким образом из моих слов следует, что художники пишут не чистый код.

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

                                                                                                            «Внутренний» — это, в том числе, следование парадигме ООП (если берем java) и лучшим стандартам кодинга.
                                                                                                            • 0
                                                                                                              Как я уже писал выше у нас с вами просто разное понимание того что означает «искусство» и «художник». Для меня искусство это то самое «я художник, я так вижу». То есть возможно и гениально, но при этом игнорирует общепринятые нормы и стандарты.
                                                                                                              И понятие ремесла у меня немного другое. Ремесленник для меня как раз таки любит свое дело и свои изделия. А чистое «зарабатывание денег» это для меня уже не ремесло, а конвейр.

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

                                                                                                              И да, айти местами это давно уже тот самый конвейр.
                                                                                                              • 0
                                                                                                                да, просто разная трактовка терминов
                                                                                                    • 0
                                                                                                      Это я не к вам апеллирую, а так, вслух грущу, что России художники не нужны…
                                                                                                • 0
                                                                                                  на первом курсе давали задачки: написать код на любом языке, который в качестве вывода выдаст сам себя. Сейчас так могут?

                                                                                                  Довольно-таки бесполезная вещь, имхо.


                                                                                                  В той атмосфере код любой программы старались довести до совершенства. Это было как личная калиграфическая роспись.

                                                                                                  И сейчас стараются. Но только если данные объёмом в десятки ГБ ВНЕЗАПНО не влезают в лимит памяти 2ГБ, или бездарно написанные алгоритмы имеют сложность О(N^6) при N порядка 3000. Суровая коммерческая разработка — это вам не тетрис на PHP.


                                                                                                  Не люблю ностальгию по системам с 640КБ. Особенно когда сравнивают "вот тогда" и "а сейчас". Сравнивать не совсем корректно: объёмы расчётов на порядки больше; компиляторы генерируют сопоставимый по скорости с ассемблером код, этого кода иногда получается аж гигабайты — столько вручную не написать; и т.д.

                                                                                                  • 0
                                                                                                    Вообще-то, я имелось ввиду качество обучении. Вы в школе и вузе много «довольно-таки полезных вещей» нарешали?
                                                                                                • 0
                                                                                                  Думаю, и ещё через 25 лет мало что изменится. Иногда нужно напоминать и о таких простых вещах )
                                                                                                • +1
                                                                                                  Не являюсь особо опытным, но считаю что 95% java-прогеров болеют ООП головного мозга. И данная статья культивирует болезнь. Например либа от сервиса антикапчи разбита на штук 20 классов. Ну что смеяться? Два-три самое то. Или биржевой бот (без аналитики, только коннектор) — вообще под сотню. И эти люди пишут, что метод на 100 строчек слишком длинный? :)
                                                                                                  • 0
                                                                                                    а почему именно java?
                                                                                                    ООП оно и в африке ООП, к языку не привязано вроде
                                                                                                    • 0
                                                                                                      У разных языков и их фанатов разные интерпретации понимания термина ООП. Реализации реально очень разные. И как правило программисты в рамках одного языка пересекаются чаще, чем в рамках разных. И это формирует общий стиль мышления и кодирования.
                                                                                                      • 0
                                                                                                        Ну, во-первых, java — первый распространенный язык высокого уровня, построенный на парадигме ООП. ООП в ее крови, поэтому выражение «95% java-прогеров болеют ООП головного мозга» бессмысленно.
                                                                                                        Во-вторых, не программеры, а языки программирования больше или меньше «тяготеют» к ООП, поэтому реализовать одну и ту же ООП структуру можно и на php, и на java, но для опытных программеров на java это естественно, а на php возможно проще процедурно решить задачу.
                                                                                                        Тем не менее реализация ООП в php (классы, объекты, наследование) вполне себе полная. В java просто более строгая, академическая.

                                                                                                        В общес, про ООП головного мозга не понятно. То же самое, что сказать, что у java программеров — main головного мозга. Ну да, есть немного, но это фича, а не баг.
                                                                                                        • 0
                                                                                                          :-). Да причем тут php и процедурно.

                                                                                                          Систему можно разбивать более чем одним способом. А еще разный способ подходит под разные задачи.

                                                                                                          Но. Когда систему бьют, чтобы бить; когда абстракции выделяют бездумно и в огромном количестве; когда количество смысла на строку текста приближается к нулю. Вот тогда мы получаем ООП головного мозга.
                                                                                                          • 0
                                                                                                            А, под «ООП головного мозга» вы имели плохой ООП анализ и дизайн? И он чаще встречается у java-программеров?
                                                                                                            Это не знаю…
                                                                                                            • 0
                                                                                                              Примерно это, да. За разными языками закреплены разные стереотипы, не обязательно обоснованные. Я просто объясняю соль шутки.
                                                                                                              • 0

                                                                                                                У людей, долго пиливших на яве в кровавом энтерпрайзе, вырабатывается характерный стиль: очень много слоёв абстракции. Думаю, причина этого — не сам язык, а особенности процесса разработки (вероятно, обоснованные в той отрасли), они потом на любом языке так пишут.

                                                                                                                • 0
                                                                                                                  Не знаю как сейчас, а раньше java был обычным языком, не обязательно enterprise. На нем писали любые библиотеки. Веб-приложения. Много клиент-серверных. Даже десктопные приложения под виндоуз (ну, под все ОС, ессно) Очень много опен-сорса было. Глоток свободы после годов тирании С/С++ )))

                                                                                                                  И везде там было ООП. Не помню особо проблем с разбором чужого кода…
                                                                                                                  • 0
                                                                                                                    И везде там было ООП.

                                                                                                                    Так на JAVA по другому никак, насколько я понимаю.