SOLID – принципы объектно-ориентированного дизайна

Post on 22-Apr-2015

1.783 views 0 download

description

SOLID – принципы объектно-ориентированного дизайна

Transcript of SOLID – принципы объектно-ориентированного дизайна

SOLID – принципы объектно-ориентированного дизайна

О чем мы сегодня поговорим

Что такое «плохой» дизайн кода в чем он выражается какие несет проблемы

Принципы проектирования SOLID Назначение Примеры использования

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

Что такое «плохой» дизайн кода?

Что такое «плохой» дизайн кода?

Повторение Отсутствие возможности

повторного использования кода Монолитность Плохая читаемость кода Неоправданная сложность Вязкость Хрупкость

Откуда берется «плохой» дизайн?

Откуда берется «плохой» дизайн?

Внесение изменений в систему, которая проектировалась без учета возможности появления таковых

Изменения в системе могут потребоваться на любой стадии проекта: Аналитика Разработка Сопровождение

Изменения в системе неизбежны

Отсутствие формализированных требований со стороны клиента

Уточнение требований на этапе разработки, после утверждения ТЗ

Реализация дополнительного функционала на этапе технического сопровождения системы

Изменения в системе неизбежны

Мы должны помнить об этом

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

Перечислим основные проблемы «плохого» дизайна

Дубликаты структур, которые должны иметь

общую абстракцию.

Повторение

Сложно выделить компоненты, которые можно использовать

повторно

Отсутствие возможности повторного использования

Монолитность

Систему сложно изменять

Код сложно понимать

Неоправданная сложность

В системе есть инфраструктура, которая или не используется, или используется неправильно

Вязкость

Делать что-то правильно сложнее, чем делать это неправильно

Изменения легко ломают систему и приводят к

новым изменениям

Хрупкость

Может получится как в комиксе – «Читая чужой код»

Решение есть

Single Responsibility

Open/Closed

Liskov Substitution

Interface Segregation

Dependency Inversion

Что это такое?

SOLID - это аббревиатура пяти основных принципов дизайна классов в объектно-ориентированном проектировании

Когда появились?

Были сформулированы Робертом Мартином в далеком 1995 году

Single Responsibility

Single Responsibility

У класса есть только одна ответственность, он умеет ее делать и делает ее хорошо.

Не должно быть больше одной причины для изменения класса.

Single Responsibility

Пример приложения «Прямоугольник»:

Требования:Расчет площади прямоугольникаВывод изображения прямоугольника на UI

Single Responsibility

Single Responsibility

Single Responsibility

Пример приложения «Модем»:

Требования:Установка соединения по телефонному номеруЗавершение соединенияОтправка данныхПрием данных

Single Responsibility

Single Responsibility

Single Responsibility

У класса есть только одна ответственность, он умеет ее делать и делает ее хорошо.

Не должно быть больше одной причины для изменения класса.

Open/Closed

Open/Closed

Программные сущности (классы, модули, методы и т.д.) должны

быть открыты для расширения, но закрыты от изменений

Open/Closed

Как этого добиться?

Open/Closed

Классы должны зависеть от абстракций

Новые фичи могут быть добавлены путем реализации абстракций

Open/Closed

Использование паттернов Стратегия Шаблонный метод

Open/Closed

Приложение «Почтовый клиент»

Требования:

Отправка почтыЗапись результатов работы в файл

Open/Closed

Open/Closed

Open/Closed

Приложение «Почтовый клиент»

Новое требование:

Запись результатов работы на диск

Open/Closed

Open/Closed

Open/Closed

Паттерн Стратегия

Open/Closed

Open/Closed

Open/Closed

Open/Closed

Паттерн Шаблонный метод

Open/Closed

Задача:

Разработать класс, реализующий шифрование данных при помощи алгоритмов DES и RSA

Open/Closed

Open/Closed

Open/Closed

Open/Closed

Программные сущности (классы, модули, методы и т.д.) должны

быть открыты для расширения, но закрыты от изменений

Liskov Substitution

Liskov Substitution

Пусть q(x) является свойством, верным относительно

