Проектування більше немає?

Тим, хто встиг коротко познайомитися з принципами Extreme Programming (ХР), часом здається, що в цій методології немає місця процесу проектування програмних продуктів. При цьому висміюються не тільки “Велике і Детальний Попереднє Проектування”, а й такі техніки як UML і гнучкі каркаси додатків. Навіть значення патернів або принижується, або геть заперечується. Насправді ж, в ХР багато проектування, але подається воно по-іншому, ніж у звичайних усталених процесах розробки ПЗ. Методологія XP оживила еволюційне проектування новими техніками, завдяки яким його тепер можна вважати цілком життєздатною стратегією. Крім того, в ХР перед проектувальником ставляться нові важкі завдання, що вимагають чималої майстерності. По-перше, це необхідність проектувати максимально простим чином, по-друге, рефакторінг, і нарешті, використання патернів в еволюційному стилі.

(Ця стаття являє собою основу моєї доповіді на конференції XP 2000 і буде опублікована в її матеріалах.)

  1. Проектування попереднє і проектування еволюційне
  2. Основоположні практики XP
  3. Переваги простого дизайну
  4. “Простий дизайн” – що ж це за звір такий?
  5. Чи порушує рефакторінг принцип YAGNI?
  6. Патерни і ХР
  7. Нарощування архітектури
  8. UML і XP
  9. Про метафорі
  10. Малюк, хочеш бути архітектором, коли виростеш?
  11. Оборотність рішень
  12. Бажання проектувати
  13. Завдання, що погано піддаються рефакторингу
  14. Проектування це чи ні?
  15. Так що ж, проектування більше немає?
  16. Подяки

Методологія Extreme Programming (XP) кинула виклик багатьом усталеним уявленням про розробку програмного забезпечення. Мабуть, найбільш суперечливою ідеєю є відмова від попереднього проектування на користь більш еволюційного підходу. Для тих, хто всіляко чорнить ХР, це повернення до розробок типу “code and fix” (“пишемо і правимо”). Для прихильників нової методології, це відмова від технік проектування (наприклад, UML), їх принципів і патернів. Нема чого турбуватися про проектування, вважають вони. Досить уважно “вслухатися” в свій код, і проектування утворюється само собою.

Що стосується мене, то я перебуваю безпосередньо в епіцентрі цих суперечок. Більша частина моєї кар’єри була присвячена графічним мовам моделювання – UML (Уніфікована мова моделювання) і його попередникам, а також паттернам. Більше того, я писав книги про UML і про патерни. Раз я тепер приймаю ХР, чи не означає це, що я відрікаюся від усього, що писав досі?

Не буду випробовувати ваше терпіння, і змушувати вас чекати, затамувавши подих, відповіді на цей драматичний питання. Коротка відповідь – ні. Докладний відповідь міститься в частині цієї статті.

Проектування попереднє і проектування еволюційне

У цій статті я опишу два стилі проектування, прийнятих у розробці програмного забезпечення. Напевно, найбільш звичним є еволюційне проектування. Визначення “еволюційний” вказує на те, що під час реалізації системи її дизайн зростає разом з нею. Проектування, в цьому випадку, є частиною процесу програмування, тому в ході розвитку системи дизайн змінюється.

У більшості випадків, еволюційне проектування – це щось жахливе. Зрештою, все одно замість дизайну системи ви отримуєте просто набір із специфічних рішень, кожне з яких ускладнює подальші зміни в програмному коді. Часто це взагалі не можна вважати дизайном (і, вже звісно, ​​такий дизайн ніяк не можна назвати хорошим). Як говорить Кент, дизайн існує для того, щоб дати можливість оперативно вносити в систему будь-які зміни. Якщо дизайн поганий, то така можливість зникає. У результаті ви будете мати справу з ентропією програмного продукту, і з часом і без того поганий дизайн системи стане ще гірше. Тепер вам буде не тільки складніше вносити в систему зміни, а й відшукувати і виправляти помилки, які починають множитися з катастрофічною швидкістю. Все це – кошмар розробок в стилі “code and fix”, коли з плином часу виправлення помилок обходиться все дорожче і дорожче.

Попереднє проектування – повна протилежність еволюційному. Воно побудоване на ідеях, запозичених з іншої області інженерної діяльності. Якщо вам треба побудувати собачу будку, то ви самі в змозі сколотити кілька дощок, щоб отримати задовільний подобу бажаного. Якщо ж ви вирішите побудувати хмарочос, то колишній спосіб не підійде – хмарочос завалиться, перш ніж ви спорудіть його хоча б наполовину. Щоб цього не сталося, вам потрібно починати з креслень, які розробляють у інжинірингових компаніях (на кшталт тієї, в якій працює моя дружина). Проектуючи, вона обчислює всі необхідні дані, іноді шляхом математичного аналізу, але найчастіше – за допомогою “Будівельних норм і правил”. Ці “Норми” представляють собою правила, по яких і створюються проектні конструкції. Всі вони засновані на досвіді реальних працюючих рішень (ну, і невеликій кількості математики). Після того, як роботи з проектування закінчені, інжинірингова компанія передає проектні креслення іншої компанії, яка займається будівництвом.

