SOLID Principles in the real world
-
Upload
epam-systems -
Category
Software
-
view
372 -
download
0
description
Transcript of SOLID Principles in the real world
![Page 1: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/1.jpg)
О принципах проектирования
Сергей Тепляков
![Page 2: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/2.jpg)
Обо мне
• Microsoft C# MVP 2011-2014
• MSFT Employee 2014- (VS Team)
• Blogger: SergeyTeplyakov.blogspot.com
• Контакты
• Sergey.Teplyakov [sobak] gmail.com
• @STeplyakov
![Page 3: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/3.jpg)
О чем будем говорить?
• О принципах проектирования в целом
• О SOLID принципах
![Page 4: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/4.jpg)
Нужны ли нам принципы проектирования?
![Page 5: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/5.jpg)
Дизайн – штука сложная!
![Page 6: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/6.jpg)
Поиск серебряной пули
• Ответ на вопрос жизни вселенной и всего такого?
![Page 7: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/7.jpg)
Мы хотим использовать опыт и знания повторно!
![Page 8: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/8.jpg)
Классические подходы
• Low coupling
• High cohesion
• Design by Contract
![Page 9: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/9.jpg)
SOLID принципы
• S – Single Responsibility Principle
• O – Open-Closed Principle
• L – Liskov Substitution Principle
• I – Interface Segregation Principle
• D – Dependency Inversion Principle
![Page 10: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/10.jpg)
Опасности принципов
• Что «сильнее» композиция или наследование?
• Остерегайтесь культа карго
![Page 11: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/11.jpg)
В чем проблема с текущим описанием?
• Принципы слишком неформальны
• Берут свое начало в 90-х (С++)
• Не ясно, когда им следовать, а когда - нет
![Page 12: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/12.jpg)
Как следовать этим принципам?
Принципы существуют для того, чтобы помогать в устранении дурных запахов в дизайне. Это не духи, которыми надо обильно поливать всю систему. Чрезмерная приверженность принципам ведет к пороку ненужной сложности.
![Page 13: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/13.jpg)
Single Responsibility Principle
• Исходное определение: У класса должна быть только одна причина для изменения
• Смысл принципа SRP: Борьба со сложностью
• SRP violation means low cohesion!
http://bit.ly/SingleResponsibilityPrinciple
![Page 14: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/14.jpg)
Любой класс из реального мира будет нарушать SRP
![Page 15: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/15.jpg)
Типичные примеры нарушения SRP
![Page 16: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/16.jpg)
Смешивание логики и инфраструктуры
• Windows сервис ходит в базу
• WCF-сервис сам содержит логику обработки запросов
• Azure Role содержит логику по перекладыванию данных из одного места в другое.
• Смешивание логики и «сохраняемости» (persistence)
![Page 17: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/17.jpg)
Смешивание логики и представления
![Page 18: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/18.jpg)
Выделяйте каждому сложному аспекту системы свой класс/модуль
![Page 19: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/19.jpg)
Я хочу иметь возможность сосредоточиться на сложных аспектах системы по отдельности, поэтому когда мне становится сложно это делать, я начинаю разбивать классы и выделять новые.
![Page 20: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/20.jpg)
Дизайн – это эволюционный процесс
![Page 21: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/21.jpg)
Актуальность SRP возрастает вместе с увеличением сложности!
![Page 22: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/22.jpg)
Пример увеличения сложности: добавление предусловий
![Page 23: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/23.jpg)
Интерфейс ContextActionBase
public abstract class ContextActionBase{ public abstract void Execute(); public abstract bool IsAvailable(); public abstract string Text { get; }}
![Page 24: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/24.jpg)
![Page 25: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/25.jpg)
Эволюция дизайна
![Page 26: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/26.jpg)
SRP – это способ поиска скрытых абстракций, достаточно сложных, чтобы им отвели отдельную именованную сущность и спрятали в их недрах все детали.
![Page 27: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/27.jpg)
Open-Closed Principle
Классы, модули, функции и т.п.) должны быть открытыми для расширения, но
закрытыми для модификации
http://bit.ly/OpenClosedPrinciple
![Page 28: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/28.jpg)
Как вы понимаете OCP?
![Page 29: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/29.jpg)
Объяснение Боба Мартина
• Они открыты для расширения. Это означает, что поведение модуля можно расширить. Когда требования к приложению изменяются, мы добавляем в модуль новое поведение, отвечающее изменившимся требованиям. Иными словами, мы можем изменить состав функций модуля.
• Они закрыты для модификации. Расширение поведения модуля не сопряжено с изменениями в исходном или двоичном коде модуля. Двоичное исполняемое представление модуля, будь то компонуемая библиотека, DLL или EXE-файл, остается неизменным (выделено мною).
![Page 30: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/30.jpg)
Нарушает ли фабрика OCP?abstract class Importer{ public abstract void ImportData();}
static class ImporterFactory{ public static Importer Create(string fileName) { var extension = Path.GetExtension(fileName); switch (extension) { case "json": return new JsonImporter(); case "xls": case "xlsx": return new XlsImporter(); default: throw new InvalidOperationException("Extension is not supported"); } }}
![Page 31: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/31.jpg)
Принцип единственного выбора
Всякий раз, когда система программного обеспечения должна поддерживать множество альтернатив, их полный список должен быть известен только одному модулю системы.
Бербран Мейер
![Page 32: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/32.jpg)
OCP != Расширяемость
![Page 33: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/33.jpg)
Определение от Бертрана Мейера
• Модуль называют открытым, если он еще доступен для расширения. Например, имеется возможность расширить множество операций в нем или добавить поля к его структурам данных.
• Модуль называют закрытым, если он доступен для использования другими модулями. Это означает, что модуль (его интерфейс – с точки зрения скрытия информации) уже имеет строго определенное окончательное описание. На уровне реализации закрытое состояние модуля означает, что модуль можно компилировать, сохранять в библиотеке и делать его доступным для использования другими модулями (его клиентами).
![Page 34: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/34.jpg)
Open-Closed Principle
• Что такое OCP? Это фиксация интерфейса класса/модуля, и возможность изменения или подмены реализации/поведения.
• Цели OCP: борьба со сложностью и ограничение изменений минимальным числом модулей.
• Как мы реализуем OCP? С помощью инкапсуляции, которая позволяет изменять реализацию без изменения интерфейса и с помощью наследования, что позволяет заменить реализацию, которая не затронет существующих клиентов базового класса.
![Page 35: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/35.jpg)
Типичный пример нарушения расширяемости (OCP)
public static int Count<TSource>(this IEnumerable<TSource> source){ var collectionoft = source as ICollection<TSource>; if (collectionoft != null) return collectionoft.Count;
var collection = source as ICollection; if (collection != null) return collection.Count;
int count = 0; using (IEnumerator<TSource> e = source.GetEnumerator()) { while (e.MoveNext()) count++; }
return count;}
![Page 36: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/36.jpg)
Расширяемость: OOP vs. FP
• В ООП: легко добавлять новый тип, сложно – новую операцию
• В ФП: легко добавлять новую операцию, сложно – новый тип
Expression Problem!
![Page 37: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/37.jpg)
Расширяемость в ООП
![Page 38: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/38.jpg)
Иногда мы хотим вынести логику за пределы иерархии!
Решение: Посетитель!
![Page 39: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/39.jpg)
Пример
![Page 40: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/40.jpg)
public interface IValidationResultVisitor{ void Visit(NoErrorValidationResult vr); void Visit(ContractErrorValidationResult vr); void Visit(ContractWarningValidationResult vr); void Visit(CustomWarningValidationResult vr);}
public abstract class ValidationResult{ private ICSharpStatement _statement;
protected ValidationResult(ICSharpStatement statement) { Contract.Requires(statement != null); _statement = statement; }
public abstract void Accept(IValidationResultVisitor visitor);}
![Page 41: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/41.jpg)
class IsIssueFixableVisitor : IValidationResultVisitor{ public bool IsIssueFixable { get; private set; } public void Visit(NoErrorValidationResult vr) { IsIssueFixable = false; }
public void Visit(ContractErrorValidationResult vr) { IsIssueFixable = vr.Error == MalformedContractError.VoidReturnMethodCall; }
public void Visit(ContractWarningValidationResult vr) { IsIssueFixable = vr.Warning == MalformedContractWarning.NonVoidReturnMethodCall; }
public void Visit(CustomWarningValidationResult vr) { IsIssueFixable = false; }}
![Page 42: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/42.jpg)
ФП подход: сопоставление с образцомpublic T Match<T>(
Func<CodeContractErrorValidationResult, T> errorMatch, Func<CodeContractWarningValidationResult, T> warningMatch, Func<ValidationResult, T> defaultMatch){ var errorResult = this as CodeContractErrorValidationResult; if (errorResult != null) return errorMatch(errorResult);
var warningResult = this as CodeContractWarningValidationResult; if (warningResult != null) return warningMatch(warningResult);
return defaultMatch(this);}
![Page 43: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/43.jpg)
Пример использования
ValidationResult vr = GetValidationResult();bool isFixable = vr.Match( error => error.Error == MalformedContractError.VoidReturnMethodCall, warning => warning.Warning == MalformedContractWarning.NonVoidReturnMethodCall, @default => false);
![Page 44: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/44.jpg)
Как пользуюсь принципами?
• Принципы – не самоцель!
• Дизайн постоянно эволюционирует. Валидируйте его согласно этим принципам на каждой итерации.
![Page 45: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/45.jpg)
Цикл постов о SOLID-принципах
• http://bit.ly/SingleResponsibilityPrinciple
• http://bit.ly/OpenClosedPrinciple
• http://bit.ly/LiskovSubstitutionPrinciple
• http://bit.ly/InterfaceSegregationPrinciple
• http://bit.ly/DependencyInversionPrinciple
![Page 46: SOLID Principles in the real world](https://reader035.fdocuments.us/reader035/viewer/2022081504/557cf856d8b42a071b8b49f4/html5/thumbnails/46.jpg)
Чего почитать по теме• О культе карго в программировании
sergeyteplyakov.blogspot.com/2013/09/blog-post_24.html
• Критика книги Боба Мартина «Принципы, паттерны и методики гибкой разработки на языке C#»sergeyteplyakov.blogspot.com/2013/12/about-agile-principles-patterns-and.html
• Цикл постов об управлении зависимостямиhttp://sergeyteplyakov.blogspot.com/2013/10/articles.html#dependency_management
• Лучшая книга по ООП эвар! – Бертран Мейер «Объектно-ориентированное конструирование программных систем»http://sergeyteplyakov.blogspot.com/2012/03/blog-post_19.html