Автопрочитывать почту

Я живу без уведомлений, потому что они меня раздражают. Исключения — баджик на иконке почты и Слака (от упоминаний через @ и личных). Если в Слаке по пустякам баджик не появляется, то почта в какой‑то момент начала подбешивать.

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

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

Отписываться от рассылок, которые мне нравятся, не хотелось. Закрывать почтовый клиент полностью — тоже, я ждал писем от сервисов логирования.

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

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

+10 к спокойствию и сосредоточенности.

Джедайские техники. Максим Дорофеев

Недавно вышла книга Путь джедая Максима Дорофеева. Перед тем как прочитать её, я решил освежить в памяти предыдущую — Джедайские техники. Заодно законспектировал.

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

Работа с проектами по Дорофееву напомнила мне GTD, но GTD я терпеть не могу, а вот «джедайство» почему‑то зашло. Возможно, потому что Дорофеев описывает, как работают (а точнее мешают нам работать) когнитивные искажения. Возможно, потому что написано простыми словами. Но в любом случае, поехали.

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

Откуда у нас вообще проблемы с эффективностью

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

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

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

…которого конечно же не существует. Вместо него Дорофеев даёт универсальный совет на все времена.

В любой непонятной ситуации — думай

Потому что…

Думать все‑таки придётся

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

Почему эффективность падает

Ресурсы организма ограничены и особенно — ресурсы мозга. Мы помним, что мозг сам по себе ленивая скотина, и заставить его работать — уже трудно. А если мы встревожены, голодны, не спали, сосредоточиться на решении задачи становится ещё сложнее.

Однако, даже если звёзды сошлись, и мы начали решать задачу, это не гарантирует, что мы её решим. Потому что…

По физиологическим причинам нам бесконечно тяжело фокусироваться на одном объекте дольше небольшого промежутка времени

Чем масштабнее и сложнее задача, тем более склонен ее исполнитель к прокрастинации

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

Память, концентрация, настроение — всё это ресурсы, которые мы тратим в течение дня.

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

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

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

Мыслетопливо

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

Основная цель методики — научиться расходовать это самое мыслетопливо экономнее. Для этого автор предлагает:

  • принять отсутствие легкого пути;
  • регулярно восстанавливаться;
  • разгружать рабочую память;
  • регулярно очищать инбоксы;
  • не распыляться.

Регулярное восстановление требуется, потому что перенапряжение «умственной мышцы» снижает её удельную работоспособность. Грубо говоря, если фигачить 4 недели в режиме аврала, то к концу вам будет сложно справляться даже с простыми задачами.

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

Практически любое развитие происходит в точке покоя

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

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

Держать инбоксы пустыми тоже полезно, потому что большое количество задач или предстоящей работы оттягивает на себя внимание, заставляет думать о том, как вы будете это решать. (Или «как мало времени у вас на всё».)

Ну и…

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

Откуда берётся тревожность

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

Их можно сравнить с двумя системами мышления по Канеману: решала — это Система 2, основательное медленное мышление, логика, рациональность и всё такое; обезьянка — Система 1, быстро, импульсивно, на эмоциях.

Обезьянка ищет способы «получить удовольствие» и «сделать быстро». Именно из‑за неё человек долго прокрастинирует прежде чем начать работать над задачей. Так вот…

Незавершенные задачи создают стремление их завершить

Если работы очень много, наше естественное (обезьянье) желание — как можно быстрее со всем этим разделаться

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

В дополнение к этому уровень тревоги поднимают уведомления. Отключить уведомления бывает трудно: «вдруг я что‑то пропущу?», «не могу, специфика работы» и проч., но…

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

«Я не замечаю уведомлений» на самом деле стоит понимать как: «Я уже не осознаю, как и в какой степени эти уведомления меня бесят»

Чтобы определить свой уровень тревожности, нужно…

