Выпуск 9 · подкаст «Тысяча фичей»

#9: Прагматичные тулы: plain text, git, shell

46:32
↓ скачать mp3

Глава «Программиста-прагматика» про ежедневные инструменты: почему plain text — самое живучее представление знаний, как сделать shell своей вотчиной (темы, prompt, алиасы, fish), чек-лист совершенства во владении редактором, зачем всегда нужна система контроля версий и философия дебаггинга — чинить проблему, а не искать виновных, воспроизводить багу тестом и читать чёртово сообщение об ошибке. Бонус: подкаст зафичерил Apple, и Александр рассказывает, на что это похоже. Полезняшка — лекция Джона Остерхаута «A Philosophy of Software Design».

Главное

  • Plain text — самое живучее представление знаний: оно не устаревает вместе с софтом и из коробки дружит со всеми Unix-инструментами и git.
  • Используйте силу командной строки и сделайте shell своей вотчиной: тема, prompt с git-веткой, алиасы для SSH-серверов, автокомплиты — а fish продуман по UX прямо из коробки.
  • Добейтесь совершенства во владении редактором: пройдите чек-лист (выделение, навигация, мультикурсор, сортировка строк, поиск по regex) и доводите найденные пробелы до мышечной памяти, исключая «авторепит».
  • Всегда используйте систему контроля версий — и проведите мысленный эксперимент с пролитым на ноутбук кофе: сколько времени займёт восстановление рабочего окружения?
  • Дебаггинг — это problem solving, а не поиск виновных: «не имеет значения, чья это была ошибка, — это всё ещё ваша проблема».
  • Сначала тест, потом фикс: воспроизведённая юнит-тестом бага — это подтверждение находки, доказательство фикса и страховка от регрессии.
  • Читайте чёртово сообщение об ошибке; «ифы не сломались» — в 99% случаев проблема в вашем коде; а предположения ничего не значат, пока не доказаны тестом или скриптом.
  • После фикса рефлексируйте: почему о баге не узнали раньше и что изменить (статанализ, новые тесты), чтобы этот класс ошибок больше не доходил до продакшна.
Расшифровка

[00:19] Здарова! Меня зовут Саша Пахомов, и я инженер, который любит своё дело. Это девятый выпуск подкаста «Тысяча фичей». Сегодня я продолжу читать книгу «Программист-прагматик» и делиться мыслями. Но прежде хочу похвастаться: подкаст «Тысяча фичей» зафичерил Apple — он попал в рекомендации, и я этому очень рад. Сложно объяснить это чувство, но попробую. Представьте: вы мечтаете, например, поехать в отпуск и заняться серфингом. Распланировали, накопили, взяли отпуск (длинный — с серфингом иначе никак), посмотрели уроки, нашли тренера, начали учиться. Поверьте, первые разы удовольствия не доставят: вы вообще не поймёте, что делаете и то ли это. Но в какой-то момент, в очередной попытке поймать волну, вы вдруг осознаёте: вы её поймали, она вас несёт, вы стоите на доске и управляете ею. В этот момент вас накрывает дикий прилив дофамина, счастья и эйфории. Именно это случилось со мной, когда я впервые поехал на доске сам, без инструктора, — и именно это случилось, когда я увидел «Тысячу фичей» в топ-чартах Apple. Спасибо всем новым и старым подписчикам — без вас бы этого не случилось.

[01:43] Давайте немного познакомимся. Я Саша Пахомов, инженер, пишу в основном на Java, большую часть времени контрибьючу в базу данных Apache Ignite 3. Мне нравится моя работа, и я постоянно нахожу в ней что-то, чем можно поделиться, — именно этим в подкасте и занимаюсь. Ещё у меня есть Telegram-канал «Душный enterprise»: в нём я пишу мысли, которые для подкаста либо слишком душные, либо просто не тот формат. А чем занимаетесь вы? Пишите в комментариях к выпуску в Telegram-канале. Это было самое длинное вступление за всё время — а теперь к основной части. Поехали!

