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

Подход к задачам


Основная часть моей работы – разбираться с тикетами, и я до сих пор продолжаю совершенствоваться в этом деле. Вот несколько вещей, которые я открыл для себя в процессе.
  • Разные задачи, проекты и команды требуют разных подходов. Например, сделать пейсмейкер без автоматических тестов было бы безответственным решением – кто-то может от этого пострадать. И вместе с тем, глупо изводиться по поводу автоматических тестов на геймджеме, куда вы отправились на выходных. Содержание понятия «хороший код» меняется в зависимости от контекста, и нужно адаптировать свой подход под конкретную ситуацию.
  • Делайте марш-броски. Бывает, что я ставлю себе цель довести какую-то функциональность до готовности в кратчайшие сроки, пусть даже срезая углы где только можно, с кодом ужасного качества и TODO на каждом шагу. Когда у меня появится что-то рабочее, тогда и буду приводить всё в должный вид. Я пришел к выводу, что это хороший способ обозначить для себя проблемные зоны, а также неплохой путь к ускорению процесса разработки. На эту тему есть статья «Выбросьте первый набросок кода».
  • Если я бьюсь головой об задачу и никак не могу сдвинуться с мертвой точки, значит, необходимо оторваться от нее на какое-то время.
  • Прежде чем начать работу над сложной задачей, я задаю себе вопрос: «А что если вообще этого не делать?» Как правило, вопрос оказывается глупым и выполнять задачу все-таки приходится. Но примерно в пяти процентах случаев я осознаю, что определенную часть работы можно спокойно пропустить.


Проектирование приложений


Мне никогда не приходилось выстраивать с нуля по-настоящему крупную систему, но я проектировал весьма солидные части функциональности, а также создавал приложения средних размеров. Вот чему я научился по ходу дела:
  • Важно понимать разницу между простотой и легкостью. Простота – это противоположность сложности. Легкость означает нечто другое, она связана с привычностью. Разделение этих двух понятий не раз помогало мне создавать более простые программы (хотя до идеала в этом отношении мне еще далеко). См. также статью «Как сделать простое легким».
  • Недопустимые состояния следует делать непредставимыми. Если удастся спроектировать систему так, чтобы предотвратить возникновение невалидных данных или типов, это устранит один из основных источников багов. Немного возни с системами типов или схемами данных обычно окупается с лихвой.
  • Тестируемость по сути своей сводится к модульности.
  • Приверженцы функционального программирования, возможно, слишком о себе мнят, но при этом часто бывают правы. С объектно-ориентированным программированием добиться хороших результатов сложнее, а с функциями, которые оперируют неизменяемыми данными – проще.


Мелочи, связанные с кодом


Вот те убеждения, которые я беру с собой в редактор кода:
  • Существует множество способов документировать код. Перечислю несколько вариантов: подробная документация, удачные названия для функций и переменных, разбивка фрагментов кода на проименованные функции, комментарии, сообщения в логах.
  • Используйте утвердительные формулировки при именовании переменных. Названия переменных типа use_widget более удобны в работе, чем что-то вроде skip_widget, так как с их помощью можно избежать двойного отрицания. Как-то раз я видел, как вызванная последним путаница образовала брешь в защите.
  • Старайтесь не менять названия идентификаторов. Если у меня есть переменная с названием в духе photo_id, то следует называть ее photo_id во всей кодовой базе, даже если это id выглядит уместным не во всех контекстах.
  • Подумайте о том, чтобы использовать перечисляемый тип данных вместо булевого. Это может дать больше ясности и расширяемости. Этот вопрос разбирается в статье «Не используйте булевый тип данных».
  • Learn X in Y minutes («Освойте X за Y минут») – отличный ресурс для тех, кто хочет по-быстрому изучить основы того или иного языка программирования (а также некоторые другие темы).
  • Не стоит слишком ломать голову над кодами состояния HTTP. Например, между кодами 401 “Unauthorized” и 403 “Forbidden” действительно существует разница, но эти различия никогда не оказывали реального внимания на мою работу – компьютерам, как правило, что одно, что другое. Иногда встречаются и важные различия, скажем, между 301 “Moved Permanently” и 307 “Temporary Redirect”, но такие случаи обычно очевидны. Если мне требуется больше минуты, чтобы выбрать подходящий код состояния, то это уже повод для беспокойства.
  • Прежде чем тянуться к чему-то новому, лучше попытаться обойтись теми инструментами, которые уже у меня в распоряжении. Вместо того чтобы устанавливать навороченный пакет Zsh, стоит проверить, не выйдет ли прописать $PROMPT и горя не знать. Вместо того чтобы устанавливать новую зависимость, лучше посмотреть, не найдется ли в стандартной библиотеке чего-то подобного.
  • Калибровка настроек дает ограниченные преимущества. Кастомизировать дотфайлы, искать идеальный редактор кода, настраивать среду разработки – всё это очень весело. Но мне не кажется, что итоговый результат экономит так уж много времени. Есть и в самом деле отличные инструменты, которые здорово мне помогли, к тому же копаться в настройках – верный способ разобраться, как работает система. Но подбор идеальной цветовой схемы – обычно не самая продуктивная трата времени, и я не замечал особой корреляции между уровнем разработчика и степенью его вовлеченности в характеристики редактора кода. Хотя дело все равно увлекательное, и я частенько этим занимаюсь.


Общение