Сесть спокойно, расслабиться, запустить секундомер, закрыть глаза и позволить своим мыслям блуждать, как им заблагорассудится. Как только, по вашим ощущениям, пройдет минута — посмотрите на секундомер: он покажет, сколько реальных астрономических секунд в вашей субъективной минуте. Этот тест — отличный индикатор вашего текущего уровня тревоги. [Если ваша субъективная минута меньше 50 секунд — это проблема, прим.]

Искажения

Кроме тревожности на наше состояние влияют когнитивные искажения. Например…

Иногда мы подсознательно ищем нечто такое (пусть даже очень сложное), что стоит выполнить один раз — и наше желание исполнится

Путаем «сложно» (или «неэффективно») с «невозможно»

Путаем временную последовательность событий с причинно‑следственной связью

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

Ответ на последний вопрос — нет, потому что…

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

Более того, мы толком не умеем планировать, тоже в частности из‑за искажений:

Ещё один неприятный момент, вытекающий из раннего составления планов, — это эффект установки (einstellung effect). Он заключается в том, что наличие у вас какой‑то идеи препятствует появлению лучшей идеи

Сам по себе метод [SMART, прим.], возможно, очень даже полезен… но на практике его применение часто запинается о черту, свойственную живым людям, — избирательность внимания. Дело в том, что чем сильнее мы сосредотачиваемся на каком‑то объекте, тем больше вероятность, что мы упустим все происходящее вокруг этого объекта

Ну и вообще, жизнью правит неопределённость.

Неопределённость

Дорофеев часто отсылает к Талебу — тому самому, который про Чёрных лебедей. Неопределённость не только не даёт предсказать свою будущую производительность, но и мешает планировать проекты.

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

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

Есть способ с этим справляться:

План проекта — это не обязательство, это план. Он может меняться под воздействием обстоятельств

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

Сила воли и контекст

У меня когда‑то щёлкнуло и я перестал полагаться на силу воли, потому что у меня её нет. Я начал создавать вокруг себя такое окружение, чтобы сделать что‑то неправильно было просто «невозможно», или дико неудобно. Дорофеев примерно о том же:

Если вы не можете чего‑то избежать — упорядочьте это

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

Ешьте левой рукой… если вы постоянно ловите себя на том, что делаете что‑то слишком часто, сделайте это занятие менее удобным

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

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

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

Контекст, в которым вы находитесь, неразрывно связан с неопределённость. Я бы даже сказал, что он (no pun intended) определяется неопределённостью:

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

Указывать расстояние в днях пути без конкретизации способа передвижения уже неуместно

Если вы роете, это не гарантирует вам норку. Но если вы этого не делаете, вам практически гарантировано ее отсутствие

При попытке впихнуть невпихиваемое: 1) выпихивается ранее впихнутое; 2) уменьшается предел впихиваемости

Автор так же говорит, что не существует панацеи против всего этого:

Если сомневаетесь в том, что сможете заставить себя следовать этой (или какой‑либо еще) модели самоорганизации, — не сомневайтесь. Вы гарантированно не сможете себя заставить ей следовать

Но как минимум…

Не надо торопиться с… обещаниями

Не надо требовать от себя раз и навсегда прекратить посещение соцсетей. Именно в этом причина вышеописанной неудачи. Попробуйте добавить в свой список ежедневные повторя­ющиеся задачи вида «провести пятнадцать минут за чтением новостей»

Методология

Закончили с «предпосылками», перейдём и к самой методологии из книги. Всю поступающую информацию мы делим на:

  • задачи;
  • проекты;
  • справочную информацию;
  • встречи.

Самое главное — не перемешивать все эти сущности

Задачи

Задача — это ответ на вопрос «Что нужно сделать». Для задачи очень важна формулировка. Видите ли…

Список задач — это инструмент преимуще­ственно для вашей внутренней обезьянки

Правильная формулировка задач призвана снизить интенсивность мыслительной жвачки

Задачу можно выполнить, по минимуму используя мышление

Последний пункт «по минимуму используя мышление» — критичен. Потому что если задача непонятная, мозг выберет вместо неё какое‑то более простое занятие. Задача будет откладываться, дело не будет делаться.

