SlideShare uma empresa Scribd logo
1 de 39
Александр Кондуфоров
AltexSoft
План
 разные подходы к внутреннему качеству приложения
 чем вреден малокачественный код
 нарастание энтропии и сложности
 технический долг
 шаблоны и принципы проектирования
 описание некоторых принципов проектирования
Клиент
Разработчики
Процесс разработки
С точки зрения клиента:
?
 расширение приложения
 исправление ошибок
 написание тестов
Момент истины
 больше времени
 больше ошибок
 иногда очень сложно
 плохое внутреннее
качество
 плохое внешнее
качество
Project timeline
Нарастание энтропии
 разные люди пишут код
 растет размер приложения
 растет связность между модулями, классами
Технический долг
% %
%
Тело кредита
 увеличение времени на
изменения
 рост количества ошибок
 черновая разработка
 отсутствие
проектирования
 рефакторинг
 улучшение качества
дизайна и кода
Вывод: лучше в долги не влезать, но иногда это необходимо
Свойства качественного кода
 расширяемость, гибкость (extensibility, agility)
 сопровождаемость (maintainability)
 простота (simplicity)
 читабельность, понятность (readability, clarity)
 тестируемость (testability)
Теперь понятно, что качественный код – это не просто какой-то
абстрактный «красивый» код, а код, которые обладает полезными
внутренними свойствами.
Как писать качественный код
Чем руководствоваться?
 здравый смысл, опыт
 паттерны проектирования
 принципы проектирования
 правила рефакторинга
 модульные тесты
Когда нужно рефакторить?
 анти-паттерны проектирования
 code smell
 костыли
 большие временные затраты на
изменения
Практики:
 парное программирование
 code review
 рефакторинг
 модульные тесты и TDD/BDD
Иерархия. Принципы и паттерны
Общие принципы проектирования
SoC: Separation of Concerns
Разделение системы на отдельные части (модули, звенья, слои,
классы), которые будут как можно меньше связаны между собой.
Достигается за счет:
 разделение на звенья (tiers)
 разделение на слои (layers)
 модульность
 разделение на классы
 инкапсуляция
DRY: Don’t Repeat Yourself
Каждая единица знания должна иметь единственное, однозначное,
официальное представление в системе.
Свойства:
 снижает затраты на поддержку/развитие/изменение.
 относится не только к дублированию кода, но и к дублированию
других абстракций системы
Достигается за счет:
 отсутствие copy-paste
 повторное использование кода
 кодогенерация, AOP
Low Coupling
Coupling (связанность) – мера, определяющая, насколько жестко
один элемент связан с другими элементами, или каким
количеством данных о других элементах он обладает.
Достигается за счет:
 однонаправленные связи
 зависимость от интерфейсов
 don‘t talk to the strangers
High Cohesion
Cohesion (сцепленность) – мера, определяющая связанность и
сфокусированность обязанностей/ответственности элемента.
Достигается за счет:
 сужение обязанностей элемента
 разделение ответственности между несколькими элементами
 группирование похожей ответственности в одном элементе
KISS: Keep It Simple and Stupid
Простота системы является основной целью и ценностью.
Связаны:
 Бритва Оккама: «Не следует плодить новые сущности без самой
крайней на то необходимости» или «Объяснение, требующее
наименьших допущений, с большей вероятностью является
правильным»
 Эйнштейн: «Все должно быть предельно просто, но не проще»
Достигается за счет:
 прагматичный подход к проектированию
 чувство меры, опыт
YAGNI: You Ain’t Gonna Need It
Не нужно добавлять функциональность пока в ней нет
непосредственной нужды.
Вытекает:
 предварительная оптимизация вредна
Достигается за счет:
 «ленивый» подход к проектированию
Минус: новый функционал может занимать много времени
Важно быть прагматиком и учитывать будущие требования!
Принципы объектно-ориентированного
проектирования
SRP: Single Responsibility Principle
1. Не должно быть больше одной причины для изменения класса.
2. Каждый класс должен быть сфокусирован на своей области
ответственности.
Цель:
 упростить внесение изменений
 защититься от побочных эффектов при изменениях
 Separation of Concerns на уровне классов
