Эффективная команда (расшифровка доклада)

Доклад "Эффективная команда" я рассказывал дважды: в Ульяновске на Стачке и в Москве на РИТ++. Видео и слайды доклада доступны в предыдущем посте. Здесь текст выступления, достаточно близкий к тому, что я рассказывал. Если текст кажется слишком длинным, почитайте сразу Резюме, если с чем-то несогласны, возвращайтесь к тексту.

Введение

Пару слов о себе: я проработал бóльшую часть времени в российских компаниях от маленького до среднего размера, занимаясь как разработкой своих продуктов, так и разработкой на заказ. Четыре года назад я пришел в небольшой (на тот момент) американский стартап Qik, который вырос и прошел через два поглощения подряд: Skype купил Qik, а Microsoft купил Skype.

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

Для меня этот доклад начался с вопросов, которые я сам себе задавал долгое время:

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

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

Под эффективностью здесь я понимаю определение, которое дает Википедия:

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

Я предполагаю, что качество зафиксировано (мы ведь все хотим создавать качественные продукты!), а вопрос состоит только в том, какой ценой будет создан продукт. Здесь я имею в виду не столько финансовый вопрос, а, скорее, затраченные ресурсы: время, нервы, огорчения и радости, упущенная выгода и т.п.

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

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

Микрокоманды

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

Идеальная команда

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

  • я разрабатываю то, что хочу;
  • мне нет необходимости с кем-то встречаться, пытаться найти общий язык;
  • быстрая обратная связь: я сделал изменение, оценил результат, исправил, двинулся вперед;
  • нет проблемы человеческих отношений;
  • я выбираю те инструменты и платформы, которые мне интересны, я развиваюсь.

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

Заказчик + разработчик

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

Команда из двух человек все так же эффективна:

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

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

Зачем нужна команда?

И все-таки, команды больше чем одного-двух разработчиков существуют повсеместно. Значит, существуют преимущества у большой команды?

Bus Factor

Самый яркий аргумент за создание большой команды - это Bus Factor. Bus Factor - это то количество членов команды, которые можно безопасно посадить в один автобус: если автобус попадет в ДТП и эти члены команды погибнут, то проект не погибнет, у оставшихся членов команды хватит знаний и навыков, чтобы успешно его продолжить. Совершенно не обязательно, чтобы событие было фатальным - в более широком смысле это может быть декрет, отпуск, увольнение, болезнь, травма, и т.п. Таким образом, bus factor является мерой равномерного распространения знаний внутри команды.

При этом размер команды сам по себе не решает проблему bus factor - если в команде только один человек обладает знаниями о какой-то части проекта, bus factor так и остается равным единице.

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

Обмен знаниями

Следующим несомненным преимуществом команды является обмен знаниями. Каждый человек обладает уникальным опытом, талантами, которые в команде могут быть раскрыты полностью. Любые формы неформальных, спонтанных технических обсуждений в здоровой команде приводит к появлению новых идей, рассмотрению проблемы с разных сторон, анализу решений. После таких обсуждений команда чувствует принятое решение "своим", а не навязанным сверху, не принятым единолично. При этом с моей точки зрения самая большая проблема микрокоманд, с которых мы начали вопрос рассмотрения эффективности - это отсутствие обмена знаниями, которое необходимо компенсировать каким-то другим образом (конференции, meetup, coworking, и т.п.)

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

Собрать профессионалов из разных областей

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

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

Сглаживание ритма работы

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

Надо делать больше!

Увеличение размера команды ради увеличения эффективности - это одна из основных ловушек процесса разработки. Что еще более удивительно, в эту ловушку попадает сама команда вместе со своим лидером. Когда лидер оказывается под давлением начальства, команда не успевает в срок выполнить задачи (в срок, который чаще всего не был согласован с командой), лидер пытается перенести давление обратно на начальство, и ему необходимо потребовать что-то, что потребует участия руководства и дополнительных расходов. Самый простой вариант - попросить нанять еще разработчиков. Все звучит очень логично, но поможет ли это команде? Сделает ли это ее более эффективной? Совершенно точно не поможет в краткосрочной перспективе: увеличение размера команды приведет к значительному снижению производительности. В долгосрочной перспективе такое изменение может быть положительным, но только если удастся держать размер в разумных пределах (3-5 человек), разделяя большие команды на маленькие (что требует соответствующего разделения продукта на компоненты).

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

Проблемы команд

Рассмотрим негативное влияние команды (большой команды) на эффективность работы.

Увеличение продуктивности? Больше встреч, чем работы?

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

