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


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


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


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


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


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


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


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


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

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


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

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


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


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

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

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


  1. jamepock
    02.05.2018 17:01
    +6

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


    1. svartalfar Автор
      02.05.2018 18:09
      +3

      Напомнить бывалым, что не написанный код содержит заведомо меньше ошибок, чем написанный.
      К сожалению, в последнее время встречаю много огромных «простыней» за авторством именно бывалых (5+ лет разработки), уверенных в себе людей


      1. jamepock
        02.05.2018 18:16
        +2

        И действительно, если ничего не писать — никогда не допустишь ошибку.

        Но вопрос огромных простыней — все ещё открытый. Часто бывает что нужно выбрать между двумя вариантами

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

        У обоих подходов есть свои плюсы и минусы, и свои союзники и противники среди программистов, но вопрос все ещё открыт :)


        1. svartalfar Автор
          02.05.2018 18:51
          +2

          Проблема с объёмом появляется тогда, когда логику проследить становится слишком трудно из-за самого объёма. Бороться нужно именно с такой ситуацией.
          А преимущества и недостатки «волшебных однострочников» можно обсудить за дружеской кружкой пива :)


        1. profesor08
          02.05.2018 21:29

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


          1. Akson87
            03.05.2018 20:54

            А поддержкой документации занимаются единороги, которые это делают идеально.


            1. profesor08
              03.05.2018 21:06

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


              1. Akson87
                03.05.2018 21:09

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


                1. profesor08
                  03.05.2018 21:34

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


                  1. Akson87
                    03.05.2018 21:39

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


                    1. profesor08
                      03.05.2018 21:48

                      Я не про комментарии строчек кода, а про описание работы функций.


        1. nekt
          03.05.2018 00:39

          метод в 20 строчек и комментарии к нему на 40 строчек — все равно меньше, чем метод на 100 строчек.


          1. andreyorst
            03.05.2018 11:58
            +4

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


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


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


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


            1. VGoudkov
              03.05.2018 13:49
              +2

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


              1. andreyorst
                03.05.2018 14:56
                +2

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

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


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

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


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

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


                1. jamepock
                  03.05.2018 15:42
                  -2

                  Комментарий должен коротко передавать суть написанного. В указаном примере из квейка комментарий, собственно, передает суть :D


                1. altrus
                  03.05.2018 15:52
                  +5

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

                  image


                1. qw1
                  03.05.2018 21:40

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

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

                  То есть, комментарии типа «да, тут некрасиво и напрашивается переписать короче и понятнее, но короче работать не будет».


                  1. andreyorst
                    03.05.2018 22:08

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

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

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


                    1. qw1
                      04.05.2018 12:00

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


                    1. michael_vostrikov
                      04.05.2018 14:48

                      3 тысячи строк кода с функциями, тела которых не превышают 20 строк

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


                      1. andreyorst
                        04.05.2018 15:16

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


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


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

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


                        1. michael_vostrikov
                          04.05.2018 15:39

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

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


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

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


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

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


                          1. Free_ze
                            04.05.2018 19:17

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


                            1. michael_vostrikov
                              04.05.2018 19:37

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


                              1. Free_ze
                                04.05.2018 20:47

                                Слишком подробно разбираться сразу во всём не стоит) Едва ли можно эффективно держать в памяти все тонкости реализации в таких объемах. Практика показывает, что скорее всего отдельные логические части в 3000 строках точно найдутся. И их не только можно выносить, но и нужно, ведь это основа SRP. Классы — это ведь просто форма пространства имен функций и (возможно) какое-то скрытое состояние.


                                1. Neikist
                                  04.05.2018 21:11

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


        1. Tab10id
          05.05.2018 18:48

          Ни разу не встречал метода на 100 строк в котором можно легко отследить логику действий (конфиги не в счет).


    1. NIKOSV
      03.05.2018 02:19

      «Не нужно додумывать слишком много. Так вы создаете проблемы, которых изначально не было.»

      Фридрих Ницше


    1. gmother
      03.05.2018 12:27
      +1

      Знавал я бывалых программистов, которые на моё искреннее удивление: «Ребята, у вас тут метод на 2000+ строк, это ок вообще?» — недоумевали: «А что такого? Всё ж понятно».


      1. qw1
        03.05.2018 21:33

        Это лучше, чем тупо порезать его пополам, потому что по кодстайлу такие длинные методы запрещены.


      1. Inine
        04.05.2018 01:24

        Ага, причем с восемью вложенными блоками и с рекурсией.


  1. zuborg
    02.05.2018 17:03
    +3

    Не хватает эпиграфа к статье )
    «Совершенство достигается не тогда, когда нечего добавить, а тогда, когда нечего отнять».


  1. aamonster
    02.05.2018 17:51
    +3

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


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


    1. svartalfar Автор
      02.05.2018 18:13
      +3

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


    1. arvitaly
      03.05.2018 06:58
      +4

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


    1. KvanTTT
      03.05.2018 09:52
      +1

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


      1. aamonster
        03.05.2018 11:24
        +1

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


      1. DistortNeo
        03.05.2018 15:50
        +1

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


        1. KvanTTT
          05.05.2018 03:19

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


  1. JustDont
    02.05.2018 18:13
    +4

    Всё бы ничего статья, но…

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

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


    1. svartalfar Автор
      02.05.2018 18:14
      +1

      Истина конечно же где-то посередине.


      1. iCpu
        03.05.2018 07:11
        +1

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

        Я не имею в виду программу с ГУИ, обработкой командной строки, работой с БД и расчётным блоком. Это разные задачи — структурные единицы, которые должны быть разнесены. А бывают иные задачи, разбиение которых ничего не даёт, кроме эстетического удовлетворения и проблем с передачей параметров. Стоит оно того или нет? Я не знаю.


        1. Antervis
          03.05.2018 09:06
          +2

          Посудите сами, если у вас есть однородная задача на 10 000 действий, то это задача на 10 000 действий. Вы можете её разбить на 1*10000, 10*1000, 100*100, 1000*10 и тд структурных единиц, но от этого она меньше не станет. Она останется задачей на 10000.

          вот только для среднего изменения в одном случае надо будет прочитать 10-15 блоков по 10 действий, а в другом — 3-4 блока по тысяче


          1. firk
            03.05.2018 13:59

            И какой из этих двух вариантов лучше? У меня вот нет однозначного ответа. С одной стороны, перемножив всё получаем 150 против 4000 действий, и первое как будто лучше, с другое — не надо недооценивать «10-15 блоков» как самостоятельную большую проблему. Возможно, это большая проблема, чем разница в 30 раз в количестве действий.


            1. Antervis
              03.05.2018 15:25

              существует миллион причин почему разделять код на блоки лучше:
              1. читается код намного больше раз, чем пишется. Монолитный код приходится читать полностью, в то время как модульный — только интересующими нас кусками.
              2. человеческая память ограничена определенным количеством действий. Один раз прочитав метод и зная, что он вычисляет какой-нибудь f(x,y,z) и не имеет побочных эффектов, повторно можно его не анализировать. Большие методы, однако, держать в голове полностью невозможно.
              3. поведение маленьких модулей проще, значит проще составить модель их ожидаемого поведения, протестировать и гарантировать корректность
              4. маленькие методы легко переиспользовать, слишком большие — невозможно. Поэтому в плохо разделенном коде чаще встречается дублирование, которое само по себе ведет к нескольким другим проблемам.

              А теперь еще раз вспомните, что все эти действия над кодом надо делать каждый раз при попытке внесения изменений.


              1. iCpu
                03.05.2018 16:50
                +1

                1) Далеко не всегда это так. Очень далеко не всегда. Есть отдельные модули, которые пишутся раз и навсегда просто потому, что их менять нет смысла. Откройте, например, OpenSSL\Crypto и посмотрите историю изменений. Половина исходников там с бородатых времён практически неизменна: менялись только лицензии и, возможно, фичи для обхода предупреждений компилятора.


                1. andreyorst
                  03.05.2018 17:28

                  Работает — не трогай.


                1. Antervis
                  03.05.2018 17:41

                  а вы не историю изменений читайте, а сам код, и учитесь на его примере


                  1. iCpu
                    03.05.2018 18:40

                    Нет уж, сами читайте код, sha1 и AES я лучше по аналитическим формулам изучу.
                    И, уж извините, OpenSSL не является эталоном качества ни по удобству, ни по качеству структурирования, ни по документированности, ни по надёжности, ни по тестам.


                1. qw1
                  03.05.2018 21:43

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


              1. firk
                04.05.2018 00:23

                Вы как будто комментарий не прочитали и отвечаете. Или я так непонятно написал? По вашим пунктам
                1) я и писал про читаемость кода
                2) а этот пункт как раз и был предметом сомнений: я совсем даже не уверен, что держать в голове 15 коротких блоков проще чем 4 длинных, и даже более того, сталкивался с ситуациями, когда эти самые короткие блоки, поделённые на отдельные функции и вложенные друг в друга, меня ужасно бесили при чтении кода — гораздо приятнее было бы прочитать одну простыню, чем ворох мелких фрагментов; если у вас такого никогда не было — это не значит что всем так же.
                3) опять та же проблема: вам надо сделать кучу мелких проверок или одну большую: усложнение графа связей между функциями само по себе добавляет проблем, и, может быть, оно добавит меньше проблем, чем решит благодаря маленькому размеру модулей, а может и нет
                4) ну, да, но переиспользование не везде будет требоваться; если вы пишете какое-то апи общего назначения — то да, вы не можете заранее полностью знать контекст его применения, а если вы пишете конкретный продукт под конкретную задачу — то уже можете знать, что какая-то функция, хоть она и могла бы быть переиспользованной в другом случае, но конкретно в вашем проекте она используется всего 1 раз и больше не будет; у многих есть склонность создавать абстракции и апи общего назначения там, где их «не заказывали» — это далеко не всегда хорошо.


                1. Antervis
                  04.05.2018 08:32

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

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

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


                  1. firk
                    04.05.2018 18:11

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


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

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


              1. michael_vostrikov
                04.05.2018 05:00

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


            1. altrus
              03.05.2018 18:57

              У меня был кейс недавно однозначный. Нужно было сохранить 50 тысяч файлов с именами 1,2,3 и т.д… Можно было всё в одну директорию, можно в 5 по 10000, в 500 по 100. Я выбрал в 50 по 1000. Тогда директория [удаленно] открывается и не зависает, и можно нужный файл быстро в файл менеджере найти. Остальные варианты ощутимо хуже.
              Так что всё по своей мере.


        1. svartalfar Автор
          03.05.2018 09:54
          +1

          Согласен с вами. Если задача требует 10 000 действий, то от них никуда не денешься. И разбиения только увеличивают количество сущностей.
          Но правильно выбраное разбиение на абстракции может разбить эту задачу на (условно) 10 * 10 * 10 * 10 структурных единиц (не только методов, но может быть и классов). В зависимости от того, на сколько глубоко нужно изучить механизм решения задачи, можно будет прочесть (условно) один метод на 10 строк. Или ещё 2-3 метода по 10 строк и так далее. Гораздо легче сфокусироваться, погружаясь в детали.

          Я столкнулся с таким, казалось бы излишним, разбиением в open source проекте, к которому готовил pull request, и оно меня спасло. Оно того стоит.


          1. iCpu
            03.05.2018 10:27
            +1

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

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


    1. Moriline
      02.05.2018 18:58

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

      А если такая задача решалась бы с помощью пары интерфейсов, ДВА десятка классов, НО БЕЗ «умно» примененных паттернов — это было бы лучше 1000 строк?


  1. Moriline
    02.05.2018 18:39
    +3

    Статья хорошая, но есть вопросы:
    1. Это вольный пересказ нескольких глав из книг Фаулера и Йордона?
    2. Статья про код, про ООП и про Java, но ни строчки кода на Java?
    И маленькое дополнение: Хотелось бы увидеть как автор доказывает и показывает , что вот этот код ( здесь пример кода) был таким, а потом стал таким и что из этого вышло и к чему привело. Или так писать плохо(тут пример плохого кода), а так писать хорошо (тут пример хорошего...) Как говорится — всё познается в сравнении.


    1. svartalfar Автор
      02.05.2018 18:55
      +3

      1. Нет, пересказа не было.
      2. Была такая мысль. Но проиллюстрировать проблемы с большим объёмом кода можно только большим объёмом кода. Который никто не любит читать :)


  1. Antervis
    02.05.2018 19:30
    +2

    есть пара оговорок. 1. зачастую написание более абстрактного кода позволяет упростить дальнейшие поддержку, тестирование и развитие, но это ценой увеличения объема. Это прямое противоречие принципу «ни строчкой больше»
    2. код должен быть разделен на логические блоки, а не параграфы. Ветку if “на 20+ строк” имеет смысл выносить в отдельную функцию только если она будет являться самостоятельной логической единицей.


    1. svartalfar Автор
      02.05.2018 21:46

      Спасибо, всё правда. Видимо, я плохо описал пример с if. Там речь шла о большом количестве кода внутри «веток». Пока дочитаешь до else, условие успеет уйти с экрана. В таком случае код «веток» следует вынести (функции, объекты и т. д.)


      1. sasha1024
        03.05.2018 05:31

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


        1. Antervis
          03.05.2018 06:36

          важно скорее то, что существует две трактовки комментария на естественном языке в обсуждении написания/чтения кода.


  1. vdonich
    02.05.2018 19:53

    «Гладко было на бумаге...»

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


  1. alwer
    02.05.2018 22:33
    -1

    В действительности количество кода косвенно влияет на количество ошибок:

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

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

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

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

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

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

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


  1. Keltir
    02.05.2018 22:33

    Нет кода — нет проблемы, всегда так говорю своим начинающим коллегам. И Вам советую


    1. tommyangelo27
      03.05.2018 08:31
      +1

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


      1. altrus
        03.05.2018 08:52

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

        Или что-то из яндекс-дзен-буддизма,


        1. mayorovp
          03.05.2018 10:11

          Сгенерированный тоже сойдет. Но отсутствующий — еще лучше.

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


          1. altrus
            03.05.2018 10:21
            +1

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


            1. mayorovp
              03.05.2018 10:24

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


              1. altrus
                03.05.2018 10:26

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


                1. mayorovp
                  03.05.2018 10:40

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


        1. tommyangelo27
          03.05.2018 13:49

          Не написанный вообще. Варианты:
          — уговорить клиента вообще отказаться от фичи (уровень Бог);
          — переиспользовать готовые фичи;
          — что-то поправить или настроить в конфигах;
          — взять готовую библиотеку.
          И только если ничего из вышеперечисленного невозможно — писать код. Причем писать как можно меньше (минимально возможное количество кода, позволяющее реализовать фичу).

          Это помогает:
          — сократить время разработки;
          — упростить саппорт.


          1. altrus
            03.05.2018 13:58
            +1

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

            Давайте по своим четырем пунктам попробуйте пройтись. Начните с конфигов)


            1. tommyangelo27
              03.05.2018 14:17

              1. Нет ли у этих сайтов фидов с ценами? Может можно добавить продукты в избранное и получать цены о них на почту? Может уже есть сервис-агрегатор и вам нужно купить подписку на него вместо разработки своей системы?
              2. Если у меня уже есть какой-то парсер, я могу добавить ваши сайты в него и дописать только необходимую часть.
              3. Если у меня есть парсер (допустим я уже делал такие задачи) — возможно в нем есть вариант конфигурировать правила разбора разметки, пользуясь например XML или YAML.
              4. Если все с нуля — поищу какие есть готовые библиотеки для парсинга, для отправки HTTP запросов, для отправки писем.
                И только потом напишу код-склейку.


              1. altrus
                03.05.2018 14:22
                +1

                1. нету, естественно. вы такое вообще видели?
                2. нету, конечно
                3. см. 2
                4. О каком парсинге речь? html-парсинге? Это подножный стандартный инструмент. Всё остальное всё равно придется ручками писать. А любое готовое типа универсальное решение которое вам (или вы) будут впаривать в итоге выйдет боком и намного дороже пары сотен своих строк.
                Я даже не беру в расчет время, необходимое на изучение и настройки этих готовых решений, и их ошибки. И вообще, зависание на чужой код.


                1. tommyangelo27
                  03.05.2018 14:48

                  1. Есть функции добавления товара в избранное, когда на почту приходят уведомления о появлении товара в наличии или изменения цены. Есть фиды, которые магазины отправляют какой-нибудь яндекс-маркет, может быть есть возможность его получить.
                  2. нет так нет
                  3. см. 2
                  4. Я подумал, что вы хотите со страницу интернет-магазина цену брать, поэтому html-парсер. Возможно, есть другие способы. Что плохого в зависимости от чужого кода, если он решает задачу? Опять же, я не имею в виду первую попавшуюся поделку с гитхаба, есть решения с большим сообществом и долгой историей. Я предпочитаю, чтобы баги фиксил кто-то другой.


                  1. altrus
                    03.05.2018 14:58

                    Я просто сам писал несколько раз такое. На php вытащить со страницы нужную информацию в нужном формате — 10-20 строчек кода с какой-нибудь simple_php библиотекой (это де факто стандарт для парсинга html в php). Не преувеличиваю. Еще немного кода засунуть это себе в БД или еще куда. Ради этого зависать на чужой непонятный софт? Вы в инете времени в 5 раз больше потратите на его поиск чем сам кодинг.

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

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


  1. firk
    02.05.2018 23:44

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


  1. SinsI
    03.05.2018 00:24
    +1

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


    1. nekt
      03.05.2018 00:40

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


      1. hippoage
        03.05.2018 00:59
        +1

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


        1. nekt
          03.05.2018 14:27

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


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


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


          1. SinsI
            04.05.2018 09:26

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


    1. DnV
      03.05.2018 03:49

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


      1. SinsI
        03.05.2018 07:49
        +2

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


        1. Kobalt_x
          03.05.2018 10:16

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


        1. Free_ze
          03.05.2018 13:40

          Дизайнеры работают после программистов? (и почему дизайнеры вообще противопоставляются разработчикам?) Что мешает отложить копипастинг до момента появления реальных различий?


      1. michael_vostrikov
        03.05.2018 09:06

        Это не так. Потому что одинаковыми они могут быть только в этот конкретный момент времени.
        Необходимость копирования можно проверить представлением в динамике — «если у нас логика изменится здесь, надо будет менять там?», «может ли быть, что там должно работать не так, как здесь?».


        1. DnV
          03.05.2018 14:37

          Чаще всего различия удаётся задать параметрами. Даже если нет, то лучше копировать по мере необходимость и сразу редактировать, чем плодить такие вот «заготовки».


  1. moonster
    03.05.2018 00:35
    +1

    Если человек не страдает самоконтролем, то никакие добрые советы ему не помогут. Неоднократно во время PR review наблюдал откровенный говнокод, которого могло бы не быть, если бы человек просто посмотрел на свою писанину второй раз.
    Мне стоило некоторого труда научиться задавать себе вопрос, а не говнокод ли я написал только что?
    К сожалению, многие разработчики не задают себе такой вопрос вообще никогда.


    1. JustDont
      03.05.2018 01:09

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


      1. moonster
        03.05.2018 01:30

        Невменяемые сроки и плохая постановка задач — все это есть. Но в хорошем проекте это скорее исключение, чем правило.
        Я, конечно, люблю идеальный код, но не являюсь его неуёмным фанатом. Должны существовать измеримые критерии качества кода, и никакой код в проекте не должен быть хуже, чем предусмотрено этими критериями. Критерии, конечно, у каждого проекта могут быть свои.
        Очень хорошо, если заказчик понимает, что качество кода непосредственно влияет на качество продукта, на стоимость его развития и поддержки. Если не понимает — лучше инвестировать время в разъяснение, окупится.
        А так — да. Никому не нужна корова, всем нужно молоко, шкура, мясо. Никому не нужен бетон, всем нужны мосты и здания. Никому не нужен Х, всем нужен У.


        1. JustDont
          03.05.2018 11:04

          Должны существовать измеримые критерии качества кода

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

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


    1. svartalfar Автор
      03.05.2018 11:24

      Самоконтроль нужен всем, это правда. Очень помогает, если на проекте есть инструмент code review (GitHub pull request, Gitter, Upsource etc.) в котором несложно предложить коллегам посмотреть на новый код.


  1. hippoage
    03.05.2018 00:50

    Про Java добавлю, что в последних версиях (начиная с 7/8) разработчики языка довольно много переносят из сторонних библиотек в основную. Сейчас ту же Guava довольно редко когда приходится использовать.

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

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


  1. Wesha
    03.05.2018 01:56

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

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


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


    1. Steed
      03.05.2018 10:21
      +2

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


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


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


      1. TheOleg
        03.05.2018 22:37

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


        1. Steed
          04.05.2018 10:53
          +2

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


          1. TheOleg
            05.05.2018 19:21

            Отлично объяснено, спасибо!


    1. svartalfar Автор
      03.05.2018 11:28

      сколько времени сожрёт её вызов чисто на запуливание-выпуливание параметров в/из стека.

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

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


  1. Telichkin
    03.05.2018 02:01

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

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


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

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


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


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

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


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


    • перестать реализовывать бесполезные фичи
    • решать с помощью кода только текущие проблемы, а не мечтать "когда мы будем как Facebook, такое простое решение работать не будет"
    • сначала написать падающий тест
    • потом заставить тест проходить
    • закончить рефакторингом
    • если рефакторинг не идет — оставьте код в покое, позже все равно поймете как сделать лучше


  1. NIKOSV
    03.05.2018 02:57

    1. Проблема не в размере кода а в его сложности и читаемости. Можно написать короткий код в стиле «смотри как я могу» в который сам автор через месяц минут 10 будет втыкать перед тем как поймет что он делает а можно написать в 2 раза длиннее но так, что любой дурак сразу поймет.

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

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


  1. altrus
    03.05.2018 05:09

    Лет 25 назад читал подобные тексты, чуть ли ни слово в слово. Неужели ничего не изменилось?

    Кодинг — это как лингвистический язык (русский, английски). Должна быть культура его разговора, его обучения. Правила, стилистика, синтаксис, орфография и всё остальное, а не феня гопника.


    1. altrus
      03.05.2018 05:17

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

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

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

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


      1. KvanTTT
        03.05.2018 09:58
        +1

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

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


      1. Druu
        03.05.2018 12:06

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

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


        1. altrus
          03.05.2018 12:08

          Тогда у вас будут поляроидные фотографии, но не будет рукописных портретов.


          1. Kanut79
            03.05.2018 12:25

            Ну если следовать вашей аналогии, то… А вот вам на паспорт что больше подойдёт: полароид или рукописный портрет, да еще в стиле какого-нибудь Пикассо, ну если совсем повезёт? :)
            Конечно даже в программирование есть место для «искусства». Вот только 99% всё равно остаются «ремеслом». И тут важнее чтобы код правильно работал и легко поддерживался, а не «я художник, я так вижу» :)


            1. altrus
              03.05.2018 12:47
              +1

              Так-то да, но если копнуть глубже, то без доктора физических наук не будет работы у слесаря.
              И дело в том, что поляроид — это не сам ремесленник, а его инструмент. Нам дали полароид на время. РКН недавно заблокировал что-то, и полрунета перестало работать. Потому что полароид — ихний. Почему у нас аналогов этих гугловских сервисов нет? Свифта нет? Потому что все радостно бегают с полароидами и думают, что крутые мастера.
              Полароиды делают те самые художники, ремесленник его не сделает. И Гугл и Майкрософт сразу же выдергивают из России любого начинающего художника, как увидят, на 100К плюс полный соцпакет и переезд для всей семьи.

              Так что до поры до времени — да, полароид удобней.


              1. Kanut79
                03.05.2018 12:56

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

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


                1. altrus
                  03.05.2018 13:13

                  Вы не правы. Когда-то давно мой друг уезжал в Микрософт. Я помню его уровень, помню, как он летал на интервью, знал о заданиях, которые ему давали, в каком отделе он работал, что делал, уровень организации труда. уровень его коллег. Потом он перешел в Гугл перед его взлетом. Так вот и там и там именно на 99.999% искусство. И даже простой гугловский сервис делают художники, хоть он и кажется элементарным.
                  Рено логан штампуют ремесленники, но создавали его не ремесленники.


                  1. Kanut79
                    03.05.2018 13:27

                    Ну у нас похоже немного разное понимание того что означает «искусство» в айти-области. Но насколько известно лично мне и гугл и майкрософт очень даже следят за качеством своего кода. То есть даже если у них и работают одни «художники», то им всё равно приходится писать «чистый» код :)


                    1. altrus
                      03.05.2018 13:35
                      +1

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

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

                      «Внутренний» — это, в том числе, следование парадигме ООП (если берем java) и лучшим стандартам кодинга.


                      1. Kanut79
                        03.05.2018 13:46

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

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

                        И да, айти местами это давно уже тот самый конвейр.


                        1. altrus
                          03.05.2018 14:02

                          да, просто разная трактовка терминов


            1. altrus
              03.05.2018 12:48

              Это я не к вам апеллирую, а так, вслух грущу, что России художники не нужны…


      1. Akon32
        03.05.2018 16:28

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

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


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

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


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


        1. altrus
          03.05.2018 16:41

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


    1. svartalfar Автор
      03.05.2018 11:36

      Думаю, и ещё через 25 лет мало что изменится. Иногда нужно напоминать и о таких простых вещах )


  1. mspain
    03.05.2018 06:53

    Не являюсь особо опытным, но считаю что 95% java-прогеров болеют ООП головного мозга. И данная статья культивирует болезнь. Например либа от сервиса антикапчи разбита на штук 20 классов. Ну что смеяться? Два-три самое то. Или биржевой бот (без аналитики, только коннектор) — вообще под сотню. И эти люди пишут, что метод на 100 строчек слишком длинный? :)


    1. altrus
      03.05.2018 07:59

      а почему именно java?
      ООП оно и в африке ООП, к языку не привязано вроде


      1. nsinreal
        03.05.2018 10:04

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


        1. altrus
          03.05.2018 10:16

          Ну, во-первых, java — первый распространенный язык высокого уровня, построенный на парадигме ООП. ООП в ее крови, поэтому выражение «95% java-прогеров болеют ООП головного мозга» бессмысленно.
          Во-вторых, не программеры, а языки программирования больше или меньше «тяготеют» к ООП, поэтому реализовать одну и ту же ООП структуру можно и на php, и на java, но для опытных программеров на java это естественно, а на php возможно проще процедурно решить задачу.
          Тем не менее реализация ООП в php (классы, объекты, наследование) вполне себе полная. В java просто более строгая, академическая.

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


          1. nsinreal
            03.05.2018 10:57

            :-). Да причем тут php и процедурно.

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

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


            1. altrus
              03.05.2018 11:09

              А, под «ООП головного мозга» вы имели плохой ООП анализ и дизайн? И он чаще встречается у java-программеров?
              Это не знаю…


              1. nsinreal
                03.05.2018 11:16

                Примерно это, да. За разными языками закреплены разные стереотипы, не обязательно обоснованные. Я просто объясняю соль шутки.


              1. aamonster
                03.05.2018 11:34

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


                1. altrus
                  03.05.2018 12:54

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

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


                  1. sumanai
                    03.05.2018 13:39

                    И везде там было ООП.

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


                    1. altrus
                      03.05.2018 13:47

                      Ну почему, и в java можно почти всё загнать в main(argv[])
                      ООП — это образ мышления. Структурирование данных, вычленение сущностей и поиск зависимостей. Одно и то же техзадание можно перевести в архитектуру будущего ПО очень по-разному — удачно и неудачно.
                      Поэтому архитекторы и дизайнеры получают в несколько раз больше простых программеров.


                    1. Free_ze
                      03.05.2018 13:48

                      Де факто никто не мешает обходиться статическими методами и полями, используя классы как пространства имен. Тем более, что статический импорт там разрешен. Такое себе ООП)


    1. vershinin
      03.05.2018 12:08

      95% не-java-проггеров (js, это я про вас) впадают в другую крайность и не структурируют код вообще. На мой взгляд лучше читать чрезмерный ООП, чем ту кашу, которую производят js девелоперы.


      1. JustDont
        04.05.2018 16:09
        -1

        Вот да, дайте мне лучше пожалуйста «больных ООП на всю голову», чем то, что довольно часто нынче творится на ниве фронтэнда в js.

        Как например (извините, наболело) этот их «серьезный, популярный, эффективный» ангуляр, разработчики которого в один прекрасный момент просто заявляют: извините, но сделать наследование наших деклараций и инъекций слишком сложно, поэтому мы этого делать не будем. Нет, нас не волнует, что мы типа косим (туториалами, модульностью, и тэ дэ) под ООП, но не имеем реализации базовых принципов ООП. Вас волнует? Ну, ваши проблемы.


  1. altrus
    03.05.2018 09:17
    +5

    Oблечь техническoе зaдaние в кoд не прoстo. Некoтoрые прoгрaммисты делaют этo с трудoм. aрхитектoры программного обеспечения, высококлассные рaзрaбoтчики, нaoбoрoт, пoстигли этo искусствo. И все же сoвершеннaя фoрмa кoдa еще недoступнa. Ею влaдеют oчень немнoгие. Тaйнa зaключaется в пoлнoй гaрмoнии фoрмы и сoдержaния. Любoй элемент языкa, oперaнд, идентификaтoр в свoем вырaжении имеет глубoкoе знaчение, пo свoей семaнтическoй идее. И вoт этa-тo идея и ее реaлизaция в кoде дoлжны нaхoдиться в пoлнoм сoзвучии. Некoтoрые прoгрaммы oсoбеннo сильны именнo этим сooтветствием. Кaждaя прoгрaммa имеет свoй ритм, если прoгрaммист, ее нaписaвший, этим ритмoм влaдеет. В твoрениях великих рaзрaбoтчикoв пoрoй мoжнo улoвить этoт ритм, нo мнoгие пишут целые прoгрaммные кoмплексы, никaкoгo ритмa не сoблюдaя и дaже не пoдoзревaя o нем. Тaкoй кoд в рaзрoзненнoм и беспoрядoчнoм ритме или сoвсем без негo или сoвсем не читaется, или зaбывaется скoрo. Нo те, пусть этo будет хoтя бы мaленькaя прoгрaммкa, где ритм сoблюден и пoстигнутa музыкa кoдингa, те читaются легкo, и прoгрaммисты их реюзaют. Нaписaннoе нa любoм языке прoгрaммирoвaния мoжет быть дaнo в любoм ритме и любoй тoнaльнoсти, нo при услoвии сooтветствия сoдержaния с фoрмoй. Следует пoмнить при этoм, чтo кaждый элемент языкa имеет свoй звукoвoй ключ и сoчетaется в кoде с рядoм других элементoв пo свoему внутреннему сoдержaнию, звукoвoму ключу и связи сo свoей семaнтикoй, кoтoрыми oблекaется весь кoд, кaк музыкaльнaя идея oблекaется звукaми. Именнo музыкaльнoй симфoнии мoжнo упoдoбить хoрoшую прoгрaмму. У великих рaзрaбoтчикoв этa гaрмoния мыслей и выражений языка программирования инoгдa вырaжaется oсoбеннo яркo. Зoвут тaких людей мaстерaми кодинга. Незримoе вoздействие прaвильнo и гaрмoничнo пoстрoеннoгo кoдa oсoбеннo великo. Внутреннее егo сoдержaние стaнoвится oсoбеннo выпуклым, кoгдa с ним внешняя фoрмa сoзвучнa. Тaйнa прoгрaммирoвaния oчень слoжнa и немнoгим дoступнa.


  1. MMTRIX
    03.05.2018 09:55

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


    1. KvanTTT
      03.05.2018 10:02
      +2

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

      Параллельно — не знаю. Но по определенной команде построить точно можно (Visual Studio).


      Или наоборот, создание блок-схемы приводит к автоматическому написанию кода?

      Есть. Но сгенерированный код не отличается хорошим качеством.


    1. svartalfar Автор
      03.05.2018 11:43
      +2

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


      1. tyomitch
        03.05.2018 19:48

        Нишевое решение


      1. mayorovp
        03.05.2018 20:35

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

        Ну и проработанный UI редактора тоже крайне важен…


    1. Areso
      03.05.2018 12:59

      RAD Studio. Автогенерация кода из алгоритма. Ну и «детские» Java, JavaScript редакторы так вполне умеют. Еще видел для C embed, неплохой вариант, если вы железячник, а не программист.


    1. tyomitch
      03.05.2018 19:46

      (комментарий перенесён в ветку выше)


  1. topheracher
    03.05.2018 09:55
    +3

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

    ООП с документацией и тестами

    heh, classic


  1. shasoft
    03.05.2018 10:06
    +2

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

    Мнение начальства: Вася хороший разработчик, который быстро пишет свой код и быстро разбирается в чужом коде. А вот Петя немного «недогоняет», потому что пишет дольше, а в чужом коде и вообще долго разбирается.


    1. altrus
      03.05.2018 10:19
      -2

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


  1. ElectroGuard
    03.05.2018 10:22

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


    1. svartalfar Автор
      03.05.2018 11:45

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


      1. ElectroGuard
        03.05.2018 13:11

        Допускает анонимные процедуры (лямбда-замыкания) прямо внутри кода. Но обычно мало кто их использует, поэтому особо не говнокодят :)


  1. Throwable
    03.05.2018 11:42

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


    Проверьте, не решал ли кто-то до вас в этом проекте такую же (или сильно похожую) задачу.

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


    Знайте и любите утилиты и API собственного проекта. Особенно, если ему больше полугода. Там могут найтись жемчужины, которые сэкономят вам десятки строк кода.

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


    Ещё знайте и любите популярные библиотеки для вашего языка или платформы

    Иногда только из-за одной функции подтягивают кучу зависимостей.


    Код заслуживает быть вынесенным в отдельную функцию

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


    1. svartalfar Автор
      03.05.2018 11:53

      Ни в коем случае не претендую на «серебряную пулю», которой не существует. Просто отметил определённые перекосы и трудности, с которыми сталкиваюсь в повседневной работе.

      Все ваши замечания очень даже по существу, и их стоит применять, организуя свой код и проект. Хотя публика может и не оценить предложение использовать копипейст :)
      Отличной иллюстрацией проблем с использованием библиотек в индустрии стала истоия «левого отступа» в JavaScript, так что о ней нескоро забудут.

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


      1. Druu
        03.05.2018 12:11

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

        Вам какую книгу удобно читать — если текст последовательный (пусть и не влазит на одну страницу) или разбит по отдельным кускам-абзацам, которые хаотично и бессистемно раскиданы по всему тому?


        1. svartalfar Автор
          03.05.2018 12:24

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

          Допускаю, что «бессистемная раскиданность» не доставляет мне проблем благодаря используемому инструменту (IDE). Читать код с большой степенью косвенности в Vim/Emacs наверное так же сложно, как читать распечатанную википедию (без браузера).


          1. Druu
            03.05.2018 14:15

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

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


  1. Vlad_fox
    03.05.2018 11:50

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


    1. svartalfar Автор
      03.05.2018 11:53

      так они его и так пишут. Разве нет?


  1. multiprogramm
    03.05.2018 11:51
    +2

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

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

    Так что я не понял посыл. С чем предлагается бороться: с количеством или низким качеством? Или под словом «код» здесь понимается только содержание методов?


    1. svartalfar Автор
      03.05.2018 11:55

      Второе. Основная боль — огромные, непомерно раздутые методы/функции (в комбинации с вложенными структурами),


      1. multiprogramm
        03.05.2018 14:16

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


        1. JimmDiGreez
          03.05.2018 14:19
          +3

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


    1. altrus
      03.05.2018 12:12

      Вообще-то))) в ООП это вторичный вопрос — большой код для метода, или небольшой, читаемый или нет.
      Есть объект, его свойства, есть необходимые методы — паблик, протектед — интерфейс к нему, Остальное разбивается на прайвет.
      Во главе — объект, его свойства и методы. А что написано в методе волновать должно только тех, кто этот метод будет дополнять/переписывать.
      Если ваш программер выдает рабочие готовые библиотеки, нечитаемость его кода терпима. Если это команда — обязательны правила для всех. В противном случае — желательны.(премируйте грамотно пишущих)


      1. sumanai
        03.05.2018 13:43

        Если ваш программер выдает рабочие готовые библиотеки, нечитаемость его кода терпима.

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


        1. altrus
          03.05.2018 14:00

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


      1. multiprogramm
        03.05.2018 14:36

        Это всё до первого бага или первого изменения требований. Тогда-то и придётся залезть в реализацию объекта и схватиться за голову.
        Если программист (1)выдаёт идеально работающий продукт, который (2)не нужно будет дорабатывать, тогда конечно не так важно, как оно написано. Первое происходит обычно никогда, а второе — обычно когда продукт никому не нужен.


    1. JimmDiGreez
      03.05.2018 14:15

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


      1. sumanai
        03.05.2018 14:35

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

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


  1. greabock
    03.05.2018 16:05

    >… Они [программисты] знают, что большую часть времени они этот код читают…

    Я вот большую часть времени вообще думаю о том, чем являются вещи и как они работают в реальном мире. Рисую диаграмки там всякие… наверное я не программист )


  1. botyaslonim
    03.05.2018 17:21

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