Поэтому, например, вместо «Вася» задача должна быть сформулирована как‑то типа «Договориться с Васей о встрече в понедельник». Таким образом:

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

Может показаться, что писать такие формулировки — долго, но…

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

Чётко поставленные задачки всегда будут побеждать крупное, общее и неконкретное

То же самое с делегированием:

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

Также автор рассказывает о том, как быть с задачами, которые «надо сделать СРОЧНО!!!»:

Есть задачи «должно быть», если их не выполнить, гнев руководства или коллег не заставит себя долго ждать Встречаются задачи‑«ублажители». Часто именно они способствуют достижению целей, их систематическое выполнение дает долгосрочный положительный эффект. Но если их не выполнять, то как минимум в краткосрочной перспективе никакой беды не будет

Многие люди изо дня в день склонны группировать «должно быть» (объединять в большие партии, чтобы сделать одним махом все сразу), оставляя «ублажители» и задачи типа «больше — лучше» на потом

…для таких «задач‑ублажителей» он советует применять принцип 20/80. Лучше делать что‑то медленно, чем не делать вовсе.

Кто не роет, у того нет норки

Проекты

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

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

А вот с планированием уже посложнее, там придётся отвечать на вопросы:

  • Что надо сделать?
  • Чтобы что? (Зачем это делать?)
  • А что ещё? (Что мы пропустили?)
  • А не то? (Что произойдет, если проект не будет выполнен?)
  • И что? (Насколько страшны и суровы последствия невыполнения этого проекта?)
  • Кому и для чего нужны результаты этого проекта­?
  • Как ещё можно достичь «чтобы что»?

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

А также не забываем о неопределённости (мы не умеем прогнозировать производительность) и искажениях (эффект установки, фокусировки, прайминг, вот это всё). Как с этим жить — ¯\_(ツ)_/¯

Справочная информация

Самое важное при добавлении новой справочной информации — определиться…

Когда (при каких условиях) этот кусочек мне потребуется? Где я, скорее всего, буду его искать в этот момент? Эти два вопроса — элемент заботы о будущем себе

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

Встречи

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

Образ жизни

Иногда мы путаем проекты с образом жизни:

Огромная часть всего того, что мы считаем проектами, на самом деле — новый способ жить

Для таких штук (в книге этого нет, но) я использую текущую инициативу.

Упарываться в новый образ жизни с головой тоже не стоит. Лучше делать как писал Буров у себя в канале — разбивать «образ жизни» на куски. Смотреть, нравится ли, и после этого принимать решение, продолжать или нет. И не давать обещаний слишком рано.

Чек‑листы

Чек‑лист помогает стандартизировать процесс выполнения какой‑либо задачи или проекта. Снова мы разгружаем рабочую память от попыток удержать всё в голове — создаём список, по которому внутренней обезьяне будет проще идти и тупо выполнять, что написано.

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

Помидоры

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

Каждый «помидор» должен состоять из трех основных этапов:

Подготовка к помидору. Просмотрите свой список задач и решите, что вы сделаете в следующие 15–25 минут

Помидор. Поставьте таймер и начните работать

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

Обзоры задач, проектов, системы в целом

Обзоры нужны, чтобы быть «рациональным фланёром» — корректировать план при возникновении новых исходных данных в контексте. Обзоры мы делим на ежедневные, еженедельные и по требованию.

Ежедневные нужны, чтобы спланировать день.

  • Просмотрите запланированные на сегодня, но не выполненные задачи. Надо ли вам в связи с этим что‑то сделать прямо сейчас?
  • Какие задачи вам надо будет выполнить завтра­?
  • Есть ли в вашем списке на сегодня задачи, которые менялись больше суток назад? Переформулируйте их.

Еженедельные — чтобы спланировать (сюрприз) неделю:

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

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

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

Ключевой момент — ограничить время и ни в коем случае не стараться сделать все сразу и идеально

Страхи и «кроме работы»

Если вдруг методология (или что‑то по мотивам, как у меня) начнёт работать, и у вас появится свободное время, вместе с ним могут появиться некоторые страхи и опасения о возможных проблемах в будущем.

