Статьи

Мысли о нулевом дефекте Менталитет TDD

Проблемы, которые привели меня сюда

  • Горячие аргументы на работе относительно того, сколько TDD достаточно и как мало, слишком мало. Как нам найти общий язык?
  • Признание технического долга и путаница в том, как его использовать. Сколько долгов слишком много?
  • Быть помеченным как педантичный и фанатик. Стоит ли когда-нибудь ценить мышление с нулевым дефектом? Когда?
  • Учебное упражнение о том, как мы можем получить конкретное понимание, используя нашу интуицию методическим способом. Как я могу передать абстрактные идеи без конкретных доказательств в строгой манере?

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

Создание абстрактного бетона

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

Это было освобождение. 

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

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

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

Нахождение точки соприкосновения в общей цели

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

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

Дальнейшие предположения и особенности моей модели читайте дальше.

Моя модель для размышлений об этом (AKA My Domain Model)


Понятия и их роль в симуляции:
  • Пользовательская история.  В этой модели пользовательская история — это наименьшая единица работы, над которой может работать команда разработчиков продукта, которая обеспечивает малейшую часть коммерческой ценности. У них также есть связанный размер.
  • Бизнес-клиенты —  генерирует случайный набор историй произвольного размера (для дискретного распределения) на каждой итерации. Их значение и размер также случайным образом назначаются при создании.
  • Product Backlog —  репозиторий для всех историй. Все новые истории добавляются в качестве основного приоритета в доставленном заказе. Ошибки случайным образом распределяются в Журнал ожидания продукта при их получении. 
  • Команда разработчиков продукта —  все и каждый, кто отвечает за выпуск релиза. Сюда входят программисты, тестировщики, технические писатели и т. Д. И т. Д. Команда разработчиков продукта просматривает журнал незавершенного производства и работает над созданием историй. Они также решают стоимость различных историй. Со временем скорость их работы может возрасти, если на конструкции указан диапазон (минимальная скорость и максимальная скорость)> 1. Функция, которая контролирует улучшение производительности команды, — это «Кривая опыта», как описано здесь:  http://en.wikipedia.org/wiki/Experience_curve_effects. Если  не вдаваться в подробности, эта кривая опыта по существу моделирует снижение затрат на разработку с течением времени.
  • Конечные пользователи —  Кому выпускает команда разработчиков продукта. Поскольку в состав команды разработчиков продукта входит * каждый *, необходимый для выпуска программного обеспечения, конечный пользователь может получить программное обеспечение сразу же после этого. Конечные пользователи обнаруживают ошибки в программном обеспечении. В настоящее время для каждой итерации задана постоянная ставка на историю. Таким образом, если процент дефектов составляет 1%, то команда с сотней завершенных историй может рассчитывать на то, что одна или несколько историй будет повторяться в журнале невыполненных работ продукта в качестве новой истории ошибок. Размер Bug Story определяется случайным образом на основе дискретного распределения размеров ошибок. 
  • Bug  Story — Bug Story — это история, которая направлена ​​на исправление дефекта в программном обеспечении. Эти истории отличаются от обычных историй тем, что они не имеют реальной ценности для команды и, следовательно, не улучшают пропускную способность. История ошибок на самом деле представляет собой дополнительные издержки, так как на ее месте можно было бы выполнить ценную работу, если бы историю ошибок не нужно было писать.
  • Команда поддержки — кому сообщают  об ошибках. В настоящее время используется только для отслеживания общего количества ошибок. Может быть использовано в будущем для устранения ошибок из-за «ошибки пользователя».

Каждое из этих понятий отображается непосредственно на объекты в моделировании Javascript.
Как работает симуляция


Во-первых, вот как работает самый верхний уровень симуляции:
function run_simulation()
{
  var simulation_settings =
  {
    'teams_to_simulate' : 10,
    'weeks_to_project' : 1 * 52,
    'story_size_distribution' : [0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4],
    'bug_size_distribution' : [0,0,0,1,1,1,1,1,1,1,1,1,2,2,2,2,2,4,4],
    'tdd_defect_ratio' : .07,
    'min_tdd_velocity' : 1,
    'max_tdd_velocity' : 16,
    'std_defect_ratio' : .14,
    'min_std_velocity' : 20,
    'max_std_velocity' : 20,
  };
  
  var tdd_std_comparison_chart = new Chart();
  var developmentProcessFactory = new DevelopmentProcessFactory(tdd_std_comparison_chart);
  
  var simulated_development_teams = new SimulatedDevelopmentTeams(simulation_settings);
  simulated_development_teams.create_tdd_development_teams_using(developmentProcessFactory);
  simulated_development_teams.create_standard_development_teams_using(developmentProcessFactory);
  
  for(var i = 0; i < simulation_settings.weeks_to_project; i++)
  {
    simulated_development_teams.iterate();
  }
  
  tdd_std_comparison_chart.draw_chart_to('value_delivered_chart');
}


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

 


