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

Код Хабра день за днём впитывает в себя время, мысли и чаяния многих людей. А этому коду, на минуточку, уже более 10 лет. За это время он оброс множеством знаний, в том числе и тайных, добавилось множество функций – в том числе и полезных, а места c bus factor = 1 – уже не “эка невидаль”, но вполне конкретные люди с ответами на часто задаваемые вопросы.

В такой ситуации сложно мечтать о чем-то большом и светлом. Можно, конечно… но очень больно. Но мечтать то хочется, и чтоб работа приносила удовольствие тоже хочется, и развития для проекта и себя – тоже хочется. 

Меня зовут Антон Каракулов, я тимлид команды бэкенд-разработки Хабра. Хабр стартовал в 2006 году, и за всё время здесь поработало, наверное, команд пять. Мне посчастливилось быть в двух из них, забегал в третью.

Все события утрированы, а совпадения — беспочвенны.

Четыре года назад я вернулся на Хабр и стал собирать новую бэкенд-команду. Главная проблема, с которой я столкнулся, — когнитивная нагрузка при работе с кодом. Этот код не всегда был логичным, простым и вообще актуальным — и это для человека, который был с ним знаком. Застарелые наслоения логики приходилось раскручивать, как неберущиеся вопросы из «Что? Где? Когда?». Казалось, для новых людей это будет ещё той охотой на ведьм.

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

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

Теперь, по прошествии времени, вот какие выводы можно сделать.

Соблюдай статус-кво

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

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

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

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

Следуй гайдлайнам. Стандартизируй

Стандартизация и формализм — наше всё. Это палочка-выручалочка, которая приходит на помощь, когда при чтении кода устал размениваться по мелочам и пытаешься сразу погрузиться в суть. 

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

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

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

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

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

Думай командно

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

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

Скоро новая команда начала потихоньку собираться, и мне показалось, что всё это время я просидел в «башне из слоновой кости». С новым кодом никто, кроме меня, не работал. Ревью он не проходил. Документацию люди видели впервые. Но всё обошлось — всем всё было понятно. Это была победа.

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

  • Понятность важнее правильности. Когда ты что-то не понимаешь, становится уже неважно, правильно это сделано или нет.

  • Поведение важнее состояния. Или: ясные интерфейсы важнее понятной реализации. Если представляешь, как с этим работать, то вопрос «почему?» не возникнет.

    Чем сложнее, тем декларативнее. Когда начинается путаница, порой важнее зафиксировать, ЧТО нужно сделать, а КАК — оставить на потом.

  • Упрощай. Думай о сложности — старайся её уменьшить. Уровни абстракций — на последнем месте.

  • Блюди контекст. Пока ты в рамках контекста — ты в безопасности, всё остальное неважно.

Пиши тесты

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

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

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

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

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

Рефакторить нужно

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

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

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

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

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

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

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

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

  • Следи за контекстом. Не надо браться переписать сразу несколько компонентов за один раз. Лучше меньше да лучше.

  • @deprecated должен быть удалён. Держи такой код ровно столько, сколько он реально нужен для работы кода. Ни больше, ни меньше. Соблюдай чистоту.

Пиши документацию, читай документацию

У документации есть удивительное свойство: когда она есть — ты её не замечаешь, а когда нет — страдаешь.

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

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

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

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

  • RTFM. Да-да, банально. Если найти так и не получается, то спроси в команде. В тебя или кинут ссылкой, или всем будет ясно, чего не хватает.

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

  • Абстракция — это интуиция. Для реализаций на базе абстракций иногда нужен толчок в виде описания концепции, чтобы это выстроилось в сочную картинку. Заодно это тест на её жизнеспособность.

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

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

  • Анонсируй любые изменения. Обязательно. Важная часть работы с документацией — её внутреннее продвижение. Это решает сразу несколько задач: сбор обратной связи на тему понятности, обмен знаниями, актуализация предметной области. 

  • RTFM. Ах да, об этом уже было.

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

Общайся

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

Вам знакомо понятие «дух стартапа»? Это когда все со всеми общаются, голову пучит идеями, возникает ощущение будущего «тут и сейчас», все на одной волне и понимают друг друга с полуслова — и тебя переполняет энергия и задор. Именно такое было у меня впечатление, когда я оказался в Хабре впервые. Мне такое нравится.

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

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

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

