“Очевидна привабливість архітектури — це структура. А структура — це те, що домінує в парадигмах і дискусіях стосовно розробки програмного забезпечення: компоненти, класи, функції, модулі, рівні й сервіси, мікро- або макро-.”
“Говорячи про архітектуру, можна сказати, що програмне забезпечення за своєю природою є фрактальним і рекурсивним, вигравіруваним і окресленим у коді. Тут важливі всі деталі.”
“Архітектура відображає важливі проєктні рішення щодо формування системи, де важливість визначається вартістю змін. (Граді Буч)”
“гарна архітектура відповідає потребам користувачів, розробників і власників не лише зараз, але й має відповідати їм у майбутньому.”
“Якщо ви вважаєте, що гарна архітектура коштує дорого, спробуйте погану архітектуру. (Браян Фут і Джозеф Йодер)”
“Єдиний спосіб крокувати швидко - це крокувати правильно. (Роберт С. Мартін)”
“Я написав дуже багато застосунків і створив дуже багато систем. І завдяки накопиченому досвіду дійшов приголомшливого висновку: Усі архітектури працюють за однаковісінькими правилами!”
“Мета архітектури програмного забезпечення — зменшити трудовитрати на створення і супровід системи.”
“Якщо трудовитрати невеликі і залишаються невеликими протягом експлуатації системи, система має гарний дизайн. Якщо трудовитрати збільшуються з виходом кожної нової версії, система має поганий дизайн. Ось так усе просто.”
“створюючи безлад, завжди рухатимешся повільніше, аніж неухильно дотримуючись чистоти,”
“Єдиний спосіб крокувати швидко - це крокувати правильно.”
“Будь-яка програмна система має дві різні цінності для тих, хто в ній зацікавлений: поведінку і структуру. Розробники відповідають за високий рівень обох цих цінностей.”
“Функціональність чи архітектура? Що цінніше? Що важливіше - правильна робота системи чи простота її зміни? Якщо поставити це запитання керівнику підприємства, він упевнено відповість, що важливіша правильна робота. Розробники часто погоджуються з цією думкою. Але вона хибна. Я можу довести помилковість цього погляду за допомогою простого логічного інструмента для дослідження крайнощів.”
“1) Якщо програма, що працює правильно, не допускає можливості своєї зміни, вона перестане працювати правильно, коли зміняться вимоги, і ви не зможете змусити її працювати правильно. Тобто програма перестане бути корисною.”
“2) Якщо програма не працює належним чином, але легко піддається змінам, ви зможете змусити її працювати правильно і підтримувати її працездатність у міру зміни вимог. Тобто програма постійно залишатиметься корисною.”
“Розглянемо матрицю президента Дуайта Девіда Ейзенгауера для визначення пріоритету між важливістю і терміновістю”
“Я маю два види справ, термінові і важливі. Термінові справи, як пра-вило, не найважливіші, а важливі — не дуже термінові!”
“Перша цінність програмного забезпечення — поведінка — це щось термінове, але не завжди важливе. Друга цінність — архітектура — щось важливе, але не завжди термінове.”
“Усі чотири види завдань можна розставити за пріоритетністю. 1. Термінові і важливі. 2. Нетермінові і важливі. 3. Термінові і неважливі. 4. Нетермінові і неважливі.”
“памʼятайте: якщо помістити архітектуру на останнє місце за пріоритетністю, розробка системи ставатиме дедалі дорожчою, і врешті-решт внесення змін до такої системи або окремих її частин стане практично неможливим. Якщо це сталося, значить, команда розробників недостатньо стійко боролася за те, що вважала за необхідне.”
"Парадигма — це спосіб програмування, що не залежить від конкретної мови. Парадигма визначає, які структури використовувати і коли саме їх використовувати. "
“Структурне програмування накладає обмеження на пряму передачу управління.”
“Обʼєктно-орієнтоване програмування накладає обмеження на непряму передачу управління.”
“Функціональне програмування накладає обмеження на присвоювання.”
“Зверніть увагу на патерн, що я навмисно використав у представленні парадигм програмування: кожна забирає у розробника якісь можливості. Жодна не додає нових можливостей. Кожна накладає якісь додаткові обмеження, негативні за своєю суттю. Парадигми говорять нам не стільки що робити, скільки чого не можна робити.”
“Ми використовуємо поліморфізм як механізм подолання архітектурних кордонів, ми використовуємо функціональне програмування для накладення обмежень на місце розташування даних і порядок доступу до них. І ми використовуємо структурне програмування як алгоритмічну основу для наших модулів. Зауважте, як точно вищесказане відповідає трьом найголовнішим аспектам вибудовування архітектури: функціональності, поділу компонентів та управлінню даними.”
“Більшість сучасних мов програмування не мають інструкції goto, а деякі, наприклад LISP, взагалі ніколи ії не мали. Нині всі програмісти використовують парадигму структурного програмування, хоча й не завжди усвідомлено. Просто сучасні мови не дають можливості необмеженої прямої передачі управління.”
“Структурне програмування дає можливість рекурсивного розкладання модулів на доказові одиниці, що, своєю чергою, означає можливість функціональної декомпозиції. Тобто рішення великого завдання можна розкласти на ряд функцій вищого порядку. Кожну з цих функцій, як і інші, можна розкласти на ряд функцій нижчого рівня, і так до нескінченності.”
“Наука працює не шляхом доведення істинності тверджень, а радше через пошук доказів. Твердження, хибність яких не вдається довести навіть після багатьох спроб, ми вважаємо істинними.”
“математика — це дисципліна, яка доводить істинність доказуваних тверджень. Наука, навпаки, - дисципліна доказу хибності тверджень.”
“Розробка програмного забезпечення не є математичною задачею, навіть при тому, що вона повʼязана із застосуванням математичних конструкцій. Ця сфера діяльності більше схожа на наукову. Ми переконуємося у правильності, зазнаючи невдачі у спробах довести неправильність.”
“Парадигма структурного програмування змушує нас рекурсивно розбивати програми на безліч дрібних і доказуваних функцій. Потім ми можемо використовувати тести, щоби спробувати довести, що ці маленькі доказові функції неправильні. Якщо такі тести зазнають невдачі, тоді ми вважаємо функції достатньо правильними.”
“Саме можливість створювати програмні одиниці, неправильність яких можна довести, є головною цінністю структурного програмування.”
“функціональну декомпозицію вважають одним із кращих прийомів на рівні архітектури.”
“Програмісти використовували покажчики на функції для досягнення поліморфної поведінки”
“ООП накладає обмеження на непряму передачу управління.”
“Факт підтримки мовами ООП надійного і зручного механізму поліморфізму означає, що будь-яку залежність вихідного коду, хоч би де вона була, можна інвертувати.”
“архітектори, які працюють у системах, що написані мовами ООП, отримують абсолютний контроль над напрямком усіх залежностей у вихідному коді. Вони не зобовʼязані узгоджувати ці залежності з потоком управління. Не важливо, який модуль викликає і який модуль викликається, архітектор може визначити залежність у вихідному коді у будь-якому напрямку.”
“Простіше кажучи, коли реалізація компонента зміниться, достатньо повторно розгорнути лише цей компонент. Це незалежність розгортання. Якщо система складається з модулів, які можна розгортати незалежно, виникає можливість і розробляти їх незалежно, різними командами. Це незалежність розробки.”
“ООП надає, за допомогою підтримки поліморфізму, абсолютний контроль над усіма залежностями у вихідному коді. Це дозволяє архітекторові створити архітектуру зі змінними модулями (плагінами), у якій модулі верхнього рівня не залежатимуть від модулів нижнього рівня. Низькорівневі деталі не виходять за рамки модулів плагінів, котрі можна розгортати і розробляти незалежно від модулів верхнього рівня.”
“Чому архітектора повинна хвилювати змінюваність змінних? Відповідь на це запитання надзвичайно проста: усі стани перегонів (race condition), взаємоблокування (deadlocks) і проблеми паралельної зміни даних, обумовленої змінюваністю змінних. Якщо в програмі немає змінюваних змінних, вона ніколи не опиниться у стані перегонів і ніколи не зіткнеться з проблемами одночасної зміни. За відсутності змінюваних блокувань програма не може потрапити у стан взаємоблокування. Інакше кажучи, всі проблеми, характерні для застосунків із паралельними обчисленнями, із якими нам доводиться стикатися, коли потрібно організувати багатопоточне виконання і задіяти обчислювальну потужність декількох процесорів, зникають самі собою за відсутності змінюваних змінних.”
“Із боку архітекторів було би розумно якомога більше коду перемістити в незмінні компоненти і якомога менше — у компоненти, що допускають можливість зміни.”
“технології реєстрації подій. Реєстрація подій (event sourcing) — це стратегія, згідно з якою зберігаються транзакції, а не стан. Коли необхідно довідатися про стан, ми просто застосовуємо всі транзакції від самого початку.”
"Отже: 1) структурне програмування накладає обмеження на пряму передачу управління; 2) обʼєктно-орієнтоване програмування накладає обмеження на непряму передачу управління;
- функціональне програмування накладає обмеження на присвоювання."
“Програмне забезпечення — матеріал для компʼютерних програм — складається з послідовностей, вибору, ітерацій та опосередкованості. Не більше й не менше.”
“Принципи SOLID визначають, як обʼєднувати функції і структури даних у класи і як ці класи повинні поєднуватися один з одним. Використання слова «клас» не означає, що ці принципи застосовні лише до обʼєктно-орієнтованого програмного коду. У цьому випадку «клас» означає лише інструмент обʼєднання функцій і даних у групи. Будь-яка програмна система має такі обʼєднання, хоч би як вони називалися — «клас» чи якось інакше. Принципи SOLID застосовуються до цих обʼєднань.”
“Мета принципів — створити програмні структури середнього рівня, що будуть: 1) толерантними до змін; 2) простими та зрозумілими; 3) основою для компонентів, придатних для використання у багатьох програмних системах.”
“Термін «середній рівень» відображає той факт, що ці принципи розробники застосовують на рівні модулів. Тобто на рівні, розташованому безпосередньо над рівнем програмного коду.”
“SRP: Single Responsibility Principle - принцип єдиної відповідальності. Активний наслідок закону Конвея: кращою є така структура програмної системи, яка формується переважно з огляду на соціальну структуру організації, що використовує цю систему, так, щоби кожен програмний модуль мав одну і лише одну причину для зміни.”
“OCP: Open-Closed Principle — принцип відкритості/закритості. Цей принцип був сформульований Бертраном Мером у 1980-х роках. Суть його така: проста для зміни система має передбачати просту можливість зміни її поведінки додаванням нового, але не зміною наявного коду.”
“LSP: Liskov Substitution Principle - принцип підстановки Барбари Лісков. Визначення підтипів Барбари Лісков відоме від 1988 року. Коротко кажучи, цей принцип стверджує, що для створення програмних систем із взаємозамінних частин ці частини мають відповідати контракту, який дозволяє робити подібну заміну.”
“ISP: Interface Segregation Principle - принцип поділу інтерфейсів. Цей принцип закликає розробників програмного забезпечення уникати залежності від усього, що не використовується.”
“DIP: Dependency Inversion Principle - принцип інверсії залежності. Код, який реалізує високорівневу політику, не повинен залежати від коду, що реалізує низькорівневі деталі. Натомість деталі мають залежати від політики.”
“Robert C. Martin. Agile Software Development, Principles, Patterns, and Practices. Prentice Hall, 2002, http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod, та https://en.wikipedia.org/wiki/SOLID_(object-oriented_design) (можна просто пошукати в Google за словом «SOLID»).”
“Традиційно принцип єдиної відповідальності визначали так: Модуль повинен мати одну й лише одну причину для зміни.”
“Модуль має відповідати за одного й лише одного актора.”
“модуль - це просто звʼязний набір функцій і структур даних. Слово «звʼязний» має на увазі принцип єдиної відповідальності. Звʼязність — це сила, що повʼязує код, відповідальний за єдиного актора.”
“Принцип єдиної відповідальності вимагає розділяти код, від якого залежать різні актори.”
“Принцип єдиної відповідальності (Single Responsibility Principle, SRP) стосується функцій і класів, але він проявляється в різних формах іще на двох вищих рівнях. На рівні компонентів він перетворюється на принцип узгодженої зміни (Common Closure Principle, ССР), а на архітектурному рівні — на принцип осі зміни (Axis of Change), що відповідає за створення архітектурних кордонів.”
“Принцип відкритості/закритості (Open-Closed Principle; ОСР) … Програмні сутності мають бути відкриті для розширення і закриті для зміни. Інакше кажучи, має існувати можливість розширювати поведінку програмних сутностей без їхньої зміни.”
“Принцип відкритості/закритості — одна з рушійних сил в архітектурі систем. Його мета — зробити систему легко розширюваною та убезпечити її від впливу змін. Ця мета досягається поділом системи на компоненти та упорядкуванням їхніх залежностей в ієрархію, що захищає компоненти рівнем вище від змін у компонентах рівнем нижче.”
“властивості підстановки: якщо для кожного обʼєкта o1 типу S існує такий обʼєкт o2 типу Т, що для всіх програм Р, визначених у термінах Т, поведінка Р не змінюється при підстановці о1 замість o2, тоді S є підтипом Т.”
“принцип розподілу інтерфейсів є проблемою мови, а не архітектури.”
“Принцип інверсії залежності (Dependency Inversion Principle, DIP) стверджує, що найбільш гнучкими є системи, у яких залежності у вихідному коді спрямовані на абстракції, а не на конкретні реалізації.”
“Кожна зміна абстрактного інтерфейсу викликає зміну його конкретної реалізації. Зміна конкретної реалізації, навпаки, не завжди супроводжується змінами і зазвичай навіть не вимагає змін у відповідних інтерфейсах. Тобто інтерфейси менш мінливі, ніж реалізації.”
“Зверніть увагу, що потік управління перетинає хвилясту лінію у напрямку, протилежному напрямку залежностей у вихідному коді. Залежності рухаються в напрямку, протилежному напрямку потоку управління, - саме тому принцип отримав назву принципу інверсії залежності.”
“Компоненти - це одиниці розгортання. Вони представляють найменші сутності, що можна розгортати у складі системи… Але незалежно від способу розгортання правильно спроєктовані компоненти завжди зберігають можливість незалежного розгортання і, відповідно, можуть розроблятися незалежно.”
“три принципи звʼязування компонентів: 1) REP: Reuse/Release Equivalence Principle - принцип еквівалентності повторного використання і релізів; 2) CCP: Common Closure Principle - принцип узгодженої зміни; 3) CRP: Common Reuse Principle - принцип спільного повторного використання.”
“Принцип еквівалентності повторного використання і релізів. Одиниця повторного використання є одиницею релізу.”
“Принцип еквівалентності повторного використання і релізів (Reuse/ Release Equivalence Principle, REP) здається очевидним, принаймні зараз. Люди, які потребують програмних компонентів багаторазового використання, не зможуть і не будуть користуватися компонентами, що не пройшли процес релізу й не отримали номера версії.”
“Принцип узгодженої зміни. В один компонент мають включатися класи, що змінюються з одних причин й одночасно. У різні компоненти мають входити класи, що змінюються в різний час і з різних причин.”
“Це принцип єдиної відповідальності (SRP), перефразований для компонентів. Так само, як принцип SRP, відповідно до якого клас не повинен мати кілька причин для зміни, принцип узгодженої зміни (ССР) вимагає, щоби компонент не мав кількох причин для зміни.”
“Принцип ССР вимагає від нас збирати докупи всі класи, які, можливо, доведеться змінити з однієї спільної причини… Цей принцип тісно повʼязаний із принципом відкритості/закритості (Open Closed Principle, OCP). Фактично він означає «закритість» із погляду принципу ОСР. Принцип відкритості/закритості (ОСР) вимагає, щоби класи були закриті для змін, але відкриті для розширення. Оскільки стовідсоткова закритість не є можливою, вона має носити радше стратегічний характер. Ми проєктуємо свої класи так, аби вони були закриті для найбільш типових із очікуваних за досвідом змін. Принцип узгодженої зміни (ССР) розвиває цю ідею, пропонуючи обʼєднувати в один компонент тільки класи, закриті для того самого виду змін. Інакше кажучи, збільшує ймовірність, що зміна вимог спричинить необхідність зміни мінімальної кількості компонентів.”
“принцип узгодженої зміни (ССР) є формою принципу єдиної відповідальності (SRP) для компонентів. Принцип SRP вимагає виокремлювати методи в різні класи, якщо вони змінюються з різних причин. Принцип ССР вимагає виокремлювати класи в різні компоненти, якщо вони змінюються з різних причин. Обидва принципи можна привести до загальної формули: Збирайте разом усе, що змінюється з однієї причини й одночасно. Розділяйте все, що змінюється в різний час і з різних причин.”
“Принцип спільного повторного використання. Не змушуйте користувачів компонента залежати від того, що їм не потрібно.”
“Класи рідко використовуються окремо. Зазвичай багаторазово використовувані класи, що взаємодіють з іншими класами, є частиною багаторазово використовуваної абстракції. Принцип CRP указує, що такі класи повинні входити в один компонент. Ми сподіваємося побачити в компонентах класи, що мають множинні залежності один від одного.”
“принцип CRP говорить не лише про те, які класи мають входити в компонент; він також повідомляє, які класи не мають обʼєднуватися. Коли один компонент використовує інший, між ними утворюється залежність. Компонент, що використовує, може потребувати одного-єдиного класу з компонента, що використовують, але це не послаблює залежність. Той компонент, що використовує, все одно залежить від компонента, що використовують.”
“Отже, принцип спільного повторного використання (CRP) більше говорить про те, які класи не мають обʼєднуватися, ніж про те, які мають обʼєднуватися. Принцип CRP указує, що класи, котрі не мають тісного звʼязку, не повинні входити в один компонент.”
“Принцип спільного повторного використання (CRP) € узагальненою версією принципу поділу інтерфейсів (ISP). Принцип ISP радить не створювати залежностей від класів, методи яких не використовують. Принцип CRP радить не створювати залежностей від компонентів, що мають невикористовувані класи. Узагальнюючи, ці поради можна обʼєднати в одну: Не створюйте залежностей від будь-чого невикористаного.”
“три принципи звʼязності компонентів вступають у суперечку один із одним. Принципи еквівалентності повторного використання (REP) та узгодженої зміни (ССР) є включаючими: обидва прагнуть зробити компоненти якомога більшими. Принцип повторного використання (CRP) - виключаючий, тобто прагне зробити компоненти якомога дрібнішими. Завдання хорошого архітектора — владнати цю суперечність.”
“Архітектор, який приділяє увагу тільки принципам REP і CRP, виявить, що проста зміна торкається надто великої кількості компонентів. З іншого боку, архітектор, який приділяє особливу увагу принципам ССР і REP, змушений буде реалізувати забагато непотрібних версій.”
“на ранніх етапах розробки проєкту принцип ССР набагато важливіший за REP, а зручність розробки важливіша за зручність повторного використання. Загалом на початку розробки найбільшу вагу має права сторона трикутника — тоді єдиною жертвою стає повторне використання. Але в міру розвитку та інтеграції в інші проєкти фокус починає зміщуватися вліво. Тобто організація компонентів у проєкті може змінюватися з плином часу. Це більше повʼязано зі способом розробки та використання проєкту, ніж із тим, що проєкт насправді робить,”
“склад компонентів майже напевно буде змінюватися із плином часу і зміщенням фокусу проєкту зі зручності розробки до зручності повторного використання”
“Принцип циклічності залежностей. Цикли в графі залежностей компонентів неприпустимі.”
“Щотижневі збірки. Щотижневі збірки часто використовують у проєктах середнього розміру. Це рішення діє так: усі розробники працюють незалежно перші чотири дні тижня. Вони змінюють власні копії коду й не турбуються про інтеграцію результатів своєї праці у спільну основу. У пʼятницю вони обʼєднують свої зміни і намагаються зібрати систему. Цей підхід має важливу перевагу, дозволяючи розробникам працювати в ізоляції чотири дні з пʼяти. Недолік очевидний — великі трудовитрати на інтеграцію у пʼятницю.”
“зі зменшенням співвідношення тривалості розробки і тривалості інтеграції знижується ефективність команди.”
“Розрив циклу. Утворену циклічну залежність завжди можна розірвати і привести граф залежностей до форми циклічно орієнтованого графа (DAG). Для цього використовують два основні механізми. 1) Застосування принципу інверсії залежностей (Dependency Inversion Principle, DIP). 2) Створення нового компонента, від якого залежать Entities i Authorizer. Для цього треба помістити в новий компонент клас (класи), від яких вони обидва залежать”
“Принцип стабільних залежностей. Залежності мають бути спрямовані в бік стабільності.”
“Компоненти, які важко змінювати, не повинні залежати від будь-яких мінливих компонентів. Інакше мінливий компонент теж буде важко змінювати.”
“Виходячи із принципу стійких залежностей (Stable Dependencies Principle, SDP), ми гарантуємо, що модулі, які важко змінювати, не залежатимуть від модулів, спроєктованих для спрощення змін.”
“Метрики стабільності. Як оцінити стабільність компонента? Один зі способів — підрахувати кількість вхідних і вихідних залежностей цього компонента. Ці числа дозволять визначити міру його стабільності. 1) Fan-in (число входів): кількість вхідних залежностей. Ця метрика визначає кількість класів поза певним компонентом, що залежать від класів усередині компонента. 2) Fan-out (число виходів): кількість вихідних залежностей. Ця метрика визначає кількість класів усередині цього компонента, що залежать від класів за його межами. 3) І (нестабільність): I = Fan-out / (Fan-in + Fan-out). Значення цієї метрики змінюється в діапазоні [0, 1]. І = 0 означає максимально стабільний компонент, I = 1 — максимально нестабільний.”
“Метрики Fan-in (число входів) і Fan-out (число виходів) визначаються як кількість класів за межами компонентів, повʼязаних залежністю із класами всередині компонента.”
“Принцип стабільності абстракцій. Стабільність компонента пропорційна його абстрактності.”
“Принцип стабільності абстракцій (Stable Abstractions Principle, SAP) установлює звʼязок між стабільністю і абстрактністю. З одного боку, він вимагає, щоби стабільний компонент також був абстрактним, аби його стабільність не перешкоджала розширенню, з іншого — що нестабільний компонент має бути конкретним, тому що нестабільність дозволяє легко змінювати його код. Тобто стабільний компонент має складатися з інтерфейсів та абстрактних класів, аби його легко було розширювати. Стабільні компоненти, доступні для розширення, мають достатню гнучкість, щоби не накладати надмірні обмеження на архітектуру. Принципи стабільності абстракцій (SAP) і стабільних залежностей (SDP) разом відповідають принципу інверсії залежностей (DIP) для компонентів. Це правильно, тому що принцип SDP вимагає, щоби залежності були спрямовані в бік стабільністі, а принцип SAP стверджує, що стабільність має на увазі абстрактність. Тобто залежності мають бути спрямовані в бік абстрактності. Однак принцип DIP сформульований для класів, й у випадку із класами взагалі відсутні півтони. Клас або абстрактний, або ні. Принципи SDP і SAP діють відносно компонентів і припускають ситуацію, коли компонент частково абстрактний або частково стабільний.”
“Головне призначення архітектури — підтримка життєвого циклу системи. Гарна архітектура робить систему легкою в освоєнні, простою в розробленні, супроводі і розгортанні. Кінцева її мета — мінімізувати витрати протягом терміну служби системи і максимізувати продуктивність програміста.”
“Продумана архітектура значно знижує ці витрати. Розділивши систему на компоненти та ізолювавши їх за стійкими інтерфейсами, можна висвітлити шляхи до майбутніх особливостей та істотно зменшити ризик ненавмисних помилок.”
“будь-яка програмна система має дві цінності: поведінку і структуру. Друга з них важливіша, тому що саме вона робить програмне забезпечення програмним.”
“Програмне забезпечення було винайдено тоді, коли знадобився спосіб легко і швидко змінювати поведінку машин. Але така гнучкість повністю залежить від форми системи, організації її компонентів і способів взаємодії між ними.”
“Будь-яку програмну систему можна розкласти на два основні елементи: політику та деталі. Політика втілює всі бізнес-правила і процедури. Політика — ось справжня цінність системи. Деталі — це все інше, що дозволяє користувачам, іншим системам і програмістам взаємодіяти з політикою, жодним чином не впливаючи на її поведінку. До деталей можна віднести пристрої введення/виведення, бази даних, вебсервери, фреймворки, протоколи обміну даними та інше. Мета архітектора — створити таку форму для системи, яка зробить політику найважливішим елементом, а деталі — безвідносними стосовно політики. Це дозволить відкладати і затримувати прийняття рішень щодо деталей.”
“Досвідчений архітектор максимізує кількість неприйнятих рішень.”
“Досвідчені архітектори скрупульозно відокремлюють деталі від політики і потім не менш скрупульозно відокремлюють політику від деталей, аби політика аж ніяк не залежала від деталей. Досвідчені архітектори проєктують політику так, аби рішення стосовно деталей доводилося приймати якомога пізніше.”
“Архітектура відіграє важливу роль у підтримці середовища розробки. У нашому випадку спрацьовує закон Конвея: Будь-яка організація, що розробляє систему, мимоволі буде формувати дизайн, структура якого повторює структуру взаємодій усередині цієї організації.”
“Гарна архітектура спрощує можливість змін системи в усіх її варіантах, залишаючи можливості відкритими.”
“Архітектуру, засновану на сервісах, часто називають сервіс-орієнтованою архітектурою (Service-Oriented Architecture, SOA).”
“Архітектори часто потрапляють у пастку, спричинену поширеним страхом перед дублюванням… Але є різні види дублювання. Є справжнє дублювання, коли будь-яка зміна в одній копії вимагає такої самої зміни в усіх інших копіях. А є удаване або випадкове дублювання. Якщо два фрагменти коду, що здаються однаковими, розвиваються різними шляхами — тобто змінюються з різною швидкістю і з різних причин — цей випадок не є справжнім дублюванням.”
“Розробка архітектури програмного забезпечення - це мистецтво проведення ліній розподілу, які я називаю кордонами. Кордони відокремлюють програмні елементи один від одного та позбавляють їх необхідності знати, що розташовано по інший бік кордону.”
“Нагадаю, що метою архітектора є мінімізація трудовитрат на створення і супровід системи. Що може перешкодити досягненню цієї мети? Залежність — і особливо залежність від передчасних рішень. Які рішення можна назвати передчасними? Рішення, що не мають нічого спільного з бізнес-вимогами — варіантами використання - системи. До них можна віднести рішення про вибір фреймворку, бази даних, вебсервера, допоміжних бібліотек, механізму впровадження залежностей тощо. У хорошій архітектурі подібні рішення є допоміжними і відкладаються на потім. Вона не залежить від таких рішень, бо дозволяє приймати їх у найостанніший момент без істотного впливу на саму архітектуру.”
“Бізнес-правила не залежать від конкретної схеми, мови запитів і решти інших деталей організації бази даних. Бізнес-правилам потрібний лише набір функцій для вилучення і збереження даних. Це дозволяє нам приховати базу даних за інтерфейсом.”
“Кордони проводяться там, де є вісь зміни. Компоненти по різні боки кордону змінюються з різною швидкістю і з різних причин. Графічні інтерфейси змінюються в інший час і з іншою швидкістю, ніж бізнес-правила, тому їх повинна відокремлювати межа.”
“Найнадійнішими є кордони сервісів. Часто сервіс — це процес, що запускається з командного рядка або за допомогою еквівалентного системного виклику. Сервіси не залежать від фізичного місця розташування. Два сервіси, що комунікують між собою, можуть або не можуть діяти на одному процесорі або групі процесорів у багатопроцесорній системі. Сервіси припускають, що всі взаємодії здійснюються через мережу. Взаємодії через кордони сервісів здійснюються дуже повільно порівняно з викликами функцій. Час між запитом і відповіддю може становити від десятків мілісекунд до декількох секунд. Взаємодії слід обмежувати, наскільки це можливо. Взаємодії на цьому рівні мають ураховувати ймовірність значних затримок. В усьому іншому до сервісів застосовуються ті ж правила, що й до локальних процесів. Низькорівневі сервіси мають «підключатися» до високорівневих сервісів. Вихідний код високорівневих сервісів не повинен містити жодної конкретної інформації (наприклад, URI) про низькорівневі сервіси.”
“Програмні системи — це описи політик. Фактично це все, що являє собою програма. Компʼютерна програма — це докладний опис політики перетворення вхідних даних у вихідні.”
“Сутність — це обʼєкт у компʼютерній системі, що втілює невеликий набір критичних бізнес-правил, які оперують критичними бізнес-даними. Обʼєкт-сутність або містить критичні бізнес-правила в собі, або має простий доступ до них. Інтерфейс сутності складається із функцій, що реалізують критичні бізнес-правила й оперують цими даними.”
“Бізнес-правила є причиною існування програмної системи. Вони складають основу функціонування. Вони породжують код, що заробляє або економить гроші. Вони — наші сімейні реліквії. Бізнес-правила мусять залишатися недоторканими, не заплямованими низькорівневими аспектами — як-от інтерфейс користувача або база даних. В ідеалі код, що представляє бізнес-правила, має бути серцем системи, а все інше — просто підключатися до них. Реалізація бізнес-правил має бути найнезалежнішим кодом у системі, готовим до багаторазового використання.”
“Візьміть до рук фундаментальну працю Івара Якобсона про архітектуру програмного забезпечення, що має назву «Object Oriented Software Engineering». Зверніть увагу на підзаголовок: «А Use Case Driven Approach» (Підхід, керований варіантами використання). У цій книжці Якобсон підкреслює, що архітектура програмного забезпечення — це структура, яка підтримує варіанти використання системи.”
“Розглядайте фреймворки відсторонено. Дивіться на них скептично. Так, вони можуть допомогти, але за яку ціну? Запитайте себе, як би ви їх використали і як захистилися би від них. Подумайте, як зберегти пріоритетність варіантів використання для архітектури. Розробіть стратегію, що не дозволить фреймворку впливати на архітектуру.”
“нарешті, кожна із цих архітектур сприяє створенню систем, що мають такі характеристики: 1) Незалежність від фреймворків. 2) Простота тестування. Бізнес-правила можна тестувати без інтерфейсу користувача, бази даних, вебсервера і будь-яких інших зовнішніх елементів. 3) Незалежність від інтерфейсу користувача. 4) Незалежність від бази даних. 5) Незалежність від будь-яких зовнішніх агентів. Ваші бізнес-правила нічого не знають про інтерфейси, що ведуть до зовнішнього світу.”
“Головним правилом, що приводить цю архітектуру в дію, є правило залежностей (Dependency Rule): Залежності у вихідному коді мають бути спрямовані всередину, у бік високорівневих політик.”
“Представлення (View) - це скромний обʼєкт, складний для тестування. Код у цьому обʼєкті дуже спрощений. Він просто переносить дані у графічний інтерфейс, жодним чином не обробляючи їх.”
“Презентер (Presenter) - це легко тестований обʼєкт. Його завдання - отримати дані від програми і перетворити їх так, аби представлення (View) могло перемістити їх на екран. Наприклад, якщо застосунку треба відобразити дату в певному полі, він має передати презентеру обʼєкт Date. Презентер має перетворити дату на рядок і помістити її у просту структуру даних, котру називають моделлю представлення (View Model), де представлення зможе її знайти.”
“Де мають перебувати такі системи ORM? Звичайно, на рівні бази даних. Насправді інструменти ORM утворюють ще один тип кордону «Скромний обʼєкт» між інтерфейсами шлюзу і базою даних.”
“Одне із завдань архітектора — вирішити, де провести архітектурний кордон і як його реалізувати, частково або повністю.”
“У кожній системі є хоча б один компонент, що створює інші компоненти, спостерігає за ними і координує їхні дії. Я називаю такий компонент головним (Main).”
“Незважаючи на всі переваги масштабованості та зручності розробки системи, сервіси не є архітектурно значущими елементами. Архітектура системи визначається кордонами, проведеними всередині самої системи, і залежностями, що перетинають ці кордони. Архітектура не визначається фізичними механізмами, за допомогою яких елементи взаємодіють і виконуються. Сервіс може бути єдиним компонентом, повністю оточеним архітектурним кордоном. Але так само сервіс може складатися з декількох компонентів, розділених архітектурними кордонами. У поодиноких випадках клієнти і сервіси можуть бути настільки повʼязані, що не матимуть архітектурної значимості.”
“Тести є найбільш ізольованими компонентами системи. Вони не потрібні системі для нормального функціонування. Користувачі не залежать від них. Роль тестів — підтримати розробку, але не роботу.”
“З архітектурної точки зору база даних не є сутністю - це деталь, що не повинна підніматися до рівня архітектурного елемента. Її відношення до архітектури програмної системи можна порівняти з відношенням дверної ручки до архітектури будівлі.”
“база даних — це не модель даних. База даних — це частина програмного забезпечення. База даних — це утиліта, що забезпечує доступ до даних. Із погляду архітектури ця утиліта не має жодного значення, це низькорівнева деталь, механізм. А досвідчений архітектор не дозволяє низькорівневим механізмам просочуватися в архітектуру системи.”
“фреймворк як деталь, що належить одному із зовнішніх кіл архітектури. Не впускайте його у внутрішні кола.”
“Якщо фреймворк запропонує породити ваші бізнес-обʼєкти від його базових класів, твердо відмовте йому! Визначте проксі-класи і тримайте їх у компонентах, що є плагінами для ваших бізнес-правил.”
“ми отримали гарний урок: не можна створити універсальну інфраструктуру, не створивши спочатку робочу інфраструктуру. Універсальні інфраструктури мають створюватися одночасно з кількома застосунками, що використовуватимуть їх.”
Тренування мозку (промо)
No comments:
Post a Comment