Я буду много говорить о цене. Я верю, что инженерия это поиск наиболее эффективных ценовых решений, и не имеет значение чем цена измеряется: долларами, часами, боевым духом или потерянными возможностями. Некоторые цены платятся сразу, некоторые идут в долг. В бизнесе это все интуитивно понимают. Но некоторые цены менее очевидны нежели другие. Поэтому очень важно донести их до команды.
Среди наиболее опасных недооцененных цен — цена сложности. Цена сложности это долг, который накапливается при усложнении функционала или технологий при решении задач. Приложение, которое делает много вещей сложнее рефакторить в сравнении с приложением, которое делает одну вещь, поэтому изменения в коде занимают больше времени. Иногда сложность неизбежная цена, но только организации которые впитали концепт, могут надеяться предотвратить издержки в этой области.
Много лет меня сильно раздражали две вещи которые слышал от ПМов:
- Как сложно будет…
- А не можешь ли ты просто…
Мне нужно было некоторое время чтобы понять сильную интуитивную реакцию на эти фразы. Сейчас ответ кажется очевидным: реализация функционала часто только малая доля работы на протяжении жизненного цикла продукта. И да, мы можем «просто» написать логику, о которой кто-то мечтает. То, что может занять две недели сейчас, повышает суммарную цену всего функционала, который будет добавляться в будущем. Фактически, я утверждаю, что время потраченное на реализацию — одна из наименее интересных опорных точек при рассмотрении цены и пользы функционала.
Обычно она хитро или умышленно спрятана в функциях, которые имеют большую цену, в долгосрочной перспективе. В Yammer долгое время была функция, которая позволяла начать сообщение с «to:» и имени пользователя, которому нужно отправить приватное сообщение или имени группы, чтоб отправить группе. В 2008 году, что бы ее реализовать, тестировать и развернуть, я потратил около часа. Потом потратил примерно 40 часов своего времени (и вероятно 40 часов других людей), на протяжении 5 лет поясняя и обосновывая этот функционал. Этот 40 кратный перерасход на коммуникацию просто для того, чтоб позаботится о функционале, с учетом, того что мы рассматривали влияние на разработчиков перед тем, как они собирались программировать. Вы можете возразить, что эту проблему решает документация, но я вас могу уверить, что это хорошо документировано в коде… где-то.
Однако, при программировании цена сложности становиться более очевидной. Впервые, открывая новую секцию кода, вам необходимо сначала сориентироваться. Чем меньше кода — тем быстрее процесс. Даже хорошо построенный и написанный чистый код занимает определенное время на изучение, если содержит много вещей. Если что-нибудь упущено, то его надо будет переделать в будущем:
- вы могли «сломать» модульный тест;
- или вы внесли новый баг который попал к конечному пользователю, это стоит, вам или отделу качества, времени еще даже перед тем как попасть к вам.
Jim Patterson, бывший руководитель продукта в Yammer, установил цель в виде ускорения команды разработчиков. Он конкретно говорил о поисках путей, по которым менеджеры и инженеры были б на одной волне, и заботились о сложности. Этот вид отношений нужен между заказчиком и разработчиками. Каждый обладает скоростью, но наименее важный фактор для скорости в вашей инженерной команде — упорство. Разработчикам нужно открыто говорить о цене сложности, которую они платят сейчас, о том, что их волнует, и о предлагаемых альтернативах, которые могут сохранить сложность. Ваши отделы качества и поддержки пользователей будут более эффективны, если вам удасться сохранить низкую сложность.
Если ваш продукт имеет два переключателя для взаимодействия, они имеют 4 состояния (off-off, on-on, off-on, on-off), которые должны быть протестированы и должны быть понятны при работе с клиентами. Если продукт имеет три переключателя, то у вас 8 состояний, для четырех же их 16. Третий переключатель добавляет 4 состояния, и это довольно просто описать и реализовать, примерно так же, как четвертый переключатель добавляет 8 состояний. Это так же справедливо и для 6-го, который додает 32 состояния. И так: «Как сложно будет добавить переключатель?» — показывает недостаточное понимание итоговой цены. «Насколько мы усложним продукт, если добавим переключатель?» — приближает нас к правильным обсуждениям.
Патологичный пример цены сложности, который должен быть вытеснен из команды разработчиков — странная привычка видеть, как люди воспринимают баги на ровне с функционалом. Вот как это обычно работает: в некоторых случаях поведение не определено в требованиях, поэтому работает одним или другим путем, основываясь на случайных решениях при реализации. В итоге, пользователи приспособляются к такому поведению и сообщают о багах, когда логика меняется, несмотря на то, что никто не разрабатывал подобное поведение. Я видел системы недавно отрефакторенные с кучей странных условных операторов, предназначенных чтобы повторить, поведение которое было прежде. Это делает вашим руководителем энтропию и увеличивает сложность. Боритесь с таким подходом. Ваши ПМы, отдел качества и разработчики должны использовать здравый смысл, чтоб решить, что должно быть в проекте, а не слепо добавлять все что, только можно.
Пользователям тоже не нравится сложность. Кроме случаев, когда вы строго дисциплинированы и активно сохраняете свой продукт простым, вы поймете что, громадное множество ваших пользователей используют крошечное меньшинство функционала. Пользователи также платят цену за сложность — в виде переобучения, когда вы добавляете новые вещи в продукт. Вы можете решить, что нашли путь для уменьшения сложности, делая вещи скрытыми или дополнительными, но вы обманываете себя. Не могу сосчитать сколько раз, когда я случайно задействовал скрытый функционал в программе, тратил неприличное количество времени, пробуя понять, что случилось или как отменить изменения.
Со стороны продукта, лучший инструмент для устранения сложности — аналитика. Исследования показывают, что большинство идей продукта не в состоянии показать ценность, и даже больше — убрать ее. Если вы систематически тестируете влияние каждого изменения, можете отменить, те которые влияют негативно, но имеющие одинаковою сложность и нейтральны также отбросьте. Изменения, которые не влияют на производительность, все еще наносят вред продукту, потому, что добавляют технический долг, за что проект будет обязан платить в будущем. Иногда наилучшим решением для продукта — убрать что-то оттуда.
Кроме определения влияния изменений, аналитика также поможет пролить свет на сложность в разрезе времени. Весь ваш функционал должен регистрировать свое использование, и делать это прозрачно для пользователя. Покажите вашей команде, где найти эти данные, также поясните, как интерпретировать их, если им не понятно. В Yammer, где аналитика собрана почти по каждой функции, делает возможным каждому видеть этот шаблон: если разработчик работает в определенной области кода, и видит, что для обслуживания функционала необходимо большое количество времени, то предлагает отрефаткорить или другие изменения. Вместо того, чтоб тихо сделать эту работу, он или она генерирует отчет об использовании функционала. Эти данные передаются менеджерам, которые могут решить что делать, или может даже лучше просто убрать функционал. Это может сохранить время даже перед тем, как что-нибудь примет более серьезную форму, потому что менеджеры начнут спрашивать, насколько часто используется функционал, который они собираются улучшить. Множество вещей, которые были похожи на хорошие идеи, на деле оказались лишней тратой времени, и при этом сохранили сложность.
Научите всю команду понимать цену сложности и использовать аналитику, чтоб сохранить ее низкой.
Сложность также приноситься людьми с хорошими побуждениями при реализации. Разработка программы подобно вызову, и вызов в создании сложных систем с простым интерфейсом особенно заманивающий. Учитывая DSL, абстракции и соблазн создания фреймворка, который может быть использован годами. Это стимулирует нас добавить большой технический долг, который мы защищаем словами наподобие, «С ним будет проще если разобраться» и «Он сохранит нам кучу времени на программирование». В программировании цена написания кода необычайно большая: потому что включает понимание, взаимодействие и обслуживание.
«Исповедуйте» простоту в вашей организации. Хорошая инженерная практика не показная или импозантная. Получая тот самый результат, с более простым кодом, он будет более ценным для вашей организации. Очень часто это ущемляет людское эго, потому что лучшим инженерам нечего улучишь. Припоминаю в начале своей карьеры с наслаждением вел документацию к проекту. Это была возможность похвастаться умным кодом, тем, что как много он делает и как легко расширяем, любому, кто имел время прочитать всю эту великолепную документацию. Я был очень легкомысленным, когда рисовал сложные системы, которые проектировал на доске с прямоугольниками, стрелками и линиями. Был уверен, что документация и иллюстрации подтверждают, что я был реальный инженер. Когда на самом деле стал инженером, я понял, что чем проще что-нибудь создавать, тем меньшее количество необходимо документации и иллюстраций, и тем проще было для коллег — мы быстрее могли построить вещи для которых нас наняли.
«Исповедуйте» простоту в продукте и коде. Значение имеет, то что используется, а не то что было построено.
«Исповедуйте» простоту даже в общении. Выкиньте жаргоны, акронимы и раздутые описания вещей. Прославляйте простую и эффективную коммуникацию. Ваши лучшие люди должны уметь пояснить детям все, что делает организация. Ваши наихудшие люди это, те которые звучат умно и официально имеют издержки, чтоб были поняты.
Простота это очень сложный инженерный вызов, так как сложность будет требовать свои проценты со временем. Без сохранения простоты, вы всегда будете отставать от конкурентов, которые пытаются разрушить вас. Убедитесь, что вся ваша команда знает это.
Kris Gale, VP Engineering at Yammer.