Достигается за счет:
 правильное проектирование
 использование паттернов проектирования
SRP: Single Responsibility Principle
SRP: неправильный вариант
public class Account
{
public string Number;
public decimal CurrentBalance;
public void Deposit(decimal amount) { ... }
public void Withdraw(decimal amount) { ... }
public void Transfer(decimal amount, Account recipient) { ... }
public TaxTable CalculateTaxes(int year) { ... }
public void GetByNumber(string number) { ... }
public void Save() { ... }
}
(с) Igor Tamaschuk
SRP: правильный вариант
public class Account
{
public string Number;
public decimal CurrentBalance;
public void Deposit(decimal amount) { ... }
public void Withdraw(decimal amount) { ... }
public void Transfer(decimal amount, Account recipient) { ... }
}
public class AccountRepository
{
public Account GetByNumber(string number) { ... }
public void Save(Account account) { ... }
}
public class TaxCalculator
{
public TaxTable CalculateTaxes(int year) { ... }
}
OCP: Open-Closed Principle
Программные сущности (модули, классы, методы) должны быть
открыты для расширения, но закрыты для изменения.
Цель:
 добиться гибкости системы
 избежать сильных переработок дизайна при изменениях
Достигается за счет:
 правильное наследование
 инкапсуляция
OCP: неправильный вариант
public class SmtpMailer
{
private readonly Logger logger;
public SmtpMailer()
{
logger = new Logger();
}
public void SendMessage(string message)
{
// отправить сообщение
logger.Log(message);
}
}
(с) Alexander Byndyu
Изменение: нужно писать лог в
базу данных
public class DatabaseLogger
{
public void Log(string logText)
{
// сохранить лог в базе данных
}
}
public class SmtpMailer
{
private readonly DatabaseLogger logger;
public SmtpMailer()
{
logger = new DatabaseLogger();
}
public void SendMessage(string message)
{
// отправить сообщение
logger.Log(message);
}
}
OCP: правильный вариант
public class SmtpMailer
{
private readonly ILogger logger;
public SmtpMailer(ILogger logger)
{
this.logger = logger;
}
public void SendMessage(string message)
{
// отправить сообщение
logger.Log(message);
}
}
LSP: Liskov Substitution Principle
1. Подтипы должны быть заменяемыми их исходными типами.
2. Наследники должны соблюдать контракт предка
Цель:
 избежать побочных эффектов и ошибок в существующем коде,
работающем с базовыми классами, при добавлении наследников
 строить правильные иерархии наследования
Достигается за счет:
 правильное наследование классов
LSP: Liskov Substitution Principle
LSP: неправильный вариант
class Rectangle {
public virtual int Width { get; set; }
public virtual int Height { get; set; }
public int CalculateArea() {
return Width * Height;
}
}
class Square : Rectangle {
public override int Height {
get { return base.Height; }
set { base.Height = value; base.Width = value; }
}
public override int Width {
get { return base.Width; }
set { base.Width = value; base.Height = value; }
}
}
class Program {
static void Main() {
Rectangle r = new Square();
r.Width = 3;
r.Height = 2;
Assert.AreEqual(6, r.CalculateArea());
}
} (с) Igor Tamaschuk
LSP: правильный вариант
class Rectangle : IFigure {
public virtual int Width { get; set; }
public virtual int Height { get; set; }
public int CalculateArea() {
return Width * Height;
}
}
class Square : IFigure {
public virtual int Side { get; set; }
public int CalculateArea() {
return Side * Side;
}
}
class Program {
static void Main() {
Rectangle r = new Square(); // fail on compilation
r.Width = 3;
r.Height = 2;
Assert.AreEqual(6, r.CalculateArea());
}
}
ISP: Interface Segregation Principle
1. Клиент не должен вынужденно зависеть от элементов
интерфейса, которые он не использует.
2. Зависимость между классами должна быть ограничена как
можно более «узким» интерфейсом.
Цель:
 ограничить знание одного класса о другом
 уменьшить зависимость между классами
 уменьшить количество методов для реализации при наследовании
