Pull to refresh

Comments 63

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

По моему, в реальности, нужно дизайнить тестируемость кода с самого начала проекта, так чтобы
1. тесты можно было писать
2. чтобы они работали быстро.

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

Кстати, про тестирование, очень рекомендую вот эту книгу: www.amazon.com/Google-Tests-Software-James-Whittaker/dp/0321803027/ Она дает представление о том, как можно получать реальную пользу от тестов.
Такой сойдет. Возникают следующие вопросы:
— где там тесты?
— каково тестовое покрытие?
— сколько времени ходят тесты?
1. Папочки features и spec
2. Около 85%
3. Зависит от машины, на трэвисе около 18 минут, у меня на ноуте минут 20.
А вы уверены что все писали test first?

У меня в текущем Java проекте, который я пишу используя обозначенный выше подход, покрытие критических подсистем ок 90%, не критически 60%, все тесты гоняются 3 секунды.
Я думаю большинство кода писалось именно в виде TDD. Но безусловно есть места где сначала писали код, а уже потом тесты.
И откуда вы это знаете?
2. Около 85%
Чего? Функций, операторов, строк кода, всех возможных путей выполнения программы, всех возможных вариантов входных-выходных параметров?
Это был риторический вопрос. Тонкий намек на то, что 85% вовсе не означает, что это хорошее покрытие.
Не уверен, что используется TDD, но тестов очень много:

  • Three independently developed test harnesses
  • 100% branch test coverage in an as-deployed configuration
  • Millions and millions of test cases
  • Out-of-memory tests
  • I/O error tests
  • Crash and power loss tests
  • Fuzz tests
  • Boundary value tests
  • Disabled optimization tests
  • Regression tests
  • Malformed database tests
  • Extensive use of assert() and run-time checks
  • Valgrind analysis
  • Signed-integer overflow checks

www.sqlite.org/testing.html
Я не против тестов, я против догматичных практик, таких как TDD.
А у меня было с картинками :) habrahabr.ru/post/170847/
Ваши шаги 5 и 10: сделать makefile или другой какой-нибудь скрипт, а потом еще заставить это работать на CI сервере с парсингом отчета дело далеко не для всех и не всегда на 10 минут. Поэтому, я в своей статье предпочел использовать NetBeans, который умеет делать такой makefile, точнее сказать, такой makefile у него является частью проекта. И показал настройку парсинга для конкретного CI сервера — Jenkins.

А вообщем, все правильно. Если уже делать первые шаги к TDD, то конечно, надо начинать с тестирования HelloWorld.
GetAdressat

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

И если уж ошибки возникают, то как правило совсем непредсказуемо, а не там, где вы их и так ожидаете, покрывая именно эти участки тестами.
К тому же… любой тест — это тоже программная реализация, в которой так же могут быть ошибки. Будем писать еще тесты на тесты?
Допустим, тест написан с ошибкой. И он проходит! Вы в полной уверенности, что код работает правильно, ищите ошибку в другом месте. Красота!

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

Что-то подсказывает мне, что большинство разработчиков все же пишут, программируют как и раньше, но дабы не расстраивать приверженцев всякого рода TDD, потом уже пишут некоторые тесты для уже работающего кода.
> Но я не представляю, как можно написать тесты для сложной системы, в которой взаимодействуют множество модулей, есть работа веб-приложения, взаимодействие с пользователем, работа с БД.

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

Насчет рефакторинга… В последнее время создается впечатление, что многие просто помешались на рефакторинге и покрытии тестами. Работает правильно — и пусть себе работает! Лучшее — враг хорошего. Пишите что-то новое, двигайтесь вперед!
Пишите что-то новое, двигайтесь вперед!

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

Все зависит от проекта. Участвовал в таких, где и 2 человека было, и 7.
А вообще предпочитаю заниматься индивидуальной разработкой. На данный момент сопровождаю несколько готовых проектов, реализованных мной, что не мешает мне писать новые.
Это я к тому, что пока на проекте один человек, все ок, все у него в голове, аритектура в его голове тоже идеальная, тесты не нужны.
Вы когда-нибудь занимались поддержкой чужого говнолегаси-кода над которым работало не одно поколение разработчиков?
Да, естественно, было и такое. Но там и тесты бы не помогли — уверен! Когда дело касается конкретного рефакторинга кода, то:
1. берется проектная документация, где описаны (не в коде) все алгоритмы, как оно должно на самом деле работать
2. смотрим в исходники и переписываем полностью весь неудачный код

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