Приблизно так само йде справа і з попередніми проектуванням при розробці ПЗ. Проектувальники заздалегідь продумують всі основні питання. При цьому вони не пишуть програмний код, оскільки не створюють програмний продукт, а тільки розробляють його дизайн. У своїй роботі вони можуть використовувати такі техніки, як UML, що дозволяє їм абстрагуватися від деяких подробиць розробок, що відносяться безпосередньо до програмування. Як тільки проектний план готовий, його можна передавати в інший відділ (або навіть в іншу компанію), де будуть вестися роботи з безпосереднього створення системи. Оскільки проектувальники працюють на деякому рівні абстракції, їм вдається уникнути прийняття низки тактичних рішень, що ведуть до ентропії програмного продукту. Програмісти ж можуть керуватися проектним планом і (якщо вони його дотримуються) створювати якісно вибудувану систему.

Такий підхід до розробки ПЗ не новий – їм активно користується безліч людей, починаючи з 70 років. За багатьма показниками він набагато краще, ніж еволюційний проектування в стилі “code and fix”, проте і у нього є істотні недоліки. Один з головних недоліків полягає в тому, що неможливо заздалегідь продумати всі питання, з якими доведеться зіткнутися під час кодування системи. Таким чином, в ході робіт неодмінно виникне ситуація, коли у програмістів з’являться питання щодо спроектованого дизайну. А що, якщо проектувальники, закінчивши свою частину роботи, вже переключилися на інший проект? Тоді програмісти починають самостійно вирішувати проблему, що склалася, відступаючи від вже прийнятих проектних рішень, і вносячи при цьому в програмний продукт частку ентропії. І навіть якщо проектувальник ще працює над проектом і може допомогти, все одно йому буде потрібно досить багато часу, щоб з’ясувати ситуацію, внести зміни до діаграми і вже потім міняти код. А при розробці, як правило, питання часу завжди стоїть гостро. Звідси ентропія (знову-таки).

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

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

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

Боротися з мінливими вимогами можна по-різному. Один з можливих шляхів – робити дизайн досить гнучким, щоб при змінах у вимогах його можна було легко міняти. Однак для цього потрібно заздалегідь знати, якого типу зміни слід очікувати. Так, при проектуванні системи можна спробувати вгадати ті області, в яких найбільш вірогідні зміни, і врахувати їх у дизайні. У цьому випадку ви, дійсно, полегшите собі роботу з очікуваними змінами у вимогах, але нітрохи не полегшите (а можливо, тільки погіршите) ситуацію із змінами несподіваними. Крім того, щоб заздалегідь визначити ті області, в яких найбільш вірогідні зміни, ви повинні прекрасно розуміти вимоги, що за моїми спостереженнями, дуже непросто.

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

Після всього цього можна подумати, що попереднє проектування взагалі неможливо. Але це не так. Так, є серйозні труднощі. Однак я зовсім не схильний вважати, що попереднє проектування гірше еволюційного в його звичайній манері “code and fix”. Сам я віддаю перевагу попереднє проектування, але проте, чудово уявляю собі всі складнощі, які з ним пов’язані і намагаюся знайти нові шляхи їх подолання.

Основоположні практики ХР

У методології XP є багато спірних моментів. Одним з ключових таких моментів є те, що вона базується на еволюційному, а не попередньому проектуванні. А як ми вже з’ясували, використання еволюційного проектування не може привести ні до чого хорошого за великої кількості сьогохвилинних проектувальних рішень та ентропії програмного продукту.

В основі цього твердження лежить крива вартості змін у програмному продукті. Відповідно до цієї кривої, по мірі розвитку проекту вартість внесення змін експоненціально зростає. Як правило, в ній використовуються поняття “фази розвитку проекту” (як кажуть, “зміна, яка на стадії аналізу коштує 1 долар, після поставки системи коштуватиме багато тисяч”). У цьому є певна частка іронії, оскільки в більшості проектів процес розробки взагалі не визначений, і там просто немає стадії аналізу, а експонентна залежність залишається в силі. Виходить, що якщо експонентна крива вірна, то еволюційне проектування взагалі не можна використовувати в роботі. Звідси ж випливає, що не можна робити помилки в попередньому проектуванні – витрати на їх виправлення будуть визначатися все тієї ж залежністю.

