Патерни проєктування та як їх класифікують в автоматизації

Усі статті, обговорення, новини про тестування — в одному місці. Підписуйтеся на DOU | QA!

Мене звати Юрій Сердюк і я працюю в міжнародній компанії P2H. З 2019 року в напрямку QA пройшов шлях від manual до automation QA.

У цій короткій статті хотів би розповісти про те, що таке патерн, навіщо їх знати та яка існує класифікація патернів. Тема дуже велика, тому всі патерни, на жаль, розглянути не вийде, але ми оглянемо декілька прикладів, які допоможуть зрозуміти тему краще.

Що таке патерни

Патерн проєктування — це типовий спосіб розв’язання проблем при проєктуванні програм. Він не може бути просто скопійований в програму, як готові функції або бібліотеки. Це загальний принцип вирішення проблеми, який потрібно адаптувати до потреб конкретної програми.

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

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

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

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

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

Класифікація патернів

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

Список патернів, які ми розглянемо для прикладу

  • Decorator
  • Facade
  • Composite
  • Factory method
  • Builder
  • Singleton
  • Chain of Responsibility

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

Приклад використання:

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

Фасад — це структурний патерн проєктування, який надає простий інтерфейс до складної системи класів, бібліотеки або фреймворку. Він дозволяє надати простий або спрощений інтерфейс до складної підсистеми та розкласти підсистему на окремі рівні.

Приклад використання:

Ми створюємо компанію і буває так, що тести знаходяться в одному проєкті, а створення всіх об’єктів — в іншому. Або в тому самому, але з можливістю доступу лише з однієї точки. Тому ми створюємо компанію через API виклик, і ми не знаємо, що відбувається «під капотом», а тільки отримуємо результат.

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

Приклад використання:

У нас є компанія, яка має в собі певні атрибути. Наприклад, employee — це окремий клас, який має підкласи. Тому ми створюємо деревоподібну структуру, яка надалі значно полегшує нашу роботу. І в такому разі нам не потрібно передавати купу параметрів, а достатньо лише один і далі працювати з ним.

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

Приклад використання:

Клас CompanyFactory містить метод create_company, який створює об’єкти компаній залежно від переданого параметру department. Тепер ми можемо використовувати CompanyFactory для створення різних типів компаній.

За допомогою фабричного методу ми можемо забезпечувати створення різних типів об’єктів, залежно від потреб нашої програми і далі передаємо не купу різних параметрів, а один об’єкт — company options, і працюємо з ним там, де нам потрібно. Це корисно для UI та API тестів.

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

Приклад використання:

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

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

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

Приклад використання:

У цьому коді ми бачимо використання патерну Singleton за допомогою декоратора @singleton, що визначений за допомогою класу. Патерн Singleton має на меті забезпечити, що з одного класу буде створено лише один об’єкт і до цього об’єкту можна буде отримати доступ з будь-якої точки програми.

Клас ReportManager є одиначкою, тому що має лише один екземпляр класу, і ми можемо отримати доступ до нього з будь-якої частини нашої програми.

Декоратор @singleton забезпечує, що лише один об’єкт класу ReportManager буде створено, тобто, коли ми створюємо екземпляр цього класу, він створюється тільки один раз і зберігається для подальшого використання.

Це дуже корисно в тому випадку, коли ми маємо декілька місць у програмі, які мають взаємодіяти з одним і тим же екземпляром класу.

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

Ланцюжок обов’язків — це поведінковий патерн проєктування, який дозволяє передавати запити послідовно ланцюжком обробників. Кожен наступний обробник вирішує, чи може він обробити запит самостійно, чи варто передати його далі ланцюжком.

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

Приклад використання:

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

Це доволі часто використовується у ситуаціях, коли ми, наприклад, відкриваємо якийсь браузер, щоб запустити UI-тести, і якщо браузер доступний — тест виконується, а якщо не доступний, то виконання іде далі.

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

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

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

👍ПодобаєтьсяСподобалось11
До обраногоВ обраному10
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

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

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

Дякую за техн. текст Українською!

трохи критики :-)
Composite — компонувальник — ну таке. Думаю багато технічних термінів не варто намагатись переводити 1 словом. Бо люди знайомі з англ. терміном просто не зрозуміють. Краще викортстлвувати оригінал і коротке пояснення, іноді навіть зі словника
composite
звідний, зведений; складний, комбінований

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