КАТЕГОРИИ: Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748) |
Принципи гарної архітектури
Принцип відкриття-закриття (Open Close Principle або OCP) Програмні суті такі як класи, модулі та функції повинні бути відкриті для розширення, але закриті для змін. Ви можете обговорювати його, коли пишете ваші класи, щоб бути впевненими в тому, що коли вам буде потрібно розширити поведінку, ви не повинні будете змінювати клас, але можете розширювати його. Подібний же принцип застосуємо для модулів, пакетів і бібліотек. Якщо у вас є бібліотека, що складається з множини класів, то є багато причин для того, щоб ви вважали за краще розширення замість зміни коду, який вже написаний (заради зворотної сумісності, повернення до попереднього тестування і т.д.). Це причина, по якій ми повинні бути впевнені, що наші модулі слідують Принципу відкриття-закриття. По відношенню до класів Принцип відкриття-закриття може бути гарантовано корисний за рахунок використання Абстрактних Класів і конкретних класів для реалізації їх поведінки. Це буде змушувати мати Конкретні Класи, що розширюють Абстрактні Класи замість їх зміни. Деякі приватні випадки цього принципу є Шаблонний Патерн і Стратегічний Патерн (Template Pattern and Strategy Pattern). Принцип Заміщення Ліскоу (Liskov's Substitution Principle) Похідні типи повинні бути здатні повністю заміщатися їх базовими типами. Цей принцип є всього лише розширенням Принципу відкриття-закриття в умовах поведінки, що означає, що ми повинні бути впевнені, що нові похідні класи є розширенням базових класів без зміни їх поведінки. Нові похідні класи повинні бути здатні замінювати базові класи без будь-яких змін у коді. Принцип Заміщення Ліскоу був введений на 1987 Conference on Object Oriented Programming Systems Languages and Applications, in Data abstraction and hierarchy. Принцип Єдиної Відповідальності (Single Responsibility Principle) Клас повинен мати тільки одну причину для зміни. У цьому контексті відповідальність розглядається як єдина причина для зміни. Цей принцип стверджує, що якщо ми маємо 2 причини для зміни класу, то ми повинні розділити функціональність на 2 класи. Кожен клас повинен мати тільки одну відповідальність, і в майбутньому, якщо нам буде потрібно зробити одну зміну ми будемо робити це в класі, який утримує цю одну відповідальність. Коли нам потрібно робити зміни в класі, який має більше відповідальностей, зміна може вплинути на іншу функціональність класів. Принцип Єдиної Відповідальності був введений Tom DeMarco в його книзі «Structured Analysis and Systems Specification, 1979». Роберт Мартін переробив цю концепцію і визначив, що відповідальність є причиною для зміни. Принцип Відділення Інтерфейсу (Interface Segregation Principle) Клієнти не повинні бути залежними від інтерфейсів, які вони не використовують. Цей принцип вчить нас піклуватися про те, як ми пишемо наші інтерфейси. Коли ми пишемо інтерфейси, ми повинні подбати про додавання тільки тих методів, які там повинні бути. Якщо ми додаємо методи, які не повинні бути там, тоді класи, що реалізують інтерфейс будуть повинні реалізовувати зайві методи так само як і інші методи. Наприклад, якщо ми створюємо інтерфейс, званий Worker (Робочий) і додаємо метод lunch break (обідня перерва), тоді всі workers (робітники) будуть мати реалізацію цього зайвого методу. А що якщо робітник виявився роботом? Інтерфейси містять методи, які не є специфічними для них, такі методи призводять до того, що інтерфейси називають забрудненими або жирними. Ми повинні уникати створення таких інтерфейсів. Принцип інверсії залежностей (Dependency Inversion Principle) - залежності всередині системи будуються на основі абстракцій. Модулі верхнього рівня не залежать від модулів нижнього рівня. Абстракції не залежать від подробиць. Даний принцип дуже важливий і гідний докладного розгляду. Принцип інверсії залежностей в деталях У протиставленні поганому дизайну, гарний дизайн архітектури повинен бути гнучким, стійким, і пристосованим до повторного використання. Чим нижче взаємозв'язок компонентів додатка один з одним, тим вища гнучкість і мобільність всієї програми в цілому. Програми, що характеризуються високим коефіцієнтом мобільності, дозволяють застосовувати свої компоненти знову і знову для вирішення однотипних задач. Це веде до зниження дублювання коду. Такі програми складаються з великого набору досить дрібних компонентів, кожен з яких виконує малу частину роботи, але виконує її якісно. Дрібні компоненти набагато простіше тестувати, реалізовувати і супроводжувати. Якщо ви дотримуєтеся принцип інверсії залежностей, то ваш код більш пристосований до змін і менше залежить від контексту виконання. Вірно і зворотне твердження. Якщо ваш додаток є хорошим прикладом вдалого дизайну архітектури, то він, в тій чи іншій мірі, дотримується принципу інверсії залежностей. Суть принципу 1. Модулі верхнього рівня не повинні залежати від модулів нижнього рівня. Обидва типи модулів повинні залежати від абстракцій; 2. Абстракція не повинна залежати від реалізації. Реалізація повинна залежати від абстракції. Традиційні методи розробки (наприклад, процедурне програмування) мають тенденцію до створення коду, в якому високорівневі модулі, як раз, залежать від низькорівневих. Це відбувається через те, що одна з цілей цих методів розробки - визначення ієрархії підпрограм, а отже і ієрархії викликів усередині модулів (високорівневі модулі викликають низькорівневі). Саме це є причиною низької гнучкості і закостенілості дизайну. При правильному використанні, ГО методики дозволяють обійти це обмеження. Розглянемо приклад програми, яка копіює в файл дані, введені з клавіатури. У нас є три модулі (у даному випадку це функції). Один модуль (іноді його називають сервіс) відповідає за читання з клавіатури. Другий - за виведення у файл. А третій високорівневий модуль об'єднує два низькорівневих модуля з метою організації їх роботи. Наш модуль copy може виглядати приблизно так. while (($ data = readKeyboard ())! == false) { writeFile (". / filename", $ data); } Низькорівневі модулі readKeyboard і writeFile володіють високою гнучкістю. Ми легко можемо використовувати їх у контексті відмінному від функції copy. Проте сама функція «copy» не може бути повторно використана в іншому контексті. Наприклад, для відправки даних з файлу системного оброблювача логів. Використовуючи принцип інверсії залежностей, можна зробити модуль copy незалежним від об'єктів джерела і призначення даних. Для цього необхідно виробити абстракції для цих об'єктів, і зробити модулі залежними від цих абстракцій, а не один від одного. interface IReader { public function read (); }
interface IWriter { public function write ($ data); } Модуль copy повинен покладатися тільки на вироблені абстракції і не робити ніяких припущень з приводу індивідуальних особливостей об'єктів вводу / виводу. while (($ data = $ reader-> read ())! == false) { $ Writer-> write ($ data); } Приблизно таким чином виглядає використання нашого модуля користувачем. $ Copier = new copier ();
/ / Копіювання даних з клавіатури в файл $ Copier-> run (new keyboardReader (), new fileWriter ('. / Filename'));
/ / Надсилання даних з файлу системного оброблювача логів $ Copier-> run (new fileReader ('. / Filename'), new syslogWriter ()); Тепер модуль copy можна використовувати в різних контекстах копіювання. Зміна поведінки модуля-копіювальника досягається шляхом асоціації його з об'єктами інших класів (але які залежать від тих же абстракцій). Незважаючи на простоту виконаних нами дій ми отримали дуже важливий результат. Тепер наш код володіє наступними якостями: • модуль може бути використаний для копіювання даних в контексті відмінному від даного; • ми можемо додавати нові пристрої введення / виведення не змінюючи при цьому модуль copy. Таким чином, знизилася крихкість коду, підвищилася його мобільність і гнучкість.
Дата добавления: 2017-02-01; Просмотров: 90; Нарушение авторских прав?; Мы поможем в написании вашей работы! Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет |