Если нельзя, но очень хочется, то нужно обязательно и ничего в мире не стоит того, чтобы делать из этого проблему!


Интересна Java? Кликай по ссылке и изучай!
Если тебе полезно что-то из того, чем я делюсь в своем блоге - можешь поделиться своими деньгами со мной.
с пожеланием
столько времени читатели провели на блоге - 
сейчас онлайн - 
Показаны сообщения с ярлыком unit тесты. Показать все сообщения
Показаны сообщения с ярлыком unit тесты. Показать все сообщения

понедельник, 17 января 2022 г.

Инженерные практики могут ускорить тебя в 100х раз

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

Почему я коллекционирую различные ускорялки? Математика проста. Пусть это конкретное решение мне даст +15% в производительности. Какое-то другое решение даст +15%. Еще где-то что-то прочитаю и попробую, снова +15%. Складываем вместе 10 подобных решений и получаем 1.15 ^ 10 = 4.04. То есть 10 подходов ускоряющих тебя всего лишь на 15% в сумме дают + 404%, а это 4х в скорости! Подходов за 10 летний опыт может собраться на порядок больше. И для 50 штук прирост будет уже 1083%, 10x. А и это 15% роста продуктивности это так, самый минимум из того, что новая практика тебе может дать. Часто введение нового подхода сама по себе в разы тебя ускоряет. 

Внимательний читатель заметит, что любой новый подход в разработке облагает автора налогом. Естественно надо закладывать время на суппорт. Часто разработчик принимает решение сам, буду ли заморачиваться с новым кодом и его суппортом или по старинке сделаю, и делает это на основе критерия. Если я скажу, что новый подход даст тебе прирост в производительности в 10 раз, а при этом потребует от тебя всего лишь по 5 минут в день больше времени - дурак не согласится. Но обычно все не так. Времени на реализацию решения надо потратить сегодня 2-3 часа, а потом еще на суппорт решения раз в неделю по 0.5 часа. А прирост будет 10-20%, что уже не так леко прочувствовать, как 2,5 часа. На одной чаше весов - вклад в часах единоразовый с небольшим вниманием, а на другой % прироста производительности. % складываются иначе, чем часы. Копить % выгоднее, чем экономить время. Не всегда, но часто.

Правда, далеко не все дивиденды от инженерных полдходов можно "складывать" как описано выше. Есть независящие инструменты. Ну например я кодирую в Idea (она удобнее), а на сервере у меня все в docker (легче чем инсталить все на host машину). Там на X% ускорился, тут на Y%. Но так как работаю я ИЛИ в идее ИЛИ с докером на сервере, то % берется не от 168 рабочих часах в месяце, а от всего времени в IDE и отдельно всего времени во время обслуживания сервера. Результат складываем и "X% + Y%" дает ((1+X/100)*develop_time + (1+Y/100)*deploy_time). И в этом случае время проинвестированное в разработку и поддержание инструмента стоит оценивать критичнее. Но есть и фундаментальные подходы, скажем как следование принципам BabyStepsRefactoring, CleanCode, UnitTesting, TestFirst. Выгода от использования этих принципов ощущается одновременно и влияет друг на друга, потому формула суммирования будет более вкусной. Возможно не (1+X/100)*(1+Y/100) - это крайность. Но чем более влияния подходов друг на друга, чем чаще они используются, тем ближе мы к пермножению процентов, а не суммированию.

Надеюсь никтон не будет спорить в наше время с тем фактом, что рефакторить код необходимо, если ты хочешь хоть как-то влиять на энтропию системы. Держать код в чистоте - значит помогать себе и другим читателям понимать, что тут происходит. Делать рефакторинг можно грубо зарывшись по уши в код и потом тратя время на исправление всех ошибок компиляции, отловку багов, а можно элегантно - вооружившись компилятором ide и юнит тестами быстро привести код в рабочий вид. Но параллельно с этим всем можно производить рефакторинг маленькими шажками, что позволит исключить дебаг из процесса. А если нужна новая функциональность, то использования подхода TestFirst и сключит дебаг так же из процесса разработки. Привет TDD! Каждая из практик ценна сама по себе, но вмсте они дают возможность избавиться от Debug вообще. 

Debug - самая сложная и неуправляемая, а потому и дорогостоящая часть в разработке. Во время Debug ты мало что понимаешь - только тыцаешь 2-3 клавиши и смотришь в стек в ожидании инсайта. А без юнит тестов рефакторинг опасен, но если ты и осмелишься - много багов уйдет на прод. А без рефакторинга сложно и за CleanCode следить. Так вскоре техдолг не даст менять сисему как того нужно бизнесу. В какой-то момент исправление 1 баги будет порождать 2 новых. Тогда лучшее, что можно сделать - заморозить его. Ну или покрыть модуля автогенерируемыми юнит тестами, затем взяться за рефакторинг модулей с целью навести порядок в модели и сделать код чуть более clean. Затем выкинуть старые автогенерируемые тесты и написать нормальные, читабельные. Этот долг придется выплатить, если хочется продлить жизнь проекту. И лучше тут пользовать подходом ПрицнипСкаута. Сделать место стоянки после себя чище, чем оно было до тебя. Каждый день плати чуть-чуть времени уделяя этим инструментам: CleanCode + Refactoring + UnitTesting. И проект проживет дольше. 

