TDD и производительность

В моем текущем проекте (игра на C ++) я решил, что во время разработки я буду использовать Test Driven Development 100%.

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

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

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

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

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

Я, возможно, что-то неправильно сделал, чтобы все еще быть так медленно? Существуют ли альтернативы, которые ускоряют производительность без полной потери преимуществ? TAD? Меньше охвата тестирования? Как другие люди переживают TDD, не убивая всю производительность и мотивацию?

127 голосов | спросил Nairou 22 J0000006Europe/Moscow 2011, 05:55:08

10 ответов


74

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

  • Время /производительность: Дать тесты медленнее, чем не писать тесты. Если вы примените это к этому, я бы согласился. Однако, если вы выполняете параллельное усилие, когда вы применяете подход, не относящийся к TDD, есть вероятность, что время, затрачиваемое на обнаружение существующего кода break-detect-debug-and-fix, поместит вас в чистый минус. Для меня TDD - это самое быстрое, что я могу пойти без ущерба для моей уверенности в кодах. Если вы найдете что-то в своем методе, которые не добавляют значение, устраните их.
  • Количество тестов: если вы кодируете N вещей, вам нужно проверить N вещей. перефразировать одну из строк Кент Бек " Тест, только если вы хотите, чтобы он работал. "
  • Закрепление в течение нескольких часов: я тоже (иногда, а не 20 минут, прежде чем останавливать линию). Это всего лишь ваш код, говорящий вам, что дизайн нуждается в некоторой работе. Тест - это еще один клиент для вашего класса SUT. Если тест затрудняет использование вашего типа, скорее всего, ваши производственные клиенты будут.
  • Подобные тесты tedium: для этого мне нужен еще один контекст, чтобы написать контраргумент. Тем не менее, остановитесь и подумайте о сходстве. Можете ли вы каким-то образом управлять этими тестами? Можно ли написать тесты против базового типа? Тогда вам просто нужно запустить один и тот же набор тестов против каждого вывода. Слушайте свои тесты. Будьте правильные, ленивые, и посмотрите, можете ли вы найти способ избежать скуки.
  • Прекратить думать о том, что вам нужно делать дальше (тест /спецификация), не так уж плохо. Напротив, рекомендуется, чтобы вы строили «правильную вещь». Обычно, если я не могу придумать, как тестировать его, я тоже не могу думать об этом. Это хорошая идея, чтобы пропустить идеи реализации, пока вы не доберетесь туда. Возможно, более простое решение затмевается упреждающим дизайном YAGNI-ish.

И это подводит меня к окончательному вопросу: как мне стать лучше? Мой (или An) ответ Чтение, отражение и практика.

например. В последнее время я продолжаю следить за

  • отражает ли мой ритм RG [Ref] RG [Ref] RG [Ref] или это RRRRGRRef.
  • % времени, проведенного в состоянии Red /Compile Error.
  • Я застрял в состоянии Red /Broken builds?
ответил Gishu 22 J0000006Europe/Moscow 2011, 09:09:39
29

Вам не требуется 100% -ный охват тестирования. Будьте прагматичны.

ответил Alistair 24 J0000006Europe/Moscow 2011, 04:48:57
22
  

TDD все еще значительно замедляет меня

Это на самом деле неверно.

Без TDD вы тратите несколько недель на написание кода, который в основном работает и проводит в следующем году «тестирование» и исправление многих (но не всех) ошибок.

С TDD вы тратите год на написание кода, который действительно работает. Затем вы завершаете окончательное тестирование интеграции в течение нескольких недель.

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

ответил S.Lott 22 J0000006Europe/Moscow 2011, 06:01:38
19
  

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

Это заставляет меня задаться вопросом, как много вы следуете за шагом «Refactor» TDD.

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

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

Несколько философских вопросов о TDD, которые могут быть полезны:

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

EDIT: На тему философии модульного тестирования, я думаю, вам может быть интересно прочитать: The Way of Testivus

И более практичная, если не обязательно очень полезная, точка:

  • Вы упоминаете C ++ как свой язык разработки. Я много раз практиковал TDD в Java, используя отличные библиотеки, такие как JUnit и Mockito. Тем не менее, я обнаружил, что TDD на C ++ очень расстраивает из-за отсутствия библиотек (в частности, насмешливых фреймворков). Хотя этот момент не очень помогает вам в вашей нынешней ситуации, я надеюсь, вы учтете это во внимание, прежде чем полностью отказаться от TDD.
ответил jaustin 24 J0000006Europe/Moscow 2011, 04:35:37
8

Очень интересный вопрос.

Важно отметить, что C ++ не очень легко тестируется, а игры в целом также являются очень плохим кандидатом для TDD. Вы не можете проверить, будет ли OpenGL /DirectX рисовать треугольник красным цветом с драйвером X, а желтый с драйвером Y легко. Если нормальный вектор карты рельефа не переворачивается после преобразования шейдера. Вы также не можете тестировать проблемы отсечения с версиями драйверов с различными настройками и так далее. Неопределенное поведение чертежа из-за неправильных вызовов также может быть проверено только с точным обзором кода и SDK под рукой. Звук тоже плохой кандидат. Многопоточность, которая снова очень важна для игр, практически бесполезна для модульного тестирования. Так что это сложно.

В основном в играх много графического интерфейса, звука и потоков. GUI, даже со стандартными компонентами, которые вы можете отправить WM_, трудно тестировать.

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

И снова я не TDD-гуру или евангелист, поэтому все это с солью.

Вероятно, я бы написал несколько тестов для основных основных компонентов (например, библиотеки матриц, библиотеки изображений). Добавьте кучу abort() для неожиданных входов в каждой функции. И самое главное, сосредоточьтесь на устойчивом /устойчивом коде, который не сломается легко.

Относительно одной ошибки, умное использование C ++, RAII и хороший дизайн делают долгий путь, чтобы предотвратить их.

В принципе, вам нужно много всего сделать, чтобы осветить основы, если вы хотите выпустить игру. Я не уверен, поможет ли TDD.

ответил Coder 28 J0000006Europe/Moscow 2011, 17:39:23
6

Я согласен с другими ответами, но я также хочу добавить очень важный момент: Рефакторинг стоит!

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

ответил Morten 23 J0000006Europe/Moscow 2011, 16:00:23
4
  

Как другие люди переживают TDD   не убивая всю производительность и   мотивация?

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

TDD о том, чтобы смирение было известно, что вы (и я!) ошибаетесь.

Для меня время написания unittests больше, чем сэкономленное в сокращенном времени отладки для проектов, которые выполняются с использованием TDD с самого начала.

Если вы не ошибаетесь, тогда TDD не так важен для вас, как для меня!

ответил Tom 24 J0000006Europe/Moscow 2011, 20:21:51
3

У меня есть только несколько замечаний:

  1. Кажется, вы пытаетесь протестировать все . Вы, вероятно, не должны, просто случаи с высоким риском и краем конкретной части кода /метода. Я уверен, что правило 80/20 применяется здесь: вы тратите 80% письменных тестов на последние 20% вашего кода или случаев, которые не покрываются.

  2. Приоритетность. Входите в гибкую разработку программного обеспечения и составляйте список того, что действительно действительно нужно сделать, чтобы выпустить через месяц. Тогда отпустите, точно так же. Это заставит вас задуматься о приоритете функций. Да, было бы здорово, если бы ваш персонаж мог сделать backflip, но имеет ли он значение для бизнеса ?

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

ответил Cthulhu 28 J0000006Europe/Moscow 2011, 19:06:23
1

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

Отладка практически устранена при использовании TDD, что делает весь процесс разработки намного более предсказуемым и, в конце концов, возможно быстрее.

Постоянный рефакторинг - невозможно провести серьезный рефакторинг без всеобъемлющего пакетного набора тестов. Самый эффективный способ создания защищенной сети, основанной на тестировании, - во время TDD. Хорошо реорганизованный код значительно улучшает общую производительность дизайнера /команды, которая поддерживает код.

ответил ratkok 28 J0000006Europe/Moscow 2011, 07:24:48
0

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

ответил JeffO 8 J000000Friday11 2011, 04:17:48

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132