True XP/TDD в Пивотал изнутри: как это выглядит и возможно ли это?

Ранее на хабре публиковалась статья о том, как в теории выглядит Xp/Tdd в Пивотал Лабс, и были вопросы о том, возможно\нужно ли это в действительности. Я попытаюсь объяснить, как это выглядит на практике и почему это может быть (внезапно) хорошо.

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


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

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

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

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

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

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

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

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

Конкретный технологический стек неважен и варьирует от проекта к проекту, наш текущий цикл выглядит, например, так: jira-ticket >> selenium feature spec >> enzyme\jest spec >> react\redux 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, а второй пишет свойства ручками.

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

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

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

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

Когда видишь работающую систему, понимаешь, насколько трудно ее внедрить и насколько много противодействия извне. Нужна, главным образом, критическая масса маньяков, готовых работать таким образом и бескомпромиссных к предложениям типа: «Ребята, давайте один день играть в сику, а один день разматывать кабель», «давайте-ка по-быстрому в продакшен» и т.п. И нужно быть готовым принимать ее целиком. Если один человек из команды опаздывает, отказывается объяснять решения, или писать тесты, или разбивать истории — система теряет смысл и демотивирует остальных. Поэтому должна быть воля и ресурс для энфорсмента. Система сейчас получает быстрое развитие на Уолл-Стрит, хотя пока неясны пределы ее возможностей. Возможно, вскоре она поглотит традиционные способы разработки, по крайней мере, в привычном банковском энтерпрайзе.

Комментарии 21

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

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

        0
        Да, гарантировать это невозможно. Пробелы в спецификации будут сколько документации, даже разнотипной, ты не напиши. Но по другую сторону находятся проекты, где вообще нет вменяемой спецификации или она настолько поверхностная, что ее доделывают на ходу, по мере выявления в ней недостатков. А порой не доделывают, а согласовывают неясные места ad-hoc где-то, с кем-то, по почте, и/или телефону, а потом, это в виде тасков, состоящих только из заголовка, спускается разработчикам. Они идут к лиду, который им это спустил и он обьясняет им, что именно нужно сделать. Да, и такое бывает. У нас на проекте, видимо, считается зазорным писать лишний текст. Соответственно выглядит и документация кода, и тестирование, и архитектура. Архитектура есть, но она тебя в принципе никак не ограничивает. Получается, что одна команда пишет так, другая — эдак. Компилится, билд не ломает- нормально. Гайдлайны — там же где и документация лежат. Их просто нет. Так работа превращается в сплошной квест. Ты просто каждый день складываешь паззл. Без картинки. Часть коллег просто демотивированна и забивают на работу где только можно. Но ниче, как-то проект двигается вперед, что удивительно. Медленно, плохо, но двигается.

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

          это другой мир, на самом деле.
      0

      Офигенная статья, и так мало комментариев. Я поражён.


      Описанные условия — адов ад. Но я хотел бы в это на полгодика окунуться. Посмотреть и пощупать как выглядит TDD и парное программирование доведённые до крайности.

        0
        пивотал, кажется, были пионерами в этой области, но сейчас их систему буквально копируют (вплоть до покупки парных станций) крупные банки, поэтому наверняка русские аутсорсеры ее тоже через какое-то время опробуют.
        0
        Осталось устранить стендапы, перевести всех на удаленку, платить не за жопочасы, а за закрытые тикеты и получится Zerocracy
          0

          Выглядит прикольно. Есть ли какие-то сравнения по качеству и скорости? Напишете статью на хабр?

            0
            нет, стендапы как были так и есть, хотя они становятся проще.

            на удаленку нельзя, в этом весь пойнт парного программирования.

            и платить за тикеты бессмысленно, программисты будут просто создавать больше тикетов.

            оплата тут вообще ортогональна процессу — там есть отдельные recognition-метрики, которые у каждого коллаборанта могут быть свои, потому что, например, это могут быть разные компании-аутсорсеры.
            0
            Отличная статья.
            Сам имею возможность поработать с сабжем. Но как часто бывает в статьях — высвечиваются привлекательные стороны, а о плохом — вроде как не и сказано — значит и нету. А это очевидно не так. Список минусов не меньше чем список плюсов. И как любое лекарство его надо принимать с умом и под присмотром квалифицированого «доктора».
            Кроме того в статье пропущена ключевая роль в этом процессе — TPM. Его квалификация и взаимодействие.
            Ничего не сказано о роли Ankor — кто такой и где его взять.
            Умалчивается а откуда беруться такие классные «десять-двадцать историй с покрытием» и что происходит когда они не классные или не беруться.
            Ну и т.д…

            В общем если представить, что проект состоит только из написания кода — то TDD\XP подход отлично решает проблему. Если же нет — то остаются пробелы и «пространство для улучшения».
              0
              Писать десять-двадцать простых историй — это как раз очень просто. Поле нужно добавить на форму — раз. Поле нужно валидировать — два. Поле нужно скрывать в зависимости от других полей — три. Введенную информацию нужно послать на сервер — четыре. Валидировать на сервере — пять. Трансформировать в поле(поля) для базы — шесть. Сохранить в базу — семь. Добавить стили — восемь. (Это написать и принять одну историю для поля, включающую все вышесказанное, трудно, а так — нет.)

              Все остальное — про ankor и TPM и прочее — это вопрос сюда не относящийся. Agile-методология бывает разная и я вообще не ее фанат, например. У нас есть стендапы и ретро, а TPMa нету совсем, ну и что.

              Мы не говорим, что TDD решает все проблемы, мы указываем, какие именно проблемы оно решает: качество кода, наличие спеков и collaboration.
                0

                А что такое "история" и чем она отличается от задачи? Судя по тому, что результатом воплощения истории не являтся готовая фича, это не UserStory?

                  0
                  история — это просто user story, я не знал как перевести. просто они очень маленькие.
                    0

                    Оно соответствует определению тут: https://en.wikipedia.org/wiki/User_story


                    То есть написано с точки зрения ползователя, повествовательно и т.д.? Или просто "записать скидку в базу данных" — то ести технические подробности

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

                      Если юзер сам программист и в состоянии посмотреть в базу, то в истории может фигурировать и база, впрочем.

                      Лишь бы тот, кто определяет юзер вэлью, не был отделен от acceptance по причине того, что у него нет прав\квалификации\ и тп
                  0
                  1. Кто пишет истории и кто их валидирует, что написаны/разбиты правильно? Видимо, сами разработчики?
                  2. На один тикет в джире несколько историй или один к одному?
                    +2
                    у нас истории пишет продакт-оунер, но это, видимо, в зависимости от клиента-проекта по разному. разработчики просматривают на планнинге, если что-то выглядит сложнее чем нужно, разбивается на несколько. общий настрой на предельно атомарные истории, т.е. лучше переборщить с гранулярностью, чем принять историю с пропущенным требованием и после заводить баги или зависнуть в неопределенном состоянии.

                    один джира-тикет — одна история, она же юзер-стори.

                    единственное ограничение, может быть, что любая юзер-стори пишется в форме какую user value она предоставляет. т.е. «as an account manager i want to see the order id field on the form filled from the same place as in the Application», а не в технической форме — «добавить или починить real database adapter implementation», что ограничивает раж рефакторинга и заставляет фокусироваться на пользовательской ценности.
                      0
                      а в статье:
                      Все истории пишутся юзерами
                        0

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

                    0
                    А вы можете показать пример таких «10 простых историй»? — а то сложно представить что вы имеете ввиду.
                      0

                      Так выше же я ответил

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

                Самое читаемое