Переглядаючи статті з проєктування ПЗ, ми постійно зустрічаємо небачені скорочення та мимохіть згадувані практики розробки.
- TDD — ну, це всі знають, спочатку пишемо тести, а потім решту коду
- BDD — щось знайоме, начебто, теж тести, але особливі
- TDD — знову? Так, стоп, тут уже не про тести зовсім. Але чому називається так само?
- DDD — bound contexts, ubiquitous language, domain...
- FDD — та скільки можна?
- MDD — серйозно, на основі діаграм?
- PDD — ...
Підходи до розробки діляться за складністю, областями застосування та цілями.
Думаю, настав час розібратися, навіщо вони потрібні, чому їх так багато, і як вони можуть бути нам корисні.
Ми почнемо знайомитися з ними від найпростіших до досить складних, розглянемо приклади використання та плюси та мінуси кожного з них.
TDD — Test-Driven Development
TDD — це методологія розробки ПЗ, яка ґрунтується на повторенні коротких циклів розробки: спочатку пишеться тест, що покриває бажану зміну, потім пишеться програмний код, який реалізує бажану поведінку системи і дозволить пройти написаний тест. Потім проводиться рефакторинг написаного коду із постійною перевіркою проходження тестів.
Звучить просто та зрозуміло. Багатьом знайомий такий підхід до розробки і навіть сам Uncle Bob активно його пропагує.
TDD вважається однією з форм правильного методу побудови програми. Філософія розробки на основі тестів полягає в тому, що ваші тести є специфікацією того, як ваша програма має поводитися. Якщо ви розглядаєте свій набір тестів як обов'язкову частину процесу складання, якщо тести не проходять, програма не збирається, тому що вона неправильна. Звісно, обмеження у тому, що правильність вашої програми визначена лише як повнота ваших тестів. Проте дослідження показали, що технологія, заснована на тестуванні, може призвести до зниження помилок на 40-80% у виробництві.
Почавши використовувати TDD, ви можете відчути, що працюєте повільніше, ніж зазвичай. Так відбувається, тому що ви працюватимете поза «зоною комфорту», і це цілком нормально.
Після того, як ви відчуєте, що написання тестів стало простою та природною частиною робочого процесу, що вам більше не потрібно думати про використання TDD під час роботи над проєктом, ви усвідомите, що TDD влилося у вашу роботу.
Ця методологія дозволяє домогтися створення придатного для автоматичного тестування програми і дуже хорошого покриття коду тестами, оскільки ТЗ перекладається мовою автоматичних тестів. Все, що програма має робити, перевіряється. Також TDD часто спрощує програмну реалізацію: виключається надмірність реалізації — якщо компонент проходить тест, він вважається готовим.
Архітектура програмних продуктів, що розробляються таким чином, зазвичай краще (у додатках, які придатні для автоматичного тестування, зазвичай дуже добре розподіляється відповідальність між компонентами, а складні процедури, що виконуються, декомпозіровані на безліч простих). Стабільність роботи програми, розробленого через тестування, вища за рахунок того, що всі основні функціональні можливості програми покриті тестами та їхня працездатність постійно перевіряється. Супроводжуваність проєктів, де тестується все або практично все, дуже висока — розробники можуть не боятися вносити зміни до коду, а якщо щось не піде, то про це повідомлять результати автоматичного тестування.
Докладніше із принципами TDD ви можете ознайомитись, у книзі Кента Бека «Екстремальне програмування. Розробка через тестування».
TDD — Type Driven Development
Type Driven Development скорочено пишеться так само, як і технологія через тестування, тому зазвичай пишуть повну назву.
При розробці на основі типів ваші типи даних та типи сигнатури є специфікацією програми. Типи також є формою документації, яка гарантовано оновлюється.
Типи являють собою невеликі контрольні точки, завдяки яким ми отримуємо безліч міні-тестів по всьому нашому додатку. Причому витрати на створення типів мінімальні і актуалізувати їх не потрібно, тому що вони є частиною кодової бази.
Розробка за типом — це ще один правильний метод побудови програми. Як і у випадку розробки на основі тестування, розробка на основі типів може підвищити вашу впевненість у коді та заощадити ваш час при внесенні змін до великої кодової бази.
З мінусів — зростаюча складність мов з динамічною типізацією. Наприклад, для JavaScript цей підхід важче застосувати, ніж для TypeScript.
BDD — Behaviour-Driven Development
Через деяку методологічну схожість поняття TDD (Test Driven Development) і BDD (Behaviour Driven Development) часто плутають навіть професіонали.
У чому відмінність?
Концепції обох підходів схожі — спочатку йдуть тести, а потім починається розробка, але призначення в них зовсім різне.
TDD — це більше про програмування та тестування на рівні технічної реалізації продукту, коли тести створюють самі розробники.
BDD передбачає опис тестувальником або аналітиком користувальницьких сценаріїв природною мовою, якщо можна так висловитися, мовою бізнесу.
BDD — Dehaviour-Driven development — це розробка, заснована на описі поведінки. Певна людина (або люди) пише опис виду «Я як користувач хочу, щоб коли я натискаю кнопку «Пуск», тоді я бачив меню як на картинці» (там є спеціально виділені ключові слова). Програмісти давно написали спеціальні тули, які подібні описи переводять у тести (іноді зовсім прозоро для програміста). А далі — класична розробка з тестами.
Якщо записувати назви тестів як пропозицій і під час запису імен методів використовувати лексику бізнес-домена, створена документація стає зрозуміла замовникам, аналітикам і тестувальникам.
Тексти сценаріїв записуються у певній формі:
Маючи (прим. given — це) якийсь контекст,
Коли (прим. when) відбувається подія,
Тоді перевірити результат.
Може вийти щось подібне:
Або інший приклад:
+Сценарій 1: На рахунку є гроші+
Маючи рахунок із грошима
І валідну картку
І банкомат із готівкою
Коли клієнт робить запит на готівку
Тоді переконатись, що з рахунку було списання
І переконатися, що готівка видана
І переконатися, що картку повернуто
BDD підхід спільно з інженерними практиками дозволив нам відмовитися від legacy-документації, що містить неактуальну інформацію, і отримувати нову документацію на льоту, зберігати її разом із проєктом, що наблизило аналітиків та тестувальників до коду.
BDD — це швидше процес, метою якого є здешевлення реалізації нових фіч. Ще на старті розробки ми маємо важливі артефакти.
Наприклад, зрозумілу для підтримки документацію. Ця документація дає можливість усім зацікавленим особам сформувати своє уявлення про продукт і сценарії користувача поведінки, які повинні бути реалізовані в ході ітерацій розробки. З BDD-підходом ми також знижуємо поріг входу до проекту нових учасників.
У чому перевага BDD?
- Тести читаються для не програмістів
- Їх легко змінювати. Вони часто пишуться майже чистою англійською
- Їх може писати product owner чи інші зацікавлені особи
- Результати виконання тестів більш «людські»
- Тести не залежить від цільової мови програмування. Міграція іншою мовою сильно спрощується.
Недоліки:
Але цей підхід має й недоліки — це довго і дорого. BDD незручний хоча б тим, що вимагає залучення фахівців тестування вже на етапі опрацювання вимог, а це подовжує цикл розробки.
Виходом із цієї ситуації може виявитися вибір відповідного BDD фреймворку та правильно збудованих процесів розробки.
Багато хто вже давно зрозумів, що тестування — це свого роду панацея від усіх хвороб, але чи це так насправді?
Безумовно, ґрунтовно протестований код працює стабільніше та передбачуваніше, але тести не позбавляють нас проблем і помилок на етапі проєктування та постановки завдань. Наступні підходи до розробки можуть допомогти вам із цим.
DDD — Domain Driven Design
Предметно-орієнтоване проєктування не є якоюсь конкретною технологією чи методологією. DDD — це набір правил, які дозволяють приймати правильні проектні рішення. Даний підхід дозволяє значно прискорити процес проектування програмного забезпечення у незнайомій предметній галузі.
Предметно-орієнтоване проектування (рідше проблемно-орієнтоване, англ. Domain-driven design, DDD) — це набір принципів та схем, спрямованих на створення оптимальних систем об'єктів.
Процес розробки зводиться до створення програмних абстракцій, які називаються моделями предметних областей. У ці моделі входить бізнес-логіка, що встановлює зв'язок між реальними умовами галузі застосування продукту та кодом.
Підхід DDD особливо корисний у ситуаціях, коли розробник не є фахівцем у галузі продукту, що розробляється. Наприклад, програміст не може знати всі області, в яких потрібно створити ПЗ, але за допомогою правильного подання структури, за допомогою предметно-орієнтованого підходу, може легко спроектувати додаток, ґрунтуючись на ключових моментах та знаннях робочої області.
Основна мета Domain-Driven Design — це боротьба зі складністю бізнес-процесів, їх автоматизації та реалізації в коді.
«Domain» перекладається як «предметна область», і саме від предметної області відштовхується розробка та проєктування в рамках цього підходу.
Ключовим поняттям DDD є «єдина мова» (ubiquitous language). Ubiquitous language сприяє прозорому спілкуванню між учасниками проєкту. Єдина вона не в тому сенсі, що вона один на всі випадки життя. Якраз навпаки. Всі учасники спілкуються нею, все обговорення відбувається у термінах єдиної мови, і всі артефакти максимально повинні викладатися у термінах єдиної мови, тобто, починаючи від ТЗ, і закінчуючи кодом.
Наступним поняттям є «доменна модель». Ця модель є словником термінів з ubiquitous language. І доменна модель, і ubiquitous language обмежені контекстом, який у Domain-Driven Design називається bounded context. Він обмежує доменну модель таким чином, щоб усі поняття всередині нього були однозначними, і всі розуміли, про що йдеться.
Приклад: візьмемо сутність «людина» і помістимо її в контекст «публічні виступи». У цьому контексті, за DDD, він стає спікером чи оратором. А в контексті «родина» — чоловіком чи братом.
Тепер про код. Важливо, щоб ваш код читався як книга, був простим і зрозумілим усім, хто володіє єдиною мовою проекту. Що я маю на увазі?
Якщо в мові проекту ви використовуєте вираз «продукт був доданий», то наступний варіант не по DDD:
var product = new Product('apple')
product.save()
Чому? У коді написано, що ми створили продукт дивним чином та зберегли його. Як же додати продукт?
Потрібно додати його. Ось DDD код:
Product::add('apple');
Архітектура:
З точки зору Domain-Driven Design абсолютно байдуже, яку архітектуру ви оберете. Domain-Driven Design не про це, Domain-Driven Design про мову та спілкування.
Але DDD майже неможливий без чистої архітектури проекту, тому що при додаванні нової функціональності або зміні старої потрібно намагатися зберігати гнучкість та прозорість кодової бази. Про порти, адаптери та цибульну архітектуру можна прочитати у чудовій статті. Зображення зверху саме з неї.
Що ж нам це дає у результаті:
- Майже всі учасники команди можуть читати код проєкту
- Постановка завдань стає більш очевидною
- Баги бізнес логіки ставати простіше шукати
- QA фахівцям набагато легше переглядати код та знаходити логічні помилки та баги
Недоліки:
- Потрібна висока кваліфікація розробників, особливо на старті проєкту
- Не всі клієнти готові піти на такі витрати, DDD потрібно вчитися всім учасникам процесу розробки
FDD — Features Driven Development
FDD — ця методологія (коротко названа FDD) була розроблена Джеффом Де Люка (Jeff De Luca) і визнаним гуру в області об'єктно-орієнтованих технологій Пітером Коадом (Peter Coad).
FDD є спробою об'єднати найбільш визнані в індустрії розробки програмного забезпечення методики, що приймають за основу важливу для замовника функціональність (властивості) програмного забезпечення, що розробляється. Основною метою даної методології є розробка реального, працюючого програмного забезпечення систематично у поставлені терміни.
Як і інші адаптивні методології, вона робить основний наголос на коротких ітераціях, кожна з яких служить для опрацювання певної частини функціональності системи. Згідно з FDD, одна ітерація триває два тижні. FDD налічує п'ять процесів.
Перші три з них відносяться до початку проєкту:
- Розробка загальної моделі
- Складання списку необхідних властивостей системи
- Планування роботи над кожною властивістю
- Проєктування кожної властивості
- Конструювання кожної властивості
Останні два кроки потрібно робити під час кожної ітерації. У цьому кожен процес розбивається завдання і має критерії верифікації.
Давайте детальніше зупинимося на кожному пункті.
Розробка загальної моделі
Розробка починається з аналізу широти кола завдань і контексту системи. Далі для кожної області, що моделюється, робиться більш детальний розбір. Попередні описи складаються невеликими групами та виносяться на подальше обговорення та експертну оцінку. Після одна з запропонованих моделей чи їх сукупність стають моделлю для конкретної області. Моделі кожної області завдань об'єднуються у загальну підсумкову модель, яка може змінюватись протягом роботи.
Складання списку функцій
Інформація, зібрана під час побудови загальної моделі, використовується для складання списку функцій. Функції об'єднуються в так звані «області» (англ. domain), а вони ж у свою чергу поділяються на підобласті (англ. subject areas) за функціональною ознакою.
Кожна підобласть відповідає певному бізнес-процесу, кроки якого стають списком функцій (властивостей). Функції представлені у вигляді «дія — результат — об'єкт», наприклад, «перевірка пароля користувача». Розробка кожної функції повинна займати не більше 2 тижнів, інакше завдання необхідно декомпозувати на дрібніші ітерації. Список властивостей у FDD — те саме, що і product backlog в SCRUM.
План за властивостями (функціями)
Далі йде етап розподілу функцій серед провідних програмістів чи з команд.
Проєктування функцій
Для кожної властивості створюється проєктувальний пакет. Провідний програміст виділяє невелику групу властивостей розробки протягом двох тижнів. Після цього залишаються докладні діаграми послідовності для кожної властивості, уточнюючи загальну модель. Далі пишуться «заглушки» класів та методів. У цей момент ми маємо сфокусуватися на дизайні програмного продукту.
Реалізація функції
Пишемо код, забираємо заглушки, тестуємо.
Після того, як властивість протестована і пішла в продукт, беремо наступну за пріоритетами властивість, повторюємо цикл дизайну/реалізації.
Отже, в результаті ми отримуємо:
- Документація за властивостями системи
- Ретельне проєктування
- Простіше оцінювати невеликі завдання
- Тести орієнтовані на бізнес-завдання
- Пророблений процес створення продукту
- Короткі ітеративні цикли розробки дозволяють швидше нарощувати функціональність та зменшити кількість помилок
Недоліки:
- FDD більше підходить для великих проєктів. Невеликі команди розробки не зможуть відчути всі переваги цього підходу
- Значні витрати на впровадження та навчання
MDD — Model Driven Development
Останнім часом багато уваги в публікаціях приділяється темі архітектури та розробці на основі моделей MDA (Model Driven Architecture) та MDD (Model Driven Development). Не вдаючись до подробиць, виділимо лише ключові моменти.
Керована моделями розробка (англ. model-driven development) — стиль розробки програмного забезпечення, коли моделі стають основними артефактами розробки, у тому числі генерується код та інші артефакти.
Якщо говорити простіше, то вся суть розробки зводиться до побудови необхідних діаграм, з яких згодом ми генеруємо робочий код проєкту.
Основна мета MDD — мінімізація витрат, пов'язаних із прив'язкою до конкретних системних платформ та програмних інфраструктур. Адже основна бізнес-логіка міститься у діаграмах і не сковує нас рамками вибору мови програмування та інструментів розробки.
Давайте трохи відвернемось і згадаємо про компілятор. Він перетворює мову програмування високого рівня в еквівалентну реалізацію машинною мовою. Моделлю у разі є програма, яка написана мовою високого рівня та приховує несуттєві деталі її реалізації. У MDD наші діаграми — це ще один рівень абстракції, який не дозволяє нам ув'язнути деталі розробки, а подивитися на картину в цілому.
Діаграми виступають як своєрідні «креслення», з яких різні автоматизовані та напівавтоматизовані процеси витягують програми та відповідні моделі. Причому автоматична генерація коду варіюється від отримання простого скелета докладання до отримання кінцевої кодової бази (що порівняно з традиційною компіляцією).
Ідея MDD не нова — вона використовувалася зі змінним успіхом і раніше. Причиною збільшеної уваги до них нині є те, що автоматизації піддається значно більше процесів, ніж раніше. Цей розвиток відбивається у появі MDD-стандартів, що веде до уніфікації відповідних коштів. Одним із таких стандартів є переглянута версія Unified Modeling Language – UML 2.0.
За стандартами Object Management Group (OMG) створення програми складається з наступних кроків:
- Спочатку розробляється модель предметної області проєктованого додатка, повністю незалежна від імплементуючої технології
- Потім вона трансформується спеціальним інструментом у платформо-залежну модель.
- Нарешті, вона переводиться у вихідний код відповідною мовою програмування
Класичний приклад застосування MDD, який використовується вже давно, — моделювання баз даних. На основі однієї концептуальної моделі даних ви можете підтримувати кілька пов'язаних із нею фізичних моделей для різних СУБД.
Які переваги ми отримуємо:
- Прискорюється виведення мінімального життєздатного продукту (Minimum Viable Product) на ринок
- Скорочується час на генерацію каркасу програми, моделі класів, бази даних
- Постійно оновлювана документація
- Для учасників проєкту діаграми набагато наочніші за код
Недоліки:
- Для використання MMD потрібно використовувати спеціальні програмні рішення, такі як Rational Software Architect, Simulink або Sirius
- Від програмістів потрібні значні знання проєктування діаграм
- Значні фінансові витрати на інтеграцію даної методології
PDD — Panic-Driven Development
Якщо ви пробували методології agile розробки, то ви, напевно, пробували і PDD.
Давайте подивимося докладніше, які принципи цієї методології.
Нові завдання пріоритетніші за старі
Щоразу, коли в середині спринту з'являється нова проблема, вона має пріоритет над будь-якою запланованою роботою. Нове завжди краще і має вищий пріоритет.
Дивно, чому це не стало одним із принципів гнучкої розробки? Націленість на забезпечення цінності для клієнта вимагає, щоб команда дбала про нові фічі та відкладала раніше певну роботу.
Пишіть стільки коду, скільки потрібно, щоб вирішити проблему
Розробники пишуть код життя. Помилки можуть бути виправлені лише кодом. Обговорення дизайну та UX може лише уповільнити розробку. Але ж ми не хочемо втрачати дорогоцінний час? Спочатку напишіть рішення, потім перевірте своє припущення щодо виправлення. Якщо виправлення працює, проблему вирішено.
Тести мають писатися наприкінці
Після того як виправлення впроваджено, тести можуть бути заплановані як завдання, яке буде зроблено в майбутньому. Тести корисні, але пріоритетними. Ви можете подбати про них пізніше. Ручного тестування має бути достатньо, щоби довести працездатність реалізованого рішення.
Довіртеся своєму інстинкту
Програмування — це мистецтво. Мистецтво має внутрішню інстинктивну складову. Довіряй своїй інтуїції. Напишіть код. Розгорніть його. Тільки сміливим усміхається успіх.
Процес гнучкий
Будь-який процес, створений для розробки, тестування та випуску програмного забезпечення, це просто набір угод і правил, які не висічені в камені. Критичні виправлення потребують різних підходів. Очікується, що ви зігнете процес, щоб виконати завдання у термін, якщо цього вимагає бізнес.
Це процес, керований менеджером
Як частина однієї команди менеджери мають право висловити свою думку з питань розвитку. Рефакторинг чи передовий досвід можуть і мають бути скасовані потребами бізнесу. Інженери можуть висловити свою думку, але вони повинні зрештою прийняти будь-які потреби, які приходять зверху.
Переваги підходу:
- Висока швидкість розробки
- Дешево
- Замовники щасливі, що знайшли тлумачних розробників.
Недолік:
- Всі переваги розіб'ються про технічний обов'язок та складність проєкту
PDD — своєрідний антипаттерн розробки, який, на жаль, ми весь час практикуємо.
Висновок
Світ agile розробки багатогранний. Ми познайомилися тільки з малою його частиною, розглянули достатню кількість практик розробки ПЗ, дізналися про їхні переваги та недоліки.
Тепер багато хто з вас дізнався щось нове про Driven Development практики і тепер, зустрівшись віч-на-віч з абревіатурами DDD, BDD, MDD ви не зазнаєте замішання, а може навіть захочете випробувати їх на практиці.