Общий процесс показан в следующем коде:
DevelopmentProcess.prototype.iterate = function()
{
  this._report.next_iteration();

  this._customer.deliver_new_stories_to(this._product_backlog);
  this._development_team.work_from(this._product_backlog);
  this._development_team.move_finished_stories_to(this._end_users);
  this._end_users.test_stories_and_report_failures_to(this._bug_queue);
  this._bug_queue.prioritize_and_move_bugs_to(this._product_backlog);
  
  this._product_backlog.report_to(this._report);
  this._end_users.report_to(this._report);
  this._bug_queue.report_to(this._report);
};


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

Создание имитируемых команд разработчиков осуществляется с помощью DevelopmentTeamFactory, которая создает команды с использованием методологии TDD, а также стандартные команды разработчиков:
DevelopmentProcessFactory.prototype.create_tdd_development = function (simulation_settings)
{
  var tdd_development_team_report = new Report();
  tdd_development_team_report.plot_results_in_color('green');
  tdd_development_team_report.plot_results_on(this._tdd_comparison_chart);
  
  var business_customers = new BusinessCustomers();
  
  var product_backlog = new ProductBacklog();
  
  var development_team = new DevelopmentTeam(simulation_settings.story_size_distribution);
  development_team.velocity_begins_at(simulation_settings.min_tdd_velocity);
  development_team.maximum_possible_velocity_is(simulation_settings.max_tdd_velocity);
  
  var random_bug_size_generator = new DiscreteDistribution();
  random_bug_size_generator.use_these_as_samples(simulation_settings.bug_size_distribution);
  
  var end_users = new EndUsers(random_bug_size_generator);
  end_users.find_this_many_bugs_per_story_per_iteration(simulation_settings.tdd_defect_ratio);
  
  var support_team = new SupportTeam();
  
  // This is an ugly construction... How to improve it??
  var development_process = new DevelopmentProcess(business_customers, product_backlog, development_team, end_users, support_team, tdd_development_team_report);
  
  return development_process;
};


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

Вот остальная часть кода: 
http://github.com/jcbozonier/Monte-Carlo-Supporting-TDD


Все должно работать в последних версиях FireFox и Chrome.
Требуется HTML 5, чтобы использовать холст для построения графиков.

Вот примерная таблица с 50 командами TDD (зеленые отметки) и 50 стандартными командами (красные отметки), каждая из которых работает в течение двух лет:

 

 
 


Не стесняйтесь открывать код и самостоятельно изменять настройки моделирования json и запускать собственные моделирования.
Обратите внимание, что, как только вы нажмете кнопку «Выполнить», ваш браузер будет работать немного. Я рекомендую Chrome за его удивительную скорость. Не убивай процесс! Я обещаю, что это закончится в конце концов. ?

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

Как это было построено


Шаги малыша.
Я начал с одной команды, которую можно было смоделировать, и просто показал итоговую статистику итераций на веб-странице. Затем я перешел к одновременному сравнению этой команды с командой, использующей стандартную модель разработки с использованием таблицы данных. Затем я нашел довольно хороший API для построения графиков HTML 5 и визуализировал ключевые данные (общее значение на дату и время).
Уроки усилены
  • Снижение количества дефектов, даже за счет снижения производительности, приводит к более высокой пропускной способности  в долгосрочной перспективе . Однако снижение уровня брака в краткосрочной перспективе вряд ли когда-либо будет оптимальным.
  • Более высокая частота дефектов приводит к гораздо большему разбросу возможных значений пропускной способности … иными словами, существует более высокая разница в том, что вы можете ожидать в плане получения ценности от команды разработчиков продукта.
  • У каждой команды разработчиков есть момент, когда высочайшая точность тестирования и качества начинает превосходить менее строгие команды. Хитрость заключается в определении того, где это начинает происходить для  вашей  конкретной компании или проекта.

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


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

Может быть, когда-нибудь я научусь?
Вывод


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

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

Если вы прочитали это далеко, вы заслуживаете награду.
Вот мои выводы по вопросам, которые я задавал в начале:
  • Как нам найти общий язык? Поделитесь нашими предположениями и сделайте их явными. Кодифицируйте их так, чтобы они не могли быть удобно сдвинуты, когда аргументы становятся неудобными.
  • Сколько долгов слишком много? Я не моделировал технический долг с точки зрения необходимого рефакторинга … просто с точки зрения вероятности появления дефектов. Слишком большой долг — это столько, что вы тратите большую часть времени на оплату расходов на обслуживание, а не на доставку стоимости.
  • Стоит ли когда-нибудь ценить мышление с нулевым дефектом? Когда? Да, это так, когда вы поставили перед собой цель достаточно большого срока службы вашего продукта.
  • Как я могу передать абстрактные идеи без конкретных доказательств в строгой манере? Надеюсь, я только что сделал.