Ах да, насчет окружающих.
  • Проблема «разработчика-одиночки». Когда программа создается усилиями одного-единственного разработчика, впоследствии поддерживать ее оказывается для других людей непростым делом. Похоже, эта закономерность срабатывает для всех, включая и меня самого. Я уже писал подробнее на эту тему.
  • Упрощенные мнения обычно оказываются неверными. Например, от некоторых слышишь заявления вроде «PHP – отстой!», да вот только на PHP держится практически весь интернет, а у современного PHP есть немало полезных возможностей. Люди, которые безапелляционно продвигают какой-либо подход, например разработку через тестирование, как правило, оказываются правы в одних ситуациях и неправы в других. Я по большей части предпочитаю работать с программистами, которые видят нюансы и понимают необходимость компромиссов, да и сам тоже пытаюсь стать таким программистом.
  • Всё всегда оказывается сложнее, чем ожидаешь. Нужно соблюдать осторожность, чтобы не принизить значимость чьей-то работы, ведь она, вероятно, намного труднее, чем кажется со стороны. Создавать прототипы всегда гораздо проще, чем делать что-то на уровне продакшна.


Карьера и общий курс


Полагаю, наибольшую важность имеют те убеждения, которые касаются общего курса.
  • Самые важные вопросы лежат вне технической сферы. Мне попадался отличный материал с этой мыслью несколько лет назад. Центральное место занимают проблемы, связанные с «реальной жизнью». То, что я создаю, помогает или вредит людям? Здоровая ли обстановка у меня в команде?
  • Набивать новый код – это в большинстве случаев самая простая часть работы. Куда больше сложностей возникает с чтением чужого кода, расстановкой приоритетов, коммуникацией, взаимоотношениями в команде и так далее.
  • Делать что-то бессмысленное – отличный способ научиться чему-то новому. Не всё должно иметь конкретное назначение – хотя случается и так, что назначение находится само по себе! Например, я потратил кучу времени на написание кастомного PNG-энкодер для своего побочного проекта. У меня и в мыслях не было, что он может где-то еще пригодиться. Однако буквально через несколько месяцев мне понадобилось по работе написать код для распознавания анимированных данных PNG, и это оказалось плевым делом – я уже в точности знал, что именно для этого требуется.
  • Важно понимать, для кого создаешь продукты. У человечества серьезные проблемы. Изменения климата, войны, авторитарные правительства, геноцид, бедность, неравенство, слежка – это еще неполный список проблем. Мне не следует тратить время на создание программ для тех, кто приносит вред окружающим. Мне не следует тратить время на создание программ ради того, чтобы начальник разбогател (даже если начальник – это я сам). В мире много работы, где можно применить свои навыки на благо людям… вот там мне по возможности и следует работать.


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

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


  1. FlyingDutchman2
    26.07.2024 11:19

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

    Я тут ничего не понял. Не мог ли бы мне кто-нибудь объяснить, что он имел в виду?


    1. economist75
      26.07.2024 11:19

      use - да, используй (утвердительная формулировка)
      skip - нет, не используй (отрицательная формулировка)


      1. 0Bannon
        26.07.2024 11:19

        use_skip_widget


        1. delphinpro
          26.07.2024 11:19
          +1

          я здесь читаю как "Использовать виджет с названием 'skip'"


        1. vladshulkevich
          26.07.2024 11:19

          use_skiped_widget


      1. FlyingDutchman2
        26.07.2024 11:19

        Что такое use и skip, понятно. Но чем плоха отрицательная формулировка skip_widget и причем тут двойное отрицание?


        1. delphinpro
          26.07.2024 11:19
          +3

          if (use_widget) {} если использовать
          VS
          if (!skip_widget) {} если не неиспользовать / если не пропускать

          во втором случае лишняя когнитивная нагрузка


          1. FlyingDutchman2
            26.07.2024 11:19

            Да, в этом что-то есть


          1. amphasis
            26.07.2024 11:19

            Тут тоже можно поспорить:

            if (!use_widget) {
              return;
            }

            vs

            if (skip_widget) {
              return;
            }


            1. delphinpro
              26.07.2024 11:19
              +1

              в этом случае читается одинаково:
              если не использовать
              VS
              если не использовать / если пропустить

              Нет двойного отрицания


          1. yappari
            26.07.2024 11:19
            +1

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

            inline dont(bool flag) { return !flag; }

            Получается вполне себе литературное dont(skip_widget).


            1. delphinpro
              26.07.2024 11:19
              +1

              дело же не только в этой переменной. полно и других примеров
              enabled_plugin / disabled_plugin например. !disabled_plugin - двойное отрицание - "не неактивный плагин"


  1. piton369
    26.07.2024 11:19
    +2

    Годный материал. Ссылки так вообще огонь! А нет ли таких же подходов к поиску информации и чтению документации? Например, я сталкивался с двумя крайностями при чтении документации.

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

    Второе когда документация выглядит так:
    Функция вывод:
    Выводит на экран.

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

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


  1. HADGEHOGs
    26.07.2024 11:19

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

    Result:Bool;

    ErrorCode:Int;

    ErrorDescription:String;

    Data:Object; - полезная нагрузка

    ExecuteTime:Int;


  1. oufucom
    26.07.2024 11:19
    +2

    Видимо пейсмейкер это электрокардиостимулятор? Если это так, лучше заменить на пейсмейкер на кардиостимулятор.