Вместо заключения

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

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

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

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

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


  1. avshkol
    00.00.0000 00:00
    +14

    Статью бы украсили примеры кода "было-стало"... ;)


    1. brutto Автор
      00.00.0000 00:00
      +3

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


      По поводу "было/стало" могу сказать что удалось уменьшить сложность (cyclomatic complexity) с ~18 (для старого) до ~3.5 (для нового). А добились этого при помощи следующих шагов:


      • с пристрастием подошли к разделению зон ответственности нашего текущего MVC-паттерна
      • для уровня M (model) применили луковую архитектуру (onion architecture)
      • внедрили в разработку принципы DDD (в том или ином виде)


    1. Didimus
      00.00.0000 00:00

      Ожидание-реальность


  1. speshuric
    00.00.0000 00:00
    +2

    Статья хорошая, но что за "кодоэйджизм" в заголовке? 10 лет для года не возраст - даже в "новых" ЯП типа Rust/Go/Kotlin есть уже код такого возраста (и не факт, что плохой). А в крупных компаниях и проектах и код постарше вполне себе трудится. Что-то из этого, конечно, надо переписать/причесать/документировать, что-то на вид от вчера написанного и не отличить. Причина плохого кода совсем не в возрасте, что и ваша статья подтверждает.


    1. Parondzhanov
      00.00.0000 00:00

      Человекочитаемость и понятность кода — важная мысль. Пытаясь решить эту задачу, я разработал язык ДРАКОН. К языку были предъявлены нетрадиционные требования:

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

      • предоставить пользователю языковые средства, которые заставляют человека мыслить продуктивно;

      • облегчить межотраслевое и междисциплинарное общение между представителями разных организаций;

      • устранить или уменьшить барьеры взаимного непонимания между работниками различных специальностей и профессий;

      • за счёт использования когнитивно-эргономического подхода к проектированию синтаксиса и семантики добиться улучшения качества программного обеспечения по критерию «понятность алгоритмов».

      На Хабре см. посты:



      1. anonymous
        00.00.0000 00:00

        НЛО прилетело и опубликовало эту надпись здесь


        1. vvzvlad
          00.00.0000 00:00
          +1

          Потому что он делится ими в любых местах и уже всех задолбал.


          1. anonymous
            00.00.0000 00:00

            НЛО прилетело и опубликовало эту надпись здесь


            1. vvzvlad
              00.00.0000 00:00
              +3

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

              Мне вчера на корпоративе было психологически сложно держать в себе отзыв на моего начальника. К чему это я? К тому, что когда меня спрашивают сегодня «почему ты начальника вчера матом обругал», ответ «ну мне было психологически сложно» никак не оправдывает меня и ситуацию не исправляет.
              Но и в целом, никто не судит: человек принес ссылку, человек получил минус. Повторять до исчерпания терпения/кармы. Процесс самостоятельно регулируется. Я лишь ответил на вопрос «Почему минусы?»


        1. VladimirFarshatov
          00.00.0000 00:00

          Поддержу. ДРАКОН как раз позволяет визуализировать ТЗ и часто определить "Царскую дорогу", одновременно снижая цикломатическую сложность решения разработчика.


          1. anonymous
            00.00.0000 00:00

            НЛО прилетело и опубликовало эту надпись здесь


    1. brutto Автор
      00.00.0000 00:00
      +1

      Спасибо за замечание. Про "эйджизм" согласен — убрал из заголовка путающее уточнение. Дополнительно во вступлении уточнил что именно имелось ввиду под этими более чем 10 годами жизни кода.


  1. blackibe
    00.00.0000 00:00
    +5

    Я вот не пойму только одного, с каких пор сайт по типу "БЛОГ" стал технически сложным? Что тут сложного? Весь хабр можно сделать за неделю. У вас пафоса будто шаттл космический запускаете в космос...


    1. anonymous
      00.00.0000 00:00

      НЛО прилетело и опубликовало эту надпись здесь


      1. Didimus
        00.00.0000 00:00

        А ещё редактор...


    1. GinoPane
      00.00.0000 00:00

      Видимо, это верхушка айсберга, и так «для души», а на самом деле там рокет саенс. На самом деле было бы интересно реальные кейсы сложности увидеть


    1. anonymous
      00.00.0000 00:00

      НЛО прилетело и опубликовало эту надпись здесь


    1. brutto Автор
      00.00.0000 00:00

      А вы верно подметили по поводу космического корабля. Правда для меня, космический корабль Хабра уже создан и запущен. Своей задачей вижу тут наладку процесса безболезненного обслуживания и модернизации этого корабля еще в течение хотя бы лет 20-30. =)


  1. ChVI-dev
    00.00.0000 00:00
    +1

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


    1. anonymous
      00.00.0000 00:00

      НЛО прилетело и опубликовало эту надпись здесь


  1. anonymous
    00.00.0000 00:00

    НЛО прилетело и опубликовало эту надпись здесь


  1. AlekseiVB
    00.00.0000 00:00

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