я занимался оптимизацией и исправлением ошибок довольно большой системы… и, знаете, мне бы не пригодились тесты ни тогда, ни сейчас я не ощущаю в них потребности.
А вы задумайтесь когда-нибудь над фактом, что если ваш тест стал сложным настолько, что в нем можно допустить ошибку, то ваш код плохо спроектирован. Это отличный показатель для качества кода. Иногда готовишь входные данные для вызова метода и понимаешь как же это неудобно тому, кто этот метод вызовет в реальной жизни… Но проще всего не обращать внимания на гниющую ногу…
Мне не нужно писать тесты, чтобы понять, хорошо или плохо спроектирован проект. Кстати, именно проект спроектирован, а не код, т.к. код как-то все же пишут. И никогда не сталкивался с подобной проблемой: «Иногда готовишь входные данные для вызова метода и понимаешь как же это неудобно тому, кто этот метод вызовет в реальной жизни…».
А вы задумайтесь над тем фактом, что любой тест — это программный код, что уже по определению предполагает возможность внесения в него ошибки, пусть даже это будет просто опечатка.
Уху! Наконец-то я нашел человека, который пишет идеальный код и сразу проектирует систему правильно! Теперь понятно, почему вам больше по душе работать в одиночку… [trollface]

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

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

Очень хорошо зарекомендовала себя следующая практика:
1. Проектируем работу алгоритма, если нужно, разбиваем его на некие составляющие.
2. Кодируем алгоритм
3. Проверяем правильность его работы
4. Исправляем ошибки, отлаживаем. п.3
5. Готово

На кой черт мне еще писать тест, чтобы еще и он правильно заработал?

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

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

Для того, чтобы вызвать методы класса Вы написали какой-то код, и передали методам какие-то параметры. Затем посмотрели что эти методы сделали. А затем сравнили результат с тем, что Вы ожидали. То есть, убедились в том, что они сделали именно то, что Вам нужно. Откуда Вы взяли эти данные? Есть несколько вариантов.

Вариант 1. Вы сразу встроили объект(ы) Вашего класса туда, где они будут использоваться и для ввода данных Ваших методов их нужно ввчести вручную с клавиатуры/мышки и т.д. Этот вариант прост и быстр, когда проверяемый Вами класс находится относительно близко от UI (каким-бы оно не было, графическим, веб или консольным). А вот если для передачи данных от пользователя требуется передать их через несколько уровней абстракции, то может их передать не очень просто.

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

Вариант 3. Вы написали отдельную маленькую программку, которая использует свежесозданный Вами класс. (отдельный main, если, напрмиер, на C/C++). И в этой программке Вы уже погоняли все методы Вашего класса для всех возможных, а может быть и невозможных данных.

Быстрее и проще всего, конечно, 1-й вариант. Но если Ваш класс сложен и Вы не написали его сразу безошибочно, то скорее всего Вам придется вводить несколько разных наборов данных, чтобы убедиться, что Ваш класс работает корректно при разных входных данных или другом начальном состоянии объекта. Вводить эти данные вручную каждый раз, при каждом прогоне не очень веселое занятие… Вы ведь можете и с вводом данных ошибиться. Поэтому, лучше вариант 2. Но у него есть свои проблемы — можно потом (после того как Вы закончите отладку нового класса) забыть вычистить отладочный код. Или позже может выясниться, что нужно еще на каких-то наборах данных проверять.

Поэтому, хорошо бы вариант 3… Но Вариант 3 такой муторный!!! Это надо отдельный проект или отдельную конфигурацию делать. И куда потом этот main деть? А еще его выбрасывать жалко. Вы же его написали. Время потратили. Пусть хранится.

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

И такой механизм существует…
Я предполагаю, что Вы сейчас ожидаете примерно следующего ответа на свою ключевую фразу «И такой механизм существует… »:

[не вставилось фото]
вот ссылка: inet777.ru/images/o_rly.jpg

И что это за чудесный механизм?

Но разочарую Вас.
Я использую примерно смесь п.1 и п.2. Хотя возможны различные варианты на тему отладки.
А вот если класс меняется или меняются какие-то условия входных данных, то я точно так же протестирую только тот функционал, который подвергся изменениям или требует проверки для новых условий.

Не вижу смысла писать программы для проверки корректности программ же. Я предпочитаю все же проектирование системы, а если это действительно сложная система с множеством взаимосвязей, то и проект будет точно так же не простой.
Жесть, пройдет несколько лет и перечитайте этот пост. Больше я вам ничего не скажу.
Т.е. Вы полагаете, что я — начинающий программист без достаточного опыта? Ну ну…
Я бы Вам посоветовал быть более осторожным с подобными выводами. Больше наверное тоже ничего я Вам не скажу.
Я вот за собой заметил, что как только мой код покрыт тестами — я начинаю пороть в нем херню. Изменения не обдумываю, за control flow не слежу, намного активнее пробую разные подходы и меньше подвергаю их критической оценке.

Провалился тест с кавычкой в исходных данных — а давай засунем addslashes() куда-нибудь. Засунули — оп, упало еще 50 тестов. Значит не сюда, значит в другое место попробуем. Или через preg_replace('/\'/' может лучше? И так пока все не загорится зелененьким.

Я не задумываюсь о последствиях preg_replace в данном конкретном месте, просто тупо пробую. Какая разница, ведь мой код покрыт тестами? Если что-то неправильно — я всегда это увижу!

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

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

И я виню в произошедшем именно TDD. Действительно стало легче писать код. Намного легче. Ведь это именно тесты позволяют мне не думать. А я — ленивая тупая скотина, и как только стало возможным не держать все в голове, я с радостью воспользовался этой возможностью. Такие дела.
Ну да, в том, что люди меньше читают, виноват телевизор. В том, что не катаются на велосипедах — автомобили. В том, что редко общаются вживую — эти ваши интернеты. Правительство там еще можно прикрутить куда-нибудь. Ленивая тупая скотина (прямая цитата автора) всегда найдет, на кого можно спихнуть свою лень и тупость.
Именно так и есть! Если можно чего-то не делать, то большинство и не будет этого делать. Вы очень верно привели в пример телевизор, автомобиль, интернет… эти блага прогресса одновременно и ограничивают большинство из нас, потакая нашей человеческой сущности — лени. Это не причина чего-то не делать, но это огромный соблазн в сторону ничегонеделания, согласитесь.

Не нужно приписывать человеку те человеческие качества, которые он приобретает за счет усиленной рекламы образа жизни, поведения, рекламы всех новшеств, прогресса. Мы — социальны — и это для многих определяет стиль их жизни — быть как большинство. На что большинство ведется? Если ты не в ногу с прогрессом, значит, ты — лох! Ездишь на велике, а не на собственном авто — лох! Не пользуешься социальными сетями — фууу!.. Человека без мобильника вообще уже как неадеквата воспринимают. Ну и, естественно, не пользуешься тестами при программировании — минус тебе, минус и еще раз минус!.. Будь как большинство — используй тесты — только тогда ты сможешь считаться по-настоящему программистом! Как-то так…

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

Не тесты делают код плохим, код становится плохим, когда кто-то решает, что теперь можно его плохо писать, потому что теперь есть тесты.

Говоря о человеческой природе… Я езжу на другой конец города в секцию боевых исскуств (велик — не мое, к сожалению), читаю книги, не имею дома телевизора, периодически встречаюсь с друзьями. А еще я пишу хороший код, пользуя BDD. Такие дела.
Давайте по порядку тогда.

1. Совершенно согласен насчет того, что говнокодеры могут что угодно попробовать изобразить. Но когда речь идет о том, что человеку только после использования тестов перестал нравится его собственный код, стиль написания программы, тут надо задуматься. Не нужно вот сразу клеймо «говнокодер» вешать, если человек сам осознал, что его код после использования некоторой техники начал деградировать.

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

3. Что за мания делать рефакторинг при любом удобном случае? Тоже дань моде, подкрепленная уверенностью в тестах, что ничего не сломается? Быть может все же стоит относиться более ответственно к проектированию системы и написанию чистого кода с хорошими комментариями изначально, а? Чтобы не было вот такого: «После получения зеленых тестов обязательно нужно провести рефакторинг нового кода.»

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

О человеческой природе…
А кто Вам сказал, что Вы пишите хороший код? Сами так решили? Похвально! А без тестов пробовали? Ах да, сломается же все быстро… как же хорошему программеру без знатного рефакторинга, как-то не по-программерски, понимаю. А чего телек не купите? Денег не заработали своим хорошим кодом? Так, для разнообразия, пусть стоит как мебель… новости хотя бы посмотреть. Хотя да, сейчас все есть в интернет, согласен. Сам телек не смотрю, но он у меня есть. Чтение книг — полезно, тут респект! С друзьями практически все периодически встречаются, но все отличие в том, что когда не было инета, то встречались практически каждый день.
Ничего сверхординарного и удивительного — обычный среднестатистический обыватель с отклонениями от общепринятого поведения в пределах нормы. Видимо, несколько разочарую вас, но чего-то уж очень уникального и из ряда вон я не заметил.

Собственно, о тестах. Я лишь хочу сказать, что какой-то уж очень значительной выгоды и облегчения труда программисту они не приносят. Нравится Вам — ради Бога, пишите избыточный код, если это добавляет Вам уверенности в надежности Вашей системы. Только не нужно преподносить тесты как нечто совершенно необходимое при разработке систем, программ. Без них пишутся многие системы и прекрасно работают.
1. Еще раз — это он почему-то решил, что теперь можно писать плохо. Тесты тут не виноваты.
2. Одно другому не мешает. Но ваши комменты к коду не скажут вам, что то-то пошло не так.
3. Это не мания, это принцип TDD. Пишем тест, пишем максимально быстро код для этого теста, делаем этот код красивым. Это правда работает, поверьте.
4. Хорошо написанные тесты дают далеко не мнимую уверенность.

Без тестов пробовал. С тестами удобнее.
Телевизор как мебель есть, телевидения нет. Не нужно.
Я и не говорил, что я уникален.

Вы можете не писать тесты, ради бога. Можете даже код не комментировать — еще время сэкономите. И не тестировать руками. Еще немного экономии. Попрыгали по клавиатуре — и в продакшн. Зато быстро же.
1. Я все-таки полагаю, что он не одинок в этом. Тесты — косвенная причина такого поведения, о чем указал сам автор.

2. Тогда не стоит путать… пусть дока остается докой, а тесты — тестами — только сигнализаторами об ошибках.

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

4. Останусь при своей точке зрения.

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

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

Позволю себе некоторые цитаты:

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

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

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

«Большое количество используемых тестов могут создать ложное ощущение надежности, приводящее к меньшему количеству действий по контролю качества.»
В качестве добавки: далеко не всегда приходится переписывать свой код. Часто это чужой код в миллионы строк. Запущенный один раз тест выдаст на экран всю документацию по проекту. Могут ли так сделать комменты?
миллионы строк чужого кода — Линукс — не менее того!
Линус Торвальдс? Ой, простите, не узнал Вас под этим ником на хабре…

Да Вы просто Бог! По сообщениям тестов понять проект в миллионЫ строк, не читая при этом в документацию и комментарии — это гениально! Бурные аплодисменты, переходящие в авации и сопровождаемые восторженными криками!

«далеко не всегда приходится переписывать свой код.» != «Пишем тест, пишем максимально быстро код для этого теста, делаем этот код красивым.»

уже коллизии в комментах появляются… пора писать тесты перед каждым сообщением! ;)
Хм, ок, аргументы у вас кончились, начался тупой троллинг.
Да нет, Уважаемый, это Вы уже начинаете путаться в собственных мыслях.