Достигается за счет:
 фокусирование интерфейсов на своей ответственности
 наследование от нескольких интерфейсов, а не от одного
ISP: неправильный вариант
public interface IBird
{
void Eat();
void Sing();
void Fly();
}
public class Parrot : IBird
{
// здорово
}
public class Pigeon : IBird
{
// ну, я не очень хорошо пою, но ладно
}
public class Penguin : IBird
{
// хм... а я вообще птица?
}
ISP: правильный вариант
public interface ICommonBird
{
void Eat();
}
public interface ISingingBird
{
void Sing();
}
public interface IFlyingBird
{
void Fly();
}
public class Parrot : ICommonBird, ISingingBird, IFlyingBird
{
// хм, ничего не изменилось
}
public class Pigeon : ICommonBird, IFlyingBird
{
// о, так лучше, я могу не петь
}
public class Penguin : ICommonBird
{
// так намного лучше! хотя я еще и плавать могу 
}
IoC: Inversion of Control
DIP: Dependency Inversion Principle
1. Модули верхнего уровня не должны зависеть от модулей нижнего
уровня. Они должны зависеть от абстракции.
2. Абстракции не должны зависеть от деталей. Детали должны
зависеть от абстракций.
Цель:
 уменьшить связанность (coupling)
Связан:
 Hollywood principle: Don’t call us, we’ll call you
Достигается за счет:
 паттерны Dependency Injection, Service Locator
 зависимость от абстракций
 IoC frameworks
IoC, DIP: неправильный вариант
class Developer
{
public void WriteApplication()
{
IApplication helloWorld = new HelloWorldApp();
WriteCode(helloWorld);
}
private void WriteCode() { ... };
}
public interface IApplication
{
string GetCode();
}
public class HelloWorldApp : IApplication
{
// реализация
}
public class VeryBigApp : IApplication
{
// реализация
}
IoC, DIP: правильный вариант
class Developer
{
public void WriteApplication(IApplication app)
{
WriteCode(app);
}
private void WriteCode() { ... };
}
public static void Main()
{
Developer dev = new Developer();
IApplication app = new VeryBigApp(); // теперь мы умеем писать что угодно
dev.WriteApplication(app);
}
Это шаблон Dependency Injection (Method Injection), но можно
использовать и другие шаблоны (например, Service Locator), а
также IoC Frameworks
Самый важный принцип
It depends !
Спасибо за внимание!
Design Principles

Mais conteúdo relacionado

Semelhante a Design Principles

Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...
Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...
Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...OdessaFrontend
 
AOP and Design Patterns (GoF)
AOP and Design Patterns (GoF)AOP and Design Patterns (GoF)
AOP and Design Patterns (GoF)Andrey Gordienkov
 
Aspect Oriented Programming and Design Patterns
Aspect Oriented Programming and Design PatternsAspect Oriented Programming and Design Patterns
Aspect Oriented Programming and Design PatternsAndrey Gordienkov
 
О сложностях программирования, или C# нас не спасет?
О сложностях программирования, или C# нас не спасет?О сложностях программирования, или C# нас не спасет?
О сложностях программирования, или C# нас не спасет?Tatyanazaxarova
 
Поговорим о микрооптимизациях .NET-приложений
Поговорим о микрооптимизациях .NET-приложенийПоговорим о микрооптимизациях .NET-приложений
Поговорим о микрооптимизациях .NET-приложенийAndrey Akinshin
 
PostSharp - Threading Model Library
PostSharp - Threading Model LibraryPostSharp - Threading Model Library
PostSharp - Threading Model LibraryAndrey Gordienkov
 
GraphQL API: Patterns | Андрей Чиж | Zlit Tech
GraphQL API: Patterns | Андрей Чиж | Zlit TechGraphQL API: Patterns | Андрей Чиж | Zlit Tech
GraphQL API: Patterns | Андрей Чиж | Zlit TechZlit
 
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#Andrey Karpov
 
API design in java project
API design in java projectAPI design in java project
API design in java projectchashnikov
 
Фофанов Илья - Лучшие практики проектирования и реализации API на C#
Фофанов Илья - Лучшие практики проектирования и реализации API на C#Фофанов Илья - Лучшие практики проектирования и реализации API на C#
Фофанов Илья - Лучшие практики проектирования и реализации API на C#Elias Fofanov
 