объектов x некоторого типа T.

Тогда q(y) также должно быть верным для объектов y типа S,

где S является подтипом типа T.

Liskov Substitution

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

Liskov Substitution

ЗадачаМы хотим реализовать свой список с интерфейсом IList<T>. Его особенностью будет то, что все записи в нем дублируются.

Данная реализация не представляет никакой опасности, если рассматривать ее изолированно.

Liskov SubstitutionВзглянем на использование этого класса с точки зрения клиента.

Клиент, абстрагируясь от реализаций, пытается работать со всеми объектами типа IList одинаково:

Liskov Substitution

Поведение списка DoubleList отличается от типичных реализаций IList. Получается, что наш DoubleList не может быть заменен базовым типом. Это и есть нарушение принципа замещения Лисков.

Проблема заключается в том, что теперь клиенту необходимо знать о конкретном типе объекта, реализующем интерфейс IList. В качестве такого объекта могут передать и DoubleList, а для него придется выполнять дополнительную логику и проверки.

Liskov Substitution

РешениеПравильным решением будет использовать свой собственный интерфейс, например, IDoubleList.

Этот интерфейс будет объявлять для пользователей поведение, при котором добавляемые элементы удваиваются.

Liskov Substitution

Проектирование по контракту

Liskov Substitution

Предусловия не могут быть ужесточены в наследнике

Постусловия не могут быть ослаблены в наследнике

Инварианты базового типа должны соблюдаться и в наследнике

Liskov Substitution

Рассмотрим пред и постусловия для интерфейса IList. Для функции Add:•предусловие: item != null•постусловие: count = oldCount + 1

Для нашего DoubleList и его функции Add:•предусловие: item != null•постусловие: count = oldCount + 2

Liskov Substitution

Interface Segregation

Interface Segregation

Клиентам не должны навязываться интерфейсы, которые им не нужны

Interface Segregation

Interface Segregation

Interface Segregation

Много небольших интерфейсов лучше чем один большой

Dependency Inversion

Dependency Inversion

Зависимости внутри системы строятся на основе абстракций.

Модули верхнего уровня не зависят от модулей нижнего уровня.

Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.

Dependency Inversion

Приложение «Печатная машинка»

Приложение должно уметь: Читать текст с клавиатуры Выводить текст на печать на

принтер

Dependency Inversion

Dependency Inversion

Dependency Inversion

Приложение «Печатная машинка»

Появилось новое требование Приложение должно уметь

сохранять текст на диск

Dependency Inversion

Dependency Inversion

Пример применения принципа DI

Dependency Inversion

Dependency Inversion

Dependency Inversion

Отсутствие инверсии зависимостей не всегда плохо.

Пример, зависимость от класса String.

Dependency Inversion

Зависимости внутри системы строятся на основе абстракций.

Модули верхнего уровня не зависят от модулей нижнего уровня.

Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.

Dependency Inversion

Поддержание кода в хорошей форме

Поддержание кода в хорошей форме

Проводить ревью кода

Находить «запахи» кода

Использовать статические анализаторы кода

Code smells

Static program analysis

Code Static analyze system

Code Static analyze system

YAGNI & KISS

You Aren’t Gonne Need It

Keep It Simple Stupid

О чем мы сегодня поговорили

Что такое плохой дизайн и откуда он берется

Как использовать принципы SOLID для улучшения дизайна

Как поддерживать код в хорошем состоянии

Использованные материалы

Материалы xpinjection.com - http://xpinjection.com/resources/ Блог Александра Бындю - http://blog.byndyu.ru/ Книга «Принципы, паттерны и методики гибкой разработки

на языке C#» - http://www.ozon.ru/context/detail/id/5800704/ Книга «Инфраструктура программных проектов. Соглашения,

идиомы и шаблоны для многократно используемых библиотек .NET» - http://www.ozon.ru/context/detail/id/5588868/

Контакты

Трёшников Павел Ведущий разработчик СМС-ИТ

▪ www.sms-automation.ru

e-mail: treshnikov@gmail.com twitter: @treshnikov