Аргументы свои я достаточно четко уже изложил.

Конечно проще оскорбить человека, сравнив его с приматом, прыгающим на клавиатуре, назвать троллем, тогда как сам не в состоянии внятно и разумно объяснить и доказать собственную правоту. Затем вознести себя до небес миллионами строк чужого кода и «А еще я пишу хороший код, пользуя BDD.». Такой ход давно известен, называется «Сам дурак!».

На сим, я полагаю, наш диалог можно считать завершенным. Спасибо.
1 миллион строк исходного кода это вполне реальный проект, который разрабатывается и поддерживается командой из примерно 10 человек, в течение, примерно 10 лет.

Таких проектов много. Очень много. Я принимал участие в двух таких проектах за последние 6 лет. Еще один проект перевалил 1млн строк уже после того, как я оттуда ушел.

Ядро Linux перевалило этот объем в районе 2000-го года. Сейчас более 15млн строк.

Конечно, если Вы работаете один, то у Вас не будет проектов в 1 млн строк исходного текста. И може быть Вам, на самом деле не надо тестов.
А можно поинтересоваться спецификой тех проектов на миллионы строк кода, которыми Вы занимались и конкретно Вашу реализацию в данных проектах? Еще было бы очень занятно узнать, сколько из этих миллионов строк занимают тесты?
Про один проект рассказать могу:
— сервер, выполняющий несколько сложных задач: система версионного контроля документов, issue tracker, система сборки, кое-что еще по мелочам.
— десктопный клиент к нему (точнее сказать, несколько клиентов для разных задач — использование и администрирование)
— библиотеки интеграции к несколькими сторонними десктопными клиентами.
— веб сервер, предоставляющий веб интерфейс к этому серверу, который используется, в том числе и интеграциями к сторонними клиентами из предыдущего пункта.