C# Desktop. Занятие 16.
C# Desktop. Занятие 16.C# Desktop. Занятие 16.
C# Desktop. Занятие 16.Igor Shkulipa
 
Статический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий ЛевановСтатический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий ЛевановYandex
 
DI в C++ тонкости и нюансы
DI в C++ тонкости и нюансыDI в C++ тонкости и нюансы
DI в C++ тонкости и нюансыPlatonov Sergey
 
Yuri Trukhin - Software developement best practices
Yuri Trukhin - Software developement best practicesYuri Trukhin - Software developement best practices
Yuri Trukhin - Software developement best practicesbeloslab
 
Статический анализ кода: Что? Как? Зачем?
Статический анализ кода: Что? Как? Зачем?Статический анализ кода: Что? Как? Зачем?
Статический анализ кода: Что? Как? Зачем?Andrey Karpov
 
. Kotlin для Автоматизации тестирования – первые впечатления
. Kotlin для Автоматизации тестирования – первые впечатления. Kotlin для Автоматизации тестирования – первые впечатления
. Kotlin для Автоматизации тестирования – первые впечатленияCOMAQA.BY
 
Архитектура в Agile: слабая связность
Архитектура в Agile: слабая связностьАрхитектура в Agile: слабая связность
Архитектура в Agile: слабая связностьAndrey Bibichev
 

Semelhante a Design Principles (20)

Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...
Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...
Функциональное программирование с использованием библиотеки fp-ts | Odessa Fr...
 
AOP and Design Patterns (GoF)
AOP and Design Patterns (GoF)AOP and Design Patterns (GoF)
AOP and Design Patterns (GoF)
 
Aspect Oriented Programming and Design Patterns
Aspect Oriented Programming and Design PatternsAspect Oriented Programming and Design Patterns
Aspect Oriented Programming and Design Patterns
 
О сложностях программирования, или C# нас не спасет?
О сложностях программирования, или C# нас не спасет?О сложностях программирования, или C# нас не спасет?
О сложностях программирования, или C# нас не спасет?
 
UA Mobile 2012
UA Mobile 2012UA Mobile 2012
UA Mobile 2012
 
Поговорим о микрооптимизациях .NET-приложений
Поговорим о микрооптимизациях .NET-приложенийПоговорим о микрооптимизациях .NET-приложений
Поговорим о микрооптимизациях .NET-приложений
 
PostSharp - Threading Model
PostSharp - Threading ModelPostSharp - Threading Model
PostSharp - Threading Model
 
PostSharp - Threading Model Library
PostSharp - Threading Model LibraryPostSharp - Threading Model Library
PostSharp - Threading Model Library
 
Tdd php
Tdd phpTdd php
Tdd php
 
GraphQL API: Patterns | Андрей Чиж | Zlit Tech
GraphQL API: Patterns | Андрей Чиж | Zlit TechGraphQL API: Patterns | Андрей Чиж | Zlit Tech
GraphQL API: Patterns | Андрей Чиж | Zlit Tech
 
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
 
API design in java project
API design in java projectAPI design in java project
API design in java project
 
Фофанов Илья - Лучшие практики проектирования и реализации API на C#
Фофанов Илья - Лучшие практики проектирования и реализации API на C#Фофанов Илья - Лучшие практики проектирования и реализации API на C#
Фофанов Илья - Лучшие практики проектирования и реализации API на C#
 
C# Desktop. Занятие 16.
C# Desktop. Занятие 16.C# Desktop. Занятие 16.
C# Desktop. Занятие 16.
 
Статический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий ЛевановСтатический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий Леванов
 
DI в C++ тонкости и нюансы
DI в C++ тонкости и нюансыDI в C++ тонкости и нюансы
DI в C++ тонкости и нюансы
 
Yuri Trukhin - Software developement best practices
Yuri Trukhin - Software developement best practicesYuri Trukhin - Software developement best practices
Yuri Trukhin - Software developement best practices
 