Столько всего не сделано!

В этом случае, как и раньше, вам придётся делать не все

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

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

В списке задач отсутствуют личные задачи

Самое страшное — не разгребание накопившихся входящих, а отсутствие ответа на вопрос «ради чего мне вообще надо поддерживать порядок

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

Попытки сделать всю работу перед тем, как заняться собой (нарушение принципа кислородной маски)

Неявные списки задач

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

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

Делегирование будущему себе

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

Нетерпимость к незавершенным делам

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

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

Итого

  • В любой непонятной ситуации — думать.
  • Думать всё‑таки придётся.
  • Регулярно проводить обзоры.
  • Уменьшить вредные переключения.
  • Не доверять силе воли, а менять контекст.
  • Кто не роет, у того нет норки.
  • Главное — не время, а мыслетопливо.
  • Найти любимое дело за пределами офиса.
  • Время и силы, которые удалось «отвоевать» у работы, тратить только на себя.
  • В этом мире не всё везде и всегда, а кое‑что иногда и местами.

Из приложений к книге

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

Список литературы

Книги:

Посты крутых ребят:

Мои посты:

Википедия:

Чёрный экран смерти в Тяжеловато, отчёт об инциденте

25 ноября в 9:10 по Московскому времени вышло обновление приложения Тяжеловато для iOS под версией 1.2.

Релиз привёл к поломке, из‑за которой пользователи в течение полутора суток не могли пользоваться приложением. Приложение открывалось на телефонах, но показывало чёрный экран и не реагировало на жесты и перезагрузку.

Устранить проблему полностью у нас не получилось.

26 ноября в 9:05 было подготовлено обновление с частичным исправлением.
В 19:42 оно стало доступно пользователям в магазине.

Предпосылки

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

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

Мы удалили AppCache‑манифест и ссылки на него в патч‑обновлении, следовавшем сразу после первой версии.

Недавнее обновление веб‑версии и перевод её с AppCache на ServiceWorker прошли гладко. В обновлении для Android «чёрных экранов смерти» также не появлялось. Тестовая сборка приложения в TestFlight и переход на ней между версиями также не показывали подобных проблем.

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

Хронология и анализ

25 ноября в 9:10 по Московскому времени мы запаблишили обновление в AppStore. Обновление должно было использовать старую кодовую базу, а после нажатия кнопки «Сохранить бюджет» — обновить ядро приложения и перейти на новую.

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

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

В 10:06 после разговора с пользователем, который непосредственно пострадал от последствий, гипотеза подтвердилась. Мы начали думать над тем, как исправить ситуацию. Почистить кэши принудительно мы могли только с помощью нативной оболочки.

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

К 20:21 исправление было протестировано на разных версиях iOS и под разными устройствами. Проблема, казалось, была решена и подготовили обновление к релизу в AppStore.

26 ноября в 0:37 после более тщательной проверки выяснилось, что обновление всё‑таки проблему не решает. Принудительное очищение кэшей в оболочке срабатывало не стабильно.

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

В 8:43 мы решили больше не рисковать и помочь пользователям обновить приложение вручную.

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

Инструкция «Что делать дальше»
Экран позора — инструкция «Что делать дальше»

В 9:05 обновление было готово к релизу.

В 11:17 исправление было отправлено в магазин.

В 18:02 приложение прошло ревью магазина.

В 19:47 исправление стало доступно пользователям.

В 19:51 появилось первое сообщение от пользователей, что чёрный экран смерти пропал.

Текущий статус

Свежая версия работает в штатном режиме.

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

Выводы и работа над ошибками

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

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

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

Также ошибкой было считать, что обновление не содержало “breaking changes”. По принципу «Сделать всё за пользователя» переход между версиями технической базы я решил сделать плавным и незаметным.

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

Компоненты — это организмы

Я достаточно долго пытался сформулировать для себя, что такое «Компонент».

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

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

Компонент, как изолированная сущность

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

Это важно, потому что проектировать что‑либо без чётко‑выделенных сущностей — больно и неэффективно.

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

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