Когда я в нем участвовало проекту было уже 13 лет. 3.5 млн строк итого, 1.8 млн строк на Java.

Моя роль — разработка. В разных частях проекта. В том числе и тесты.

Тесты там были только интеграционные. И занимали около 10% исходного кода по строкам. Тестов было мало, потому что их созданием озаботились только после, примерно, 8 лет существования проекта, когда стали понимать, что поддерживать функциональность без тестов уже невозможно — ручное тестирование слишком дорого. Функциональности много. Ну и как в это время тесты стали популярны.
Тю, да конечно я делаю свой код плохим, кто ж еще? И я вполне отдаю себе в этом отчет. И также понятно, почему именно я это делаю — я почувствовал безнаказанность.

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

Конечно, никто не мешает и сейчас программировать вдумчиво и осторожно, а ездить только на велосипеде. Просто тесты (и автомобили) сделали это необязательным, и тем здорово упростили жизнь (лично мне).
Хотя раньше тратил в сто раз больше усилий мозга, сидел в дебаггере, перепроверял себя по десять раз и все равно имел шанс где-то что-то забыть


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

Тесты НЕ делают красивый код необязательным. Вообще не понимаю, откуда эта чушь взялась в ваших головах.
Да нет же, как раз делают. Раньше красивый код был необходимостью — иначе я бы сам не смог в нем ориентироваться и тогда уж точно наделал бы ошибок. Да и «перепроверка себя по сто раз» в случае запутанного, непонятного кода — вряд ли осуществима.

А сейчас я могу проверять любой код. Для того, чтобы убедиться, что код не содержит ошибок, мне больше не нужно на него смотреть и анализировать. Я могу, конечно, это делать, но могу теперь и не делать. Раньше не мог не делать, теперь могу. И даже злоупотребляю этим.
Если вы поставите пожарную сигнализацию, начнете ли вы менее бережно обращаться с огнем? Будете ли менее тщательно проектировать проводку? Если поставите сигнализацию на машину или квартиру, станете ли оставлять ее открытой? Дико сомневаюсь. Ваше поведение останется прежним, просто вы будете спать крепче по ночам. Так и с тестами: ничего не поменялось, просто появился парень, прикрывающий вам спину и сводящий ваши ошибки к минимуму. Я так и не понял, с какого перепугу я вдруг должен начать писать код, за который мне будет стыдно.
У вас просто дар какой-то приводить некорректные примеры. Ошибка в программе — это далеко не уничтоженная навсегда собственность пожаром.
И, кстати, да… и чего это вдруг столько машин во дворах развелось по ночам? Раньше как-то в гараж старались спрятать. Должно быть, тут все же сигнализация успокаивает владельцев авто. Не так ли? А за это спокойствие многие автовладельцы и платятся вещами, забытыми в авто, автомагнитолами и колесами. Вот это более явная аналогия.
Я так и не понял, с какого перепугу я вдруг должен начать писать код, за который мне будет стыдно.