[02:31] Итак, продолжаю читать «Программиста-прагматика» (ссылка на книгу всегда есть в описании выпуска — скачивайте, давайте читать вместе). Глава называется «Тулы для прагматичных программистов»: то, что прагматичные программисты используют в ежедневной работе. Уже не высокоуровневые софт-скильные темы, а вполне down-to-earth: инструменты. Речь пойдёт про plain text, shell, редакторы кода, систему контроля версий, поиск багов, управление текстом и многое другое.

[03:31] Первый раздел — «Сила текста». Мысль такая: если основной материал бариста — кофе, рецепты, кофемашина и сырьё, то наш основной материал — знания. И управлять знаниями — сохранять их, передавать — лучше всего, по мнению авторов, с помощью plain text. Не видео, не аудио, не бинарные файлы, открывающиеся в специальных программах. Что такое plain text? Авторы определяют его как формат, который человек может понять без специальных тулов: условно, открыть файл в консоли и сразу увидеть, что там, извлечь знание. Если для извлечения знания нужен специальный инструмент — проигрыватель для видео, декодер для бинарного формата, — это уже не plain text. Чем он хорош? Во-первых, это формат, автоматически застрахованный от устаревания: кодеки видео меняются, софт для чтения других форматов устаревает, лицензии заканчиваются — а plain text открывается множеством редакторов независимо от тулов. Во-вторых, мы автоматически интегрируемся со всеми существующими инструментами: банальные Unix-команды — less, tail, cat, — git, любые IDE без дополнительных плагинов: всё заточено под plain text по умолчанию. И последний тейк: знание — это не только документация или тикет в джире, это, например, и входные тестовые данные программы. Представляем их в plain text — проще тестировать, проще видеть изменения в git. Одни плюсы. Думаю, это всем плюс-минус очевидно: текстовое представление информации выдержало проверку временем. В него очень просто вносить изменения: поменялось поведение системы — сделал pull request в документацию, и она up-to-date. А в видео- или аудиоинструкцию просто так кусочек не законтрибьютишь — придётся перезаписывать, целый гемор. (Про поддержание документации в актуальном состоянии копий сломано немало — может быть, тема для отдельного подкаста.)

[08:11] Следующий раздел — Shell Games: про интерактивную оболочку, про терминал, с которым мы, программисты, имеем дело каждый день (я-то уж точно). Shell здесь противопоставляется GUI-приложениям: графические интерфейсы — это хорошо, красиво и часто удобно, но они ограничены своим дизайном: если интерфейс задизайнен на просмотр и редактирование текста, это всё, что вы с ним сделаете, — эффективно запроцессить или вырезать кусок текста навряд ли получится. Для универсальной работы с plain text shell — один из самых мощных инструментов. Совет раздела: используйте силу командной строки. Не пренебрегайте знанием команд вашей системы. Навскидку из того, чем я владею хорошо и что реально увеличивает мою продуктивность: less, cat, grep, tail, утилитарные вещи вроде «создать директорию, перейти в директорию». Стандартный набор, который на кончиках пальцев — без мануалов и гугла, — позволяет чувствовать себя комфортно в системе, особенно когда подключился по SSH сервер подправить. Я всегда выбираю командную строку, а не GUI, если есть возможность.

