Читаю осенью: Прагматичный программист

Пост создан 2023-11-06

Как-то раз я проснулась и поняла, что сегодня и далее я буду становиться очень-очень хорошим программистом. После недолгого изучения книжного Реддита, я остановилась на «The Pragmatic Programmer: From Journeyman to Master» от Дэвида Томаса и Эндрю Ханта и пошла просвещаться.

О чем книга

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

Развиваемся

Уже в 1999 году Дэвид и Эндрю понимали, что технологии не будут ждать пока вы выйдете на пенсию. В «Chapter 1. A Pragmatic Philosophy, Invest Regularly In Your Knowledge Portfolio» советуют:

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

Пробуем идеи

В «Chapter 2. A Pragmatic Approach, Tracer Code versus Prototyping» описываются методики тестирования и демонстрации идей.

Tracer Code, aka трассирующие пули 1 – так называемый скелетон приложения. Скелетон нужен, чтобы связать все части и показать демо заказчику. Но это не прототип: прототип можно выбросить, когда идея будет оттестирована, а вот «пуля» еще послужит в дальнейшей разработке.

Активнее всего в работе мне помогает прототипирование.

Пример прототипирования

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

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

Дано: реакт, микрофронтенд, меню и главная страница в отдельных модулях.

Доказать: можно ли сократить разработку за счет компромисса?

Я накидала уродливый Vanilla JS + HTML/CSS прототип, где цветными блоками обозначила все секции в текущем дизайне. Копировала руками существующие стили, чтобы воссоздать старый дизайн, и сверху переписывала их новыми, согласно моей задумке.

Макет выглядел как Chanel, моя предлагаемая реализация – Walmart. Однако, мы ударили по рукам, потому что time-to-market сократился на пару недель. Все остальные улучшайзинги попали в бэклог.

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

GUI плохо

A benefit of GUIs is WYSIWYG—what you see is what you get.
The disadvantage is WYSIAYG—what you see is all you get.

The Pragmatic Programmer

Если кто и говорит, что графические интерфейсы не нужны, это не я. Я люблю просматривать изменения в файлах перед коммитом. Однако, в «Chapter 3. The Basic Tools, Shell Games» авторы уверены, что необходимо развивать навык использования консоли, и противопоставляют различные выкладки с командами шелла gui-клиентам.

Пример: В каких файлах с расширением jpeg не было изменений за последнюю неделю?

Shell:

bash
find ~/Downloads -name '*.jpeg' -mtime +30 -print

GUI: Ищем в поиске *.jpeg файлы. Кликаем на фильтрацию по дате. В фильтрах выставляем начальную и конечную дату.

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

Дебажим

В «Chapter 3. The Basic Tools, Psychology of Debugging» авторы вспоминают про коллективную ответственность. Неважно, кто сделал баг: ты или твой сосед, важно, чтобы он был устранен.

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

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

Определяем сложность

В «Chapter 6. While You Are Coding, The O() Notation» приводится ПРИМЕРНЫЙ чек-лист определения сложности алгоритма.

  • O(n), если используется простой цикл от 1 до n (Simple loops);
  • O(m x n), если циклы вложены друг в друга, где m и n – пределы циклов (Nested loops);
  • O(lg(n)), если алгоритм каждый раз располовинивает сет из данных и продолжает работать с его частью (Binary chop);
  • O(n lg(n)), если алгоритм разделяет сет данных и продолжает отдельную работу с его частями независимо (Divide and conquer);
  • O(n!), если алгорим оценивает не только сет данных, но и их комбинацию. Ака поиск пути, шахматы и так далее.

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

И, классика: никаких. преждевременных. оптимизаций. Никогда.

Рефакторим

На одной из работ программисты из соседних команд использовали фразу «Бизнес хочет/не хочет» по любому поводу.

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

В «Chapter 6. While You Are Coding, When Should You Refactor?» нашли контр-аргумент для сочувствующих бизнесу. Рефакторинг – это рост. Плохой код можно «прооперировать» сейчас, а не тогда, когда он разрастется и пустит корни. Это будет дольше и дороже.

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

Ну и классический совет: нужно разделять разработку фичей и рефактор старого кода в своих мерж-реквестах.

Пишем Доку

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

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

В «Chapter 7. Before the Project, The Specification Trap» даются советы по написанию доки.

Формат

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

Напишите документацию, которая научит кого-нибудь, как завязывать шнурки.

The Pragmatic Programmer

Чему нас учит упражнение? Что без картинок, схем и видео порой не обойтись.

Избыточность аналитики

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

Что будете делать?

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

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

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

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

Общаемся

It's a mistake to think that the activities of a project – analysis,

design, coding, and testing – can happen in isolation. They can't.

The Pragmatic Programmer

Пожалуй, напоследок порассуждаю о «Chapter 7. Before the Project, Don't Be A Slave to Formal Methods» и командах.

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

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

Дизайнеры общаются с дизайнерами, разрабы с разрабами. Количество задач увеличивается. Время проведения общих встреч стремится к бесконечности. И тогда приходит ФОРМАЛИЗАЦИЯ.

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

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

Авторы подчеркивают, что расслоение команды приводит к ситуации «мы vs они», «дизайнеры vs разрабы», что позже выливается в плохую коммуникацию.

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

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

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

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

Заключение

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

Странно осознавать, что за 25 лет существования книги все еще встречаешься с тем, что считается «плохими практиками».

Рекомендую к прочтению, если вас не смущают периодические выкладки С++ кода и восхищение PERL'ом.


Footnotes

  1. Пули, которые оставляют за собой след. Пример

  2. Логирование из PHP