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

Эрик Дитрих* около 10 лет провел на должностях, где его основной функцией было написание кода. Еще 10 лет были связаны с управлением программистами, их обучением, консультированием организаций, практикой оценки кодовой базы, а в наши дни и контент-маркетингом. Но во всех этих ролях он в той или иной степени писал код. И, по своим расчетам, прошел больший путь, чем 94% работающих в отрасли. Получается некое противопоставление: программист со стажем, который общается с кучей новичков в программировании.

Специально для своего блога Эрик попытался обобщить весь свой опыт в виде кратких советов, которые он хотел бы дать молодым программистам. Под катом — наиболее важные, на взгляд автора, уроки и выводы из его 20-летней карьеры.

*Обращаем ваше внимание, что позиция автора может не всегда совпадать с мнением МойОфис.


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

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

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

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

Вот пять советов, которыми я хочу поделиться с молодыми специалистами.

1. Дублирование знаний — наихудший вариант

«Избегайте программирования методом копипаста!»

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

Прекратите это. Немедленно. Это ужасная и неряшливая практика.

Вот проблемы, связанные с таким подходом:

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

  2. Теперь в процессе таких изменений у вас удвоенный шанс внести ошибки.

  3. Вы создали «шаблон проектирования», и теперь ваш код просит нового, избыточного метода, по мере того как ваша глобальная экспансия продолжается.

  4. Трудоемкость изменений стремительно возрастает со временем.

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

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

  7. Это беспорядок. И это — копипаст — лишь та проблема, которая лежит на поверхности.

«Копипаста» — это только начало

Настоящая проблема — это дублирование знаний в вашей системе.

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

  • Цикл for и комментарий к коду прямо над ним, объясняющий начальное значение, конечное значение и приращение.

  • Глобальной переменной присваивается значение в теле программы, а затем (возможно) повторно присваивается значение из файла конфигурации.

  • Таблица базы данных со столбцами «PretaxTotal» (итого без учета налога), «Tax» (налог) и «Total» (итого).

  • Широкомасштабная ERP-система, которая хранит данные о клиентах в своем модуле CRM, а затем еще раз — в биллинговом модуле.

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

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

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

И, помните, это лучшие сценарии.

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

Возможно, вы реализуете триггер базы данных при каждом изменении столбца «Total», чтобы убедиться, что PretaxTotal + Tax по-прежнему равны Total. Или, возможно, вы пишете громоздкую логику проверки состояния, чтобы занести в журнал предупреждение, если значение глобальной переменной по умолчанию не совпадет с присвоенным значением в конфигурационном файле.

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

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

2. Код — это пассив

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

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

И мы не одиноки в этом праздновании.

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

Забудьте обо всем этом.

Я понимаю, почему мы смотрим на код как на актив. Но реальность такова, что код — это сплошной пассив.

Меньше — значит больше

Знаете, что может быть еще лучше, чем сделать за 10 строк кода то, что кто-то другой сделал за 100? Сделать это за 0 строк кода.

Возьмите и напишите строку кода:

printf("Hello World!"); 

Как вы думаете, сколько всего может пойти не так?

  • Будет ли этот код выполняться в среде, позволяющей вывод на консоль?

  • Не станет ли эта волшебная строка впоследствии проблемой?

  • Разве вы не должны вести журнал? Это передовая практика.

  • Вы хотя бы раз задумались о том, как это отразится на безопасности?

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

Вы думаете, что это доводит общее количество вещей, которые могут пойти не так, до 20?

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

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

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

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

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

Я люблю код.

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

3. Старшие разработчики: доверяй, но проверяй

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

Я многому у них научился.

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

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

Но не все старшие разработчики созданы (или, в моем случае, выдвинуты на эту должность) одинаково.

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

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

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

Дейл расскажет вам, что не так с так называемыми профессиональными ORM
Дейл расскажет вам, что не так с так называемыми профессиональными ORM

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

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

4. TDD — это оправдано, и это меняет правила игры

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

  • Что лучше: IDE или простой редактор?

  • Apple, Windows или Linux?

  • Что вы думаете о PHP?

  • Табуляция или пробелы?