[10:14] Дальше: shell можно кастомизировать под себя и сделать своей вотчиной, где уютно и всё настроено. Можно поставить тему — сейчас их куча, ставятся одной строкой: комфорт не только для пальцев, но и для глаз. Можно настроить prompt — текст, который вы видите, когда shell готов принимать команды. У меня это текущая директория плюс git-ветка и индикатор изменений: если есть незакоммиченные изменения — горит звёздочка. Достаточно стандартный prompt из одной из тем oh-my-zsh — наверное, самой популярной системы плагинов для zsh на Mac. Раз уж говорю про окружение — ещё я использую iTerm2. Дальше — алиасы, вообще топ-тема: прописываются в bashrc или zshrc, короткие сокращения для набора команд или вызова скрипта. У меня на работе есть с десяток серверов с нетривиальной аутентификацией — не просто ssh, там Kerberos и ключи. Чтобы не писать эту команду каждый раз, у меня короткие алиасы — буквально пять-шесть символов на каждую машину: ввёл — и ты там. Очень удобно. И последнее — автокомплиты: в oh-my-zsh этим занимаются плагины (у меня стоит плагин для git — и, по-моему, всё): они добавляют функции автодополнения, чтобы по табу shell подсказывал, что печатать дальше. В этом плане очень интересно выглядит shell под названием fish. Я его поставил и вообще планирую на него перейти — он мне очень нравится. Его сделали люди, которые думают про UX: если zsh — обычная альтернатива bash, то fish — альтернатива, в которой подумали, как будет себя чувствовать человек, только что всё установивший. Конфигурация настолько простая и замечательная, что я в восторге. Советую попробовать всем, у кого Mac, — пишите в комментариях, как вам.

[13:46] Дальше — power editing, сила редактирования. Совет с порога: добейтесь совершенства в использовании редактора. Что такое совершенство? Авторы приводят довольно исчерпывающий чек-лист, по которому можно прогнать себя и найти слабые места. Давайте пройдём интерактивно, вместе со мной. Выделение посимвольно, по словам, строчкам, параграфам — специальными командами, без трекпада и мышки: в IDEA и в Vim могу — галочка. Навигация по функциям и модулям — да; а вот по разделителям (поставил курсор на открывающую скобку — прыгнул на закрывающую) — честно, не могу: надо изучить хоткей. Посмотреть код до и после изменений: git blame и git history в IDEA — да, но с трекпадом; без него не могу. Комментирование блока кода одной командой — да: выделил и слэш. Undo/redo — да. Сплит на два окна и навигация между ними: в IDEA такого паттерна у меня нет — я просто быстро переключаюсь между окнами, и не понимаю, зачем мне два окна перед глазами (разве что дифф смотреть); а вот в Vim эту команду надо освоить. Переход на строчку по номеру: не знаю, как в IDEA, — но у меня другой паттерн: если номер строки и нужен, то из стектрейса, а я просто копирую стектрейс, делаю Analyze Stack Trace — и прыгаю по нему, правда, трекпадом. Отсортировать выделенные строчки — прикольная команда, и я не знаю как; а ведь знаю, когда нужно: сравнить два текста глазами, когда они отсортированы, намного проще. Поиск по строке или регулярному выражению: в IDEA — Ctrl+F и галочка regex, в консоли — grep, в less — слэш; а вот в Vim быстрый поиск надо изучить. Мультикурсор: видел в университете — преподавательница размножила курсор строчек на двадцать и начала печатать одновременно во всех; у меня просто башню снесло, все такие: «а как вы это сделали?!» (По-моему, у неё был WebStorm.) В IDEA то же самое: Ctrl или Command — и натыкиваем. Суперфича; использую нечасто, но для однотипного текста типа XML — удобно. Умеем-могём. Показать ошибки компиляции в проекте — IDEA компилирует при запуске теста и показывает всё в одном окне. Запуск тестов — Ctrl+R на последних или кнопкой по директории. Ну что, надеюсь, вы прошли этот чек-лист со мной. Сколько у вас пробелов? У меня нашлось несколько — теперь знаем, куда копать.

[18:42] Дальше — советы, как улучшать навык. Поймали себя на мысли, что наверняка существует более быстрый способ сделать то, что вы делаете, — сразу ищите его и тренируйте мышечную память. Мало знать хоткеи — важно довести до автомата: когда перестаёшь думать и руки делают сами, навык получен. Прокачивайте редактор плагинами — почти все редакторы дают плагинную систему. (Кстати, какие у меня плагины в IDEA? Я особо не устанавливаю — считаю, чем ближе окружение к дефолтному, тем лучше, но это личное мнение. Котик загрузки с радугой… кроме котика — Copilot ставил.) А если плагина нет — всегда можно написать свой: это и один из челленджей авторов. Я свой плагин писал — для KDE. Спасибо, опыт мне не понравился, больше не хочу. Ещё челлендж: исключить из профессиональной жизни «авторепит» — это когда зажимаешь клавишу или тык-тык-тык. Каждый раз, когда нужно, например, стереть слово, — заресерчьте, как это сделать одним сочетанием: в macOS Option+Backspace удаляет слово, Command+Backspace — строку. И челлендж «неделя без трекпада и мышки» — достаточно экстремально; я бы начал с одного дня, желательно без митингов: максимально программистский день с минимумом коммуникаций и GUI (я, например, не представляю, как быстро навигировать в Telegram, Slack, Zoom или Google Meet без мышки, а вот в IDE и консоли — точно можно). Возможно, когда-нибудь устрою себе такой день — чисто изучить возможности клавиатуры.

[21:50] Следующая часть — система контроля версий. Совет: всегда используйте систему контроля версий. Чаще всего это git (бывают ещё SVN и прочие — их много, но решают они одну проблему и дают плюс-минус один фичерсет). Рассказывать, что такое git, не буду — все слушатели с ним так или иначе работали. Авторы подсвечивают преимущества: это не только «вернуться назад во времени» (кстати, когда я в университете изучал git, я воспринимал его именно как time-travel-инструмент — «можно поэкспериментировать и откатиться», — а не как инструмент коллаборации и ведения проекта). Можно посмотреть автора изменений, разницу между версиями файла, посчитать, сколько строк изменено с какого-то момента и какие файлы меняются чаще всего, — и куча всего ещё. Использование системы контроля версий давно стало стандартом де-факто. Если интересно, что я думаю про коммит-месседжи и как их оформлять — послушайте второй выпуск. А завершить разговор про git стоит мысленным экспериментом авторов с пролитой кружкой: представьте, что вы прямо сейчас разливаете кофе на ноутбук — всё, он выключился и больше недоступен. Сколько времени займёт восстановление рабочего окружения на новом ноутбуке? Чем дольше — тем хуже; а если что-то потеряно безвозвратно — совсем плохо. Правильное использование VCS приводит к тому, что как минимум проекты, код и знания восстанавливаются мгновенно: всё в git, склонировал — и всё. Но пролитый кофе — это ещё и восстановление учётных записей и софта; навряд ли кто-то ставит софт на свою машину Ansible-скриптами (если да — респект). Я эксперимент мысленно провёл: наверное, полдня уйдёт на восстановление моего мака. Такие дела.

[24:52] Следующая тема — поиск багов. Честно, не совсем понимаю, почему это в главе про ежедневные тулы — git понятно, shell понятно, но я бы не сказал, что дебажу каждый день; ну да не суть. Кстати, раздел про философию исправления багов зашёл мне в этой главе больше всего. Авторы говорят: воспринимайте поиск бага как problem solving, как челлендж — а не как что-то апатичное и унылое («опять дебагать, опять логи…»). Бага — это задача, которая стоит перед вами. Совет: концентрируйтесь на исправлении проблемы, а не на поиске виновных. Не имеет значения, чья это была ошибка, — это всё ещё ваша проблема. Тут я согласен на 100%. Я не раз видел, как люди ищут не проблему, а человека, который её внёс: смотрят, после чьих изменений случилась регрессия, чей это класс… Да какая разница! Понимаю, найти виновного и попросить его решить проблему — проще всего. Но мы команда, и проблема у нас общая: бага — в нашем продукте. Мне кажется супердиким искать виновного и тыкать в него пальцем: это и странно само по себе, и максимально неэффективно. Неужели кто-то думает, что, ткнув человека в его багу, добьётся того, что он больше не будет писать баги? Нет — он код писать не будет, вот это точно. Ладно, отошёл от темы. Ещё советы: не паникуйте — когда на вас давят сроки, босс и все спрашивают «когда-когда», максимально дистанцируйтесь от давящего окружения и спокойно ищите. Не тратьте время и эмоциональный ресурс на «этого не может быть, это невозможно»: может — и случается прямо сейчас; примите как данность и ищите причины. И докапывайтесь до истинной причины, не избавляйтесь от симптомов — тут дико плюсую. Признаемся: когда мы видим какую-то фигню в системе, ручки чешутся прикрыть её ифчиком, сделать workaround, быстренько фиксануть. Задача в джире закрыта, «был баг — нет бага»; с точки зрения внешнего наблюдателя вы молодец и герой — тот, кто реально решает проблемы, а не тот, кто два дня ковыряется. Снаружи тот, кто закрыл дырку за два часа, и тот, кто нашёл настоящую причину за два дня и решил её раз и навсегда, выглядят одинаково. Но мы-то программисты-прагматики и понимаем: выглядеть героем снаружи и быть им для себя — две совершенно разные вещи. Кстати, референс: в предыдущем, восьмом выпуске я рассказывал про флэки-багу с Mockito на Jenkins — «типы не совпадают». Я ведь мог просто вызвать у мока reset() в сетапе теста — и это бы сработало: видимой проблемы не стало бы. Но это был бы симптом: настоящая проблема — моки в многопоточном коде — осталась бы, и мы бы на неё наступили снова. Как истинный программист-прагматик, я докопался до сути — подробности в конце восьмого выпуска.

[29:56] Окей, майндсет настроен — с чего начать? Авторы: исправляйте на корню все ворнинги компиляторов и выставляйте максимально строгие флаги компиляции. Если багу может найти компилятор — программист не должен тратить на неё время. Плюсую — и добавлю: существует много статических анализаторов: PMD, FindBugs и прочие. Ни одна современная серьёзная Java-разработка не обходится без этого джентльменского набора чекстайлов: исправляйте баги на этапе статического анализа, а не в продакшене. Дальше: интервьюируйте баг-репортера — человека, который нашёл багу, — максимально глубоко; лишней информации при поиске сложных проблем не бывает. Согласен полностью: собирайте все логи, дампы, стектрейсы, jstack — всё, что можете: это сэкономит кучу времени. Дальше: багу в идеале надо воспроизвести. Вот с этого лично я и начинаю — прямо с места в карьер: поднимаю локально, открываю юнит-тест и пишу. В большинстве случаев багу можно воспроизвести юнит-тестом, и это мой пункт ноль — до дебага и даже до гугла. Согласитесь, самое соблазнительное — скопировать вывалившийся стектрейс, вставить в гугл, найти и пофиксить за полчаса. Иногда я так и делаю, когда совсем соблазн. Но в 90% случаев сознательно не иду этим путём: сначала пишу тест, воспроизводящий багу, и только потом иду в код разбираться, гуглить, фиксить. Что тут важно (это, можно сказать, часть практики TDD): я добился красного теста — есть подтверждение, что бага найдена: я хочу от системы такого поведения, а оно вот такое. Фикшу — тест зеленеет: есть подтверждение, что бага исправлена. И гарантия, что её не будет в будущем: регрессию никто не отменял, а тест остаётся и цементирует поведение системы. Такой фикс несёт намного больше ценности, чем быстрый однострочный («молодец, поправил» — а в следующем релизе опять). Воспроизводите баги тестом, потом фиксите — ну, или фиксите, потом покрывайте тестом, не так важно. Совет авторов звучит ровно так: сначала тест, потом фикс.

[33:27] Следующий совет — на случай, когда сообщение об ошибке нетривиальное (не голый NullPointerException, а библиотека выдала что-то странное — как Mockito с его «типы не совпадают»). Звучит он так: читайте чёртово сообщение об ошибке. Я и сам себя на этом ловил: что-то упало — паника-паника, бежим в код, в git log, кто последний менял… А иногда очень полезно просто вдумчиво, внимательно, спокойно прочитать, что написано. Часто вдумчивое чтение сообщения об ошибке — уже почти решение проблемы; как минимум вы максимально приблизитесь к пониманию, что пошло не так. Дельный совет. Дальше — распространённые сценарии багов. Первый класс — чувствительность к входным данным: на вход пришло не то — отрицательное число, null, строка не в том формате — и недотестированный код падает; если у вас есть датасет, который ломает программу, авторы предлагают искать проблемную запись бинарным поиском (о нём ниже). Второй — регрессии: вчера работало, сегодня нет; тесты проходили — теперь падают. Их главное отличие: можно найти конкретный коммит, сломавший систему. И ищем мы его не чтобы ткнуть автора носом — а чтобы найти дифф, в котором содержится бага: так проще решить проблему. Мы решаем проблему, а не ищем виновных. Поиск сломавшего коммита организуется бинарным поиском — да, тем самым: делим отсортированный список пополам, идём влево или вправо… все так или иначе его реализовывали. Той же техникой можно искать и коммит с регрессией, и строчку данных в большом датасете, и много чего ещё. Тут отсылочка ко второму выпуску «Тысячи фичей», где я рассказывал, как искал дичайшую багу внутри генератора OpenAPI-спеки Micronaut: я применил ровно этот метод и, честно говоря, без него не знаю, как нашёл бы.

[36:49] Дальше авторы приводят такой кекс: когда проблема нетривиальная, люди начинают говорить — «да этого не может быть, это бага во фреймворке, это syscall неправильно отработал, это JVM сломалась». Что угодно, кроме их собственного кода: их код работает идеально, это снаружи что-то не то. Авторы называют эту ситуацию — в моём вольном переводе — «ифы сломались». И тейк такой: нет, ребят, ифы не сломались. Как только посещает мысль «компилятор что-то не то скомпилировал» — в 99% случаев проблема всё-таки в вашей программе, там и ищите. А оставшийся процент — когда уже всё перепробовали: бывает, как у меня с генератором, — там бага действительно была во фреймворке; но как я к этому пришёл и какими размышлениями — снова второй выпуск. Дальше: ничего не предполагайте — доказывайте. Думаете, что багу вызывает вот этот параметр и он приводит к out of memory error? Предположения сами по себе ничего не значат: напишите тест, скрипт на питоне, на баше — что угодно, что докажет (или опровергнет) предположение. Неистово плюсую. Чем опытнее я становлюсь и чем больше пишу кода, тем меньше доверяю себе — как бы парадоксально это ни звучало. Я знаю, что могу ошибиться: я человек, могу что-то забыть, не понять, не догнать — настроения нет, вчера вина попил, — куча причин, почему я могу сломаться как человек. Поэтому я всегда хочу доказательство: написать тест, воспроизвести, остановиться дебаггером и увидеть значение, распечатать его — найти то, что другой разработчик может открыть, посмотреть и сказать «ну да». Объяснить свою картину мира — это не доказательство: я могу ошибаться и, скорее всего, буду. А вот воспроизвести так, чтобы и другой смог воспроизвести у себя, — это я называю «доказать».