ДНК компонентов

Организм развивается под действием ДНК и внешней среды. Компоненты — так же.

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

Давайте на примерах.

Чтобы Текстовое поле могло выжить, оно должно уметь показывать, что в него можно ввести текст и отображать этот введённый текст.

Кнопка должна уметь показывать, что на неё можно нажать, и по нажатию что‑то произойдёт.

Если компонент не умеет делать то, что «должен», он не нужен — то есть он не выживает.

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

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

Если присмотреться повнимательнее, то видно, что одно из таких «внутренних правил» — это принцип единственной ответственности. Этот принцип (SRP) — часть ДНК компонента, которая составляет часть исходных данных, которые определяют жизненный путь компонента.

Компонент во внешней среде

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

Снова на примерах. Форма поиска — это совокупность компонентов — сообщество:

У каждого организма в этой совокупности есть собственная роль — специализация:

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

Внешняя среда может и будет меняться. Если среда меняется так, что наличия просто Текстового поля внутри Формы поиска недостаточно, поле может приспособиться и превратиться в Автокомплит, поле с Тегами, что‑то ещё, что позволит ему делать свою работу — выживать — лучше.

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

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

Эволюция компонентов

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

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

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

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

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

Эволюция среды

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

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

Кнопка — отличный пример. Когда на сайте нет никаких форм кнопка мимикрирует под ссылки — она выглядит как кнопка, нажимается как кнопка, по нажатию что‑то происходит — но это не кнопка.

И это я ещё даже не говорю о компонентах‑паразитах; это, пожалуй, на какой‑нибудь другой раз.

Дизайн‑системы Экосистемы

Компоненты собираются в сообщества; сообщества — в группы; группы сообществ — в экосистемы. Экосистема — набор внешних и внутренних правил, по которым живёт проект.

Например, SRP — часть экосистемы, потому что диктует, как компоненты определяют свою специализацию. Наличие функции поиска на сайте — тоже часть экосистемы, потому что определяет, будет ли существовать, например, Форма поиска. Любое отношение между компонентами (симбиоз, паразитарные отношения) — всё это части экосистемы.

Экосистема (дизайн‑система) — это не «плакат со всеми сущностями в нашем проекте», нет. Это набор принципов и правил, которые определяют ценность проекта в целом и набор правил, по которым живут и развиваются сущности в этом проекте.

Капец ты двинутый

Как ни странно, всё это помогает проектировать системы с учётом таких старых друзей, как например SOLID.

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

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

Ссылки

Как и зачем мы переписали Тяжеловато на Тайпскрипт

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

Почему поддерживать код стало дорого

Было несколько причин.

Не было тестов

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

Не было нормальной архитектуры

Приложение, я напомню, я написал за 2 недели на коленке, там было не до архитектуры. (Ох уж этот дух стартапа!) По‑хорошему, после запуска надо было взять пару недель и отрефакторить там всё хорошенько, но что‑то (всё?) пошло не так.

Не было документации

Которая бы напомнила, что и как работает, и почему именно так. Казалось бы приложеньице маленькое, что там помнить‑то, но нет! Как хранятся даты?.. Это поле стейта за что отвечало? Так, это‑то с чем связано? Господи, а это что ещё за хрень? И прочее‑прочее‑прочее.

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

И вот в 2019 году — случилось. Мне бомбануло окончательно, и я начал думать, как это можно изменить.

Как это можно было изменить

Мне было понятно, что если я начну исправлять ситуацию, меня будут преследовать две мысли.

Я это уже делал. Зачем тратить силы на то, что уже сделано?

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

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

Поуправлять разработкой — это передать опыт, попробовать посмотреть на процесс шире, выйти в надсистему. У меня как раз на примете было два человека, кто хотел и мог бы помочь: Виктор Дёмин и Фёдор Кузнецов. Собственно, с ними мы и затеяли весь этот карнавал.

Реанимация проекта — я не то чтобы рассчитывал на это, этот пункт скорее был бонусным. Меньше ожиданий — лучше. Однако, проект ожил.

