Принципы и шаблоны проектирования GRASP / SOLID

(ЧАСТЬ 2)

Романенко Константин

Тетерятников Алексей

GRASP: general responsibility assignment software patterns

общие шаблоны распределения ответственностей

Шаблоны GRASP: план доклада

  • Что такое шаблон проектирования ?
  • Шаблоны-принципы и связь с SOLID
  • Шаблоны-роли

Что такое шаблон проектирования ?

Характерная задача проектирования [классов] и эффективный способ ее решения.

Имя - Задача - Решение - Результаты

Буддистский шаблон решения проблем

У вас есть проблема ?

Да

Нет

Тогда не волнуйтесь!

Можете ли вы ее решить?

Нет

Да

Действуйте!

классификация шаблонов GRASP

Основные шаблоны

  • Information expert (Информационный эксперт)
  • Creator (создатель)
  • High Cohesion (Высокая cцепленность)
  • Low Coupling (Низкое связывание)
  • Controller (Контроллер)

Дополнительные шаблоны

  • Protected Variations (Устойчивость к изменениям)
  • Polymorphism (Полиморфизм)
  • Indirection (Перенаправление)
  • Pure Fabrication (чистая выдумка, синтетика)

High Cohesion & Low Coupling

принципы: high cohesion / low coupling

Cohesion - Сцепленность

 the act or state of sticking together tightly

Coupling - Связывание

the act of bringing ... together

"... система должна состоять из слабо связанных классов,  которые должны содержать связанную бизнес — логику." 

Низкое связывание

Low Coupling

принцип GRASP: low coupling

Для конкретного класса: как добиться возможности повторного использования и незначительного влияния изменений ?

Минимизировать количество данных о других элементах!

Пример нарушения: циклическая зависимость

принцип GRASP: low coupling

A

B

public class A {
   private B b;
   public A() {
     this.b = new B(this);
   }
}
public class B {
   private A a;
   public B(A a) {
     this.a = a;
   }
}
принцип GRASP: low coupling

Как обнулить связывание: атрибуты

  1. Удалить атрибуты нестандартных типов

Катавасия

кличка: String

ночноеЗрение: NightVision

принцип GRASP: low coupling
  1. Удалить атрибуты нестандартных типов
  2. Не вызывать службы классов другого типа
  3. Для параметров, возвращаемых значений и локальных переменных избавиться от нестандартных типов

Катавасия

void питаться()

void спать()

Мышь найтиМышь()

...

Как обнулить связывание: методы

принцип GRASP: low coupling

Катавасия

void питаться()

void спать()

...

Как обнулить связывание: полиморфизм

  1. Удалить атрибуты нестандартных типов
  2. Не вызывать службы классов другого типа
  3. Для параметров, возвращаемых значений и локальных переменных избавиться от нестандартных типов
  4. Отказаться от наследования и реализации интерфейсов

Нулевое связывание... А как же ООП?

принцип GRASP: low coupling

Высокая сцепленность

High Cohesion

принцип GRASP: high cohesion

Как обеспечить сфокусированность ответственности класса, управляемость и ясность?

Класс должны содержать сцепленную бизнес — логику!

Пример нарушения

принцип GRASP: high cohesion

Data

 - temperature: int

- time: int;

...

 - calcTemperature(): int

- calcTime(): int;

Пример реализации

принцип GRASP: high cohesion

TemperatureData

- temperature: int

...

- calcTemperature(): int

TimeData

- time: int

...

- calcTime(): int

принцип GRASP: high cohesion

Сцепленный класс

Менее сцепленный класс

приватное свойство или метод

публичное свойство или метод

принципы GRASP: high cohesion / low coupling

Максимизируйте сфокусированность

Минимизируйте зависимости

приватное свойство или метод

публичное свойство или метод

Связь с принципами SOLID

принципы GRASP и SOLID

High Cohesion

GRASP

SOLID

Высокая сцепленность

Единственная ответственность

Single Responsibility

Низкое связывание

Разделение интерфейсов

Low Coupling

Interface Segregation

принцип GRASP: protected variations

Устойчивость к изменениям

Protected Variations

Как спроектировать систему классов, чтобы изменение в одном классе не оказывало нежелательного влияния на другие классы?

Распределите ответственности, чтобы обеспечить устойчивый интерфейс!

принцип GRASP: protected variations

Точки вариации и точки эволюции

Точка эволюции - предполагаемая точка ветвления, которая может возникнуть в будущем

Точка вариации - точка ветвления в существующей на данный момент системе

принцип GRASP: polymorphism

Полиморфизм

Как обрабатывать альтернативные варианты поведения на основе типа? 

Для однотипных классов используйте полиморфные операции!