[39:37] И финал темы: багу нашли, пофиксили, тестом воспроизвели (не всегда возможно, согласен, но в большинстве случаев можно). Теперь задайте себе вопрос: а почему о баге не узнали раньше? Очень полезный момент рефлексии, который мы на работе делаем редко — я стараюсь. Что мы не учли при разработке, что так случилось? И если в ответе содержится решение или экшен — сделайте его: зарефакторьте кусок кода, поменяйте процесс, что угодно. И второй вопрос: что нужно сделать, чтобы такое не повторялось? Написать больше end-to-end тестов, тестировать на каждый коммит — решений много. Завершающая мысль авторов: сделайте так, чтобы такого рода багу нельзя было внести, — а если это повторится, вы должны узнать об этом настолько быстро, насколько возможно. В идеале — упасть должна компиляция: обратились к null-полю — пусть статический анализатор скажет об этом, и у вас целого класса таких ошибок больше не будет, до продакшна они доходить перестанут. Новые тестовые сценарии, интеграционные, end-to-end, функциональные тесты — всё это должно решать проблему узнавания о баге. До продакшна она доходить не должна.

[41:22] Следующая часть — управление текстом. Тут авторы дают несколько идей про инструменты, которыми мы, разработчики, редко пользуемся профессионально. Хорошо бы уметь процессить plain text утилитами вроде awk и sed. Честно говоря, я ни ту, ни другую не знаю на уровне «выдери мне такую-то часть строки awk-скриптом» — синтаксис, ну, не очень. Как это сделать на Python — скажу, а на awk или sed — нет. Справедливости ради, авторы тут же говорят: если вам, как и мне, тяжело с этими Unix-командами — используйте языки программирования, заточенные под это. Помню, в первом издании книги в этой части приводили Perl; теперь — Python и Ruby. Вот так: времена меняются, Perl ушёл. Про Python согласен: язык, которым отлично делается процессинг текста — что-то выдрать, поменять, заменить, вставить. Тот самый язык «в обойме» для такого рода задач: быстрый веб-сервис или распределённое приложение — наверное, не на Python, а вот для таких утилит — идеальный инструмент. Я его для этого и использую, хотя, справедливости ради, редко. Авторы советуют изучать языки манипуляции текстом — и, думаю, мне правда стоит уделить этому больше внимания: Python всегда установлен, и я его знаю — почему не использовать? Сами авторы, кстати, собирают свою книгу с помощью Ruby: препроцессинг, добавление сносок, номеров страниц, синтакс-хайлайтинг кусков кода — всё на Ruby, а книга представлена в plain text. Респект им.

[43:42] Последнее в этой главе — инженерные ежедневники. Авторы говорят: посмотрите на инженеров на заводе — они всегда ходят с карандашиком за ухом и ежедневником, постоянно делают пометки, потому что знают, что что-то забудут: ежедневник для них — must-have инструмент. Так и нам стоит использовать тулы для заметок и туду-листов — просто чтобы разгрузить голову. От себя добавлю: я пришёл к модели с двумя инструментами. Первый — встроенные Notes на macOS: они отлично синхронизируются с телефоном и планшетом. Например, готовлю заметку для подкаста: читаю книжку в Kindle, записываю хайлайты в Notes — а когда нужна табличка из книги целиком, беру телефон, открываю ту же заметку на том же месте, делаю фотку — и она тут же на компьютере. Очень удобно. А если нужно что-то не забыть — тудушку оставить, — тут я использую божественный инструмент под названием Todoist. Максимально простой и понятный, синхронизируется с телефоном, планшетом и маком, есть интеграции и API. Если меня кто-то о чём-то просит на работе — я всегда закидываю это шорткатом в Todoist, и так ничего не забываю. Особенно если что-то пообещал — это по-любому окажется в Todoist.

[45:40] На этом выпуск подошёл к концу. Если он вам понравился — обязательно поделитесь им с коллегами или друзьями: давайте прокачивать себя и людей вокруг. С меня, как обычно, полезняшка. Это лекция Джона Остерхаута «A Philosophy of Software Design» — очень интересный философский подход к осмыслению того, как мы пишем программы. У него, кстати, есть одноимённая книга. Всем советую. Ну а на этом всё. Услышимся!