Постановка: что, зачем и чего не делаем
Самый частый вид работы — сделать то, чего в проекте ещё нет. Кнопку, отчёт, поле, интеграцию, целый раздел. И самая частая ошибка в нём — начать писать код раньше, чем сформулирована задача.
Раньше эта ошибка сама себя ограничивала: пока пишешь первые двести строк, успеваешь понять, что делаешь не то. Теперь двести строк появляются за минуту, и понимание не успевает. Отсюда знакомая картина: готовая, работающая возможность, которая решает не ту задачу.
Постановка — это ответы на три вопроса, и записываются они до первой строки кода.
| Вопрос | Что в ответе |
|---|---|
| Что именно делаем | одно предложение без «и», «а также», «заодно» |
| Зачем | что человек сможет после того, чего не мог до |
| Чего не делаем | список соседних хотелок, которые сюда не входят |
Третий вопрос — самый полезный и самый пропускаемый. Задача «сделать выгрузку в таблицу» безгранична: а фильтры? а несколько листов? а по расписанию? а по почте? Без явного «в этот раз не делаем» границы задачи определяются тем, насколько вы устали, а не тем, что нужно.
Вторая ловушка постановки — формулировать решением, а не задачей. «Добавить галочку в настройках» — это решение. Задача под ним: «бухгалтеру нужно отключать округление для одного контрагента». Формулировка решением закрывает дорогу к более простому варианту и часто оказывается неверной: может, галочка не нужна вовсе, а нужно правило по типу договора.
Отличить просто: задача говорит про человека и его затруднение, решение — про элемент интерфейса или кусок кода. Если в формулировке есть слово «кнопка», «поле», «таблица», «флаг» — вероятно, вы записали решение.
И третье, про агента. Соблазн — отдать ему постановку: «придумай, как лучше сделать выгрузку». Он придумает, и это будет разумно. Но разумно вообще, а не для вашего случая: он не знает, что выгрузку открывают в древней программе, которая не понимает объединённых ячеек, что её делают раз в квартал, и что человек, который её делает, не различает вкладки в таблице.
Постановку делает тот, кто знает предметную область, а знает её человек. Агенту отдают то, что после неё: разбить на шаги, предложить, как реализовать, написать. Это будет темой четвёртой главы.
Есть один вопрос, который стоит задать агенту на этапе постановки, и он единственный: «что ещё придётся решить, если делать вот это». Не «как сделать» и не «что делать», а какие вопросы всплывут по дороге. Ответ на него — список тем, о которых вы не подумали: права доступа, что показывать в старых записях, как это скажется на скорости. Каждую тему вы решите сами, но знать о них лучше до начала.
Это тот же приём, что в главе про края: агент хорош в перечислении того, что бывает, и плох в решении, что из этого важно именно здесь. Перечисление — работа по большому объёму знаний; решение — работа по знанию вашей области, которого у него нет.
Признак готовности
Задача сформулирована. Следующий вопрос — как вы узнаете, что она сделана. Ответ нужен до начала работы, а не после.
Признак готовности — это список из четырёх строк, и каждая проверяется отдельно.
1. Обычный случай работает. Самое очевидное и потому иногда пропущенное: взяли типичные данные, прошли путь целиком, получили то, что ожидали. Не «код выглядит правильным», а «я это запустил и увидел».
2. Края обработаны. Пусто, ноль, очень много, отрицательное, дважды подряд. Об этом отдельная глава — здесь важно, что края попадают в список готовности, а не остаются на «если будет время».
3. Старое не сломалось. Новая возможность почти всегда трогает что-то общее: запрос, функцию, таблицу, стиль. Проверка «а то, что было, работает по-прежнему» — отдельный пункт, и в проекте с живыми тестами он стоит одну команду.
4. Видно, если сломается. Если новое перестанет работать в среду вечером, узнаете ли вы об этом? Запись в журнал, счётчик, письмо при ошибке — что-то должно быть, иначе поломка будет жить до первого обращения от человека.
Про четвёртый пункт стоит сказать подробнее, потому что его пропускают чаще прочих. Он кажется избыточным: «я же только что всё проверил». Но проверили вы сегодня, а работать оно будет год, и вокруг него будут меняться другие вещи.
Минимальный вариант четвёртого пункта — запись в журнал при неудаче, две строки кода. Средний — счётчик успешных и неудачных попыток. Больший нужен не всегда, и решает это цена поломки: выгрузка, которую делают раз в квартал, и списание денег требуют разного.
Наконец, про агента в этой главе. Список готовности отдавать ему нельзя по той же причине, по которой нельзя отдавать постановку: он не знает, что для вас существенно. Зато отлично работает обратное — отдать ему готовый список и попросить проверить каждый пункт. Это механическая работа, и в ней он хорош: прогнать, сравнить, доложить.
Разница принципиальная: в первом случае он решает, что считать готовым, во втором — проверяет ваше решение. Первое — ваша работа, второе — его.
Края: где обычно ломается новое
Края — это места, где новое ломается. Их стоит перебрать вслух до начала работы, а не обнаруживать по одному в обращениях от людей.
Шесть общих краёв встречаются почти в любой задаче.
| Край | Как звучит вопрос |
|---|---|
| пусто | а если записей ноль? список пустой, поле не заполнено? |
| ноль | а если количество ноль, сумма ноль, делитель ноль? |
| очень много | а если записей сто тысяч? страница, память, время |
| отрицательное | а если возврат, скидка больше цены, минус на складе? |
| дважды подряд | а если нажали кнопку два раза? отправили запрос повторно? |
| одновременно | а если двое делают это в одну секунду? |
К ним добавляются края самой задачи, и вот они как раз самые дорогие.
Данные за прошлый период. Новая логика применяется к тому, что уже посчитано по-старому. Отчёт за сентябрь по новым правилам и за август по старым — это либо нормально и надо объяснить, либо ошибка и надо пересчитать. Молчание здесь — худший вариант.
Записи, созданные до правки. Вы добавили обязательное поле. У миллиона старых записей его нет. Что показывать, чем заполнять, считается ли такая запись корректной — три вопроса, которые придётся решить, и лучше до, чем после.
Практический приём, который помогает: перебрать края списком вслух, а ответ записать даже тогда, когда он «ничего не делаем». «Записей ноль — показываем пустую таблицу с подписью, это нормально» — это решение. Отсутствие строчки про ноль — это не решение, а пропуск, и отличить их потом невозможно.
Про агента здесь хорошая новость: перечисление краёв он делает отлично. Опишите задачу и попросите список того, что может пойти не так, — он назовёт и шесть общих, и часть тех, что специфичны для вашей области. Дальше вы отбираете: часть невозможна, часть неважна, часть придётся обработать.
И последнее: край, который решили не обрабатывать, — тоже решение, и оно записывается. Через полгода, когда край всё-таки наступит, разница между «мы решили, что этого не бывает» и «мы об этом не подумали» определит, как быстро вы почините.
Порядок работы: тонкий срез
Постановка есть, признак готовности есть, края перебраны. Остаётся сделать — и здесь главное решение касается порядка.
Есть два способа разбить работу. Слой за слоем: сначала вся база, потом вся логика, потом весь экран. Тонким срезом: одно поле проходит сквозь все три слоя, потом второе, потом третье.
Слой за слоем кажется разумнее: похожее делается вместе, не надо переключаться. Но у него есть свойство, которое перевешивает всё остальное: работающего результата нет до самого конца. Ошибка, допущенная в первом слое, вскрывается на третьем — когда переделывать дорого, а вы уже уверены, что первые два сделаны.
Тонкий срез даёт работающий результат через час. Он бесполезен как продукт — одно поле из десяти, — но бесценен как проверка: путь проложен, слои состыкованы, край найден. Остальные девять полей идут по проложенному пути и занимают вместе меньше, чем первое.
Теперь про агента, и здесь стоит быть точным, потому что именно в этой главе он полезнее всего.
| Шаг | Кто делает |
|---|---|
| постановка | вы: он не знает предметной области |
| признак готовности | вы: он не знает, что существенно |
| перебор краёв | он предлагает, вы отбираете |
| разбиение на срезы | он предлагает, вы утверждаете |
| первый срез | он пишет, вы читаете и запускаете |
| остальные срезы | он: путь проложен, работа однотипная |
| проверка по списку готовности | он прогоняет, вы смотрите результат |
Ключевая строка — первый срез. Его стоит прочитать целиком и запустить самому, даже если он написан за минуту: по нему принимаются все решения, которые дальше повторятся девять раз. Ошибка в подходе, замеченная на первом срезе, стоит десять минут; на десятом — полдня переделки.
Последнее про порядок: после каждого среза — запуск. Не после всех, не в конце дня, а после каждого. Причина та же, что у тонкого среза вообще: чем меньше изменений между «работало» и «не работает», тем меньше мест, где искать.
Это правило звучит занудно, пока не сработает: три среза подряд без запуска, потом ошибка — и вы ищете её в трёх местах сразу вместо одного. Время, сэкономленное на пропущенных запусках, возвращается с процентами.