Как стать программистомКарьераПереводы

Искусство быстрой разработки

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

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

  1. Длинное витиеватое вступление
  2. Измеряйте то, как Вы тратите своё время
  3. Прекратите многозадачность
  4. Цепочки задач
  5. Делайте вещи один раз
  6. Ищите и устраняйте точки замедления
  7. Сначала структурируй, затем полируй
  8. Следите за будущим
  9. Шумите
  10. С ног на голову
  11. Комментарии к статье

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

0. Длинное витиеватое вступление

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

Соблазнительно приписывать эту тенденцию поведению Негативной Нелли [примечание: английский фразеологизм Negative Nellie, описывающий человека, видящего во всём только отрицательные стороны и воспринимающего мир только в негативном ключе], но я считаю, что её причины лежат глубже; Я обвиняю знаменитую басню о Черепахе и Зайце — историю, в которой эксцентричный заяц и целеустремленная черепаха соревнуются в беге, пока не приходят к выводу

Медленный, но упорный, побеждает в гонке

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

Во всём виновата басня

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

Быстрый и упорный побеждает в гонке

Эпилог: Зайца и Черепаху растоптали. Их останки переработали в крем-суп и подали его в чашке из черепашьего панциря. (Забавный факт: после доказатльства Чарльзом Дарвином замечательной Галапагосской Черепахи, им же была захвачена пара таких черепах как закуска в дорогу к дому. Факт.) [примечание: «Во время нашего пребывания в верхней области мы питались одним только черепашьим мясом; грудной щит, изжаренный вместе с мясом на нем (подобно тому, как гаучосы приготовляют (carne con cuero), очень вкусен, а из молодых черепах варится превосходный суп; но в других видах это мясо, на мой взгляд, безвкусно.» — из воспоминаний Дарвина о Галапагосах]

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

Но есть и плохие новости…

Мир любит тех, кто двигается медленно.

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

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

Медлительность принята по умолчанию. Медлительность — это просто. Скорость — это сложно.

О чём на самом деле эта статья.

На самом деле эта статья о счастье. Серьёзно. Я использовал слово «быстрой» в заголовке для привлечения внимания тех, кто хотел прийти и сказать мне, что «быстро» — это на самом деле «медленно».

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

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

Это важное чувство и стоящее достижение.

Да, также, если Вы быстры, Вы стоите больше денег, а деньги — корень счастья.

Так давайте же перейдём к рекомендациям.

1. Измеряйте то, как Вы тратите своё время

Суть

Установите себе ПО, которое умеет записывать и составлять отчёт о потраченном времени при работе за компьютером. Это даст Вам мотивацию на сокращение краткосрочных трат времени, которые не окупятся (соцсети, игры, новостные ленты и так далее).

Подробнее

Первый шаг к быстрой разработке состоит в наведении порядка в рабочем времени. А первый шаг в наведении порядка — это измерения.

Есть множество инструментов, которые позволяют Вам отслеживать затраченное время. Я использую RescueTime — довольно неплохое приложение! Оно фиксирует работу с активными окнами приложений и URL-адреса, а я могу группировать эти данные в активности. Например, здесь я могу увидеть, на что я трачу своё время за компьютером каждый день:

RescueTime

Я надеюсь, Вы не любите подробных описаний к отчётам 🙂 То, что Вам необходимо получить от инструментов — это действенные показатели. Информация, которая заставит Вас подумать: «Я должен это изменить!».

Лично я задал себе вопросы типа: “Я реально вчера потратил 2 часа на Slack? Могу ли я сократить это время?” Метрики также показали мне, что иногда я буду проводить часы в Jira за написанием и уточнением требований для задач, когда в идеале это должен делать профессиональный менеджер продукта (об этом ниже в разделе 8: Шумите).

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

2. Прекратите многозадачность

Суть

Поделите Ваши сессии программирования на неразрывные куски хотя бы по 30 минут. В идеале — двухчасовые сессии.

Подробнее

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

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

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

Multitasking
Monotasking

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

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

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

Но конечно же это не так. Многозадачность крайне контрпродуктивна. И это вдвойне истинно, когда приходит время снова писать код.

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

Рассмотрим вот такой пример кода:

[cc lang=»JavaScript»]
const rawResults = await goGetResults();
const results = parseSortAndFilterResults(rawResults);

if (status === ‘READY’) {
render(results);
} else {
messages.on(‘ready’, data => render(data.results));
}
[/cc]

Если Вы незнакомы ни с одной из конструкций, то Вам нужно понять, что делает метод goGetResults, потом — метод parseSortAndFilterResults, что содержит результирующий объект. Потом надо понять, что же такое status, где и когда он может меняться. И где событие «READY» может быть вызвано, а также какие данные оно подаст на вход. И так далее.

Когда Вы впервые садитесь работать над кодом, Вы будете перескакивать по методам, связанным с этим самым кодом, чтобы освоиться. Через 5, 10, 15 минут Вы будете размещать всё больше и больше информации в своей краткосрочной памяти, а Ваш великолепный разум начнёт строить карту логических связей.

Процесс начинает работать. Вы в зоне продуктивности.

И тут звонит телефон.

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

Stupid garbage collector

Теперь Вам надо просматривать код заново — ещё раз загружать информацию из долгосрочной памяти в краткосрочную. Предположим, это займёт пять минут нагрузки на Вашу память, и вот — Вы снова в потоке. Но теперь появляется оповещение о сообщении в Slack. А потом email, потом коллега постучал Вам по плечу, после чего пришла СМС-ка. И так далее, и так далее.

Мой совет довольно очевиден, но я всё же дам его Вам: как минимум цельтесь в куски времени непрерывного написания кода по 30 минут. Поставьте таймер.

Поставьте телефон в авиарежим (научный подход рекомендует положить его в отдельную комнату). Закройте все приложения на копмьютере, которые могут присылать оповещения. Да и вообще, и macOS, и Windows имеют режим работы “не беспокоить”. Я обнаружил, что даже иконка обновления информации на вкладке браузера или иконке приложения могут отвлечь моё внимание. Так что я предпочитаю вообще закрывать и вкладки, и приложения.

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

Когда сессия подойдёт к концу, немного растяните её и подумайте, что Вы можете сделать до того, как броситься проверять email/СМС/чаты/твиттер, а затем сделайте то, что нашли, до того, как произойдёт сборка мусора.

30 минут — это хорошо, но двухчасовая сессия — это Очень Хорошо! В зависимости от загрузки на неделе я стараюсь организовать 3-4 таких сессии. Время с 9:30 до 11:30 утра подходит мне больше всего. Постарайтесь выделить в календаре время и внести эти сессии в него [чтобы никто не смог поставить встречу на это время]. Как только Вы увидите прирост продуктивности от применения данного подхода, обязательно прочитайте книгу «В работу с головой» Кэла Ньюпорта.

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

У меня нет оповещений. Вообще нигде. У телефона нет рингтона, я не получаю оповещений о новой почте, из чатов или о твитах — и на телефоне, и на компьютере. Вообще.

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

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

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

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

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

3. Цепочки задач

Суть

Вы переключаетесь между задачами без потерь? Если Вы тратите время на переход между задачами, похоже, Вас ожидает битва процессов Git-flow и Agile.

Подробнее

В основном я работаю над раздельными задачами (например, тикеты в Jira, проблемы в GitHub). Это планируемые части работы, которые можно собрать, обработать в feature-ветке, а затем слить обратно в master.

Таким образом, в основном время на работу определяют две вещи:

  1. Задача и то, как она были описаны её требования
  2. Процессы разработки (тот же git-flow), используемые для фактического выполнения работы и отправки кода на бой

При неправильном подходе это может привести к постоянному снижению производительности.

Пример: представим, что несколько лет назад мне пришлось бы заменить простое сердечко лайка для статьи, нажимаемое в один клик, на иконку апплодисментов, которая считает клики по ней, принимая до 50 кликов [так сделано на ресурсах Medium]. Было решено, что эта задача должна быть разделена на две подзадачи:

  1. Доработать API, чтобы считать количество нажатий
  2. Обновить UI, заменив сердечко на ладошки апплодисментов

Через какое-то время я завершаю задачу про API в отдельной функциональной ветке и создаю pull-request. Может уйти день-два на code-review, приёмочные тесты и релиз. В то же время я начинаю работу с UI. Но чтобы разработать UI, мне потребуется функционал, который пока существует в непринятой на бой ветке API.

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

Никакого простоя между задачами. Круто. Этот подход будет работать во многих случаях. Но время от времени Вы будете замечать подозрительную возню за спиной. Обернитсь — Git тут же ударит Вас прямо в лицо. В том случае, если Вы будете следовать одной из двух распространенных практик git: rebase или squash.

Описание хода событий ниже может быть сложным, но если Вы поняли ситуацию, то, скорее всего, Вам уже приходилось сталкиваться с подобной проблемой: если я создаю ветку UI от ветки API, то у меня будут все коммиты изменений от API в ветке UI (по сравнению с master). Если я сделаю rebase ветки API (который уберёт набор коммитов, оставив один) или же squach со слиянием в master (который тоже уничтожит коммиты, сжав их), у меня останутся по сути несуществующее в master коммиты в ветке UI, которые содержат изменения. Теперь, если другой разработчик изменит один из файлов, с которыми я работаю в своих ветках, меня ждут проблемы. Git скажет мне, что я тоже меняю эти файлы, ведь у меня есть такие коммиты. Иногда это выливается в ненужный конфликт объединения, но, что хуже, иногда Git просто затрёт изменения другого разработчика (ведь у меня есть коммиты, которые поменяли те же файлы!). И если всё это пройдёт приёмочное тестирование, то меня ждёт баг в боевой среде.

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

В примере API/UI, я должен был закончить задачу API и ждать, пока она будет слита в master, после чего только начинать работать над UI. И переключиться на какую-то другую необходимую задачу. Возможно даже мне забросят в спринт незапланированную задачу, так как всё остально заблокировано ожиданием.

И ни одна из описанных выше ситуаций не похожа на движение стада бизонов. Это больше похоже на поведение зайца из оригинальной басни.

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

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

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

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

No squash&rebase!

Отрицательные стороны очевидны: Ваши коммиты в master это больше не часть релиза. Вам уже не поможет бинарный поиск при дебаге git bisect, потому что большинство коммитов — это даже не рабочий код. Хотя предположу, что если Вы даже знаете, что такое git bisect, возможно, Вы допускаете слишком много ошибок в master.

Суть проста. Создавайте коммиты прямо во время работы. Поместите код задачи в имя коммита, чтобы его было видно при git blame, но никогда не используйте squash или rebase. Если Вам нужен код из другой ветки, объединитесь с ней. Если Вам нужен код из трёх других веток, объединяйтесь со всеми ними! Их коммиты будут и в Вашей ветке безо всяких дальнейших конфликтов на бою.

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

Плохо реализованный Agile губителен для Вашей производительности

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

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

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

Это нелогично и контрпродуктивно, так как основывается на огромном недопонимании мира Scrum.

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

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

(Я разошёлся, так что я пойду дальше и скажу, что количество story points, которые Вы закрыли во время спринта, также не имеет никакого отношения к тому, как много Вы реально достигли. Любое изменение скорости разработки между спринтами показывает исключительно изменение точности оценки. Сентиментальные слова “отличная работа, команда, мы закрыли 45 очков за спринт!” или высокомерные “мы всего лишь закрыли 37 очков!” одинаково бесполезны. Полезным комментарием будет: “наша скорость разработки в текущем спринте отклонялась не более, чем на 20% от предыдущего спринта — отличная работа, команда! Мы даём предсказуемые сроки, несмотря на множество неизвестных — это поможет нам планировать будущую работу ещё более точно!”.)

ОК, я слегка вышел за пределы означенной тему, но я завершу всё это вопросом: «Ваши Agile/Scrum практики заключаются в том, что Вы делаете меньше работы? Если да, то на кой чёрт они Вам нужны?».

4. Делайте вещи один раз

Суть

На пишите баги.

Подробнее

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

Глупый бизон, тормозит всю команду.

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

Я верю в том, что есть способ никогда не доставлять на продакшн баги. И я предпочитаю верить в это (несмотря на кучу доказательств обратного), потому что, как только я покупаю футболку с надписью «Bugs happen», я даю себе разрешение не стремиться к достижению успеха безошибочного кода.

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

Две причины проблем я вынес из этого исследования:

  1. Когда я почти закончил работу над заданием, с которым провёл несколько дней, и мне уже не терпится перейти к следующей задаче, я терял терпение. Таким образом, я мог бы сделать один последний маленький рефакторинг, но вместо этого срезал углы и не перепроверял код ещё раз.
  2. Тот же случай, что и в пункте 1, но теперь я делаю code-review. Кто-то другой сделал последнее маленькое изменение, а я поленился пересмотреть весь pull-request. (Если я пропустил баг в своём code-review, я мог сделать тоже самое и при программировании).

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

Вместо этого я иду на прогулку. По району, по офису, вокруг столба — да где угодно! Я переключаюсь на что-то отличное от кода на минуту-другую.

После этого я возвращаюсь на рабочее место и становлюсь собственным самым строгим критиком: «Черт возьми, сломал новую функцию, которую только что написал Идиот Дэвид [автор статьи]». Чтобы найти недостатки в работе Идиота Дэвида, у меня есть два пути.

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

Во-вторых, я пройдусь по разнице между моей веткой и master в GitHub/BitBucket, читая строчку за строчкой так, как если бы код писал тот, кого я очень сильно не люблю (не так уж далеко от истины, кстати). Стоит делать это в некоем визуальном инструменте, так как есть что-то особенное в этих зелёных и красных строчках, что делает меня безумно придирчивым засранцем. Я буду надменно смеяться, когда я обнаружу, что Идиот Дэвид оставил закомментированную строку кода или накосячил с типами переменных.

По моим расчётам в 80% самостоятельных code-review, которые я делал за прошедшие несколько лет, я нашёл что-то, что можно исправить. Эти глупые маленькие ошибки, которые мог бы найти коллега, который затем написал бы комментарий к моему pull-реквесту, затем я бы прочитал его, затем исправил, затем напечатал «исправил», а затем сообщил, что ветка готова к повторному ревью. Этот поиск в итоге экономит мне столько времени!

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

Так что в следующий раз, когда Вы соберётесь создать pull-реквест, когда Вы уже увидите diff на экране и потянетесь к кнопке «Create pull request», сходите за стаканом воды, потянитесь и передохните. Затем ещё раз перечитайте diff с целью поиска ошибок.

5. Ищите и устраняйте точки замедления

Суть

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

Подробнее

Это может быть сложно. Как Вам понять, что Вы медленнее в чём-то, чем Вы могли бы быть? Иногда это происходит тогда, когда Вы видите кого-то, кто делает то же самое, что и Вы, но в два раза быстрее. Впервые, когда я увидел человека, который использует вкладку «Производительность» в Chrome DevTools, я был в шоке. И я пошёл и перечитал всю документацию об этом.

(Стоило бы создать главу “Знай свои инструменты”, но там особенно не о чем рассуждать. Знай свои инструменты.)

Чтобы начать применять такой самоанализ, когда Вы выполните следующую задачу, потратьте несколько минут, чтобы подумать о том, на что Вы потратили время. Что-нибудь выделяется? Вы потратили три часа, пытаясь найти свойство для вертикального выравнивания в CSS? Может быть, вы застряли в проверке синтаксиса, расшифровывая регулярное выражение или почесывая голову над FULL RIGHT INNER OUTER JOINs. Может быть, есто что-то, чего Вы до конца не понимаете?

CSS, например, особенно проблематичен, потому что людям кажется, что они могут использовать его, даже не читая документацию. И это здорово, потому что CSS в три раза больше JavaScript, и даже в 2019 году страдает от вызывающей ярость несовместимость между браузерами.

(Я наврал про «в три раза больше» — не верьте всему, что читаете.)

Когда вы определили что-то, на что, как Вы подозреваете, Вы тратите слишком много времени, Вы можете спросить себя: «Собираюсь ли я выполнять эту работу еще много лет, не тороплюсь, чтобы глубоко понять эту концепцию, применение которой в итоге окупится?». Скорее всего, ответ «Да», так что грызите гранит науки и RTFM.

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

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

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

Конечно же я больше этим не занимаюсь, потому что теперь я знаю все. 🙂

6. Сначала структурируй, затем полируй

Суть

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

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

Подробнее

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

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

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

Если задача достаточно сложная, выполните фундаментальную часть работы, а затем попросите кого-то провести ревью (ну, или, Вы знаете, поболтайте с другими об этом решении). Не тратьте неделю на то, чтобы поработать над чем-то, сделать это идеальным и отточенным, протестировать до 100%, только чтобы представить его на рассмотрение кода и получить более простой способ сделать это.

7. Следите за будущим

Суть

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

Подробнее

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

Несколько общих предположений:

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

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

Когда дело доходит до разделения функциональности, Вы можете следовать как минимум одному очень простому правилу: храните код, который делает разные вещи в разных файлах. Операции с базой данных, вызовы API, манипулирование данными, утилиты, рендеринг пользовательского интерфейса — все эти вещи должны лежать в своих отдельных файлах. (Повторюсь: это самый необходимый минимум, Вы должны действительно приложить немало времени и усилий для разработки архитектуры своего приложения.)

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

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

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

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

Если вы пишете CSS, но не создаёте модули, у меня для Вас хорошая новость: Вы ужасно непродуктивны, но есть несколько хорошо документированных способов вырваться из этой дыры. CSS-модули являются лучшим вариантом, но БЭМ — вполне приемлемая альтернатива.

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

8. Шумите

Суть

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

Подробнее

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

Представьте, что компания может быть в два раза быстрее конкурентов!

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

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

Услышьте меня…

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

Если Вы уберёте менеджера или скрам-мастера, разработчики поставят Slack и продолжать кооперироваться. Вы можете поувольнять дизайнеров, и разработчики будут работать над тем, как всё должно выглядеть. Вам даже не потребуется продуктолог или BA, или ещё кто-то, кто собирает требования — разработчики сами всё соберут и напишут код. И действительно нет нужды тратить деньги на QA. Просто внедрите процесс приёмки, где разработчики будут делать всю приёмку сами — что может пойти не так?

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

Это бьёт по производительности, но я думаю, что причина такой распространенной проблемы в том, что снижение производительности редко вызывает боевую тревогу. Если Вы производите автомобили, Вы можете почитать отчёт и спросить: “Почему мы доставили только 45,000 машин за прошедший месяц?!”. Но если Вы пишете код, то разница не так очевидна — она скрыта за естественной изменчивостью выпуска новых версий ПО. Никто не кричит: «Почему в прошлом месяце мы отправили только 34,5 новых кнопки?!»

И Ваша скорость Agile-процесса тут также не поможет, так как разработчиков поощряют за учёт всех аспектов задачи при оценке, включая QA, точнение требований и так далее. Во всяком случае, похоже, что Вы делаете больше, потому что трудозатраты, которые обычно не отслеживаются на Scrum-доске, внезапно отслеживаются.

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

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

С ног на голову

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

  • Будьте сплоченным, тесно интегрированным составом. Все ходят на все встречи. Все вовлечены в дела всех остальных. Разработчики идут на сессии дизайна и наоборот. Все ходят на встречи по стратегии компании и в «ратуши». Результат: одно бессмысленное одночасовое собрание в день может снизить производительность на 12,5%. (Совет: никогда не начинайте свои встречи вовремя, простой способ сжечь еще несколько процентов.)
  • Реализуйте дьявольский треугольник обработки задач: крошечные маленькие задачи, git-стратегию, которая затрудняет переключение с предыдущей задачи, и процесс контроля качества, который занимает несколько дней, чтобы задача перешла в master. Результат: Вы снизите производительность почти на 5%, если сделаете свои задачи достаточно маленькими. Будьте внимательны, Вы должны реализовать все три части, чтобы получить желаемый урон производительности.
  • Не тратьте время и деньги на Scrum-мастеров, продуктологов и другой подобной фигни от Jira. Разработчики могут сделать все это. Результат: с командой, скажем, из 7 разработчиков, отказ от одного профессионального не-разработчика может снизить производительность на целых 15%.
  • Будьте «итеративными». Cмутно опишите, что нужно построить, позвольте разработчику потратить неделю на написание кода, а затем скажите им, что Вы действительно хотели. Результат: постоянное применение таких итераций может скостить еще 5–10%.
  • Когда работа, которую Ваша команда обязалась сделать в спринте, завершена раньше срока, направляйтесь к столу для пинг-понга. Результат: если Вы заканчиваете на 1 день раньше каждый второй спринт, это еще 5% от вашей производительности.
  • Максимизировать доступность. Убедитесь, что у Всех включены уведомления. Если кто-то не отвечает на электронное письмо, перейдите к его столу и подтолкните его. Также не нужно работать удаленно, все должны постоянно находиться в офисе (обязательно — open space!), чтобы Вы могли обсуждать разные вопросы. Сотрудничество! Результат: это трудно измерить, но я прикидываю, что должным образом внедренный режим непрерывного раздробленного внимания может привести к снижению производительности до 20%.

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

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

Комментарии к статье

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

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

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

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

Искусство быстрой разработки: 3 комментария

  1. Отличная статья. Некоторые вещи до боли похожи на текущее мое место работы.

    1. Василий Алибабаевич, согласен полностью, как с нас писали
      может это и не перевод статьи ?

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *