Компания
67,88
рейтинг
14 сентября 2011 в 12:00

Разное → Как перестать беспокоиться и начать работать?

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

Реальность такова, что Agile без правильных инженерных практик очень быстро закончится. Если вы не будете прилагать усилия, которые гарантируют высокий уровень качества разработки и состояния системы в целом, то по мере усложнения проекта контроль будет быстро утрачен. В результате сделать всё, что запланировано в итерации, у вас не получится, а о значимом релизе (значимый — значит, с какой-то новой функциональностью, которая будет доступна пользователям, а не просто рефакторинг) раз в месяц вы будете только мечтать, потому что стабилизация важного релиза будет занимать гораздо больше, чем месяц.

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

Тесты, тесты, тесты


Я написал слово «тесты» 3 раза, не потому, что повторять слова по три раза весело, а потому что мы используем 3 вида тестов:
  1. Модульные тесты бизнес-логики. Эльба — это совокупность нескольких взаимодействующих друг с другом сервисов (веб, хранилище данных, сервис справочников, сервис печати и т.д.) Все эти сервисы и серверную часть веба мы пишем в TDD стиле. Про TDD сказано и написано очень много. Основным плюсом этой методологии я считаю создание ситуации, в которой написание тестов — это не рутинная и не скучная работа. Постепенно наращивать тесты и фанатично писать кода ровно столько, чтобы текущий набор модульных тестов проходил, но ни строчкой больше — это очень весело, это такая ментальная игра, вроде шахмат. Кроме того, честно покрывая каждую строчку вашего кода модульными тестами, вы получаете более совершенный код. Тут уместен фанатизм: если возник код, который можно стереть и при этом не упало ни одного теста, этот код должен быть стерт немедленно, в воспитательных целях. Стоит сказать, что представление о хорошем коде у каждого свое: студенты считают совершенным код, который компилируется, а некоторые разработчики любой код, который работает. К счастью можно не спорить по этому поводу. Прекраснейший человек Uncle Bob давно обобщил все, что стоит обобщать в области формальных характеристик хорошего кода и написал серию статей об этом. Мы в Эльбе считаем хорошим тот код, который удовлетворяет принципам SOLID. Если вы до сих пор не знаете что это и при этом не являетесь Хаскелл-разработчиком, то есть вероятность, что вы живете неправильно или зря :) Код, покрытый модульными тестами, легко наращивать и модифицировать: тесты гарантируют неизменность старой бизнес-логики, а SOLIDность позволяет делать важные изменения сугубо локально (у вас ведь нет копипастов и 3 классов, которые делают одно и тоже?) — вы достигаете заявленной цели, скорость разработки не снижается и все происходит с заданным качеством.

  2. Модульные тесты для клиентского JavaScript. Серверная бизнес-логика это прекрасно, но конечные пользователи видят веб-приложение. И они хотят не просто наблюдать унылые страницы, все должно летать и взрываться. Поэтому мы пишем много клиентской логики. Тут нет ничего нового по сравнению с серверной бизнес-логикой: код должен быть SOLIDным и покрытым тестами, просто язык другой. Такими образом мы тестируем классы и контролы общего назначения (например, клиентские валидаторы).

  3. Функциональные тесты веб-приложения. Все модульные тесты могут проходить, но это вовсе не гарантирует, что у пользователя нет никаких проблем с конкретной страницей. Мы не тестируем модульными тестами заполнение полей каждой формы и обработку этих полей на сервере. Чтобы зафиксировать правильное поведение конечных страниц, мы используем функциональные тесты. Фактически мы повторяем поведение пользователя: кликаем на ссылку, ожидаем загрузку страницы с определенным набором полей, заполняем эти поля, проверяем корректность валидации, нажимаем на кнопку «сохранить» и убеждаемся, что именно то, что было вписано в поля, осело в нашем хранилище. Даже если на странице, в зависимости от каких-то условий, меняется какая-нибудь маленькая надпись — на это есть тест. Если разработчик говорит, что невозможно протестировать все условия, под которые он писал код, значит, он писал этот код пьяным или врёт (речь идёт об обычной бизнес-логике, а не о научных приложениях, например). Вот так понятно может выглядеть тест:

    [Test]
    public void ChangeEmailWithGoodPassword()
    {
           const string newEmail = "hello_habr@gmail.com";
     
           Prepare();
     
           emailSettingsPage.Email.TypeValueAndWait(newEmail);
           emailSettingsPage.Password.TypeValueAndWait("superpassword");
           emailSettingsPage.SaveButton.Click();
           emailSettingsPage.WaitSaveSucceded();
           emailSettingsPage = emailSettingsPage.Refresh();
           emailSettingsPage.Email.WaitValue(newEmail);
    }
    

    А вот что происходит при запуске теста:



    Чтобы писать такие понятные тесты, мы для них строим абстракции над страницами и контролами, благодаря которым сильно снижается сложность их поддержки, повышается читаемость и даже появляется возможность писать функциональные тесты по TDD!

Запуск тестов


Тесты пишутся для того, чтобы их запускать, поэтому очень важно, чтобы тесты запускались легко (одной кнопкой!), стартовали мгновенно и быстро отрабатывали. Тогда разработчики действительно будут их запускать. Наши модульные тесты именно так себя и ведут, 1700 тестов отрабатывают за 2 минуты. С функциональными тестами все не так просто, ведь каждый тест предполагает загрузку страницы (зачастую нескольких) с последующей проверкой. Это занимает от нескольких до десятков секунд. Но с учётом того, что всего функциональных тестов у нас более 2000, прогон всех тестов на одной машине занимает порядка 7 часов. Очевидно, что еще не родился такой разработчик, которому хватит терпения дождаться прохождения всех функциональных тестов. Поэтому разработчик запускает или только что написанные тесты, или те, которые тестируют модифицированные страницы. После этого разработчик делает коммит, и в дело вступает билд-сервер, который, общаясь с системой контроля версий, понимает, что появилось что-то новенькое и добавляет коммит в очередь. Очередь разгребается агентами — физическими или виртуальными машинами, смысл существования которых заключается в том, чтобы прогонять весь набор тестов по каждому коммиту. Мы используем 20 агентов для того чтобы проверять корректность работы во всех значимых для нас браузерах. Можно легко увидеть список упавших тестов и начать их поднимать. При этом у нас есть несколько веток в системе контроля версий (стабильная и ветки, в которых мы делаем новые фичи). И на каждую крупную ветку мы напускаем агентов.



Отдельного упоминания должно удостоиться время, когда мы поднимаем тесты. Затягивать тут нельзя. Я слышал, что в некоторых командах в Майкрософте вся работа останавливается и не возобновляется, пока есть хотя бы один упавший тест. Так делать мы, честно говоря, не пробовали и поднимаем тесты ежедневно (этим занимается дежурный инженер), а перед каждым релизом, во время стабилизации (в тяжелых случаях — вся команда).

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

Парное программирование


Мы пишем почти весь код в парах и стремимся к общему владению кодом. То есть у нас нет разделения: серверный программист, клиентский или, скажем, разработчик БД. Любой член команды может взять любую задачу. Понятно, что компетентность и вовлеченность в проект или в какую-то его область у всех разная, поэтому чтобы распространить знания мы используем пары. А ещё вдвоем гораздо веселее. Честно. А самое главное, что это ничуть не медленнее — при работе в паре разработчики вообще не отвлекаются на посторонние дела.

Pre-commit code review


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

Планирование


Это, конечно, нельзя назвать инженерной практикой в чистом виде, просто планирование настолько важная часть жизни команды разработки, что не говорить о нем совершенно невозможно. Все, о чем я писал выше, было связано с качеством, но качество не может быть единственной целью. Хороший код, множество тестов и релизы, которые очень стабильны, но происходят раз в полгода или реже, быстро заведут проект в тупик. Это может работать в заказной разработке, если у вас есть клиент, понимающий что он хочет, готовый за это хорошо заплатить и ожидающий просто качественного воплощения своих желаний. Во всех остальных случаях нужны более частые релизы, чтобы была возможность проверить правильность своих идей и подкорректировать их. В итоге нужно понимать, что команда сумеет сделать в ближайшие несколько недель с высокой степенью достоверности. А парное программирование и общее владение кодом требует, чтобы до начала работы все разработчики понимали задачи одинаково. Мы это обеспечиваем с помощью planning poker — широкоизвестной практики команд, применяющих гибкие методологии разработки. Классический подход состоит в том, что команда набирает несколько задач в очередную итерацию разработки (мы используем двухнедельные итерации) и голосует сколько «идеальных» часов займет каждая задача. Наше ноухау состоит в инновационной форме представления результатов голосования, мы используем вот такой mindmap:



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

Баги


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

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

Рефакторинг


Какой русский программист не любит рефакторинг? Несмотря на то, что наличие тестов позволяет довольно спокойно проводить любой рефакторинг, всё равно не всегда удаётся уделить этому достаточное количество времени по той же причине, по которой растёт количество багов, — релиз раз в месяц. Если баг можно закрыть (или не закрыть), ничего при этом не потеряв (и даже не демотивироваться), то ввязавшись в рефакторинг, порой отступить уже нельзя и некуда. Чтобы решить данную проблему, ещё один день в итерацию выделяется под «день свободного творчества», в который можно делать всё, что угодно: рефакторить, делать какие-нибудь магические вещи. А кто-то в этот день, как это не парадоксально, по собственному желанию фиксит баги!

Дежурный инженер


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

Релиз-инженер


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

На самом деле, как правило, дежурный инженер и релиз-инженер — один человек.

Результат


Действуя таким образом, нам удается уже почти 2 года делать 1 значимый релиз в месяц. Система развивается очень динамично, но мы не боимся делать несколько апдейтов в неделю (не все удается запланировать: законодательство меняется слишком стремительно и рост пользователей в последние полгода произошел очень существенный), наши инженерные практики делают разработку очень управляемой и прогнозируемой.
Технические детали
IDE: Microsoft VisualStudio + JetBrains ReSharper
Continuous Integration сервер: JetBrains TeamCity
Багтрэкер: JetBrains YouTrack
Функциональные тесты: Selenium
VCS: Mercurial
Web-сервер: Microsoft IIS + nginx
БД: MS SQL Server

P.S. Может быть, это не очевидно из текста, но у нас есть тестировщик. Он все время загружен работой и работает очень хорошо :)
P.P.S. Спасибо горячо нами любимой компании ДжетБрейнс за отличные инструменты :)
Автор: @evgeny_kobzev