Контроль! Divide et impera! Разделяй и властвуй!

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

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

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

Команда склонна к росту

Как мы уже обсуждали, при росте команды ее общая эффективность начинает падать при достижении некоторого критического размера (3-5 человек), при этом также падает и эффективность каждого отдельного члена команды. Как было отставание от сроков, так и осталось. Можно пытаться найти любую внешнюю причину падения производительности, но сложнее всего просто признать неэффективность команды. Однако одним из "выходов" является дальнейшее увеличение численности команды, которое, само собой, уменьшит эффективность еще больше. Таким образом, происходит дальнейшее разрастание команды, заводящее ситуацию в тупик.

В качестве еще одного примера можно привести практику составления плана по найму новых сотрудников на достаточно длительный срок (полгода-год). В этой ситуации лидер команды, не имея четкого представления об объеме и сложности задач на такой длительный период времени, пытается перестраховаться и заносит в план по найму нескольких новых сотрудников "на всякий случай". Отдел найма, который получил утвержденный план, будет изо всех сил стараться его выполнить, так как выполнение плана является для них критерием эффективности. Эти сотрудники будут наняты, и теперь команде придется вырасти, даже если в этом не было необходимости.

Увеличение числа связей

С ростом команды число связей между людьми растет как квадрат от количества членов команды. Каждая такая связь требует времени: надо поздороваться, перекинуться парой слов, уговорить использовать что-то и т.п. Здесь самым важным является то, что число связей растет значительно быстрее роста самой команды, естественным образом ограничивая размер эффективной команды. С моей точки зрения это 3-5 человек.

Человеческие отношения

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

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

  • можно ли использовать мат?
  • "жаворонки" vs. "совы";
  • тон разговора: кто-то говорит резко, а для другого это может быть обидно;
  • аудитория разговора: можно ли высказывать негативное мнение о чужой работе так, что это услышит вся команда?

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

Кастовая структура

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

Гораздо большей эффективности команда может достигнуть при отсутствии каких-либо кастовых разделений: более опытные разработчики либо сами, либо в паре с другими членами команды, либо на этапе review участвуют в создании самых сложных или ответственных частей системы, обеспечивая корректность основной архитектуры. Инженеры с меньшим уровнем знаний растут, выполняя все более сложные задачи, участвуя в парном программировании. Конечно, чтобы это было возможно, уровень команды должен быть более-менее однородным. Если сотрудники низкой квалификации рассматриваются как способ выполнения совсем простой, рутинной работы, такую работу лучше автоматизировать силами "старших" разработчиков.

Как остановить рост команды?

И все-таки, если большая команда - это огромное количество проблем, а команда нам все-таки необходима, как соблюсти баланс размера команды? Как сделать так, чтобы команда оставалась эффективной?

Автоматизация не дает команде расти

Автоматизация позволяет не только не нанимать большое количество людей для решения рутинных задач, но и кардинально улучшает качество выполняемых работ, исключая из работы "человеческий фактор". Более того, процесс автоматизации связан с созданием инструмента, который является внутренним продуктом, то есть вслед за разработкой сразу происходит применение продукта, возникает обратная связь и мотивация полезности: "то, что я делаю, является полезным другим людям". Такая мотивация повышает эффективность работы, делает задачу автоматизации увлекательной. Желательно, чтобы автоматизацией не занималась специальная команда, т.к. отсутствие связи с реальным клиентом внешнего продукта компании также демотивирует ("я все время делал только внутренние сервисы").

Примеры автоматизации:

  • Chef/Puppet вместо ручной настройки каждого сервера (автоматизация труда системных администраторов);
  • Capistrano и подобные системы разворачивания проекта (вместо ручных действий при каждом deploy);
  • облако вместо работы с "железными" серверами;
  • ORM вместо ручного создания таблиц/хранимых процедур (конечно, это применимо не всегда);
  • и т.п.

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

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

Качество не дает команде расти

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

Команда производит некачественный продукт, и это обычно обнаруживаются уже после того, как продукты был выпущен. Менеджмент компании находится в состоянии истеричной попытки сделать хоть что-то, чтобы исправить положение. Команда, до выпуска продукта находившаяся в убеждении, что они делают все правильно, вдруг понимает что что-то пошло не так, впадает в депрессию. Команда либо пытается спихнуть вины за провал на внешние факторы: другие команды, процессы, болезни, климат, либо принимает на себя вину за проблемы качества, обещает все исправить в ближайшее время. При этом ключевых выводов о причинах такого низкого качества не делается, вместо этого вводится процесс оценивания багов по приоритетам, метрики количества обнаруженных/исправленных багов, исправлению багов отводится фиксированный процент времени разработки. Команда боится вносить какую-либо серьезные изменения в код, так как это может привести к еще большему количеству багов. Без больших изменений исправить ситуацию не удается, мотивация внутри команды страдает ("мы только и делаем, что исправляем баги"), в то же время в силу повышенного внимания к команде со стороны руководства они ощущают себя "избранными мучениками", страдающими "за дело". Все это не приводит к эффективной работе, а значит менеджмент принимает единственно верное с их точки зрения решение: команду надо увеличить, что приводит, конечно же, к еще большим проблемам.

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

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