В основі XP лежить припущення, що цю криву можна згладити до такої міри, щоб можна було застосовувати еволюційний проектування. Таке згладжування, з одного боку, виникає при використанні методології XP, а з іншого, воно ж в ній і використовується. Це ще раз підкреслює тісний взаємозв’язок між практиками ХР: не можна використовувати ті частини методології, які припускають існування згладжування, не використовуючи ті практики, які це згладжування здійснюють. Саме це є основним предметом суперечок навколо XP. Багато хто починає критикувати використання, не розібравшись в тому, як його треба досягати за допомогою здійснення. Часто тому виною власний досвід критикує, який упустив в розробках ті практики, які дозволяють здійснювати інші. В результаті, раз обпікшись, такі люди при згадці про ХР і на воду дують.

У практик, за допомогою яких здійснюється згладжування, є безліч складових. В основі всіх їх лежить Тестування і Безперервна інтеграція. Саме надійність коду, яку забезпечує тестування, робить можливим все інше в цій методології. Безперервна інтеграція необхідна для синхронної роботи всіх розробників, так щоб кожна людина могла вносити в систему свої зміни і не турбуватися про інтеграцію з іншими членами команди. Взяті разом, ці дві практики можуть чинити істотний вплив на криву вартості змін у програмному продукті. Я отримав ще одне підтвердження цьому в компанії “ThoughtWorks”. Навіть застосування всього двох практик, тестування та безперервної інтеграції, істотно позначилося на результатах. Можна навіть засумніватися, чи справді потрібно (як це прийнято вважати в ХР) слідувати всім практикам, щоб отримати помітний результат.

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

Джим Хайсміт (Jim Highsmith) у своєму чудовому викладі методології XP використовує аналогію з звичайними вагами. На одній чаші лежить попереднє проектування, на іншій – рефакторінг. У більш традиційних підходах до розробки ПЗ переважує попереднє проектування, оскільки передбачається, що передумати ви не можете. Якщо ж вартість змін знизиться, то частина проектування можна робити і на більш пізніх стадіях роботи, у вигляді рефакторінга. Це зовсім не означає відмови від попереднього проектування. Однак тепер можна говорити про існування балансу між двома підходами до проектування, з яких можна вибрати найбільш підходящий. Що стосується мене, то іноді мені здається, що до знайомства з рефакторингом я працював, як однорукий каліка.

Всі ці основоположні практики (безперервна інтеграція, тестування і рефакторінг) створюють нове середовище, в якій еволюційне проектування виглядає цілком переконливо. Втім, ми ще не з’ясували, де ж у цих ваг точка рівноваги. Особисто я впевнений, що не дивлячись на поверхове враження, методологія ХР – це не просто тестування, кодування і рефакторінг. У ній знайдеться місце і для попереднього проектування. Частково воно виробляється ще до написання першого рядка коду, але більша його частина припадає на той час, який передує реалізації конкретного завдання протягом ітерації. Втім, така ситуація являє собою нове співвідношення сил між попередніми проектуванням і рефакторингом.

Переваги простого дизайну

У ХР дуже популярні два гасла: “Do the Simplest Thing that Could Possibly Work” (“Шукайте найпростіше рішення, яке може спрацювати”) і YAGNI (“You Aren’t Going to Need It” – “Це вам не знадобиться”) . Обидва вони уособлюють собою одну з практик ХР під назвою Простий дизайн.

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

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

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

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

Інша причина, по якій простий дизайн краще складного, це відмова від принципу “блукаючого вогника”. Складну конструкцію набагато важче зрозуміти, ніж просту. Саме тому будь-яка модифікація системи робить її все більш складною. Це, знову-таки, веде до збільшення вартість робіт в період між тим часом, коли дизайн системи став більш складним, і часом, коли це дійсно стало необхідно.

Такий стиль роботи багатьом здається абсурдним, і треба сказати, що вони мають рацію. Мають рацію за однієї умови – абсурд вийде, якщо цю практику почати застосовувати в звичайному процесі розробки, а всі інші практики ХР ігнорувати. Якщо ж змінити існуючий баланс між еволюційним і попередніми проектуванням, то YAGNI стає дуже корисним принципом (тоді і тільки тоді).

Підіб’ємо підсумок. Вам не потрібно витрачати сили на те, щоб внести в систему нову функціональність, якщо вона не знадобиться до наступної ітерації. Навіть якщо це практично нічого не коштує, вам не потрібно це робити, оскільки це збільшить загальну вартість модифікації. Однак для того, щоб свідомо застосовувати такий принцип на ділі, вам потрібно використовувати ХР або іншу подібну методологію, яка знижує вартість змін.

“Простий дизайн” – що ж це за звір такий?

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

У книзі Extreme Programming Explained Кент призводить чотири критерії простої системи. Ось вони в порядку убування важливості:

  • Система успішно проходить всі тести
  • Код системи ясно розкриває всі початкові задуми
  • У ній відсутня дублювання коду
  • Використовується мінімально можливу кількість класів і методів

Успішне тестування системи – досить простий критерій. Відсутність дублювання коду теж цілком чітка вимога, хоча більшість розробників потрібно вчити, як цього досягти. Найскладніше ховається в словах “розкриває початкові задуми”. Дійсно, що ж це значить?

