Четыре мо­даль­но­сти написания кода

Опубликовано 9 марта 2021 г.

Обновлено 10 марта 2021 г.

Программирование

Я достаточно часто переключаюсь между разными модальностями, или режимами написания кода.

Промышленное программирование

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

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

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

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

Творческое программирование

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

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

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

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

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

Программирование библиотек

Написание библиотечного кода, третья модальность, перенимает многие свойства творческого программирования, но обязывает разработчика соблюдать больше условий. Код должен быть производительным и надёжным, а ещё обратно совместимым и следующим принципам defensive programming — учитывать максимально возможное количество edge cases и предсказуемо вести себя (и ломаться) при “мусоре на входе” и прочих странных обстоятельствах: когда входные данные не помещаются в памяти, если операция прервалась в процессе выполнения (транзакции в БД) или кончилось место на диске, когда функции библиотеки вызываются асинхронно или параллельно, и возможны race conditions.

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

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

Программирование в стартапе

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

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

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

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

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

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

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

Читать дальше