Поднимите любую из этих тем и посмотрите, какие соревнования по крику возникают между теми, кто имеет твердое мнение. Так что, учитывая все это я понимаю, что вступаю на похожую территорию с вопросом «TDD или не TDD».

Я хочу не проповедовать, а поделиться собственным опытом.

Около 10 лет назад я был скептиком в отношении TDD. Заметьте, я не был скептиком в отношении модульного тестирования: я принял его как полезную технологию практически с самого начала.

Но TDD? Я не был настолько уверен.

Я решил написать в блоге статью о том, почему TDD не так уж и хорош.

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

Но у судьбы были другие планы.

Мое «озарение» с TDD

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

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

Но потом произошла забавная вещь.

Я был настолько зациклен на этой неудобной парадигме, что в один из дней умудрился потратить 4-5 часов на написание кода, ни разу не запустив приложения, чтобы проверить, работают ли мои изменения. Обычно я запускал приложение каждые 10 минут или около того чтобы проверить, действительно ли мои изменения работают.

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

Но произошла странная вещь: все работало.

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

В итоге я написал совсем другую статью о TDD. И больше ни разу не оглянулся назад.

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

Изучите TDD. Вы не пожалеете.

5. Доказательства — сила

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

Доказательства — это все.

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

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

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

Исправьте это.

Важность доказательств

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

Доказательства принесут вам аргументы, уважение, руководящие роли и карьерный рост.

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

И под словом «доказать» я не имею в виду «найти что-то вроде поста о вреде "глобального состояния" и апеллировать ко мне как к авторитету». Я имею в виду «найти модули в вашей кодовой базе с глобальным состоянием и без него и сравнить их с частотой инцидентов в тикетах JIRA» или что-то в этом роде.

Кто-то в вашей команде потребовал, чтобы вы использовали библиотеку или API, отличную от той, которую вы выбрали, из-за якобы «лучшей производительности»? Это вас не удовлетворяет?

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

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

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

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

А если заглянуть еще дальше, то это открывает широкие возможности для карьерного роста.

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

Пользуйтесь (или не пользуйтесь) этим на здоровье

Когда я писал этот пост, я был настроен философски. На самом деле я писал его во время перелета из Чикаго в Хьюстон, с бокалом вина в руке и отказавшись от Wi-Fi. Поэтому мне оставалось только разговаривать со стюардессами (я сижу в первом ряду, так что они здесь крутятся) и вспоминать о своей карьере.