Самые общие компоненты критерия качества:

  • continuous integration как способ автоматизировать контроль качества;
  • unit-testing как способ проверки алгоритмических и других базовых участков кода;
  • системное тестирование как способ проверки компонентов;
  • интеграционное тестирование для анализа взаимодействия компонентов и тестирования продукта в целом;
  • ручное тестирование;
  • анализ покрытия кода каждым из способов тестирования;
  • проверка стиля кода;
  • статический анализ кода с целью выявления уязвимостей, ошибок и т.п.;
  • динамический анализ, например, корректности блокировок в многопоточных программах;
  • профилирование, microbenchmarks, контроль использования памяти;
  • нагрузочное тестирование;
  • слепое тестирование на предмет поиска уязвимостей;
  • постоянное интеграционное тестирование в боевом окружении с целью быстрого выявления отказов;
  • тестирование с имитацией отказов;
  • анализ всех необработанных исключений;
  • наличие нескольких окружений для тестирования изменений;
  • автоматизированный мониторинг с большим количестве различных проверок, эшелонированная защита с целью раннего выявления сбоев.

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

История из жизни: команда разрабатывает серверную систему, состоящую из большого количества компонентов. Каждый разработчик по сути занимается своим компонентом (здесь и кроется проблема!). Система разрабатывается долго, в течение 2 лет, после бурных обсуждений архитектуры. Я разговариваю с одним из разработчиком, он с гордостью рассказывает о своем компоненте, показывает тест, который демонстрирует, что этот компонент свободно перемалывает сетевой трафик на скорости 20 Гбит/с. Через какое-то время команда предпринимает попытку собрать все компоненты воедино, но оказывается, что все вместе они нормально не работают. То есть эти 20 Гбит/с в одном из компонентов системы ничего не говорят ни о работоспособности, ни о производительности системы в целом. Просто критерий качества был выбран неверно: никто не пытался с первого дня разработки запускать интеграционный тест. Эта же проблема определяла такой долгий срок разработки относительно простой системы.

Кросс-функциональность

Как вы думаете, кто запечатлен на фотографии? Это 1922 год, баскетбольная команда из США. Это - команда, они почти все одинаковые, кроме двух тренеров, игроки готовы в любой момент выйти на поле. Каждый будет играть на своей позиции, но они играют вместе, готовы заменить друг друга, помочь в любой момент.

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

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

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

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

В идеале, кросс-функциональность означает, что одну задачу может довести до конца один человек, даже если эта задача требует знаний из разных областей, таких как верстка, разработка, системное администрирование и тестирование. Если разделять выполнение задачи на этапы в соответствие с функциональными обязанностями, возникает большое количество "передач управления" между членами команды, которые приводят к задержкам, а также возможны возвраты на предыдущие этапы, если, например, на этапе тестирования окажется, что все было разработано неверно. Если задачу разделить на отдельные задачи опять-таки по функциональному признаку, ситуацию это не улучшит, когда несколько разных людей будут делать "независимо" куски одной и той же, изначально логически цельной, задачи. Сказанное не означает, что над одной задачей должен работать только один человек, это может быть парное программирование, несколько людей, но это не должен быть конвейер вида: разработка-тестирование-системное администрирование. Лучше, если каждый из тех, кто занимается задачей, сможет довести свою часть до конца (или в паре в случае парного программирования).

Что происходит снаружи команды?

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

Дробление на компоненты

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

Самое частое и естественное (и, на первый взгляд, верное) разделение - это деление по языку программирования/методу разработки: команда БД, команда Java, команда Objective C/iOS/Mac и т.п. Такое разделение рождается естественным образом - в связи с открытием нового направления разработки в компанию нанимают специалиста в новой области, например Python, а он набирает свою команду. В результате команды разделяются по специализации без учета тех компонентов, которые они реализовывают.