Статический анализ кода: Что? Как? Зачем?
Статический анализ кода: Что? Как? Зачем?Статический анализ кода: Что? Как? Зачем?
Статический анализ кода: Что? Как? Зачем?
 
. Kotlin для Автоматизации тестирования – первые впечатления
. Kotlin для Автоматизации тестирования – первые впечатления. Kotlin для Автоматизации тестирования – первые впечатления
. Kotlin для Автоматизации тестирования – первые впечатления
 
Архитектура в Agile: слабая связность
Архитектура в Agile: слабая связностьАрхитектура в Agile: слабая связность
Архитектура в Agile: слабая связность
 

Mais de Alexander Konduforov

Recommender systems for E-commerce
Recommender systems for E-commerceRecommender systems for E-commerce
Recommender systems for E-commerceAlexander Konduforov
 
Machine Learning and Azure Machine Learning
Machine Learning and Azure Machine LearningMachine Learning and Azure Machine Learning
Machine Learning and Azure Machine LearningAlexander Konduforov
 
ИИ персонажей в онлайн шутере Survarium
ИИ персонажей в онлайн шутере SurvariumИИ персонажей в онлайн шутере Survarium
ИИ персонажей в онлайн шутере SurvariumAlexander Konduforov
 
Ling to SQL and Entity Framework performance analysis
Ling to SQL and Entity Framework performance analysisLing to SQL and Entity Framework performance analysis
Ling to SQL and Entity Framework performance analysisAlexander Konduforov
 

Mais de Alexander Konduforov (8)

Recommender systems for E-commerce
Recommender systems for E-commerceRecommender systems for E-commerce
Recommender systems for E-commerce
 
Fast data munging in R
Fast data munging in RFast data munging in R
Fast data munging in R
 
Machine Learning and Azure Machine Learning
Machine Learning and Azure Machine LearningMachine Learning and Azure Machine Learning
Machine Learning and Azure Machine Learning
 
ИИ персонажей в онлайн шутере Survarium
ИИ персонажей в онлайн шутере SurvariumИИ персонажей в онлайн шутере Survarium
ИИ персонажей в онлайн шутере Survarium
 
Real-time ASP.NET with SignalR
Real-time ASP.NET with SignalRReal-time ASP.NET with SignalR
Real-time ASP.NET with SignalR
 
New in Entity Framework 4.0
New in Entity Framework 4.0New in Entity Framework 4.0
New in Entity Framework 4.0
 
ASP.NET MVC: new era?
ASP.NET MVC: new era?ASP.NET MVC: new era?
ASP.NET MVC: new era?
 
Ling to SQL and Entity Framework performance analysis
Ling to SQL and Entity Framework performance analysisLing to SQL and Entity Framework performance analysis
Ling to SQL and Entity Framework performance analysis
 

