tag:blogger.com,1999:blog-5198245118514831160.post3339228128063969093..comments2023-06-08T17:53:25.496+03:00Comments on Программист - это звучит гордо: TDD есть опиум для народаReanGDhttp://www.blogger.com/profile/00430212774743063809noreply@blogger.comBlogger14125tag:blogger.com,1999:blog-5198245118514831160.post-77505353938105450372015-06-02T23:29:01.054+03:002015-06-02T23:29:01.054+03:00Я всё хожу и думаю вот об этой реплике: "Дале...Я всё хожу и думаю вот об этой реплике: "Далее - какая-то фрагментарность мышления - вот на вашем видео с примером разработки "виселицы" через TDD, меня разрывался мозг: вот тут мы какую-то заглушку в код добавили, там недоделали, там забыли, при каждом новом тесте - добавлялись какие-то случайные куски кода, а какой-то цельной картины не появлялось. Так и хотелось сказать: все хватит! остановитесь! сейчас мы сядем, подумаем, и все эти недоделки нормально проработаем и закодим. Кстати, та часть, где забыли учесть случай с удвоенной буквой в слове - ИМХО именно из-за такого фрагментарного подхода к задаче - не пришел в голову тест - в коде ошибка, если сесть и помедитировать над кодом - это было очевидно."<br /><br />Честно говоря, это заставило меня задуматься.<br />Но я пришёл к выводу, что тут вовсе нет никакой проблемы с TDD. Забытая удвоенная буква - это на самом деле забытое ТРЕБОВАНИЕ к задаче. Я мог бы его точно так же забыть и без TDD. В обычной жизни требования как-то зафиксированы, поэтому так просто не забываются. TDD начинается там, где требование ясно и пора начинать кодить. <br /><br />"сейчас мы сядем, подумаем, и все эти недоделки нормально проработаем" - не всё так просто. У вас создалось обманчивое впечатление, потому что в случае виселицы требования к задаче предельно просты и понятны, и они точно не будут меняться. В реальной жизни всё сложнее. Мы часто не понимаем до конца требования, даже сам заказчик толком не может сформулировать, как оно должно правильно работать. Требования точно будут меняться по ходу проекта. Заказчику надо дать некий первый вариант, и когда он пощупает, он начнёт лучше понимать, куда двигаться дальше. Это итеративная разработка, бро. <br /><br />И совершенно точно сложные мысли проще сформулировать в виде простых примеров. <br />Вот пример из сегодняшней беседы с заказчиком.<br />- Должны ли карточные транзакции, отосланные, но ещё не подтверждённые из эквайринга, включаться в сумму "доступно" на обзоре?<br />- Ээээ... ХЗ... Дай-те ка подумать... Мммм... Ну, если у меня на счету 100 рублей, а я заплатил два раз карточкой по 20, то в "доступно" должно быть 60. asolntsevhttps://www.blogger.com/profile/16632087166612261207noreply@blogger.comtag:blogger.com,1999:blog-5198245118514831160.post-52491250730290958792015-06-02T23:14:52.753+03:002015-06-02T23:14:52.753+03:00:) Точно-точно.
А как иначе! Плохой инструмент - в...:) Точно-точно.<br />А как иначе! Плохой инструмент - всё плохо. Конечно замкнутый круг. asolntsevhttps://www.blogger.com/profile/16632087166612261207noreply@blogger.comtag:blogger.com,1999:blog-5198245118514831160.post-2451581395726578082015-05-28T22:43:56.773+03:002015-05-28T22:43:56.773+03:00Какой-то замкнутый круг получается, язык/IDE меня ...Какой-то замкнутый круг получается, язык/IDE меня плохо защищает, мне нужно больше тестов, но язык/IDE не позволяют легко и просто менять много тестов вслед за кодом - эффективность падает. Хоть на java переходи.ReanGDhttps://www.blogger.com/profile/00430212774743063809noreply@blogger.comtag:blogger.com,1999:blog-5198245118514831160.post-59067977609656072862015-05-28T22:39:39.813+03:002015-05-28T22:39:39.813+03:00Только я не против юнит тестов, когда они к месту ...Только я не против юнит тестов, когда они к месту - очень даже помогают, я против категоричных утверждений - вот это хорошо, а по другому - не правильно.<br />А в остальном - золотые слова, согласен серебрянной пули не существует, есть плюсы и минусы у каждой технологии. В каких-то случаях больше подходит один подход, в каких-то другой. И возможно, если бы я вживую пообщался с кем-нибудь из основателей движения TDD, я бы круто изменил свою точку зрения. Но к сожалению (или к счастью :) ) пока что мой опыт и задачи, которые приходилось решать - плохо ложатся на философию TDD, ну или как говорят его сторонники - я просто не умею его готовить.ReanGDhttps://www.blogger.com/profile/00430212774743063809noreply@blogger.comtag:blogger.com,1999:blog-5198245118514831160.post-19814647686881407822015-05-28T22:10:11.644+03:002015-05-28T22:10:11.644+03:00Боюсь, в корне неверный вывод. Если язык и IDE ещё...Боюсь, в корне неверный вывод. Если язык и IDE ещё не достигли такого уровня, значит, компилятор и IDE меньше защищают вас от ошибок - значит, наоборот, вам нужно больше тестов. <br /><br />А в том, что ваша производительность при этом падает, виноваты вовсе не тесты, а слабый язык/IDE.asolntsevhttps://www.blogger.com/profile/16632087166612261207noreply@blogger.comtag:blogger.com,1999:blog-5198245118514831160.post-38814554253411890302015-05-28T14:23:48.655+03:002015-05-28T14:23:48.655+03:00Я не девелопер, продукшн код не пишу, но мне интер...Я не девелопер, продукшн код не пишу, но мне интересно наблюдать за "за и против ТДД и юнит тестов". Тут есть наброс от опытного, но достаточного провокативного чела, с опиранием на научные исследования этой темы. Первая часть http://www.rbcs-us.com/documents/Why-Most-Unit-Testing-is-Waste.pdf и вторая http://www.rbcs-us.com/documents/Segue.pdf (во второй части больше по делу, в первой больше воды). Там вот как раз главный упор на думание и проработку задачи. Бонусом примеры как ТДД и настрой на тестабильность кода убивает архитектуру. Местами очень спорно, но как точку зрения стоит изучить. Я отчасти наслышан про проблемы упомянутого там "nordic client" т.к работал в нём.<br /><br />Мне кажется радикальные утверждения приведённые во втором абзаце этого поста (Да я согласен, что тесты...) и "100% покрытие" именно радикальные. Всяко есть люди продающие ТДД именно так, но я уверен, что настоящие лидеры и практиканты ТДД этого не делают и не агитируют.<br /><br />Как ни странно я согласен с выводами как Владимира так и Андрея :) С одним "но", если интеграционные тесты начинают бегать дольше полу часа - работать с продуктом становится очень неудобно, это неоспоримый плюс тест-пирамиды. НО и это можно было бы решать не только тестами, но и разбиением продукта на более мелкие компоненты. Истина где-то по середине и всегда есть несколько решений :)Sergei 'sserzant' Sergejevhttps://www.blogger.com/profile/13795222875746832203noreply@blogger.comtag:blogger.com,1999:blog-5198245118514831160.post-74761325318958759642015-05-27T02:36:44.846+03:002015-05-27T02:36:44.846+03:00Кажется моя основная проблема в том, что для испол...Кажется моя основная проблема в том, что для используемых мною языков - IDE еще не достигла такого уровня, что бы делать за меня такие вещи, а значит TDD пока не для меня.ReanGDhttps://www.blogger.com/profile/00430212774743063809noreply@blogger.comtag:blogger.com,1999:blog-5198245118514831160.post-73607644717600824872015-05-26T23:41:58.214+03:002015-05-26T23:41:58.214+03:00Пример со складыванием чисел некорректен.
Потому, ...Пример со складыванием чисел некорректен.<br />Потому, что не бывает такого REST-сервиса, который только складывает два числа. Бывает REST-сервис, который выполняет гораздо более сложную задачу - ну там, рассчитывает какой-нибудь график выплат кредита, скажем. Для которого в т.ч. нужно сложить два числа. И использовать ещё несколько других функций. Интеграционный тест на этот REST-сервис тоже безусловно нужен. Но покрыть им все называнные комбинации - сложно, если не невозможно. Это ж надо такой график подобрать, в котором попались бы все эти граничные значения. И если тест упал, ты никогда не знаешь, упал он из-за баги в функции сложения или в какой-то другой функции.<br /><br />Ну а если кто-то решит поменять тип данных с float на double, ему по-любому придётся менять очень много кода. Даже без тестов. Придётся менять все вызовы этой функции. По-любому большая работа. Тут плюс-минус девять вызовов погоды не делает. Тем более что такие вещи обычно делает за нас IDE. asolntsevhttps://www.blogger.com/profile/16632087166612261207noreply@blogger.comtag:blogger.com,1999:blog-5198245118514831160.post-27446853743272697532015-05-24T23:53:41.016+03:002015-05-24T23:53:41.016+03:00С TDD: тут приходится в первую очередь - не СОЗДАВ...<br /><br />С TDD: тут приходится в первую очередь - не СОЗДАВАТЬ, а ЛОМАТЬ, только одно это уже выбивает из колеи. Мало того мы ломаем ненаписанный, абстрактный алгоритм - и этим мы помогаем мозгу? Далее - какая-то фрагментарность мышления - вот на вашем видео с примером разработки "виселицы" через TDD, меня разрывался мозг: вот тут мы какую-то заглушку в код добавили, там недоделали, там забыли, при каждом новом тесте - добавлялись какие-то случайные куски кода, а какой-то цельной картины не появлялось. Так и хотелось сказать: все хватит! остановитесь! сейчас мы сядем, подумаем, и все эти недоделки нормально проработаем и закодим. Кстати, та часть, где забыли учесть случай с удвоенной буквой в слове - ИМХО именно из-за такого фрагментарного подхода к задаче - не пришел в голову тест - в коде ошибка, если сесть и помедитировать над кодом - это было очевидно. Вообще такой индуктивный подход - от частных случаев в тестах к общему алгоритму, уж извините больше свойственен нашей прекрасной половине человечества (http://efamily.ru/articles/109/2975), лично мне гораздо проще дедуктивный способ - в общем реализованном алгоритме вычислять и проверять частности в тестах.<br /><br />И напоследок: хоть и обещал не придираться к фразам, но не могу не пройтись по "Тестируемый код даёт хороший дизайн", ибо убил в свое время кучу времени на разбор постов Сергей Теплякова: http://sergeyteplyakov.blogspot.ru/2013/04/vs.html, где он делает вывод: "Помните о том, что тестируемость далеко не всегда приведет вас к хорошему дизайну, в то время как хороший дизайн не только обеспечит тестируемость, но даст еще и массу других преимуществ" С чем я согласен.<br />ReanGDhttps://www.blogger.com/profile/00430212774743063809noreply@blogger.comtag:blogger.com,1999:blog-5198245118514831160.post-6172099079041152492015-05-24T23:52:37.840+03:002015-05-24T23:52:37.840+03:00Спасибо за ответ. Написал сначало длинный ответ, п...Спасибо за ответ. Написал сначало длинный ответ, про выдирание фраз из контекста, придирки к формулировкам, но подумал, что этак можно месяцами играть в пин-понг изголяясь в нахождении новых оттенков смысла каждой фразы и в итоге толка не будет.<br /><br />Поэтому предлагаю пример задачи: найти среднее арифметическое чисел типа float в векторе. (Я сразу оговорюсь, что сейчас говорю о полноценных приложениях, а не о библиотеках - там правила немного другие)<br />Попробуем накидать по ней тесты:<br />- Тест с вектором в котором штук 10 случайных чисел<br />- Тест с пустым вектором<br />- Тест с очень большим вектором<br />- Тест с экстремально маленькими числами (ну что бы элементарно ноль в результате не получался)<br />- Тест с экстремально большими числами (вдруг переполнение вылезет)<br />- Тест с большими и маленькими числами (для увеличения точности имеет смысл отсортировать вектор и складывать от маленьких к большим)<br />- Минимум 3 теста на спец. значения NaN, INFINITY и -INFINITY<br /><br />Итого даже не на бизнес фичу, а на элементарную функцию сходу пришло в голову 9 тестов, при готовой реализации, можно еще десяток придумать по нюансам кода, это к слову про "тесты, которые его тестируют - а их немного, ну там, один-пять-десять". При полноценном тестировании по канонам unit-тестов, их будет очень много. И это я еще не брал динамические языки, там будет еще куча тестов из серии - как наш код отреагирует на передачу строки вместо вектора.<br /><br />Ну допустим мы решили что точности float нам не хватает и переделываем функцию на работу с более точным типом - double. Сколько тестов при этом придется менять? Да все, пусть минимально, но абсолютно все, минимум типы чисел поломаются в тестах. Вот про это я и говорю при упоминании "тысяч сломанных тестов". Что ж это за помогающие тесты при рефакторинге, когда вслед за изменением функции я их тут же все переписываю?<br /><br />А вот что характерно - более высокоуровневые тесты при таком изменении почти не сломались бы. У нас как работал какой-нибудь (в лучших традициях микросервисов) REST сервис, принимающий xml, так он и продолжил бы работать и плевать ему на то, что там внутри. Максимум, что сломается - в ответе придет более точное значение. Но это как раз ожидаемое поведение - мы поменяли тип на более точный - в ответе нам пришел более точный результат. Мало того, эти тесты еще бы сам REST сервис тестировали, парсинг xml, генерацию xml, как это все работает вместе и т.п. Ведь пользователь в конце концов будет пользоваться всеми этими модулями вместе, поэтому нам важно знать как это рабоает вместе.<br /><br />Я не к тому, что именно в этой задаче нужно использовать только интеграционные тесты. Я лишь пытаюсь показать, что выстраивать пирамиду типа "100 unit тестов, 10 интеграционный, 1 проверка живого тестировщика" - странная затея, зачастую дешевле и легче проверить код только интеграционными тестами н-р.<br /><br />Без TDD: вот описанный выше пример - типичный по размеру кирпичик на которой обычно разбивается задача - на час, ну может два. Вот неужели так сложно взять, "загрузить" его в голову целиком, продумать, обсудить с коллегами при необходимости, погуглить и потом одним куском написать? Ну не требует это каких-то гениальных мозгов и супер усилий. Все просто - думаем, пишем, пробегаем по коду - находим нетривиальные и сложные места - пишем по ним тесты - закрепляя результат, переходим к следующей задаче.ReanGDhttps://www.blogger.com/profile/00430212774743063809noreply@blogger.comtag:blogger.com,1999:blog-5198245118514831160.post-41964977105055971122015-05-24T01:34:42.302+03:002015-05-24T01:34:42.302+03:00Ну и давайте пройдусь подробнее по пунктам.
Многие...Ну и давайте пройдусь подробнее по пунктам.<br />Многие вещи вы говорите правильно, но есть нюансы, из которых складываются неверные выводы. <br /><br />1. Вы немножко искажаете слова.<br />Цитирую: "Заменять документацию только тестами - глупо. Избегать функциональных тестов, только потому что они медленнее и сложнее - неправильно." и ещё: "написанный по TDD код никогда переписывать не придется". И это: "с TDD они познают дзен и вот прям щас с первого раза напишут правильно"<br />А никто и не говорит, что только тестами. Никто и не говорит, что функциональных тестов надо избегать. И уж точно никто и никогда не говорил, что код не придётся переписывать. Скорее наоборот, тесты помогают код смелее рефакторить.<br /><br />2. Вы жалуетесь на то, что в презентациях слишком простые примеры. <br />Увы, это так. Но в этом виновато вовсе не TDD, а формат выступления. Мы пробовали использовать более сложные примеры - для зрителей это оказывается слишком сложно. Уже после описания проблемы у них дымится мозг, до тестов даже не доходит. Но это вовсе не значит, что TDD не применимо для более сложного кода. Ещё как применимо. <br /><br /><br />3. Вы сами себе противоречите.<br />В одном предложении вы говорите, что пишите сложный код (менеджер потоков, инжекты какие-то), а в следующем говорите, что код-то в основном тривиальный. По-вашему, тесты и для сложного кода не написать, и для простого не написать.<br /><br />P.S. Тесты для многопоточного кода, конечно, тоже можно писать. Более того, там они ещё более необходимы, т.к. отлавливать ошибки в таких программах на порядки сложнее.<br /><br />4. "Но нужно понимать, что бенефиты дает детальная проработка задачи, но никак не написанный заранее тест."<br />Спасибо, кэп! Конечно, важна детальная проработка. А тест помогает детально проработать. Не надо противопоставлять. TDD - это не замена мозга. TDD - это способ РАЗРАБОТКИ, т.е. инструмент для той самой детальной проработки. TDD - не замена мозга, TDD - помощник мозга.<br /><br />5. Вы неправильно поняли<br />"разработка чего-то нового требует эволюционного проектирования и соответственно регулярной переделки кода."<br />Совершенно верно! И как раз для эволюционного проектирования тесты и нужны! И регулярная переделка с тестами идёт как по маслу - не боишься сломать.<br /><br />6. "Юнит тесты хорошо, а другие плохо"<br />Никто не говорит, что другие тесты - это плохо. Другие тесты тоже нужны, но их должно быть на порядок меньше. Другими словами, если что-то можно протестировать юнит-тестом, выбери юнит-тесты. И только если никак (все эти сеть и БД), бери следующий вид тестов.<br /><br />7. "Что бы узнать как работает код в общем случае - нужно, как ни странно, посмотреть на код."<br />Совершенно согласен! Никто и не говорит, что замена документации - это только тесты. Конечно же, код плюс тесты. <br /><br />8. Вы преуменьшаете<br />Ваши "исключения" ("иногда по коду не понятно...") - это как вовсе никакие не исключения, а самая что ни на есть ежедневная действительность. И именно в этих случаев тесты и выполняют роль документации. Всё так и есть.<br /><br />9. Троллинг динамических языков (особенно JavaScript) - это пять баллов.<br />Вот тут я полностью согласен. Действительно, там приходится писать тесты для того, с чем мог бы справиться компилятор. Я их тоже недолюбливаю.<br /><br />10. "любой более менее серьезный рефакторинг приведет к переписыванию тысяч тестов."<br />Это говорит явное непонимание сути юнит-тестов.<br />С какой стати придётся менять тысячи тестов? Если меняется бизнес-логика метода, должны поменяться только те тесты, которые его тестируют - а их немного, ну там, один-пять-десять. <br /><br />11. "Вот только легко тестируемый код не дает никаких гарантий качества получившегося приложения."<br />Универсальный троллинг. Позволяет затроллить всё что угодно, потому что ничто не свете не может дать никаких гарантий. А документация даёт гарантии? Нафиг документацию. А ваш мозг даёт гарантию? Нафиг мозг. <br /><br />Тестируемый код даёт не 100% гарантию, но большую степень уверенности. Тестируемый код даёт хороший дизайн (низкая связанность и всё такое), который позволяет легко менять код в будущем. <br />asolntsevhttps://www.blogger.com/profile/16632087166612261207noreply@blogger.comtag:blogger.com,1999:blog-5198245118514831160.post-60889061740053751752015-05-24T01:17:37.203+03:002015-05-24T01:17:37.203+03:00"Тесты далеко не единственный способ обеспече..."Тесты далеко не единственный способ обеспечения качества кода, еще есть мозг"<br />Спасибо, кэп! Спасибо, что напомнили.<br /><br />Почему вам так хочется противопоставить тесты и мозг? Либо одно, либо другое. Либо пиши тесты, либо используй мозг. Включите мозг - и больше ничего не надо. Не слишком ли примитивное видение проблемы?<br /><br />Конечно, всю работу делает наш мозг. Беда только в том, что наш мозг медленный и быстро устаёт. Даже самые одарённые из нас не способны активно думать слишком долго, запоминать слишком много и постоянно делают ошибки. Мозгу надо помогать. Надо делать какие-то упражнения или как-то перекладывать часть нагрузки на что-то другое. Я знаю только два способа помогать мозгу: это спорт и TDD. Ну, ещё Шерлок Холмс использовал для этой цели кокаин. Знаете ещё способы - делитесь, с удовольствием попробую. Но не надо говорить мне: "просто включите мозг". asolntsevhttps://www.blogger.com/profile/16632087166612261207noreply@blogger.comtag:blogger.com,1999:blog-5198245118514831160.post-75636916919203954352015-05-20T11:26:19.734+03:002015-05-20T11:26:19.734+03:00"Тесты далеко не единственный способ обеспече..."Тесты далеко не единственный способ обеспечения качества кода, еще есть мозг"<br />Да, да и еще сто раз да - использование мозга и здравого смысла на мой взгляд позволяют избежать гораздо большего количества проблем, чем поведение вроде "мы работаем по эджайл и поэтому у нас идеальный продукт" или "у нас есть юнит тесты, поэтому приложение прекрасно будет работать всегда" )<br />Маринаhttps://www.blogger.com/profile/18041990863384205957noreply@blogger.comtag:blogger.com,1999:blog-5198245118514831160.post-24186836286567507572015-05-20T09:17:32.344+03:002015-05-20T09:17:32.344+03:00Красавчик, я прослезился :) Больше не буду теперь ...Красавчик, я прослезился :) Больше не буду теперь тебя TDD заставлять делать ))))))))))Maxim Shulga (aka MaxBeard12)https://www.blogger.com/profile/05615743910272666556noreply@blogger.com