Ранее на хабре публиковалась статья о том, как в теории выглядит Xp/Tdd в Пивотал Лабс, и были вопросы о том, возможнонужно ли это в действительности. Я попытаюсь объяснить, как это выглядит на практике и почему это может быть (внезапно) хорошо.
В последние полгода мне пришлось поработать в одном из больших банков на проекте с Pivotal Labs, в их нью-йоркском офисе. Это очень отличается от всей энтерпрайс-разработки, которую мне приходилось видеть до этого.
Первое, что бросается в глаза — это парные рабочие места, одинаковые эппл-машины с предустановленным софтом, двумя клавиатурами и двумя мониторами. Все работают в парах, пары ротируются внутри команды каждый день. Ты никогда не знаешь, где ты будешь сидеть завтра, с кем работать и над какой историей. Тебя могут перебросить из команды в команду в любой момент.
Рабочее время жестко ограничено, с девяти до полпервого работаем, затем час обед, затем продолжаем до шести. В шесть ноль одну ты свободен.
(Да, это на самом деле выглядит столь же чудовищно, как кажется. Ты не можешь втихаря установить любимый текстовый редактор, ты не можешь полдня раскачиваться, читая новости или технические ревью, ты не можешь обустроить угол и потрепаться с соседом, ты не можешь попробовать впихнуть новый фреймворк или библиотеку. Первые три месяца ты привыкаешь к новым личным границам, к тому, что кто-то смотрит когда ты печатаешь или думаешь, к тому, что половину или больше времени ты смотришь как работает другой, но уснуть или выключиться полностью не можешь, потому что он рассчитывает, что ты понимаешь, что происходит. Если ты ведешь, то ты объясняешь вслух каждый свой шаг).
Поэтому все, что тебе остается, это спросить его, какая история у нас сегодня в приоритете, и начать ее делать. Все требования пишутся в формате when-it-should, под который легко делать тестовые спецификации. Все спеки пишутся вперед имплементации, если кому-то срочно хочется наоборот, то напарник его поправит. В процессе обычно один пишет тест, второй имплементацию, потом наоборот.
(По духу это напоминает сериалы, где двое полицейских ездят по кругу по улице в одной машине, едят гамбургеры и комментируют происходящее).
К концу дня доделанная или недоделанная история, идет в Wip-коммит и завтра ее может начать кто-нибудь другой. Обычно за день успевают закончить одну историю и начать вторую, иногда больше — история никогда не распространяется на несколько дней и историю нельзя сохранить за собой. В коммите подписываются оба, но никого не наказывают, потому что вдвоем редко делаются рискованные изменения: они просто будут переписаны завтра.
На дженкинсе всегда включены тесты. Задеплоить на дев что-то в обход немыслимо, напарники не поймут. Закоммитить что-то без тестов — тоже, никто просто не поймет, что это, и скорее всего просто откатят. Написать в спеки что-то непонятное — тоже. Поэтому спеки всегда отражают то, что в тикет-трекере, а код работает так, как написаны спеки. Закоммитить просто тесты — можно, имплементацию еще кто-то завтра напишет.
Все спеки обязательно пишутся в абстрактном виде и включают мок-имплементацию, чтобы исключить зависимости от внешних сервисов. Не бывает такого, чтобы «тесты сломались потому что данные на внешнем сервисе обновились».
Конкретный технологический стек неважен и варьирует от проекта к проекту, наш текущий цикл выглядит, например, так: jira-ticket >> selenium feature spec >> enzymejest spec >> reactredux mock implementation >> react/redux real implementation >> spring boot backend service spec >> backend mock implementation >> spring boot backend real test with oracle mq whatever
.
Ui всегда использует consumer-driven contracts, то есть мы пляшем не от того, что есть в базе, а от того, что мы хотим видеть на форме.
История, которая в обычном виде выглядела бы как «нарисовать форму с десятью полями, валидировать и отослать в базу», начинает выглядеть как десять-двадцать историй с покрытием в пятьсот-тысячу тестов. Поместить поле на форму — одна история. Отформатировать инпут — другая. Отобразить данные из бэкенда — третья. Привязать данные бэкенда к базе — четвертая. Если где-то блок из-за недостатка информации, то состояние бэклога будет точно отображать блок, а не «у нас бэклоге живет история на сто пойнтов, которая кочует из спринта в спринт». Все истории пишутся юзерами и им понятны, нет историй из серии «рефакторинг базы данных», которые не сопровождаются user value.
Собственно баги при этом не оцениваются, не засоряют бэклог, видишь баг — почини, закоммить, пометь, к какой истории он относится. Так здоровее.
Персонально меня радует то, что такая система практически отодвигает любые дискуссии об implementation на этап, когда это уже никому не интересно. Если мы сейчас не знаем, какую базу данных мы хотим, мы будем читать данные из файла или мок-сервиса. Если нам не нравится сегодняшняя база, мы завтра напишем новый адаптер, потому что у нас есть спеки.
Весь код по определению прошел ревью. Не бывает такого, что кто-то пишет таб с двумя пробелами, а кто-то с четырьмя, а у кого-то вообще эклипс и табы. Не бывает, что один пользуется lombok, а второй пишет свойства ручками.
При том, что уровень программистов не бог весть какой, они часто ротируются и не очень хорошо знают нижележащие языки и фреймворки (что исключает суперостроумные хаки и красивости), они все по необходимости хорошо знают тестовые библиотеки, отличают моки, стабы и фейки, и могут писать внятные спецификации и при необходимости могут написать тестовую библиотеку самостоятельно.
Любые минимальные улучшения мгновенно распространяются по ротации пар, начиная от удобной горячей клавиши и заканчивая параметрами гит-комманд или особенностями фреймворка.
Ротация сильно способствует сохранности социальных навыков и позволяет очень быстро вовлекать новых людей, фактически за один цикл ротации обычно человек уже понимает, что происходит. При этом видение проекта в целом ему, как правило, не требуется, что исключает жаркие войны. Кроме того, нет неловкости от того, что «этот код писал наш старый друг дядя Вася и он обидится, если мы его удалим».
В командах обычно мир и благорастворение воздусей, потому что ротирующимися парами воевать друг с другом довольно неудобно. Поэтому все, в целом, дружат.
Когда видишь работающую систему, понимаешь, насколько трудно ее внедрить и насколько много противодействия извне. Нужна, главным образом, критическая масса маньяков, готовых работать таким образом и бескомпромиссных к предложениям типа: «Ребята, давайте один день играть в сику, а один день разматывать кабель», «давайте-ка по-быстрому в продакшен» и т.п. И нужно быть готовым принимать ее целиком. Если один человек из команды опаздывает, отказывается объяснять решения, или писать тесты, или разбивать истории — система теряет смысл и демотивирует остальных. Поэтому должна быть воля и ресурс для энфорсмента. Система сейчас получает быстрое развитие на Уолл-Стрит, хотя пока неясны пределы ее возможностей. Возможно, вскоре она поглотит традиционные способы разработки, по крайней мере, в привычном банковском энтерпрайзе.
Автор: rudnevr