Які етапи проходить задача в гнучкій розробці ПЗ та як оптимізувати час на її виконання

Доброго дня, мене звати Богдан, зараз я працюю Senior Software Engineer в компанії Check24 GmbH. За вісім років роботи мені доводилось брати участь у не малій кількості проєктів. І майже завжди головним болем був час і швидкість закриття задач. Клієнти намагаються максимально стиснути терміни виконання, програмісти намагаються вибити більше часу на різні другорядні задачі типу тестів, рефактору, оновлень тощо.

Тому у своїй команді я почав замислюватись над тим, які етапи проходить задача (таск) від моменту, коли вона потрапила до програміста, і до моменту, коли вона викотилась на прод. Від чого залежить час виконання задачі? Чому іноді витрачений час виходить за межі оціненого часу? І у цій статті я хотів би розкрити основні етапи роботи над задачею. А також трохи розкрити питання, куди йде час під час розробки.

Отже, маємо задачу, створену тестувальником/проєкт-менеджером/клієнтом. Зазвичай її поділяють на три категорії — новий функціонал (нова фіча), удосконалення (імпрувмент) і усунення помилки (баг фіксинг). Всі ці категорії проходять однакові етапи з однією відмінністю — витратою часу на виконання того чи іншого етапу, але про це ми поговоримо пізніше.

Етап перший — ознайомлення з таском

На цьому етапі ми отримуємо таск з Джири або іншого подібного інструменту, читаємо, заглиблюємося і намагаємося вияснити незрозумілі моменти. Швидкість виконання зазвичай залежить від налагодженої комунікації в команді і якості опису задачі. Чим краще описана задача, тим швидше можна приступати до її аналізу. Якщо в команді є новий співробітник, в нього на ознайомлення йде набагато більше часу, також він забирає час інших членів команди для уточнення деяких моментів.

Етап другий — аналіз коду

Ми починаємо аналізувати код, який маємо, щоб зрозуміти, як імплементувати задачу. Швидкість на цьому етапі сильно залежить від якості кодової бази, до прикладу, важче зрозуміти один клас на 2000 рядків, який є прикладом для книжки про антипатерни, ніж 10 класів по 200 рядків, які зпроєктовані за всіма правилами. Якість кодової бази залежить від наступного етапу — розробки. Якщо раніше були ухвалені правильні рішення щодо розробки, то аналіз коду забирає менше часу. Звісно, більш досвідчений розробник швидше заглибиться і в погано написаний код, але йому все одно доведеться витратити трохи більше часу на аналіз поганого коду, ніж на добре написаний код. Також на цьому етапі варто обговорити шляхи реалізації. Мається на увазі дотримання хороших практик, використання патернів, автоматичні тести тощо.

Тут варто відступити і трохи пояснити. Часто бізнес диктує умови, і часу на написання «ідеального» коду недостатньо. Тому доводиться відмовлятись від імплементації чогось додаткового, наприклад, тестів або додаткового рефакторингу коду. Тому бажано обговорити всі аспекти виконання задачі перед розробкою.

На цьому ж етапі іноді варто переглянути оцінений час виконання задачі або розбити таск на декілька підзадач.

Етап третій — розробка

Одна з основних частин роботи на таском. На цьому етапі ми вже знаємо, як це працює, і що потрібно робити. Швидкість виконання залежить в першу чергу від об’єму задачі і досвіду програміста, але великий вплив мають два інших фактори. Перший — як ми хочемо імплементувати задачу (мається на увазі дотримання хороших практик, використання патернів, тести тощо). Це ми б мали обговорити ще на етапі аналізу. Другий — наскільки хорошою є існуюча кодова база для розширення. І якщо перший фактор — це дискусійне питання і часом чимось можна знехтувати задля швидкої реалізації нового функціоналу, то другий фактор — це якраз наслідок попередніх рішень першого фактору.