Комментарии (41)

  • +10
    Что бы перестать беспокоиться и начать работать надо перестать беспокоиться и начать работать.
    Хороший кофе тоже не помешает.
    • +4
      Название это всего лишь аллюзия :)
  • +1
    Хороший топик, читал с интересом. Долго втыкал в вашу доску… только так и не понял, откуда взялась цифра 49.

    Улыбнула хренька для шняги (:
    • 0
      49 это просто номер итерации.
      • 0
        Потом 49 меняется на 50 и все вокруг этого кружка стирается и рисуется заново?
        • 0
          Да, именно так. На практике не всегда стирается все (если что-то не успели сделать, нет смысла стирать и переоценивать заново)
    • 0
      должна же быть 42?
      • 0
        41 была за 14 недель до момента снимка :)
        • 0
          *42
      • 0
        Тоже об этом подумал. Но тогда это должен был быть идеал.
  • +1
    Гыгы, «как я перестал бояться и полюбил бомбу». Отличны фильм, кстати.
    Раз уж «контур» пишет про «эльбу» — реквестирую формы уведомления налоговой и прочих всяких фондов об открытии счета!:)
    • 0
      Налоговая пока не поддерживает такие уведомления, но может быть скоро утвердят. Пока это процедурно невозможно
      • 0
        Да я про банальную форму С-09-1
        • 0
          Это же бумажка, если я не ошибаюсь. Это точно может быть в электронном виде?
          • 0
            Пока это бумажка, разумеется. Утверждена приказом ФНС России от 09.06.2011 № ММВ-7-6/362.
            В том же приказе содержится пункт
            3. Управлению информатизации (В.Г. Колесников), ФГУП ГНИВЦ ФНС России (Р.В.Филимошин) обеспечить разработку и сопровождение программного обеспечения, реализующего представление сообщений, предусмотренных пунктами 2 и 3 статьи 23 Налогового кодекса Российской Федерации, в электронном виде.

            В любом случае у вас в Эльбе и документоводе полно бумажек!
            • 0
              Ну это если нет никаких вариантов. Например дистанционной регистрации ООО нет, что тут поделаешь (: А тут-то можно подождать электронного формата, вполне реально, что он скоро выйдет
              • 0
                Вот кстати дистанционная регистрация ООО есть, через gosuslugi.ru :)
                Правда представляю какую панику попытка такой регистрации вызовет в налоговой.
  • 0
    Интересная статья, спасибо.
    Если не секрет, можно ещё немного про технические детали:
    Какие ORM используете, что можете сказать про них?
    IoC/DI контейнеры?
    • +1
      ORM — Linq 2 SQL. Можем сказать, что это очень легкий ORM, который легко использовать. Мы стараемся работать с базой в не реляционном стиле, нормальными формами там и не пахнет. Первая версия системы была на файлах. Сейчас все в таблицах, но мы можем скакануть на какую-нибудь Кассандру в любой момент, если пользователи начнут нас настолько любить, что текущие технологии перестанут вывозить нагрузку.
      DI контейнер был Windsor в начале, давно уже пользуемся RoboContainer, это опен-сорс разработка Павла Егорова — разработчика Контура. Очень хорошая вещь, сама делает много предположений, то, что очевидно без конфигурирования, не приходится конфигурировать никогда
  • +6
    Спасибо! Очень интересно. А можно немного вопросов задать?
    Для начала о составе команды
    Что у вас за ребята? Вы берете опытных разработчиков или недавних студентов? Сколько времени нужно человеку, чтобы прийти и начать что-то изменять?

    О разделяемом владении кодом
    Какой у вас размер системы? Неужели получается в большой системе добиться разделяемого владения?
    Я имею ввиду не формального а реального. Чтобы любые два разработчика (например со стажем 4 и 6 месяцев), взяли и внесли доработку в ядровую часть системы?
    Или по факту на каждую функциональность системы есть специалист который РЕАЛЬНО и вносит изменение в формально всеобщий разделяемый код?

    Используете ли какие-либо инструменты для мониторинга качества кода?
    Стилистика (StyleCop)? Возможности рефаекторинга (FxCop и студийные ворнинги)? Метрики кода? Какие-нибудь системы для анализа слабой связанности (студийные или сторонние)?
    Если да, то как это происходит? Есть какой-то день или на каждый комит?
    Или тестов, считаете, достаточно?

    О покрытии кода
    Ммм. Когда говорят о 100% покрытия кода, или даже о 80% у меня всегда острый приступ недоверия. Было время и я предполагал что только 100% покрытия спасут Россию и все время скорбил о недостижимости этой цифры. Потом послушал мнение Джоеля и успокоился.
    Неужели такое возможно? Какое у вас реальное покрытие всего проекта? Не какого-то отдельного модуля а именно всего? Что вам пишет TeamCity?

    • +2
      Вопросы задавать конечно можно, отвечаем с удовольствием :)
      1. У нас около 8 разработчиков, менеджер разработки, который тоже пишет код и верстальщик, который сильно участвует в программировании client-side. Изначально все разработчики были опытными и их было двое. Потом еще пара опытных присоединилась. За последнее время появилось трое вчерашних или сегодняшних студентов. Тесты человек может начать изменять прямо сразу, а все остальное зависит от его бэкграунда (например, писал ли он до этого веб-приложения, программировал ли на .NET) Первое время новичок конечно сидит в паре в режиме read-only почти независимо от его уровня, привыкает к нашим подходам и стилю кодирования. А потом многие уже начинали фиксить баги и забирать клавиатуру у напарника. Мы стараемся не создавать каких-то собственных монструозных фрэймворков, это снижает порог вхождения. Максимальный срок, который проходил до полного погружения — 3 месяца
      2. У нас более 400 экранов. Каждый экран это разметка и довольно много javascript, плюс вызов нескольких классов с серверной бизнес-логикой. Еще сервис справочников, для того, чтобы подсказывать юзеру адрес при вводе, сервис печати, всякие роботы, которые отсылают отчеты в налоговую или в пенсионный фонд. Размер довольно велик, фунционально я думаю у нас больше фич, чем, например, у вконтакте. Хотя может я там не всем пользуюсь :) Насчет ядра и владения кодом. У нас нет чего-то, что можно быо бы назвать ядром. И у нас нет разработчиков ядра. Любой разработчик пишет server-side и client-side и сервис потрогать может. Пары все время разбиваются и меняются. У нас нет областей отвественности, но есть люди которые лучше представляют разные участки системы. Порой создается ситуация узкой специализации, мы с ней сразу же начинаем настойчиво бороться. Самое главное, что мы не делим людей на аристократов, которые пишут некое ядро и плебеев, которые делают печатные формы. Тимлидер тоже делает печатные формы, а новичок в паре с кем-то, вполне своими руками может внести изменения в какой-то важный класс.
      3. Нет, не используем. Мы для этого используем code review. Злой reviewer стирает плохой код безжалостно и демонстрирует хороший :)
      4. Если вы пишете в режиме tdd у вас ведь не может быть непокрытого тестами кода, верно? :) На практике конечно 100% покрытие невозможно, например нельзя до конца честно оттестировать корректно ли мы делаем pdf или excel документ. У нас классы бизнес-логики покрыты тестами очень хорошо, тесты их и породили. А взаимодейтвие мы тестируем функциональными тестами, там наверное покрытие вообще не померять, набор вариантов ввода в форму очевидно очень велик, мы тестируем принципиальные моменты и нюансы. Что пишет ТимСити завтра посмотрю :)
      • 0
        Еще у нас есть iphone-разработчик, но он в наши игры не сильно играет :)
  • 0
    В первом пункте про тесты вы пишете «модульные тесты». Вы имеете в виду юнит-тесты (тестирование каждого класса в изоляции от других классов) или именно модульные тесты (мелко-интеграционные, включающие взаимодействие двух-трех-нескольких классов)?
    У нас тут просто жаркие дискуссии по этому поводу :)

    Ну и в догонку про технологии — у вас Asp.net MVC? Что майкрософтовская технология — понятно, а какая именно — не очень :)
    • +1
      1. Имеем в виду unit. Модульные тесты это же буквально unit :) Взаимодействие классов может быть в тесте (например экземпляр класса для создания, хочет, чтобы в конструктор передали еще пару классов), мы передаем так называемые Mockи обычно.
      2. Asp.Net WebForms
      • 0
        >2. Asp.Net WebForms

        Суровые ребята! Хотя понятно, что когда начинали Asp.Net MVC могло еще не быть.
        У нас огромный, десятилетний проект (просто залежи говнокода :) постепенно, шаг за шагом переводится на MVC.
        • 0
          На самом деле было уже MVC, но еще невнятное. А мы как-то не видим смысла переводить на MVC, запаривались, чтобы говнокода не было, в вебе серверный код максимально тупой, просто делает перевызовы к классам, а всякими событиями и своими WebControlами мы пользуемся ограниченно и вдумчиво
          • 0
            Честно-говоря, после использования MVC 3 с Razor (ну и jQuery конечно), WebForms вспоминаются как ад. В MVC контроллерах тоже логики минимум, но сама концепция — посто сказка!
            • 0
              А нам хорошо, нам даже не надо вспоминать ад — мы в нём :))) Хотя местами концепция WebForms во многом нам помогла и определила направление развития клиент-сайд части. Если интересны подробности, могу вкратце рассказать, хотя это вполне возможно может потянуть на отдельный пост.
              • +1
                Да, расскажите пожалуйста.

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

                К счастью сейчас тот архитект слил, наняли двоих умных и опытных ребят и все пошло как по маслу.
                • 0
                  Благодаря вынесению большей части логики на клиент + использованию Repository Pattern делает кодебехайнды довольно компактными, поэтому ада нет (по крайней мере на новых страницах), туда всего лишь надо заинжектить нужные репозитории и потом в нужном месте присунуть вызов к репозиторию через DataBind синтаксис (мы пришли к выводу, что круто иметь один глобавльный DataBind(), хотя у нас этого не получается сделать, так как есть куча старых мест, где с датабиндами всякое колдунство).
                  Т.к. на клиенте очень много логики надо уметь удобно с этим работать, поэтому мы почти не пишем low level JS кода, а строим абстракции над страницами (почти как в функциональных тестах). Работа строится так: создаём страницу, накидываем на неё контролов (UserControlы или WebControlы), которые помимо своей вёрстки пишут рядышком JS, который регистрирует контрол (экземпляр JS «класса») в глобальном дереве контролов (которое может быть какой угодно глубины, за счёт наличия композитных контролов, типа лайтбоксов, которые могут содержать другие контролы). JS «классы» контролов пишутся в соответствии с MVC, сложные контроллеры покрываются тестами. В итоге, чтобы подвеситься на change какого-нибудь инпута MyInput (именно такая айдишку мы даём в ASP коде, просто пишем <x:InnInput id=«MyInput» runat=«server» /> и больше ничего) достаточно в конструкторе JS «класса» страницы написать this.controls.MyInput.change(somecallback).

                  Вкратце как-то так
                  • 0
                    Интересно, спасибо!
  • 0
    Я потому и уточнил, что под «модулем» может подразумеваться и класс, и, допустим, библиотека :) С тех. терминологией в русском языке не все утряслось еще.

    За ответ спасибо, хотя по первому пункту и было бы любопытно подискутировать, но будет совсем оффтопик :)
    • 0
      Можно и подискутировать :) Мое мнение по первому пункту такое — так делать вполне нормально (тестировать логику интеграционно), но tdd так не получится. Зато в качестве бонуса получатся более полные примеры использования классов
      • 0
        получится «почти-тдд» :) Написать тест сначала для маленькой подсистемы проблем обычно нет. Они выполняются подольше — это минус, да.

        А у вас хрупкими тесты не получаются? То есть если какая-нибудь функция перешла из одного класса в соседний, это не влечет массовый тестоповал? :)
        • 0
          Если я все верно понял, то нет. Сломается компиляция, по ошибкам компиляции вы придете к тестам, которые по-прежнему предполагают наличие этой функции в классе A, если вы соблюдаете принцип SRP из SOLID, то таких тестов не много, потому что функция должна делать толко одно дело, вы понимаете, что надо все перезамкнуть на класс B и вообще никто не свалится после того, как начнет компилироваться. Другой вопрос, что если вы соблюдаете SRP то непонятно какого черта вы функцию в какой-то другой класс потащили? :) Хотя конечно может пролезла в код гомосятина, класс раньше делал 2 дела, вы решили дать классу одну отвественность и исправить эту досадную оплошность.
  • 0
    Молодцы.
    У нас всё так же, только мы используем модель feature branches.
    Это позволяет в любое время иметь stable сборку и избавляет от необходимости некоторых мелочей типа упомянутой вами pre-commit code review (коммит в принципе ничего не ломает и его ревьюят позже).
    • 0
      А мы делаем precommit-review не потому что коммит может сломать. Просто хочется делать ревью пока все помнят контекст и не обкладывать этот процесс всякими автоматизирующими инструментами. Все прозрачно, хочешь закоммитить, зовешь ревьюера, он ревьюит. Это гарантирует, что точно отревьюят пока автор помнит, что он там писал-то :)
      • 0
        Ааа, вот в чем дело. У нас просто сильная декомпозиция задач, коммиты частые, и звать ревьюера на каждый — чудовищно отвлекать его от работы. Поэтому контекстом является вся feature в целом, перед merge.
        Тем не менее, вы реально молодцы, с удовольствием пообщался бы в оффлайне.
        • 0
          Евгений не пишет код с тех пор как мы перешли на dvcs, поэтому информация немного неактуальная :D Сейчас у нас такая же идеология как и у вас (feature branches), но ревьюим мы чаще, чем один раз перед вливанием, потому что порой фичи низшего уровня декомпозиции иногда бывают слишком объёмными и ревью такой фичи может занять день, что очень печалит и выматывает.

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

Самое читаемое Разное