Назад Зміст Вперед

3.1. Проектування класів із врахуванням властивостей сoupling та cohesion

Взаємодія (Coupling)

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

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

В далекому кінці взаємодії видніється жахлива ситуація, в якій клас А знає дещо, що не відносяться до API класу В, а клас В знає щось подібне про клас А - це ДІЙСНО ПОГАНО. Якщо один з класів зміниться, є ймовірність, що буде зруйновано інший клас. Подивимось на очевидний приклад сильної взаємодії, яка стала доступною через слабку інкапсуляцію:


class DoTaxes {
  float rate;
  float doColorado() {
    SalesTaxRates str = new SalesTaxRates();
    rate = str.salesRate;//це мав би бути виклик методу
                                                                      //rate = str.getSalesRate("CO") для обробки rate
  }
}
class SalesTaxRates {
  public float salesRate;         //має бути private
  public float adjustedSalesRate; //має бути private
  public float getSalesRate(String region) {
    salesRate= new DoTaxes().doColorado();     //знову!
//необхідно робити регіональні обчислення                    
//із поверненням adjustedSalesRate;
  }
}

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

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

Увя’зка (Сohesion)

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

class BudgetReport {
  void connectToRDBMS(){ }
  void generateBudgetReport() { }
  void saveToFile() { }
  void print() { }
}

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

Замість того, щоб вставляти весь код в один клас звіту, краще почати розробку спочатку:


class BudgetReport {
  Options getReportingOptions() { }
  void generateBudgetReport(Options o) { }
}
class ConnectToRDBMS {
  DBconnection getRDBMS() { }
}
class PrintStuff {
  PrintOptions getPrintOptions() { }
}
class FileSaver {
  SaveOptions getFileSaveOptions() { }
}


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