Основна перевага програмного коду, в даному випадку – його ясність. ХР всіляко підкреслює, що хороший код – це код, який можна легко прочитати. Скажіть ХР-шнику, що він пише “заумний код”, і будьте впевнені, що облаяли цієї людини. Але розуміння задумів програміста, який написав код, залежить також і від досвіду і розуму того, хто цей код намагається прочитати.

У своїй доповіді на конференції XP 2000, Джош Керіевскі (Josh Kerievsky) призводить хороший приклад на дану тему. Він піддає аналізу, можливо, найбільш відкритий з усіх кодів ХР – JUnit. JUnit використовує декоратори (патерн Decorator), для того, щоб доповнити тестові сценарії додатковим поведінкою, таким як синхронізація доступу та встановлення початкових передумов для груп тестів. Так як подібна поведінка реалізується в окремих класах-декоратор, код тестів стає простіше, ніж якщо б ця функціональність присутня в них самих.

Проте в даному випадку потрібно задати собі питання: а зрозуміліше чи буде код, отриманий в результаті цих операцій? З моєї точки зору так, але я-то знайомий з патерном Decorator. Для тих, хто не має про нього чіткого уявлення, цей код може здатися досить складним. Аналогічно цьому, в JUnit використовуються методи-вставки (pluggable methods), які, за моїми спостереженнями, більшість програмістів розцінюють як що завгодно, але тільки не як просте і зрозуміле рішення. Виходить, що структура JUnit є простою для досвідчених проектувальників, але складною для менш досвідчених програмістів?

Я думаю, що одним з найбільш очевидних та корисних порад, які тільки можна дати, це уникати повторів в коді, як проголошується в ХР (“Once and Only Once”) і в книзі Pragmatic Programmer’s (принцип DRY – Don’t Repeat Yourself) . Дотримуйтесь цього принципу, ви підете далеко вперед. Але це далеко не все, що необхідно для простого дизайну. А створити простий дизайн – це дуже складне завдання.

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

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

Чи порушує рефакторінг принцип YAGNI?

Ця тема порівняно недавно спливла в списку розсилки, присвяченому XP, і коли незабаром ми заговорили про роль проектування, нам варто її обговорити.

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

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

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

Патерни і ХР

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

Суть в тому, що часто патерни використовуються надто активно. Відома історія про програміста, який, прочитавши в перший раз книгу Банди Чотирьох (видана російською мовою у видавництві “Пітер” під назвою “Паттерни проектування” – прим. Перекладачів), ухитрився використовувати 16 патернів в 32 рядках коду. Пам’ятаю чудовий вечір, підігрітий всього-навсього одним стаканчиком солоду, коли ми з Кентом накидали статтю під назвою “Не патерни проектування: 23 дешевих трюку”, де розповіли про такі речі, як використання оператора “if” замість патерну “стратегія”. У кожному жарті є частка правди. Патерни нерідко використовуються там, де без них цілком можна було б обійтися, однак це не робить гірше саму ідею. Все питання в тому, як ви їх використовуєте.

Згідно з однією з існуючих теорій, прагнучи до простого дизайну, ви прийдете саме до паттернам. Для деяких видів рефакторінга це відбувається абсолютно явно, проте і без рефакторінга, приймаючи прості проектні рішення, ви починаєте використовувати патерни, навіть якщо до цього ви нічого про них не знали. Може бути, це і так, але чи так уже гарний цей шлях? Звичайно ж, краще заздалегідь уявляти собі, з чим ви зіткнетеся, і мати при собі книгу, щоб не винаходити все самому. Кожен раз, коли я відчуваю, що на підході ситуація, коли можна використовувати патерн, я дістаю з полиці книгу Банди Чотирьох. Для мене саме словосполучення “ефективний дизайн” свідчить про те, що використання патерну виправдано. Зрештою, призначення патернів полягає саме в полегшенні створення простого дизайну системи. Точно так само і Джошуа пропонує приділяти більше уваги питанню, як можна спростити поступовий перехід до використання патернів. З цієї точки зору, патерни в ХР використовуються трохи незвичним чином, однак це зовсім не означає, що при цьому їх значення якось принижується.

Читаючи деякі списки розсилки, я приходжу до висновку, що багато хто взагалі бачать в ХР якесь заперечення патернів. І це при тому, що більшість творців цієї методології були, свого часу, в числі лідерів руху за використання патернів! Не знаю, як для всіх інших, але для мене патерни досі абсолютно необхідні. Методологія ХР може служити процесом розробки, але патерни – це основа мистецтва проектування, мистецтва, без якого не обійтися, яким би процесом ви не користувалися. Знову-таки, різні процеси можуть використовувати патерни по-різному. Так, в ХР вважається, що не потрібно використовувати патерн до тих пір, поки в ньому дійсно не опиниться необхідності, а також що потрібно приходити до використання патерну поступово, шляхом спрощення реалізації. Тим не менш, знання патернів було і залишається абсолютно необхідним.

