Тетерятников Алексей
Романенко Константин
Серия докладов
Время | Веха | Имена |
---|---|---|
середина 1980-х | шаблоны программирования | Кент Бек, Уорд Каннингем |
1988-1994 | шаблоны "Банды четырех" (GoF) | Эрих Гамма Ричард Хелм Ральф Джонсон Джон Влиссидес [ozon.ru] |
Время | Веха | Имена |
---|---|---|
1997 | принципы и шаблоны GRASP | Крэг Ларман [ozon.ru] |
2002 | принципы SOLID |
Роберт Мартин |
1970-е разработчик APL, Lisp, Smalltalk
1997 принципы GRASP
2005 соавтор большого масштабируемого Scrum (Large-Scale Scrum)
Консультант и автор в области разработки ПО
Автор известных книг:
Автор известных книг:
Принцип проектирования – это методологическое правило, которое выражает общий взгляд на разработку ПО.
Принцип проектирования – это методологическое правило, которое выражает общий взгляд на разработку ПО.
Хороший принцип является одновременно:
Абстрактным -
принцип должен описывать универсальное правило, а не конкретную практику.
Опровергаемым -
у разумного человека должна быть возможность не согласиться с принципом.
1. Декомпозиция на ответственности
Уход за котом
Задаемся вопросом:
"что делает класс?"
1. Декомпозиция на ответственности
Описывается порядок ухода за котом -
ответственность одна?
Задаемся вопросом:
"что делает класс?"
Уход за котом
2. Причина для изменений должна быть только одна
Уход за котом
2. Причина для изменений должна быть только одна
Наполнить миску
Приготовить
Проверить запасы
Помыть
Расчесать
{
Светить лазером
Бросать мяч
}
{
{
}
}
Уход за котом
3. Изменяемые вместе элементы должны быть рядом
Кормить
Процедуры
Развлекать
Помыть
Расчесать
Уход за котом
Светить лазером
Бросать мяч
Наполнить миску
Приготовить
Проверить запасы
Что должно храниться в одном классе?
Изменения одного элемента обязательно приведет к изменению других
Кормить
Наполнить миску
Приготовить
Проверить запасы
Что должно храниться в одном классе?
Изменения одного элемента обязательно приведет к изменению других
Кормить
Наполнить миску
Приготовить
Проверить запасы
Нет причин изменять элемент отдельно
Что должно храниться в одном классе?
Изменения одного элемента обязательно приведет к изменению других
Класс имеет высокую связанность
Кормить
Наполнить миску
Приготовить
Проверить запасы
Нет причин изменять элемент отдельно
1. Код разбивается на мелкие модули;
2. Четкое понимание, что делает модуль;
3. При совместной разработке упрощает процесс слияния кода.
Поступают новые требования
Поступают новые требования
Базовый кот из программы
"уход за котом"
Шкаф
Подними кота на шкаф
Подклей угол шкафа (он его сгрыз)
Жди пока кот выспится
Базовый Кот
Спальня
Спать()
Базовый кот из программы
"уход за котом"
Шкаф
Подними кота на шкаф
Подклей угол шкафа (он его сгрыз)
Жди пока кот выспится
Базовый Кот
Спальня
Спать()
Ошибки в наследовании
Ошибки в наследовании
Невозможно установить правильность модели, рассматриваемой изолированно
Предусловия
Постусловия
Программирование по контракту
Предусловия
Постусловия
Программирование по контракту
Кот:
Рост: <50 см;
Пушистый;
Вес: <20 кг.
Предусловия
Постусловия
Программирование по контракту
Кот полон энергии
Базовый Кот
Спальня
Спать()
Кот:
Рост: <50 см;
Пушистый;
Вес: <20 кг.
Программирование по контракту
Правило для производных классов:
1. Согласует поведение базового и производного класса;
2. Гарантирует корректность работы ПО при замене базового класса производным.
Клиенты не должны вынужденно зависеть от методов, которыми не пользуются
Интерфейс кота
Имя
Жирные интерфесы
Уход за котом
Жирные интерфесы
Выставка котов
Уход за котом
+
Интерфейс кота
Титул
Имя
Назначить титул (v)
Жирные интерфесы
Выставка котов
Ветеринарная клиника
Уход за котом
Интерфейс кота
История болезней
Титул
Имя
Назначить титул (v)
Внести болезнь (v)
+
+
Разделение интерфейса в зависимости от клиентов
Выставка котов
Ветеринарная клиника
Уход за котом
Интерфейс кота
Имя
Интерфейс болеющего
Имя
История болезней
Внести болезнь (v)
Интерфейс Конкурсанта
Имя
Титул
Назначить титул (v)
1. Код разбивается на мелкие модули;
2. уменьшает связанность между классом и его клиентом (low coupling).
1. Модули верхнего уровня не должны зависеть от модулей нижнего уровня. И те и другие должны зависеть от абстракций.
2. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.
Коробка
Спальня кота
Постели подушку на дно
Подклей коробку (он её сгрыз)
Жди пока кот выспится
Базовый Кот
Спальня
Спать()
Коробка
Шкаф
Постели подушку на дно
Подклей коробку (он её сгрыз)
Жди пока кот выспится
Подними кота на шкаф
Подклей угол шкафа (он его сгрыз)
Жди пока кот выспится
Спальня кота
Базовый Кот
Спальня
Спать()
Абстрактное спальное место
Шкаф
Домик для кота
Коробка
Спальня кота
Подготовка
Восстановление
Жди пока кот выспится
Базовый Кот
Спальня
Спать()
1. Контроль над зависимостями в исходном коде;
2. Позволяет сделать модули автономными, переиспользуемыми;
Программные сущности должны быть:
Разделять модули, которые изменяются по разным причинам
SRP
Как достигается?
DIP
+
Выстраивать зависимости таким образом, чтобы не было зависимостей от наиболее изменяемых модулей
Абстрактное спальное место
Шкаф
Домик для кота
Коробка
Спальня кота
Подготовка
Восстановление
Жди пока кот выспится
Базовый Кот
Спальня
Спать()
Примеры OCP в СИС
Новое поведение импорта / экспорта задается добавлением нового наследника ConfigItem
Реорганизация представлений
Примеры OCP в СИС
Принципы нацелены на создание структур, которые:
GRASP: классификация шаблонов по Ларману
GRASP: классификация доклада
GRASP: классификация доклада
GRASP: high cohesion / low coupling
Cohesion - Связность (Сцепленность)
the act or state of sticking together tightly
Coupling - Зацепление (Связывание, Сопряжение)
the act of bringing ... together
GRASP: low coupling
Как добиться незначительного влияния изменений и возможности повторного использования ?
Минимизировать количество данных о других элементах!
GRASP: low coupling
Катавасия
датаРождения: DateTime
кличка: String
ночноеЗрение: NightVision
GRASP: low coupling
Катавасия
void питаться()
void спать()
Мышь найтиМышь()
...
GRASP: low coupling
Катавасия
void питаться()
void спать()
...
GRASP: low coupling
GRASP: high cohesion
Как обеспечить сфокусированность обязанностей объектов, их управляемость и ясность?
Сфокусируйтесь на обязанностях класса!
GRASP: high cohesion
Связный (сцепленный класс)
Менее связный (несцепленный класс)
приватное свойство или метод
публичное свойство или метод
GRASP: high cohesion / low coupling
Максимизируйте сфокусированность
Минимизируйте зависимости
приватное свойство или метод
публичное свойство или метод
GRASP: protected variations
Как спроектировать систему, чтобы изменение элементов не оказывало нежелательного влияния на другие элементы?
Распределите обязанности, чтобы обеспечить устойчивый интерфейс!
GRASP: protected variations
Точка эволюции - предполагаемая точка ветвления, которая может возникнуть в будущем
Точка вариации - точка ветвления в существующей на данный момент системе
GRASP: polymorphism
Как обрабатывать альтернативные варианты поведения на основе типа?
Для однотипных классов используйте полиморфные операции!
GRASP: шаблон-роль information expert
Каков базовый принцип распределения обязанностей?
Назначьте обязанность тому классу, который обладает достаточной информацией для ее выполнения!
GRASP: шаблон-роль information expert
GRASP: шаблон-роль creator
Какой класс должен отвечать за создание нового экземпляра некоторого класса?
Смотри дальше!
GRASP: шаблон-роль creator
Например, при разработке набора настольных игр, объект класса Board включает в себя 0..n
объектов класса Square
GRASP: шаблон-роль controller
Какой класс должен отвечать координацию выполнения системных операций, поступающих
на уровне UI?
не переключайся!
GRASP: шаблон-роль controller
(Внешний контроллер)
Калькулятор пенсии
Контроллер
Веб-сервис
GRASP: шаблон-роль controller
LadyHandler
MilitaryHandler
ПрецедентHandler
Калькулятор пенсии
Веб-сервис
GRASP: шаблон-роль indirection
Как распределить обязанности, чтобы снизить уровень зацепления несвязанных напрямую классов?
Присвойте обязанности промежуточному объекту, который перенаправляет связи!
GRASP: шаблон-роль indirection
Адаптер расчета пенсии
ПрецедентHandler
Калькулятор пенсии
GRASP: шаблон-роль pure fabrication
Какой класс должен обеспечить реализацию high cohesion/low coupling, если шаблон expert не подходит ?
Присвойте обязанности искусственному классу, не представляющему конкретного понятия предметной области!
Цель программной инженерии - построения ПО высокого качества.
Качество ПО лучше всего видится как компромисс между целым рядом различных целей, а не как единый фактор
Действительное значение имеют внешние факторы, понятные пользователям (корректность, простота использования, эффективность, своевременность и др.)
Принципы SOLID и GRASP направлены на улучшение качества внутренних факторов, и только через внутренние факторы возможно управление системой.
(по мотивам книг Бертрана Майер)
Библиография
Крэг Ларман. Применение UML 2.0 и шаблонов проектирования (ozon.ru)
Гамма Эрих, Влиссидес Джон, Хелм Ричард, Джонсон Р. Приемы объектно-ориентированного проектирования. Паттерны проектирования (ozon.ru)
Кристофер Александер. Язык шаблонов. Города. Здания. Строительство (ozon.ru)
Блог С. Теплякова (http://sergeyteplyakov.blogspot.com)
SOLID
Р. Мартин "Принципы, паттерны и методики гибкой разработки на языке C#"
Р. Мартин "Чистая архитектура. Искусство разработки программного обеспечения"
Р. Мартин "Чистый код: создание, анализ и рефакторинг"
GRASP
Kent Beck, Ward Cunningham Using Pattern Languages for Object-Oriented Programs