До прикладу, якщо архітектура є високо зв’язаною, то шанс зламати щось в неочікуваних місцях є дуже великим, але така архітектура є результатом минулих рішень. Маємо дещо замкнуте коло, якщо ми хочемо якомога швидше викотити новий функціонал на прод, то в короткій перспективі ми можемо відмовитись від імплементації хороших практик і тестів (зазвичай це і є аргументація бізнесу, чому в нас немає часу на автоматичні тести). Але в довшій перспективі ми будемо отримувати довший аналіз коду, довшу розробку та довше тестування (про це в наступному розділі). Відзначу, що написання тестів — це також етап розробки. Якість і швидкість написання тестів залежить також від досвіду розробника.

У своїй роботі я часто був свідком, коли вирішували відмовитись від тестів, рефакторингу, або просто писали жахливий спагеті-код, бо «треба на вже». А потім дивувались, звідки так багато багів. Але в той же час програмісти в своїй роботі також намагаються створити щось «ідеальне», і розробка затягується на тижні, а то й місяці, викотити на прод хоча б щось робоче не виходить. А потім розводять руками зі словами: «Зате в нас є тести!».

Етап четвертий — тести

Якщо задача має помилки в роботі, то це не імплементована задача. Тому результат кожної розробки повинен бути протестований, всі виявлені помилки мають бути усунені. Тестування поділяється на два типи — ручне і автоматичні тести. Ручне тестування зазвичай займає більше часу, ніж автоматичне, але його не можна повністю замінити автоматичним. Швидкість етапу переважно залежить від об’єму задачі, але бувають винятки. Також є свої фактори впливу, автоматичні тести прискорюють процес і навіть можуть виловити деякі баги ще під час розробки, але на їх написання витрачається час при розробці.

Як відбувається тестування без автоматичних тестів на практиці? Ми розробили якийсь функціонал, тестуємо руками всі випадки, які б міг зламати наш новий код, виявляємо помилки, повертаємось до етапу розробки, виправили помилки, знову тестуємо, і так, поки кількість помилок не наблизиться до нуля. Передаємо задачу тестувальнику/проєкт-менеджеру/клієнту. Останній тестує і знаходить помилки в неочікуваних місцях (бо до того всього в проєкті маємо спагеті-код і вибуховою хвилею змін зачіпає багато чого) і повертає на доопрацювання.

Розробник виправляє виявлені помилки, разом з цим створює ще більше нових, про які дізнається з подальших тестувань. Процес виявлення/виправлення помилок може тривати безкінечно. Автоматичні тести можуть бути хорошим запобіжником таких ситуацій, вони допомагають швидко протестувати код і виявити помилки в неочікуваних місцях, хороша кодова база також запобігає утворенню багів. До факторів впливу також потрібно віднести досвід програміста. Досвідчений програміст може уникнути елементарних помилок у коді. Також на цьому етапі зазвичай тестує не тільки програміст, а і той, хто створив задачу, але його час на тестування не завжди враховується.

В цьому місці я хотів би зупинитись на одвічному питанні, що краще — юніт-тести чи Е2Е-тести. Покажу на дуже спрощених прикладах.

Ситуація, коли імплементовані тільки Е2Е-тести. Е2Е-тести описують різні поведінки кінцевого користувача — це означає, що якщо ми маємо тести для кошика замовлень, а для сторінки авторизації не маємо, то тести покажуть помилку тільки для кошика. Якщо ми зробили зміни в класі User, який потрібен для сторінки авторизації і кошика замовлень, то навіть якщо тести покажуть, що ми не маємо помилок на сторінці кошика, це не є свідченням того, що ми не зламали сторінку авторизації.

Ситуація, коли імплементовані тільки юніт-тести для класу User. Добре написані тести виявляють помилки і для сторінки авторизації, і для кошика. Але навіть якщо всі юніт-тести зелені — це ще не свідчення того, що ми імплементували правильно задачу згідно з описом.

Відповідь десь посередині.

Етап п’ятий — розгорнення

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

При ручному розгорнені часто виникають біль і сльози. В деяких ситуаціях процес може покласти сервер і/або забрати багато часу.

Етап шостий —тести на проді

Відповідно після розгорнення на «живих» серверах нового функціоналу його бажано ще раз протестувати. Тут вступає в роль четвертий етап, але в легкій формі. Зазвичай це загальні тести для пересвідчення, що «все працює і нічого не зламано». Автоматичні тести якщо є, то працюють, як і на четвертому етапі, на повну потужність, але наш час вони практично не забирають. При правильному налаштуванні розгорнення вони запускаються автоматично і автоматично надсилають сповіщення про помилку. Зазвичай помилки на цьому етапі виявляються рідко, і він не забирає багато часу, але швидкість все ж залежить від об’єму задачі.

Етап сьомий — баг-фіксинг

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

Отже, функціонал на проді в деяких випадках може не працювати. Для цього створюють так звані «баг-тікети», і їх потрібно «пофіксити». Кожна задача, навіть для усунення помилки, проходь всі описані вище етапи і займає відповідно час, але під час фіксингу основна задача досі не працює або працює некоректно. Скільки часу потрібно на фіксинг? Не так багато, як на реалізацію основної задачі, але кількість таких «баг-тікетів» може бути великою. Трапляються випадки, коли задачу викочують з певними знайомими багами, тому цей етап завжди дискусійний.

Наразі це всі етапи, які я визначив для себе. Деякі з них важливі, деякі менш важливі. На всі етапи витрачається час, але в різних категоріях, про які я згадував на початку, таких як нова фіча, удосконалення і баг-фіксинг, він витрачається по-різному. До прикладу, на баг-фіксингу йде набагато більше часу на аналіз, ніж на розробку. Інколи я витрачаю декілька годин на аналіз, що не так, і потім кілька хвилин в мене займає зміна одного рядка на етапі розробки, щоб усунути помилку. Тести також займають мало часу, якщо вони автоматичні. Для нових фіч я витрачаю менше часу на аналіз і більше на розробку, оскільки маю написати ще велику кількість тестів. А на удосконаленні зазвичай витрачається багато часу на тестування, щоб пересвідчитись, що існуючий функціонал не зламаний.

Висновок

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

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

👍НравитсяПонравилось5
В избранноеВ избранном3
LinkedIn
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

В принципе вы описали стандартный процесс гавношлепства так знакомый каждому гребцу на галере. И каким боком тут вообще гибкая разработка ПО? И без Жиры конечно никуда.

Знаючи, на що витрачається час на кожному етапі розробки і при аналізі проєкту загалом, можна прискорити час виконання кожного таску в короткій або довшій перспективі

Это понятно. Но вы обещали рассказать

як оптимізувати час на її виконання

И все-таки как?

Зазвичай, бізнес не вдається в деталі технічної частини і вимагає якомога швидше викотити новий функціонал на прод

Это как не интересоваться планированием и ходом постройки собственного дома бригадой строителей и требовать как можно быстрей выполнить все работы. Очень дальновидно. Хотя если дом не для себя строите, а как подрядчик, то и хер с ним.

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

Это описание классического гавнокодера, а не программиста. А где же этика и профессионализм? Или в вашей компании практикуют пытки? Так это запрещено конвенцией ООН. Чесслово, не инженеры пошли, а кикие-то мамкины кодошлеперы. Постоянный и беспощадный рефакторинг на проекте залог его успеха.

своїм досвідом оптимізації часу на проєктах

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

В принципе вы описали стандартный процесс гавношлепства так знакомый каждому гребцу на галере. И каким боком тут вообще гибкая разработка ПО? И без Жиры конечно никуда.

В принципі, я описав стандартний процес розробки :)

Это как не интересоваться планированием и ходом постройки собственного дома бригадой строителей и требовать как можно быстрей выполнить все работы. Очень дальновидно. Хотя если дом не для себя строите, а как подрядчик, то и хер с ним.

Під «деталями технічної частини» малося на увазі покриття тестами/дотримання стандартів програмування/технічний борг і т.д. зазвичай бізнес цим не цікавиться так само як і ви не стоїте над будівельною бригадою і не перевіряєте співвідношення піску до цементу :)

Это описание классического гавнокодера, а не программиста. А где же этика и профессионализм? Или в вашей компании практикуют пытки? Так это запрещено конвенцией ООН. Чесслово, не инженеры пошли, а кикие-то мамкины кодошлеперы. Постоянный и беспощадный рефакторинг на проекте залог его успеха.