Мої поради тим, хто працює за методологією ХР і використовує патерни:

  • Не бійтеся витратити час на вивчення патернів
  • Добре подумайте, коли краще всього застосувати патерн (не надто рано)
  • Добре подумайте, як краще всього реалізувати патерн в його найпростіших формі, а вже потім вносите доповнення
  • Якщо ви застосували патерн, а потім зрозуміли, що без нього було б краще – прибирайте, не сумнівайтеся.

Мені здається, що в методологію ХР варто було б включити окремим пунктом вивчення патернів. Боюся, що мені не під силу придумати, як це можна внести до практики ХР, але у Кента це напевно вийде.

Нарощування архітектури

Що ми називаємо архітектурою програмного продукту? З моєї точки зору, термін “архітектура” передає ідею основних елементів системи, тих її частин, які важко змінити. Вони є фундаментом, на якому можна побудувати все інше.

Яку роль відіграє архітектура в еволюційному проектуванні? Критики ХР вважають, що ця методологія взагалі не визнає роботи над архітектурою, що вся суть ХР – відразу сідати за написання коду, і сподіватися на те, що рефакторінг вирішить всі проблеми з проектуванням. Смішно сказати, але вони праві, і, може бути, в цьому полягає деяка слабкість ХР. Всім відомо, що найагресивніші прихильники ХР – Кент Бек (Kent Beck), Рон Джеффріз (Ron Jeffries) і Боб Мартін (Bob Martin) – прикладають дуже багато сил, щоб взагалі уникнути будь-якого попереднього проектування архітектури. Не додавайте в систему базу даних, поки вона вам дійсно не знадобилася. Працюйте спочатку з файлами, а база даних з’явиться в наступній ітерації, в результаті рефакторінга.

Я заслужив репутацію боягузливого ХР-шника, і в цій якості змушений не погодитися з підходом моїх більш сміливих колег. Мені здається, що краще почати з загального начерку архітектури системи – подумати про те, як розділити додаток на рівні, як побудувати взаємодію з базою даних (якщо вона вам знадобиться), який підхід застосувати до управління веб-сервером.

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

Цікаво, а якщо перевернути все навпаки? Якби ви спочатку вирішили не використовувати EJB, не було б складніше в останній момент внести його в систему? Чи справді не варто починати робити систему з EJB, поки ви остаточно не переконаєтеся, що без цього не обійтися? Це питання зачіпає відразу кілька факторів. Зрозуміло, працювати без такого складного компонента легше і швидше. Однак іноді легше щось викинути з системи, ніж вставити.

Отже, я б все ж порадив почати роботу з приблизної оцінки архітектури системи. Якщо ви бачите велику кількість даних і безліч різних користувачів, сміливо включайте в архітектуру базу даних. Якщо ви повинні працювати зі складною бізнес-логікою, використовуйте модель предметної області. Однак не забувайте про повагу до богів YAGNI, і в сумнівних випадках віддавайте перевагу більш простим рішенням. Крім того, завжди будьте готові викинути шматок архітектури, якщо бачите, що він не приносить нічого корисного.

UML і XP

Мені ставлять досить багато питань щодо моєї прихильності методології ХР, причому найчастіше люди цікавляться – як я можу поєднувати її з вірністю UML. Хіба вони не виключають один одного?

Так, в ХР і UML є декілька взаємовиключних аспектів. Так, в ХР істотно знижується значення діаграм. Не дивлячись на те, що офіційна позиція ХР з цього приводу говорить: “використовуйте їх, якщо це допомагає вам у роботі”, але існує і неофіційний підтекст: “справжній ХР-шник не малює діаграм”. Це підкреслюється ще й тим фактом, що таким людям, як Кент, незручно використовувати діаграми. Я, наприклад, ніколи не бачив, щоб Кент по своїй волі малював діаграму програмного продукту, неважливо навіть на мові UML, або якому іншому.

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

По-друге, діаграми програмних продуктів зазвичай асоціюються з важкими процесами розробки. У таких процесах велика частина часу йде на побудову діаграм, що не дуже допомагає в роботі, а іноді навіть шкодить. Саме тому я вважаю, що людей потрібно вчити, як використовувати діаграми правильно і уникати різних пасток, а не просто говорити “малюй діаграму, якщо тобі без неї зовсім не обійтися, бідолаха”, як це зазвичай роблять затяті ХР-шники.

Ось мої поради тим, хто хоче правильно використовувати діаграми:

По-перше, поки малюєте діаграму, не забувайте, для чого ви це робите. Основна її перевага – комунікація з людьми. Щоб комунікація була ефективною, потрібно відображати на діаграмі тільки важливі аспекти, не звертаючи уваги на всі другорядні. Така вибірковість – основа правильної роботи з UML. Не треба відображати на діаграмі кожен клас – тільки найважливіші. У класів не потрібно задавати кожен атрибут або операцію – тільки найважливіші. Не треба малювати діаграми послідовності для всіх варіантів використання і сценаріїв – ну, і так далі. Найпоширеніша проблема з використанням діаграм це те, що їх намагаються зробити максимально всеосяжними. Однак найкращий джерело всеосяжної інформації – це програмний код, так як саме його найлегше синхронізувати з кодом. Для діаграми ж всеоб’емлімость – ворог удобопонятно.

Найчастіше діаграми використовуються для того, щоб проаналізувати проектні рішення ще до написання коду. Нерідко при цьому виникає відчуття, що в ХР цього робити не можна. Це зовсім не так. Багато хто вважає, що перед розробкою складного завдання стоїть ненадовго зібратися всією командою для її попереднього проектування. Проте, коли проводите такі зібрання, не забувайте, що:

  • вони повинні бути дійсно недовгими
  • не потрібно обговорювати всі подробиці (тільки найважливіше)
  • ставитеся до отриманого в результаті проектного рішенню як до начерку, а не як до кінцевої версії, несхильною змінам

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

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

Багато ХР-шники використовують CRC-картки. Це не суперечить UML. Особисто я весь час задіюю якусь суміш з CRC та UML, і взагалі, користуюся будь-якими техніками, які полегшують мені виконання поточного завдання.

Крім того, UML-діаграми використовуються в якості документації по проекту. Як правило, у своїй звичайній формі це модель, редагована за допомогою деякого CASE-інструменту. Ідея тут полягає в тому, що ведення такої документації полегшує роботу. Насправді, найчастіше вона взагалі не потрібна, оскільки:

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

Отже, якщо ви хочете мати поточну документацію по проекту, враховуйте всі перераховані вище проблеми:

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

І, нарешті, останній аспект використання UML для документації – передача проекту в інші руки (наприклад, від однієї групи розробників інший). Згідно з методологією ХР, створення документації – така ж завдання, як і всі інші, а значить, її пріоритет повинен бути визначений замовником. У цій ситуації може стати в нагоді UML, зрозуміло, за умови вибірковості діаграм, які створювалися з метою полегшення комунікації. Пам’ятайте, що програмний код – це основний репозиторій докладної інформації, а діаграми служать для узагальненого представлення основних аспектів системи.
Про метафорі

Ну ось, тепер я можу зізнатися публічно – я до сих пір не можу зрозуміти, що ж це за штука така, ця метафора. Я бачив, як вона працює (у проекті С3 вона спрацювала просто чудово), однак це зовсім не означає, що я розумію, як це зробити, не кажучи вже про те, щоб пояснювати це іншим.

Метафора – одна з практик ХР. Вона будується на системі імен, підході, розробленому Уордом Каннінгем (Ward Cunningham). Суть цього підходу в тому, що ви визначаєте якийсь набір імен, які служать словником для опису предметної області проекту. Надалі система імен з цього набору служить для іменування класів і методів системи.

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

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

Часто критики ХР вказують на те, що для роботи над проектом необхідна хоча б приблизна архітектура системи. На що прихильники цієї методології відповідають: “Так це і є метафора”. Насправді, я до сих пір не чув, щоб хто-небудь виразно пояснив, що ж це таке, метафора. Мені здається, що такий пробіл все ж потрібно якось ліквідувати.

Малюк, хочеш бути архітектором, коли виростеш?

За останнє десять років стало дуже популярно словосполучення “архітектор програмного забезпечення”. Особисто мені такий термін використовувати дуже важко. Справа в тому, що моя дружина – інженер-будівельник. А відносини між архітекторами та інженерами-будівельниками кілька …. натягнуті. Інженери вважають, що архітекторам нічого не варто намалювати цілу купу симпатичних малюночків, а потім інженери повинні в поті чола обчислювати, зможе така симпатична конструкція триматися вертикально, або відразу розвалиться. Саме тому я завжди намагався уникати терміну “архітектор”. Самі судіть, якщо моя власна дружина не стане ставитися до мене з професійним повагою, то чого мені чекати від інших?

У області програмування термін “архітектор” має безліч значень. (Втім, в області програмування будь-який термін має безліч значень.) Однак, як правило, тут присутній якийсь підтекст: “Я вже не просто якийсь там програміст, я – архітектор”, що можна зрозуміти як “Тепер я архітектор, і мені не пристало займатися програмуванням “. Питання тільки в тому, чи дійсно потрібно відмовлятися від тривіального програмування, якщо збираєшся стати технічним лідером.

Таке питання зазвичай викликає бурю емоцій. Скільки разів я бачив, як люди не на жарт сердилися при думці, що як архітектори вони вже не грають такої важливої ​​ролі. “У ХР немає місця досвідченим архітекторам!” – Такий крик я чую досить часто.