Не навреди!

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

То есть, нельзя было пофлексить что‑то, что уже работало. Нельзя было выпилить фичу просто так, на то должна быть веская причина. И, разумеется, нельзя было просрать пользовательские данные. (Если вдруг что‑то пошло не так, напишите, пожалуйста, на support@fuckgrechka.ru.)

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

Дальше оставалось определить стек и технические ограничения.

Стек и технические ограничения

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

Одним из технических ограничений «со звёздочкой» было минимальное количество зависимостей и размер бандла. Вторым — отсутствие классов: у нас только функциональные компоненты.

Второе действительно заставляет думать про отделение бизнес‑логики от административной. Хуки помогли не размазывать логику по жизненному циклу компонентов, а собрать её в одной функции — SRP, все дела.

Последним (и по совместительству определяющим ход разработки) ограничением был выбор между двумя стульями: JS или TS. Сейчас расскажу, почему выбрали Тайпскрипт.

Почему выбрали Тайпскрипт

Мне хотелось нормальных типов, а не 0 !== '0' и вот этого всего. Хотелось проектировать, как нормальный человек, а не писать тонны jsdoc к каждой функции. Хотелось, чтобы код сам говорил, что он делает, а не прятался за комментариями, которые один хрен устареют и потом сиди‑думай, чему верить. В Тайпскрипте всё это в какой‑то мере есть.

Типы

Да, присвоить переменной типа string значение типа number уже не выйдет — и это прекрасно! Потому что за пределами классической песочницы‑туду‑листа, я буду путать не string и number, а структуры данных и сущности. И если редактор мне подсказывает: «дорогой, у тебя здесь должен быть просто Record, а не Spend», то я готов писать хоть на C#.

Автоматическая документация

Идеальная документация — это та, которой нет, а её функция выполняется. Типы, интерфейсы и сигнатуры функций — это и есть такая документация.

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

Ещё Тайпскрипт позволяет использовать тип‑алиасы для примитивов. Например, DayStartTimeStamp — тип, который описывает временную метку в UTC, отсылающую к началу определённого дня.

Это алиас для обычного number, просто он назван понятно. Я мог быть указать где‑то в комментарии, что startDate указывается в миллисекундах по UTC… но если у меня есть возможность указать это прямо в коде — то я лучше так и сделаю.

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

А вот так эта функция потом используется:

Понимать такой код потом получается быстрее и менее напряжно.

Архитектура

А этот параграф — ода интерфейсам. Если вы однажды упоролись по SOLID, то обратной дороги уже нет, проектировать систему без абстракций становится больно.

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

Тесты и рефакторинг

Для разработки мы выбрали методологию TDD. Здесь Тайпскрит тоже пришёлся кстати, потому что имея типы и интерфейсы проще создавать (или генерировать, кому как больше нравится) стабы и моки.

В рефакторинге же самое кайфовое — использовать встроенные инструменты IDE: rename symbol, extract function и прочее. Мне не нужно беспокоиться, переименовал ли я все сущности в проекте — об этом позаботится IDE. Моё дело — подобрать правильное название, дальше — пусть потеют роботы.

Минусы

Самый жирный минус Тайпскрипта — он требует времени. Много. Дополнительного. Времени.

Оно будет уходить на то, чтобы покрыть функции и методы типами, привести в соответствие с типами все аргументы, понять, почему какой‑то тип не работает для метода из сторонней библиотеки. (Здесь шутка про «нельзя просто так взять и написать быстрый черновик функции, не используя any».)

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

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

Окей‑окей, а когда обновление‑то?

А оно в продакшене уже :–)

  • Если вы пользуетесь веб‑версией, то скорее всего, приложение на телефоне обновилось само.
  • Обновление для Android появилось в магазине пару недель назад.
  • Обновление для iOS появится совсем скоро.

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

Ссылки

О приложении:

Скачать БЕЗ РЕГИСТРАЦИИ И СМС:

Крутые ребята:

Хвастаюсь книгами:

Всякое‑техническое:

Раньше