Это один из примеров связки практик. Есть и другие практики. И тот из нас, кто научится использовать их по максимуму будет производительнее чем тот, кто не будет в 100 раз, в 1000 раз, а может и в 10000 раз. Возьмем студента новичка без опыта разработки - сложная задача может просто его застопорить на недели (если вообще задача будет решена), тогда как опытный миддл сделает ее за два дня. Вот и решай на сколько более производительный тот, кто сделал работу в сравнении с тем, кто не сделал ее. Я же верю в то, что хоть в среднем по индустрии Middle не сильно отличается от Senior (так просто устоялось), их производительность может отличаться в весятки, а то и сотню раз. Вопрос в том, остановился ли Senior в развитии на уровне инструментария Middle и дальше качает только SoftSkills или продолжает поиск инструментов его ускоряющих.

понедельник, 20 августа 2012 г.

В чем разница: "тесты до" или "после" кода?

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

Сам по себе плохо работает, его поддерживают тяжеловесные инж. штуки: рефкторинг, test list, OOP, unit testing, и только если все в комплексе, тогда получится. А еще голову надо сломать об стену, пока не станешь на рельсы - причем ломать надо конкретно, по очень привычным направлениям: не дебажь, но откати; не думай об архитектуре сильно - рефакторинг сам позаботится о ней; пиши код по чуть-чуть, после безжалостно рефакторь его; не реализуй мысль, не обождавшую в тестлисте; не верь тому, что пишешь; страшно - пиши тесты; не предполагай - проверяй тестами. И это только из числа первых шишек.

Понятно, почему в XP коуч в команде личный есть. Обычно, с ТДД потому и спрыгивают, что внедряют его ребята не совсем опытные, в проекте не совсем подготовленном. И тут двухдневным тренингом не отделаться - необходимы комплексные меры, либо очень подготовленный (рефакторинг, ООП, юнит тестирование) проект. А еще, что ставит почти финальную точку - то, что учим ТДД с нуля на простых вещах, а на проекте тем временем ждет хороший такой легаси проект, к которому прикрутить ТДД еще надо ой как постараться - тут тебе и high coupling и low cohesion. Тут-то и возникает первое заблуждение - TDD для проектов "с нуля". Пускай так, но когда наступает этот первый проект - его тесты будут ужасными, потому как все ждали нового проекта, чтобы применить в нем ТДД, но все это время ни на йоту не прокачались в unit тестировании.

Тесты-якоря - от которых каждый раз спотыкаясь, с матом, хочется избавиться случаются от отсутствия опыта. ТДД на новом проекте так же не заведется. Опять же нет коуча, того парня или той девушки, которая 100 раз подавляли в себе желание спрыгнуть с ТДД, потому как: "сложно написать тест", "это отнимает много времени", "заказчик никогда не пойдет на это" и так далее...

Очень сильно запомнился вопрос "нафига ТДД", но его можно нагуглить, а я хочу немного приоткрыть вопрос "в чем разница - писать тесты до или после кода?". А разница огромна и вот почему:

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

- Сode coverage тестами (написанными после кода) низок. А еще полагаться на тулзу, которая говорит что на проекте 80% code coverage можно, но я бы не стал сильно. Потому как можно написать такой один тест, который походит по основным флоу и соберет X%, но это вовсе не значит что функциональные требования покрыты - просто процессор побывал в некотором числе строк. Вот если закомментировать любую строку в коде проекте и при этом соответствующий функциональности тест свалится всегда - вот тут 100% покрытие. С ТДД кода пишется настолько мало, насколько это нужно для зеленой полосы. Но если какая-то строчка проскочила тут, то на этапе рефакторинга она должна быть удалена, потому как удаляется весь код, который не приводит к поломке тестов. Дабл чек. Покрытие максимальное и становится меньше 100% только за счет того, что где-то написали больше чем надо было для теста, а на рефакторинге схалтурили :) Но это тут каждый сам себе доктор. Идем дальше, о рефакторинге...

- Рефакторинг всегда по чуть чуть приводит к той самой хорошей архитектуре, о которой изначально не стоило думать. Умеешь делать рефакторинг, понимаешь принципы ООП - будет тебе счастье. Тут ТДД тем лишь ценный, что предоставляет для рефакторинга зеленую полосу так часто, как это возможно - каждые 10-15 минут (при условии, что с ТДД у нас проблем нет). И рефактори себе на здоровье: поломал - откати, есть зеленая полоса и стало чище - коммить! Когда пишем код а потом покрываем его тестами - рефакторинг не очень то и хочется делать - поломаешь ведь. А с ТДД рефакторинг в кайф. Представь, что тебе придётся собирать кубик рубика (что само по себе задача не простая, даже если знать как) без того самого основания на котором все держится - это возможно, но чертовски сложно, постоянно все ломается. Так и рефакторинг без тестов. Тесты и есть то самое основание кода. Верти себе грани на здоровье. Рефакторинг в кайф - это еще одно преимущество, которое мне дает ТДД в процессе разработки.

- Любой человек ошибается часто. Глупые ошибки он делает приблизительно раз в 5 минут. Это я по себе и коллегам, с кем удалось в паре поработать, сужу. Банальная очепятка. Думаю одно - пишу другое. Нет тестов, нет фидбека о том, что ты ошибся. Поработал 2 часа? Вот тебе и 20 ошибок, которые надобно отладить. А для этого кто нужен? Дебаггер. Ничего против не имею, использую регулярно, но с ТДД я его использую, когда мне хочется (допустим, любопытно что-то), а не когда я вынужден это делать потому как система не работает и я понятия не имею в чем дело - а это самый дорогой процесс. С ТДД его можно максимально сократить. Поломал что-то? 5 минут всего прошло от коммита? Ривертни и попробуй еще раз. Снова ошибся - сделай перерыв.

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

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