Разделение системы на более мелкие компоненты (как в серверной, так и в клиентской разработке) добавляет ей гибкости, позволяет более тонко формировать команды. Компоненты при этом, конечно, должны быть по возможности однородны, т.е. использовать одни и те же framework'и, языки программирования. Формирование команд по принципу "данная команда может сама предоставить конечному пользователю новую функциональность" гораздо правильнее. Примером такого формирования может быть команда "управление пользователями", которая реализует на всех уровнях, от базы данных через серверные компоненты к web-страницам и интерфейсу клиентам, функциональность по аутенфикации пользователей, регистрации, удалению, поддержке интерфейсов аутенфикации для других внутренних сервисов. Такая команда может сама (без помощи других команд) предоставить пользователю новую существенное возможность, например, поддержка аутенфикации через Facebook.

Архитектура проекта

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

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

  • никаких усилий, сразу: наша команда разрабатывает непосредственно продукт для конечного пользователя, все что, мы разработали, сразу становится доступно;
  • очень много усилий, 6-9 месяцев: наша команда разработала набор хранимок в БД, которые теперь должна обернуть команда серверной разработки в подходящий API, а потом команда библиотеки общего клиентского кода предоставит API для клиентских приложений, который будет оборачивать серверный API, и на этом этапе обнаружится дефект в реализации, который приведет снова к пути по цепочке, ну и наконец, команда разработки клиентского приложения возьмет новую версию библиотеки общего клиентского кода и прикрутит пользовательский интерфейс к той новой продуктовой возможности, которую мы выпустили 6 месяцев назад; затем клиентская команда обнаружит проблему в еще одном компоненте, не связанном никак с нашей командой, и отложит релиз еще на 2 месяца.

Какой вариант нравится больше? Какой из них мотивирует на создание новых и новых возможностей нашего продукта? При каком варианте эффективность будет выше?

Функциональное разделение

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

Чтобы выпустить продукт, разработчикам необходимо тестирование. Так как есть выделенная команда тестирования, тестированием разработчики себя не обременяют, отправляя в команду тестирования любые по качеству варианты продукта. Команд разработки много, команда тестирования выстраивает все входящие заявки в очередь и обслуживает их в прозрачном режиме. Она готовится тестировать новую версию продукта А, начинает тестирование, но обнаруживает несколько простых критических багов и возвращает версию команде разработчиков. Что произошло? Время команды тестирования потеряно зря, т.к. простые критические баги должны отсекаться на этапе разработки. Разработчики ждали результатов тестирования долго, но получили по сути не несущий информации ответ, что в новой версии критические баги, возможно даже не связанные с новой функциональности. После быстрого исправления багов новая версия встает в очередь на тестирование, и все повторяется сначала.

Каков будет результат? Команда тестирования перегружена, демотивирована, команды разработки всю вину за срыв сроков сваливают на команду тестирования и т.п. Такая схема не работает. Команда должна быть кросс-функциональна: и тестирование, и разработка должны быть ее частью. Данное утверждение не означает, что нет смысла объединить всех тестировщиков из разных продуктовых команд в единую "гильдию" для обмена опыта в области тестирования, выработки общих стандартов и т.п. Но разработка продукта не должна проходить через конвейер команд разного подчинения, выполняющих разные функции.

Dev vs. Ops

Чуть подробнее о взаимодействии разработчиков и системных администраторов: эффективность их совместной работы будет определяться их умением хорошо взаимодействовать. Конечно, хорошо, если системные администраторы и разработчики находятся в одной команде, но даже если команда системных администраторов автономна, необходимо обеспечить взаимопонимание общей цели - это успешная эксплуатация продукта в боевом окружении. Шаги по достижению это цели могут быть самыми разными - автоматизация конфигурации, выкатки, обслуживание мониторинга, настройка отказоустойчивых сервисов и т.п. Для улучшения взаимодействия можно одного из системных администраторов прикрепить к команде разработки, чтобы он почувствовал, как разрабатывается данный сервис. И наоборот, команда разработки видит задачи, которые стоят перед системным администратором, о существовании которых никто из команды даже и не подозревал.

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