Приведу приклад. Зазвичай розробка нової фічі у мене починається з протипування і якщо фіча горить бо ПМи провели дослідження і їм от навчора це треба, а прототип виглядає повністю робочим або це тестова фіча яка невідомо чи взлетить і потрібно розробити прототип для того ж дослідження то часу не так багато на роздуми про етику і професіоналізм бо як ви влучно підмітили для бізнесу потрібно робочий софт... Скажу так, на рівні прототипу там не завжди пахне етикою і професіоналізмом :)

Да не нужно его оптимизировать. Для бизнеса нужен работающий софт, производящий профит.

До речі, мені приходилось проєктувати з нуля декілька таких працюючих проєктів так як технічний борг був настільки великим, що рефактор зайняв би 70% роботи. Клієнти самі приходили і казали «ось є старий ми хочемо з нуля новий».

До речі, мені приходилось проєктувати з нуля декілька таких працюючих проєктів так як технічний борг був настільки великим, що рефактор зайняв би 70% роботи. Клієнти самі приходили і казали «ось є старий ми хочемо з нуля новий».

Так это и есть результат прототипов с душком, запущенных в продакшн. Долг он ведь не с ровного места растёт. Рефакторинг это лекарство от таких запоров и непроходимости — и тесты будут и архитектура стройная и конвенции кода и CI/CD вылизанный до полного автоматизма и так далее. А с тем подходом что вы описали, вы обречены с нуля переписывать в следующий ноль и так в рекурсии

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

Классики от горя взяли и написали книги по Domain-Driven-Design чтобы по граблям не топтаться :)
Тут же человек пишет про то что им яйца в тиски бизнес загоняет, а свои не достаточно большие чтобы сказать погодьте ребята, не гоните коней, давайте сядем и разберем что к чему и как оно работать должно.

Вот про третий раз это то ли из DDD, то ли из POSA5. В той же DDD книжке пример как классно описали домен по докам, а потом как начались хотелки в проде — то оказалось, что разбивка кривая и надо переделывать нафиг. Поэтому часто лучше довести прототип до прода, и на нем собрать грабли, чем делать фулл-скейл энтерпрайз, не потоптавшись по домену в продакшне. Энтерпрайз переписывать дороже будет)

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

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

Зачем сидеть в песочнице? Заимплементил и выкатился, прошёл тесты свои и пользователи потыкали и в прод. Но это никак не коррелирует с DDD и другой внутренней кухней. Если чего будет и не так, то от кривых реквайроментов. Ну на это есть следующие итерации

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

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

И как предлагаешь скорректировать неверное разбитие на микросервисы, когда один из них пишут в Индии на Джаве, а другой — в Украине на Питоне?

Так это же не техническая проблема, а организационная. Наладить коммуникацию, понять домен, выработать общий язык (Ubiquitous Language), разбить по контекстам (Bounded Context) используя например Event Storming, выстроить workflows, определить контракты между ними на уровне DTOs. Кто сказал что легко будет? DDD, он не о паттернах больше, а о том как понять доменную область и занести ее в имплементацию системы.

Все проблемы — организационные)))
Всегда можно найти лучшего человека в отрасли, и заплатить ему, чтобы он сделал проект. Или купить готового конкурента. Но почему-то так не делают — видимо, организационные проблемы)

Потому что гавношлепство и аутсорсинг по fixed price схеме :) Зачем там DDD или высокие материи? Там клей и сопли и немного знаний жабаскрипта

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

Так это нормальный процесс разработки. Переосмысливать, рефакторить, архитектуру менять, переписывать. Бизнес тоже на месте не стоит и правила меняются

пиарная статья не удалась )))
пищи еще, но более правдоподобно )))

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

А еще — писал ее не ты,
потому что в твоих каментах, когда ты пишешь — ты запятые почти не используешь ))
проф-деформация простого програмиста ))

Перед публікацією статті редактори ДОУ її вичитують і розставляють коми в потрібних місцях ;)

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

Подписаться на комментарии