Все це нагадує стан справ з проектуванням в цілому. Я не думаю, що при використанні методології ХР зникає необхідність в умінні добре проектувати. Більше того, саме завдяки основоположникам ХР – Кенту Беку, Бобу Мартіну, і звичайно ж, Уорду Каннінгем – я, свого часу, дізнався, що таке справжнє проектування. Однак зараз багатьом може здатися, що ці люди перестали грати роль технічних лідерів (у загальноприйнятому розумінні).

Для прикладу можна взяти одного з технічних лідерів компанії “ThoughtWorks”, на ім’я Дейв Райс (Dave Rice). Дейв вже давно працює в компанії і заслужив неофіційну мантію технічного лідера в проекті, над яким працює близько п’ятдесяти осіб. Що ж означає його лідерство? У першу чергу, те, що він проводить більшу частину часу з програмістами. Він допомагає тим, кому це необхідно, і намагається бути поруч на випадок, якщо його допомога знадобиться. Цікаво відзначити, де розташовується його робоче місце. Як заслужений працівник компанії, він міг би вибрати будь-яке приміщення за своїм бажанням. Якийсь час тому він сидів в офісі з Кара (Cara), який відповідав за випуск системи. Проте, ось уже кілька місяців, як Дейв перебрався в кімнату до програмістам (у тому самому стилі “war room”, який звеличує ХР). Для нього дуже важливо перебувати разом з розробниками, тому що в цьому випадку він знає, що відбувається, і завжди може протягнути руку допомоги тим, хто перебуває у скруті.

Ті, хто вже знайомий з методологією ХР, зрозуміють, що я описав наявне там поняття “тренера” ​​(“coach”). Це ще один приклад гри словами, яку так люблять в ХР. Технічний лідер команди називається “тренером”. Підтекст зрозумілий кожному: в ХР лідер вчить програмістів і допомагає їм приймати рішення. Щоб бути тренером, потрібні не тільки відмінні технічні знання, але і хороші якості людської натури. Як зауважив Джек Боллс (Jack Bolles) на конференції ХР 2000, для знавців-одинаків скоро взагалі не залишиться місця. Ключ до успіху – навчання та взаємодопомога.

Пізніше, на обіді, який відбувся після конференції, Дейв і я розмовляли з людиною, яка критикував ХР. Ми почали обговорювати все більш детально, і на подив, з’ясували, наскільки схожі наші підходи. Всі ми воліли адаптивні, ітеративні розробки. Всі погоджувалися з важливістю тестування. Ми з Дейвом ніяк не могли зрозуміти, звідки ж тоді таке неприйняття ХР? І тут наш опонент сказав чудову фразу: “останнє, що я допущу у себе на роботі, це щоб мої програмісти робили рефакторінг і тицяли ніс у проектування”. Після цього все стало ясно. Підсумок нашим концептуальним розбіжностям підвів Дейв, коли сказав мені наостанок: “Цікаво, навіщо брати на роботу програмістів, якщо ти їм не довіряєш?” У ХР найцінніше, що може зробити досвідчений розробник – це передати свої знання молодшим колегам. Замість архітектора, який один уповноважений приймати всі важливі рішення, у вас є тренер, який вчить, як потрібно приймати такі рішення. Як говорить Уорд Каннінгем, таким чином досвідчений розробник поширює свої знання, і приносить проекту набагато більше користі, ніж будь-який герой-одинак.

Оборотність рішень

На конференції XP 2002 Енріко Цінанотто (Enrico Zaninotto) прочитав цікавий доповідь, в якій вказав на зв’язок між гнучкими методологіями і “полегшеним” процесом виробництва в промисловості (lean manufacturing). З його точки зору, одним з основних положень обох методів є зменшення складності процесу шляхом підвищення його оборотності.

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

Прагнення до вироблення оборотних рішень є основною причиною, по якій гнучкі методології настійно рекомендують тримати весь код в системах управління вихідним кодом (source code control systems). Зрозуміло, це не гарантує оборотність рішень, особливо якщо вони довгострокові. Однак це додає команді деяку впевненість в такій можливості, навіть якщо вона використовується дуже рідко.

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

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

Бажання проектувати

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

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

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

У цю задачу входить постійний нагляд за програмним кодом системи. Якщо раптом буде відмічено, що якісь модулі стають заплутаними, необхідно відразу вживати заходів щодо виправлення цієї ситуації, поки вона не вийшла з-під контролю. При цьому “зберігачу дизайну” зовсім не потрібно все робити самому – йому достатньо переконатися, що цю проблему вирішив хтось інший.

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

Завдання, що погано піддаються рефакторингу

Чи можна вносити в систему всі проектні рішення шляхом рефакторінга, або ж все-таки існують деякі речі, які настільки всепронікающі, що додати їх згодом буде дуже і дуже складно? На даний момент ортодокси ХР стверджують, що все можна додати пізніше, а саме тоді, коли воно знадобиться. Тому принцип YAGNI може бути застосований в будь-якій ситуації. Я все ж, сумніваюся, чи немає тут винятків із правила. Візьмемо, наприклад, підтримку декількох мов (локалізацію). Може бути, якщо працювати над нею з самого початку, можна уникнути мук з приводу того, як її внести в систему на більш пізніх стадіях розробки?

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

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

Крім того, завжди варто враховувати знання проблеми. Якщо вам вже доводилося кілька разів займатися локалізацією, то ви напевно будете застосовувати в роботі деякі патерни, а значить, у вас більше шансів зробити все правильно з самого початку. Якщо ви досвідчений фахівець, то, напевно, буде краще розробити якісь попередні структури (чого ніяк не можна порекомендувати новачкам). Я б сказав, що ті, хто знає, як це робиться, можуть самі судити про витрати, які потрібні для виконання такого завдання. Однак, якщо ви ніколи раніше не займалися такими проблемами, ви не тільки не можете правильно оцінити завдання, але і швидше за все, будете допускати помилки в її вирішенні. У такому випадку, краще буде внести потрібні доповнення в систему пізніше. Якщо ж ви так і вчинили, а тепер відчуваєте масу труднощів, то повірте, вам було б куди важче, почни ви працювати над цим завданням з самого початку. Тепер ваша команда вже більш досвідчена, ви краще розумієте предметну область і вимоги до системи. Часто, озираючись назад, вам здаватиметься, що раніше це було б зробити набагато простіше. Смію вас запевнити, все могло бути набагато складніше, якщо б почали працювати над цим на початку проекту.

Ця проблема пов’язана з питанням порядку виконання вимог користувача (user stories). У книзі Planning XP ми з Кентом ясно позначили наші розбіжності. Кент вважає, що єдиним фактором, що визначає порядок робіт над завданнями, повинна бути їх важливість для замовника. Тепер на таку ж точці зору встав і Рон Джеффріз, який раніше дотримувався іншої думки. Я, все ж, не можу з ними погодитися. Мені здається, що повинен існувати певний баланс між важливістю завдання та технічних ризиком. Так, якщо використовувати наш приклад, то я став би займатися локалізацією раніше, ніж це було б потрібно, саме щоб знизити ризик. Втім, це було б виправдано, тільки якщо локалізація мала б бути присутнім вже в першому випуску системи. Випустити програму якомога раніше – одна з життєво важливих завдань. Все, що не потрібно в першому випуску, потрібно вносити в систему після нього. Враження, яке справляє на замовника працюючий програмний код, просто невимовно. Перший випуск програми змушує його зосередитися на проекті, підвищує рівень довіри до розробників, і крім того, є потужним джерелом нових відомостей. Робіть все від вас залежне, щоб цей день настав якомога швидше. Навіть якщо ви знаєте, що витратите більше зусиль, якщо внесете нову функціональність пізніше, все одно краще буде зробити це після першого випуску системи.
(Нещодавно опублікована стаття Джима Шо (Jim Shore) описує деякі ситуації, включаючи додавання в систему локалізації та підтримки транзакцій. Виявилося, що описані тут потенційні проблеми зовсім не є непереборним бар’єром).

Проектування це чи ні?

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

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

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

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

Так що ж, проектування більше немає?

Ні в якому разі. Однак змінилася сама суть проектування. Проектування в ХР вимагає від людини таких якостей:

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

Такий ось вражаючий список вимог. Втім, стати хорошим проектувальником завжди було непросто. У даному випадку, ХР не полегшує життя, принаймні, не мені. Однак я вважаю, що методологія ХР дозволяє нам по-новому поглянути на проблему ефективності проектування, тому що саме вона знову зробила еволюційне проектування розумною стратегією програмних розробок. А я великий фанат еволюції. Якби не вона, на якому дереві я б зараз сидів?
Подяки

За останні кілька років я запозичив і крав ідеї у величезної кількості чудових людей. Здебільшого їхні імена зникли в нетрях моїй пам’яті. Втім, я ще пам’ятаю, що перехопив кілька хороших ідей у ​​Джошуа Керіевскі. Крім того, я пам’ятаю, скільки чудових зауважень отримав від Фреда Джорджа (Fred George) і Рона Джеффріз. Не можу не сказати про те потоці ідей, які безупинно виходять з Кента і Уорда.

Я завжди відчуваю вдячність до людей, які задають питання і знаходять помилки. Я полінувався заводити довгий список всіх тих, хто мені в цьому допоміг, але в цьому списку обов’язково були б імена Крейга Джоунса (Craig Jones), Нігеля Торна (Nigel Thorne) і Свена Гортса (Sven Gorts).

19 червня 2013 рік

Ресурс: Martin Fowler

Comments are closed.

Post Navigation