Site icon AppTractor

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

Я не думаю, что я очень быстр в абсолютном смысле, но я гораздо быстрее, чем 5 лет назад.

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

Забота

Главное, что помогло — это желание стать быстрее.

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

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

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

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

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

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

Принимайте решения на основе целей

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

Пример: Какую структуру данных использовать для текста в текстовом редакторе?

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

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

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

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

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

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

Пример: Мне потребовалось очень много времени, чтобы научиться писать «уродливый» или «грязный» код. В идеальном мире я бы поддерживал качество всей своей работы на пределе своих возможностей. Но я обнаружил, что могу написать значительно больше, если немного расслаблюсь. Я предпочитаю иметь готовый проект, отшлифованный на 80%, чем 1/3 проекта, отшлифованного на 100%. Это особенно верно для экспериментов, прототипирования и тестирования, где качество не имеет такого большого значения. Но даже производственный код часто имеет короткий период полураспада — я полагаю, что половина моего кода выбрасывается или переписывается в течение первого года.

Раньше я не задумывался об этом, и в результате тратил много времени:

Фокусируйтесь

Я работаю блоками по 2-3 часа, в течение которых я не делаю ничего другого — никакой электронной почты, Slack, Twitter, Hacker news, болтовни с соседом и т.д.

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

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

Если мне нужно прерваться в определенное время (например, на встречу), я ставлю будильник, а не пытаюсь вспомнить и не беспокоюсь об этом.

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

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

Прочитайте также «Глубокая работа«, «Ваш мозг на работе» (последняя книга немного поп-психологическая, но все же полезная).

Работайте блоками

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

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

  1. Записать, чего я хочу добиться.
  2. Прикинуть, как я буду это делать.
  3. Пройтись по коду и составить краткий список изменений, которые необходимо внести.
  4. Вносить изменения одно за другим в порядке их появления в списке.
  5. Прочитать diff и исправить очевидные ошибки, улучшить комментарии, подобрать более удачные имена переменных и т.д.
  6. Протестировать и отладить. Вернуться к шагу 2, если я понял, что сделал неправильный выбор и нужно сделать что-то по-другому.
  7. Коммит, мердж, приготовление чая.

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

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

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

Вносите небольшие изменения

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

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

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

Прочитайте также «Инкрементное программирование«.

Сокращайте циклы обратной связи

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

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

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

Примеры:

Иногда можно обойти длинные петли обратной связи, работая параллельно. Когда я работаю над проектами с длительным временем компиляции (например, инкрементные сборки Materialize иногда занимают 14 минут), я иногда отвлекаюсь, и когда компиляция заканчивается, я уже забываю, что тестировал. Чтобы уменьшить это влияние, я иногда составляю список из нескольких экспериментов и запускаю по одному на каждом декстопе, при этом на каждом рабочем столе открыт текстовый файл с объяснением того, что я делаю. К тому времени, когда я закончу настройку последнего эксперимента, первый, надеюсь, уже завершится. Это все равно не так эффективно, как просто более короткие петли обратной связи, а для бенчмарков это требует наличия большого количества дополнительного оборудования, чтобы избежать помех. Но иногда это лучшее, что я могу сделать.

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

Записывайте материал

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

Все это не требует больших усилий. Обычно я пишу около 100 слов в день.

Сократите количество частых ошибок

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

Примеры:

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

Прочитайте также “Чек-лист. Как избежать глупых ошибок, ведущих к фатальным последствиям”.

Сделайте низкоуровневые навыки автоматическими

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

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

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

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

Рефлексируйте

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

zig pretty-print in gdb?
command-line version of magit to avoid emacs startup times
  try gitui
clipboard daemon with history
try tracy
fix focus hang/crash on big rg (need to limit input?)

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

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

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

И т.д.

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

Примеры:

Источник

Exit mobile version