Я полагаю, что с этими тезисами можно поспорить, если очень постараться.

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

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

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


  1. Admz
    22.12.2022 14:36
    +5

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


    1. kenbekov
      22.12.2022 14:46
      +7

      А есть доказательства?


      1. GospodinKolhoznik
        22.12.2022 15:08
        +29

        Кокаинум!


        1. akuli
          22.12.2022 19:12

          Это волшебное слово такое?


          1. avitek
            22.12.2022 21:21
            +11

            Это картинка со звуком

            (https://www.youtube.com/watch?v=CDEG5pA9O-Q)


      1. developer7
        22.12.2022 15:14
        +5

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


        1. Portnov
          22.12.2022 15:20
          +39

          Напомнило историю от вузовского преподавателя по программированию. Лабораторная работа: численное вычисление синуса. На турбопаскале. Студент приносит программу, преподаватель смотрит в код и видит там очевидные ошибки. Пытаясь объяснить студенту, почему это всё ерунда, запускает программу, вводит икс — а программа выдаёт верное значение. Вводит другой икс — опять правильный ответ. Ну как так-то, в коде столько ошибок! При внимательном изучении кода оказывается: на последней строчке программы стоит в начале строки 100 пробелов (чтобы выйти за пределы экрана турбопаскаля по умолчанию), а потом написано: writeln(sin(x)).


          1. shai_hulud
            22.12.2022 15:47
            +12

            на последней строчке программы стоит в начале строки 100 пробелов (чтобы выйти за пределы экрана турбопаскаля по умолчанию), а потом написано: writeln(sin(x)).

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


          1. BartonFink
            22.12.2022 23:52
            +5

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


    1. vkni
      23.12.2022 06:06
      +2

      Несложные программы на Хаскеле/OCaml/SML/Clean примерно так и работают — запускаются с первого раза и работают правильно. Никакого тестирования, обычно, не требуется.

      Но это относится, разумеется, только к относительно несложным программам.


      1. 0xd34df00d
        23.12.2022 07:57
        +3

        А сложные программы на агде просто не запускаются.


  1. FollowerOfDarkness
    22.12.2022 14:43
    +7

    "На самом деле я писал его во время перелета из Чикаго в Хьюстон, с бокалом вина в руке и отказавшись от Wi-Fi. Поэтому мне оставалось только разговаривать со стюардессами (я сижу в первом ряду, так что они здесь крутятся) и вспоминать о своей карьере. " - замотивировали, пошел дальше работать


    1. perfect_genius
      23.12.2022 20:56

      А потом самолёт тряхнуло и вино переместилось из бокала на клавиатуру...


  1. Rio
    22.12.2022 14:53
    +20

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


    1. MentalBlood
      22.12.2022 15:21
      +4

      когда ты всерьёз любишь кодить

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


      1. RH215
        22.12.2022 19:04

        Никогда, кстати, не понимал тех, кто любит кодить ради кода. Это как любить класть кирпич вместо того, чтобы любить строить дома.


        1. goodbear
          22.12.2022 22:29
          +8

          Назовем это парадоксом Тетриса )


          1. 5oclock
            23.12.2022 00:25
            +2

            В Тетрисе как-раз цель - удалять кирпичи :)


            1. elFurion
              25.12.2022 11:27

              Или класть кирпичи так долго, как это возможно. Как посмотреть на это :)


    1. radtie
      22.12.2022 15:45
      +16

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

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


      1. vvbob
        23.12.2022 00:23

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


        1. BugM
          23.12.2022 04:08
          +1

          Тут по разному бывает. Иногда оно правда под запас и правда нужно.

          Допустим есть какой-то модуль http клиента. Там есть метод PATCH со своими особенностями реализации. Используется он? Вероятно нет. Нужен? Точно да. Удалять не надо.


          1. vkni
            23.12.2022 06:09

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


          1. vvbob
            23.12.2022 14:17

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


          1. ITurchenko
            23.12.2022 15:52

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

            Еще и перед начальством за строки кода в день отчитаться можно будет. Плохо что ли? Хорошо!


          1. 0x131315
            25.12.2022 02:34

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


            1. BugM
              25.12.2022 02:44

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

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

              История гит это слабая отмазка. Там его найти примерно невозможно в реальной жизни.


        1. vkni
          23.12.2022 06:08
          +1

          После введения VCS это его не должно беспокоить — как только они понадобятся, он всегда может их взять.


          1. vvbob
            23.12.2022 14:19

            Примерно это я ему и говорил, он согласился, но явно остался недоволен в итоге, хоть лишний код мы в итоге и почистили :)


    1. un1t
      22.12.2022 17:24
      +4

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


    1. vkni
      23.12.2022 08:24

      Но как же трудно бывает объяснить это новичкам.

      Есть такое понятие ИКР. :-)


    1. vitaly_il1
      23.12.2022 08:31
      +1

      Как кто-то сказал - "лучший код это ненаписанный код".


  1. staticmain
    22.12.2022 15:03
    +7

    printf("Hello World!");

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


    1. vesper-bot
      22.12.2022 15:50
      +6

      Это специально сделано, чтобы показать, что что-то может пойти не так.


    1. GospodinKolhoznik
      22.12.2022 16:28
      +10

      Символ переноса это пассив


      1. GoodDay-lab
        22.12.2022 23:52
        +1

        Два пассива :)


      1. maxwolf
        23.12.2022 00:53
        +2

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


  1. korvint
    22.12.2022 17:01
    +1

    Программирую с 1991-го. Подписываюсь под каждым утверждением автора!

    Как это - приятно, когда умные люди так хорошо формулируют твои мысли!


  1. ulovka22
    22.12.2022 17:27
    +2

    если принять модель, что Total - это PretaxTotal + Tax, это приведет к постоянным вычислениям в запросах, где требуется Total


    1. kspshnik
      24.12.2022 20:14

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


  1. odinesnik
    22.12.2022 19:11
    +1

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


    1. blueboar2
      23.12.2022 19:07
      +2

  1. mvv-rus
    22.12.2022 19:22
    +16

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

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

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

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

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

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


    1. pintor
      22.12.2022 23:52
      +3

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

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

      Вот я считаю, что 100% использую TDD в варианте "Outside In".

      Это когда пишутся только высокоуровние тесты, которые тестируют пользовательские сценарии.

      Вот пример стандартного теста (пример на python с pytest, т.к. на java или чем-то подобном будет лишний бойлерплэйт):

      def test_answer_to_question(client, pub_sub_mock):
          # given
          question = Question.objects.create(...)
          
          # when
          url = f"/api/v1/questions/{question.id}"
          response = client.put(url, { "answer": "some answer" })
      
          # then
          assert response.status_code == 200
          question.refresh_from_db() # тут перечитываем вопрос из БД
          assert question.answer == "some answer"
          pub_sub_mock.assert_called_once_with({
              "event": "question.answered",
              "id": question.id
          })

      Тест делает следующее:

      • приводим систему в некое начальное состояние

        • сохраняем в БД объект Question

      • выполняем над ней определенное действие

        • отвечаем на вопрос делая PUT запрос в API

      • проверяем только сайд-эффекты

        • API вернул код 200

        • свойство объекта Question изменено в БД

        • Event был отправлен во очередь сообщений

      На последнем проеке таких тестов было процентов 95, и покрывали 100% бизнес сценариев. Остальные 5% тесвов покрывали разные технические штуки.

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

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


      1. mvv-rus
        23.12.2022 00:25
        +2

        А разве это - тот самый модульный тест, который в TDD должен использоваться по фэн-шую?


        1. pintor
          23.12.2022 01:10
          +9

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

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

          По моему мнению TDD — это когда сначала тест, потом код. И все, больше нет никаких дополнительный условий.

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


          1. euroUK
            24.12.2022 09:00

            Только это не TDD


    1. nronnie
      24.12.2022 03:49
      +1

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

      Это не так, хоть я и не адепт прямо-таки "ортодоксального" TDD "сначала тесты". TDD навязывает писать слабо связанный (coupled) код, который как раз и позволяет разрабатывать и тестировать модули в любой последовательности и независимо друг от друга.


  1. shasoftX
    22.12.2022 23:08
    -1

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

    Работаю в SAP R/3

    Система позволяет писать SQL команды в ABAP. Есть два подхода выбирать записи из нескольких таблиц

    1. Выбирать последовательно. т.е. выбрали из A, потом по списку записей из A выбрали данные из Б, потом из В и т.д.

    2. Сделать один мега-запрос через join

    Вот только когда поступает от заказчика вопрос вида: а почему не выбирается такая та строка из такой-то таблицы по таким условиям, то разработчиков, которые выбрали способ 2 хочет просто убить. Да, вы умный разработчик, вы можете написать JOIN с 2+ таблицами в одном запросе. Но вот чтобы потом определить это "почему" приходится раскручивать этот запрос вручную. А если там ещё и данных много, то этот процесс затягивается.

    А при пункте 1 это делается достаточно быстро.

    Поэтому меньше кода - не всегда лучше.


    1. ap1973
      22.12.2022 23:58
      +6

      Может я что-то не понял, с SAP не знаком, но вы серьезно считаете, что выполнить 1 + А запросов лучше чем 1? А если есть В, то вообще жесть. Про Г я молчу. Или в САПе какой то другой SQL?


      1. v2kxyz
        23.12.2022 01:04
        +1

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

        P.S. Еще есть нюанс, в SAP все "старые"(т.е. 90%) названий таблиц и полей "обфусцированы", т.е. имеют длину в 4-5 символов и это не сокращение на английском, а больше похоже на рандомный набор букв (что например по вашему может значить поле loekz?). Это несколько затрудняет чтение запросов, если с конкретным модулем не сильно часто работаешь.


      1. shasoftX
        23.12.2022 06:18
        +1

        выполнить 1 + А запросов лучше чем 1?

        Да. Особенности работы в SAP.

        Если запрос выполняется меньше 30 секунд, то особой разницы в выполнении 1-го или 1+A запросов нет.

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

        При этом удобно потом в отладчике искать "почему не выбралось нужное". А вот если у вас 1 запрос, который больше 10 минут работает (а это распространенная ситуация) и тащит сразу из 1+A таблиц, то поиск ответа становится реально болью. Так что более длинный код помогает потом в сопровождении.

        Или в САПе какой то другой SQL?

        Просто там объемы данных большие. К примеру была ситуация когда запрос падал в дамп потому что что был исчерпан лимит времени ответа от сервера БД. Вызывалась команда вида "DELETE FROМ table WHERE ..." и эта команда через 20 минут роняла сервер приложений в дамп потому что это был предельный лимит выполнения команды на сервере БД. А сервер БД просто не успевал за 20 минут выполнить команду. Пришлось разбивать её по полю на несколько отдельных команд.


        1. euroUK
          24.12.2022 09:10

          Много данных, плохой код или плохая БД?

          в общем случае в MS SQL, delete при удалении существенного количества записей падает в табличную блокировку, что на активной рабочей системе приводит к мертвому подвисанию .

          Секреты как этого избежать тоже известны, но тут нет иного SQL, просто здравый смысл


          1. shasoftX
            24.12.2022 11:55

            В данном случае много данных. И в большинстве случаев это основная причина тормозов в SAP.


            1. euroUK
              24.12.2022 12:21

              Много это сколько?


    1. mironchenko
      23.12.2022 11:04
      +1

      Не нужно убивать разработчиков. Нужно уметь работать с SQL :)
      Если серьезно, то однозначно JOIN c N таблицами единственно правильное решение.


      1. shasoftX
        23.12.2022 11:14
        +4

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

        В ABAP разница между 1 и 1+N запросом несущественна. Само собой если это не делается в цикле.

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


        1. nronnie
          24.12.2022 04:19
          +1

          Это вот еще одна догма со времен двузвенных систем, серверов на 486 процессоре и коаксиальных сетей: "не дай бог сделать лишний запрос или вытянуть из БД хоть одну ненужную запись или колонку". Миллион лишних записей зря тянуть в приложение, конечно, не стоит, но сейчас часто практичней забрать из БД в разумных объемах что-то ненужное и обработать уже в приложении, чем лезть из кожи вон обязательно засовывая всю логику запроса в одно SQL выражение.


          1. euroUK
            24.12.2022 11:05
            +1

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


            1. nronnie
              24.12.2022 16:12

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


              1. ap1973
                24.12.2022 17:52

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


                1. shasoftX
                  24.12.2022 18:46

                  Не знаю как в 1C, но в SAP нет никакой консоли. Вы пишите в системе разработки (где данных может и не быть вовсе), потом несете в тестовую систему (где данные тоже могут только примерно соответствовать реальным), а потом в продуктив. И частенько бывает, что то, что у вас в разработке летало, в тесте немного притормаживает, а в продуктиве просто становится колом. Потому что в продуктиве данные вот такие, на которые запрос не был готов.

                  p.s.знаю что иногда делают хаки для выполнения запросов непосредственно даже в продуктиве. Но обычно за такое головы отрывают, если обнаруживается.


                  1. ap1973
                    24.12.2022 18:49

                    Как страшно жить, сочувствую


          1. vvbob
            24.12.2022 11:11

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

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

            Часто все эти переборы пишут не от большого ума/опыта, просто по другому не умеют.


  1. vvbob
    23.12.2022 00:17
    +7

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

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


    1. Rio
      23.12.2022 09:55
      +1

      Вот да, всё так и есть. Я поэтому стараюсь новичкам привить мысль, что в процессе разработки всегда нужно задумываться — а зачем именно мы делаем то, что делаем? Какова цель написания данного кода? Но всё равно, не всегда получается достигнуть понимания. Даёшь, допустим, несложную задачку на пару часов (ну там, скриптик написать, перекладывающий поток данных из COM-порта в сокет). Через неделю интересуешься, как там дела; отвечают, что нужно ещё полгода разработки ) Ээ, окей, а зачем? А вот, чтобы построить универсальную расширяемую архитектуру, красиво всё на паттернах запилить, и всё в таком духе... В очередной раз пытаешься объяснить, что здесь всё это совершенно не нужно, потому что задача вообще не в этом, а нужен простой скриптик на пол-страницы. На этом моменте, бывает, даже обижаются, что я ничего не понимаю и рушу их идеалы )

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


    1. Sau
      23.12.2022 11:10
      +2

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

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

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


      1. vvbob
        23.12.2022 14:11

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


  1. AlexunKo
    23.12.2022 05:28

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


  1. alien1900
    23.12.2022 07:32
    +4

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

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


    1. Soukhinov
      23.12.2022 12:50

      Думал, что если посмотрю оригинал, то станет понятнее. Не стало.


    1. arheops
      23.12.2022 15:36

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

      Именно про этот кусок могу сказать, что очень часто копи-паст более читаем и часто при изменении одного куска другой кусок с него скопипасчен НЕ ПОДЛЕЖИТ изменению. А елси подлежит — да надо создать метод.


  1. RemiZOffAlex
    23.12.2022 10:47

    Обломов - это такая субъективщина


  1. vadimr
    23.12.2022 11:47

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

    Что ему тут не нравится? А если нет файла конфигурации, или в нём нет искомого значения?


  1. Soukhinov
    23.12.2022 12:39

    По поводу объёма кода давно решил для себя так: «Мой код — мой враг». Или, другими словами, код — это необходимое зло для решения задачи. А количество зла надо минимизировать.

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

    Помимо нагрузки на память большой объём кода снижает скорость дальнейшей разработки. Реализацию многих функций можно условно разделить на 2 этапа: 1) рефакторинг имеющегося кода для того, чтобы новая функция реализовалась максимально просто и естественно 2) собственно реализация новой функции. Т.е., грубо говоря, новую функцию можно реализовать за день, но на подходящей для этого кодовой базе. А сделать кодовую базу подходящей — это рефакторинг, который может занимать несколько дней. И вот время время этого рефакторинга как раз связано с объёмом кодовой базы (больше кода — медленнее рефакторинг).


    1. arheops
      23.12.2022 15:39
      -1

      Размер кода не важен. Важна его читаемость. Если у вас есть код, который занимает три строчки, и вы на нем зависаете на минуту и другой в 10 строчек — который вы понимаете за 10 секунд, то какой вариант вы выберете для дальнейшего изменения через 5 лет?


      1. Soukhinov
        23.12.2022 16:20

        Речь про объём кода шла «при прочих равных условиях».


  1. bondeg
    23.12.2022 22:55

    Ну да, зачем нам быстрая работа приложения, зато денормализацию БД не провели и потешили своё эго.)

    В остальном советы уровня "прочти любую книгу о программировании".


  1. cudu
    23.12.2022 23:27
    +1

    Немного надоедает слышать про копипасту и изменения.

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

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


    1. nronnie
      24.12.2022 03:30

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


  1. DungeonLords
    24.12.2022 11:50

    printf("Hello World!"); 

    Как вы думаете, сколько всего может пойти не так?

    • Не станет ли эта волшебная строка впоследствии проблемой?

    Респектую статье и привожу пример 2019 года, когда более года тушили corrupt memory, который проявил себя из-за sprintf(). Я кстати так и не понял, точно ли этот баг окончательно поправили?..