История вторая, которая объясняет, почему первая история приводит к плохим последствиям. Мы случайно замечаем, что один из серверных компонентов, разрабатываемый другой командой, работает скорее всего неправильно (потребляет слишком много CPU). Мы обращаемся к разработчикам, объясняем ситуацию, разработчики пожимают плечами и отправляют к админам, т.к. у них нет доступа к серверам. Админ неохотно соглашается помочь, готов посмотреть логи, но не знает, что в них искать. Мы обращаемся обратно к разработчикам с вопросом, что искать в логах, но те затрудняются ответить, т.к. логи читают либо админы, либо тестировщики. В результате просим админа вырезать кусок лога и передаем его разработчикам на анализ. И т.п. История длится без всякого решения порядка недели, в результате откладывается выход одной из новых возможностей продукта. Наконец из отпуска выходит системный администратор, который работает без "стены" в голове, и он в течение 15 минут обнаруживает, что исполняемый файл сервиса был собран в отладочном режиме без необходимых библиотек поддержки, осуществляющих оптимизацию, что и привело к повышенному использованию CPU. С моей точки зрения, мораль этой истории двояка:

  • разделение dev/ops приводит к неэффективности, задержкам, излишним коммуникациям;
  • причина проблемы (неправильно собранный исполняемый файл) - это несомненная ошибка разработчика, готовившего релиз; выкатка такого релиза в боевое окружение - ошибка системного администратора, не проверившего элементарные вещи; но админы выкатывают то, что им передают разработчики, им запрещено проявлять самостоятельность (например, пересобрать исполняемый файл правильно); в результате разделение разработчиков а админов привело к серьезной ошибке.

История третья. Внедрение Chef в небольшой компании с тремя командами серверной разработки под чутким руководством одного системного администратора. Первая команда очень быстро начинает разрабывать шефовские рецепты. Может быть, потому что они использовали Ruby on Rails, и язык Ruby был им близок, может они самые гибкие из всех трех команд. Методом проб и ошибок команда доходит до конца и выкатывает автоматически сконфигурированное унифицированное окружение, повышает стабильность работы сервиса. Вторая команда вначале смотрит скептически, но увидев реальные результаты работы первой команды, подключается к написанию рецептов, две команды и админ работают вместе, постоянно улучшая код кукбуков. Третья команда смотрит на это и стоит на позиции "мы разрабатываем, а админы эксплуатируют", поэтому вопрос автоматизации конфигурации их не интересует. Первая и вторая команда легко наращивают сложность системы, повышают надежность за счет автоматического управления конфигурацией. В конце концов команда админов пишет рецепты Chef для серверных компонентов третьей команды без участия разработчиков. Результат оказывается плохо сопровождаемым, из-за этого при выкатках случаются проблемы. Третья команда наконец начинает участвовать в разработке рецептов для своих компонентов, но они так и не могут построить нормальные рецепты. Месяцы рефакторинга, и третья команда решает не допускать админов к изменению своих рецептов, т.к. "они могут накосячить". Градус недоверия между третьей командой и админами максимален, совместная работа идет плохо, страдает качество работы сервиса в целом.

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

Dev vs. QA

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

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

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

Product Owner / Product Manager

Еще один человек, который находится рядом с командой и играет ключевую роль в эффективности команды - это product owner или product manager или даже project manager, его должность может называться по-разному. Это может быть один человек или команда продукта, которая включает в себя также и дизайнеров, но всегда должен быть тот единственный человек, который ответственен за продукт, который определяет видение продукта, направление развития. Разработка программного обеспечения - это все-таки творческий процесс, который не похож на изготовление деталей на заводе. И удовлетворение от творческого процесса наступает не в момент перечисления заррплаты на счет, а при виде результата, когда продукт попадает к пользователю, когда продуктом пользуются. Задача продуктового человека направить усилия команд разработки в таком направлении, чтобы получился востребованный продукт, использование которого принесет удовлетворение разработчикам, а также мотивирует команду на движение вперед. Команда при хорошем продукте остается собранной, эффективной, быстро адаптируется под изменение продукта.

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

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

Роль процессов в эффективности

Существует огромное количество современных, модных методологий разработки (Scrum, Lean, Kanban и т.д.), многие из которых обещают увеличение производительности команды (эффективности) после внедрения. Я уверен, что сама по себе методология разработки не позволит увеличить эффективность или решить какие-либо проблемы, ее применение позволяет выявить те проблемы, которые приводят к неэффективности. Если команда эффективна, никакой процесс разработки ее не испортит, а неэффективную команду хороший процесс разработки, при наличии внутреннего желания команды измениться, может вывести уровень большей эффективности.

Резюме

Маленькая команда (3-5 человек)

Большие команды неэффективны из-за проблем взаимодействия, поэтому только небольшие команды без проблемы bus factor.

Сильные профессионалы

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

Экспертиза из разных областей

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

Продуктовое видение

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

Возможность выпускать продукт

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

Автоматизация

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

Фокус на качестве

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

Вместо заключения

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

Комментарии

Comments powered by Disqus
Contents © 2015 Andrey - Powered by Nikola