Design Principles

  • 2. План  разные подходы к внутреннему качеству приложения  чем вреден малокачественный код  нарастание энтропии и сложности  технический долг  шаблоны и принципы проектирования  описание некоторых принципов проектирования
  • 4. С точки зрения клиента: ?
  • 5.  расширение приложения  исправление ошибок  написание тестов Момент истины  больше времени  больше ошибок  иногда очень сложно  плохое внутреннее качество  плохое внешнее качество
  • 6. Project timeline Нарастание энтропии  разные люди пишут код  растет размер приложения  растет связность между модулями, классами
  • 7. Технический долг % % % Тело кредита  увеличение времени на изменения  рост количества ошибок  черновая разработка  отсутствие проектирования  рефакторинг  улучшение качества дизайна и кода Вывод: лучше в долги не влезать, но иногда это необходимо
  • 8. Свойства качественного кода  расширяемость, гибкость (extensibility, agility)  сопровождаемость (maintainability)  простота (simplicity)  читабельность, понятность (readability, clarity)  тестируемость (testability) Теперь понятно, что качественный код – это не просто какой-то абстрактный «красивый» код, а код, которые обладает полезными внутренними свойствами.
  • 9. Как писать качественный код Чем руководствоваться?  здравый смысл, опыт  паттерны проектирования  принципы проектирования  правила рефакторинга  модульные тесты Когда нужно рефакторить?  анти-паттерны проектирования  code smell  костыли  большие временные затраты на изменения Практики:  парное программирование  code review  рефакторинг  модульные тесты и TDD/BDD
  • 12. SoC: Separation of Concerns Разделение системы на отдельные части (модули, звенья, слои, классы), которые будут как можно меньше связаны между собой. Достигается за счет:  разделение на звенья (tiers)  разделение на слои (layers)  модульность  разделение на классы  инкапсуляция
  • 13. DRY: Don’t Repeat Yourself Каждая единица знания должна иметь единственное, однозначное, официальное представление в системе. Свойства:  снижает затраты на поддержку/развитие/изменение.  относится не только к дублированию кода, но и к дублированию других абстракций системы Достигается за счет:  отсутствие copy-paste  повторное использование кода  кодогенерация, AOP
  • 14. Low Coupling Coupling (связанность) – мера, определяющая, насколько жестко один элемент связан с другими элементами, или каким количеством данных о других элементах он обладает. Достигается за счет:  однонаправленные связи  зависимость от интерфейсов  don‘t talk to the strangers
  • 15. High Cohesion Cohesion (сцепленность) – мера, определяющая связанность и сфокусированность обязанностей/ответственности элемента. Достигается за счет:  сужение обязанностей элемента  разделение ответственности между несколькими элементами  группирование похожей ответственности в одном элементе
  • 16. KISS: Keep It Simple and Stupid Простота системы является основной целью и ценностью. Связаны:  Бритва Оккама: «Не следует плодить новые сущности без самой крайней на то необходимости» или «Объяснение, требующее наименьших допущений, с большей вероятностью является правильным»  Эйнштейн: «Все должно быть предельно просто, но не проще» Достигается за счет:  прагматичный подход к проектированию  чувство меры, опыт
  • 17. YAGNI: You Ain’t Gonna Need It Не нужно добавлять функциональность пока в ней нет непосредственной нужды. Вытекает:  предварительная оптимизация вредна Достигается за счет:  «ленивый» подход к проектированию Минус: новый функционал может занимать много времени Важно быть прагматиком и учитывать будущие требования!
  • 19. SRP: Single Responsibility Principle 1. Не должно быть больше одной причины для изменения класса. 2. Каждый класс должен быть сфокусирован на своей области ответственности. Цель:  упростить внесение изменений  защититься от побочных эффектов при изменениях  Separation of Concerns на уровне классов Достигается за счет:  правильное проектирование  использование паттернов проектирования
  • 21. SRP: неправильный вариант public class Account { public string Number; public decimal CurrentBalance; public void Deposit(decimal amount) { ... } public void Withdraw(decimal amount) { ... } public void Transfer(decimal amount, Account recipient) { ... } public TaxTable CalculateTaxes(int year) { ... } public void GetByNumber(string number) { ... } public void Save() { ... } } (с) Igor Tamaschuk
  • 22. SRP: правильный вариант public class Account { public string Number; public decimal CurrentBalance; public void Deposit(decimal amount) { ... } public void Withdraw(decimal amount) { ... } public void Transfer(decimal amount, Account recipient) { ... } } public class AccountRepository { public Account GetByNumber(string number) { ... } public void Save(Account account) { ... } } public class TaxCalculator { public TaxTable CalculateTaxes(int year) { ... } }
  • 23. OCP: Open-Closed Principle Программные сущности (модули, классы, методы) должны быть открыты для расширения, но закрыты для изменения. Цель:  добиться гибкости системы  избежать сильных переработок дизайна при изменениях Достигается за счет:  правильное наследование  инкапсуляция
  • 24. OCP: неправильный вариант public class SmtpMailer { private readonly Logger logger; public SmtpMailer() { logger = new Logger(); } public void SendMessage(string message) { // отправить сообщение logger.Log(message); } } (с) Alexander Byndyu Изменение: нужно писать лог в базу данных public class DatabaseLogger { public void Log(string logText) { // сохранить лог в базе данных } } public class SmtpMailer { private readonly DatabaseLogger logger; public SmtpMailer() { logger = new DatabaseLogger(); } public void SendMessage(string message) { // отправить сообщение logger.Log(message); } }
  • 25. OCP: правильный вариант public class SmtpMailer { private readonly ILogger logger; public SmtpMailer(ILogger logger) { this.logger = logger; } public void SendMessage(string message) { // отправить сообщение logger.Log(message); } }
  • 26. LSP: Liskov Substitution Principle 1. Подтипы должны быть заменяемыми их исходными типами. 2. Наследники должны соблюдать контракт предка Цель:  избежать побочных эффектов и ошибок в существующем коде, работающем с базовыми классами, при добавлении наследников  строить правильные иерархии наследования Достигается за счет:  правильное наследование классов
  • 28. LSP: неправильный вариант class Rectangle { public virtual int Width { get; set; } public virtual int Height { get; set; } public int CalculateArea() { return Width * Height; } } class Square : Rectangle { public override int Height { get { return base.Height; } set { base.Height = value; base.Width = value; } } public override int Width { get { return base.Width; } set { base.Width = value; base.Height = value; } } } class Program { static void Main() { Rectangle r = new Square(); r.Width = 3; r.Height = 2; Assert.AreEqual(6, r.CalculateArea()); } } (с) Igor Tamaschuk
  • 29. LSP: правильный вариант class Rectangle : IFigure { public virtual int Width { get; set; } public virtual int Height { get; set; } public int CalculateArea() { return Width * Height; } } class Square : IFigure { public virtual int Side { get; set; } public int CalculateArea() { return Side * Side; } } class Program { static void Main() { Rectangle r = new Square(); // fail on compilation r.Width = 3; r.Height = 2; Assert.AreEqual(6, r.CalculateArea()); } }
  • 30. ISP: Interface Segregation Principle 1. Клиент не должен вынужденно зависеть от элементов интерфейса, которые он не использует. 2. Зависимость между классами должна быть ограничена как можно более «узким» интерфейсом. Цель:  ограничить знание одного класса о другом  уменьшить зависимость между классами  уменьшить количество методов для реализации при наследовании Достигается за счет:  фокусирование интерфейсов на своей ответственности  наследование от нескольких интерфейсов, а не от одного
  • 31. ISP: неправильный вариант public interface IBird { void Eat(); void Sing(); void Fly(); } public class Parrot : IBird { // здорово } public class Pigeon : IBird { // ну, я не очень хорошо пою, но ладно } public class Penguin : IBird { // хм... а я вообще птица? }
  • 32. ISP: правильный вариант public interface ICommonBird { void Eat(); } public interface ISingingBird { void Sing(); } public interface IFlyingBird { void Fly(); } public class Parrot : ICommonBird, ISingingBird, IFlyingBird { // хм, ничего не изменилось } public class Pigeon : ICommonBird, IFlyingBird { // о, так лучше, я могу не петь } public class Penguin : ICommonBird { // так намного лучше! хотя я еще и плавать могу  }
  • 33. IoC: Inversion of Control DIP: Dependency Inversion Principle 1. Модули верхнего уровня не должны зависеть от модулей нижнего уровня. Они должны зависеть от абстракции. 2. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций. Цель:  уменьшить связанность (coupling) Связан:  Hollywood principle: Don’t call us, we’ll call you Достигается за счет:  паттерны Dependency Injection, Service Locator  зависимость от абстракций  IoC frameworks
  • 34. IoC, DIP: неправильный вариант class Developer { public void WriteApplication() { IApplication helloWorld = new HelloWorldApp(); WriteCode(helloWorld); } private void WriteCode() { ... }; } public interface IApplication { string GetCode(); } public class HelloWorldApp : IApplication { // реализация } public class VeryBigApp : IApplication { // реализация }
  • 35. IoC, DIP: правильный вариант class Developer { public void WriteApplication(IApplication app) { WriteCode(app); } private void WriteCode() { ... }; } public static void Main() { Developer dev = new Developer(); IApplication app = new VeryBigApp(); // теперь мы умеем писать что угодно dev.WriteApplication(app); } Это шаблон Dependency Injection (Method Injection), но можно использовать и другие шаблоны (например, Service Locator), а также IoC Frameworks