принципы protected variations & polymorhpism

Пример реализации

class PasswordReminder {
     // соединение с абстрактной СУБД
     private DBConnectionInterface dbConnection;
 
     PasswordReminder(DBConnectionInterface dbConnection) {
         this.dbConnection = dbConnection;
     }
}

Связь с принципами SOLID

принципы GRASP и SOLID

Dependency inversion principle

SOLID

GRASP

Устойчивость к изменениям

Protected Variations

Открытость/закрытость

Open/closed principle

Инверсия зависимостей

Полиморфизм

Принцип подстановки Барбары Лисков

классификация шаблонов в докладе
  • Information expert (Эксперт)
  • Creator (Создатель)
  • Controller (Контроллер)

Шаблоны - роли

  • Indirection (Перенаправление)
  • Pure Fabrication (чистая выдумка, синтетика)

RDD: responsibility driven design

Проектирование на основе ответственностей

шаблон-роль GRASP: information expert

Информационный эксперт

Каков базовый принцип распределения ответственностей ?

Информация должна обрабатываться там, где она содержится!

Эксперт: пример

шаблон-роль GRASP: information expert

Эксперт: пример нарушения

шаблон-роль GRASP: information expert

AreaCalculator

public double sum() {
     foreach(shape : this.shapes) {
         if(is_a(shape, 'Square')) {
            area.append( pow(shape.length, 2) );
         } else if(is_a(shape, 'Circle')) {
            area.append( pi() * pow(shape->radius, 2) );
         }
     }
 
     return array_sum(area);
}

Эксперт: пример реализации

шаблон-роль GRASP: information expert

interface ShapeInterface {
     public double area();
}

class Circle implements ShapeInterface {
    public double area()  {

          return pi() * pow(shape->radius, 2)

    }

}

шаблон-роль GRASP: information expert

Эксперт: пример реализации

Создатель

Какой класс должен отвечать за создание нового экземпляра некоторого класса? 

Смотрим дальше!

шаблон-роль GRASP: creator

Создатель

  1. Содержит или агрегирует объекты целевого класса
  2. Активно использует
  3. Обладает данными инициализации

Например, при разработке набора настольных игр, объект класса Board включает в себя 0..n 

объектов класса Square

шаблон-роль GRASP: creator
шаблон-роль GRASP: creator

Создатель: пример реализации

Контроллер

Какой класс должен отвечать координацию выполнения системных операций, поступающих

на уровне UI? 

Отдельный класс Controller!

шаблон-роль GRASP: controller
шаблон-роль GRASP:controller

Пример реализации: REST-Контроллер

роль в GRASP: indirection

Перенаправление

Как перераспределить обязанности, чтобы избавиться от прямого связывания классов?

Присвойте обязанности промежуточному объекту, который перенаправляет связи!

Используйте интерфейс!

РассчитатьНалог(позиция)

<<Интерфейс АдаптерРасчетаНалога>>

шаблон-роль GRASP: indirection

Перенаправление: пример

РассчитатьНалог(позиция)

<<АдаптерСистемы1>>

РассчитатьНалог(позиция)

<<АдаптерСистемы2>>

шаблон-роль GRASP: indirection

Перенаправление: пример

ГлавныйНалоговыйАдаптер

...

Продажа

ПолучитьВеличинуНалогов(Продажа)

РассчитатьНалог(позиция)

sum =итого()

роль в GRASP: pure fabrication

Чистая выдумка (синтетика)

Какой класс должен обеспечить реализацию high cohesion/low coupling, если шаблон expert не подходит ?

Присвойте обязанности искусственному классу, не представляющему конкретного понятия предметной области!

Итоги GRASP

  • Предпочтение "простым" классам, экспертам своей ответственности
  • При усложнении определенная функциональность или связь с другими классами выносится в отдельную структуру
  • Точки изменения защищаются с помощью абстрактных (полиморфных) операций (необходимо оценивать вероятность возможных модификаций) 
  • Для конкретной решения задачи можно "синтезировать" класс, отсутствующий в предметной области (например, Контроллер)

Общие итоги SOLID и GRASP

Общие итоги SOLID и GRASP

Цель программной инженерии - построения ПО высокого качества.

Внешние факторы понятны пользователям (корректность, простота использования, эффективность, своевременность и др.)

 Для разработчика так же важны внутренние факторы качества, которые делают ПО простым для понимания, модификации, документирования, поддержки и рефакторинга.

Библиография

1. Крэг Ларман. Применение UML 2.0 и шаблонов проектирования (ozon.ru)

3. GRASP на youtube

1. Крэг Ларман. Применение UML 2.0 и шаблонов проектирования (ozon.ru)

GRASP

By Сибирские интеграционные системы