Постараюсь объяснить еще раз: 1) потому что так проще и 2) это более не приводит к ошибкам. Раньше писать тяп-ляп у меня не получалось, я так или иначе должен был садиться и вникать. Теперь я «сажусь и вникаю» только если мне этого вдруг захочется, или появится куча лишнего времени. Если же времени нет, и я очень спешу, то «парень, прикрывающий мне спину» оказывается вполне ощутимым подспорьем, позволяет мне кодить не думая и сам следит.за тем, чтобы я нигде не напортачил.

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

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

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

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

Может быть, я бы ее не гнал, если б был более сознательным, но тогда успевал бы в четверг значительно меньше. И уж точно я бы её не гнал, если б она не прокатывала. А так — имеем, что имеем. Я стараюсь успеть побольше, Добрый парень мне всё прощает.
Т.е. в тестах вы нашли того, кто говорит вам «Все зашибись, бро, твой код прекрасен»? Ну так вы его не так поняли, он сказал, что ваш код работает, он не следит за его красотой. Это делают другие парни. Code Climate, например.
Вопрос к специалистам по TDD.
Регулярно читаю о том какой TDD хороший, и мучаюсь от такого. что никак не могу его применить. Я разработчик SMS-шлюза. Типичная messaging система: принял сообщения от внешней системы, чего-нить с ним поделал, отправил дальше и так во все стороны. Основная часть работы системы это: сетевой обмен, отправить/получить из БД (или очереди), переформатировать, маршрутизация. Естественно, при этом возникает куча процессов.

Ну вот никак не понимаю как тут применять TDD. Почитал wiki получается, что многопроцессные messaging системы — это сплошные слабые места для TDD:
* сетевой обмен
* БД
* межпроцессное взаимодействие

Привлекает в TDD то, что внеся любые изменения (а их вносить приходится много и постоянно), можно вжих-х-х — прогнать тесты и найти проблемы.

Подскажите куда капать, чего почитать? Или это не лечится?
* Сетевой обмен. Если нет возможности поднять локальный сервер для тестов или организовать какой-нибудь sandbox, то обмен по сети обычно эмулируется. Если сервис сторонний, то за правильностью его работы следят его разработчики, это уже не ваша забота, вы проверяете правильность отправки данных на сервер и правильность обработки ожидаемых вернувшихся данных. Если в спецификации к сервису описаны возможные коды ошибок, отказов, итд — эмулируете, проверяете. Если же это ваш сервис, что он проверяется отдельно на прием данных извне, их обработку и отправку во внешний мир. Таким образом разделяется поле ответственности.
Для тестирования сети в Ruby, например, существует уйма библиотек. Моя любимая — WebMock.

* БД. А какие проблемы с БД? Создаете тестовую базу данных, наполняете тестовыми данными — и вперед.

* Межпроцессоное взаимодействие. Почти аналогично сетевому обмену: эмулируете интерфейс взаимодействия с другим процессом, проверяете правильность работы вашего кода с ним. Правильность работы того_самого_процесса должен проверять его разработчик.

Я, например, периодически эмулирую даже обращение кода к Redis. Если команда простая (get/set), то необычного поведения системы не предвидится. Причем, эмуляция дает нам пару плюсов: 1) код не будет обращаться к внешнему процессу, что сэкономит время; 2) тест сообщит нам, если код по какой-то причине лишний раз обратится к проверяемой функции или передаст не те аргументы.

Безусловно, есть те вещи, которые слишком сложно или невозможно покрыть тестами. Тут уж ничего не поделаешь. TDD — это не г-подь б-г, а всего-навсего инструмент, причем, не везде применимый.
Sign up to leave a comment.