SlideShare ist ein Scribd-Unternehmen logo
1 von 33
S.O.L.I.D.
Принципы
объектного
проектирования
классов
Обо мне
Alexander Nemanov
alexander@asoft4web.com
Skype: asoft4web
FB:
https://www.facebook.com/alexander.nemanov
S.O.L.I.D. - принципы
1. Принцип единственности ответственности (SRP: Single Responsibility
Principle)
2. Принцип открытости/закрытости (OCP: Open/Closed Principle)
3. Принцип подстановки Лисков (LSP: Liskov Substitution Principle)
4. Принцип разделения интерфейса (ISP: Interface Segregation Principle)
5. Принцип инверсии зависимостей (DIP: Dependency Inversion Principle)
SRP - Принцип единственности ответственности
Формулировка:
Не должно быть больше одной причины для изменения класса
Каждый объект должен иметь одну обязанность и эта обязанность должна
быть полностью инкапсулирована в класс.
SRP - Принцип единственности ответственности
class Order
{
public function calculateTotalSum() {/*...*/}
public function getItems() {/*...*/}
public function getItemCount() {/*...*/}
public function addItem($item) {/*...*/}
public function deleteItem($item) {/*...*/}
public function printOrder() {/*...*/}
public function showOrder() {/*...*/}
public function load() {/*...*/}
public function save() {/*...*/}
public function update() {/*...*/}
public function delete() {/*...*/}
}
SRP - Принцип единственности ответственности
3 различный типов задач (3-и причины для изменения одного класса):
• работа с самим заказом
• отображение заказа
• работа с хранилищем данных
Решение:
Сделать отдельные классы. Чтобы каждый класс занимается своей
конкретной задачей и для каждого класса была только 1 причина для его
изменения.
SRP - Принцип единственности ответственности
class Order {
public function calculateTotalSum() {/*...*/}
public function getItems() {/*...*/}
public function getItemCount() {/*...*/}
public function addItem($item) {/*...*/}
public function deleteItem($item) {/*...*/}
}
class OrderRepository {
public function load($orderID){/*...*/}
public function save($order){/*...*/}
public function update($order){/*...*/}
public function delete($order){/*...*/}
}
class OrderViewer {
public function printOrder($order){/*...*/}
public function showOrder($order){/*...*/}
}
SRP - Принцип единственности ответственности
Проблема: Задача валидации данных
Первое решение:
class Product {
public function isValid() {
return $this->price > 0;
}
}
Решение: отдать ответственность за валидацию данных продукта другому
объекту. Причем надо сделать так, чтобы сам объект продукта не зависел
от конкретной реализации его валидатора.
$validator = $this->get('validator');
$errors = $validator->validate($product);
OCP - Принцип открытости/закрытости
Формулировка:
• программные сущности (классы, модули, функции и т.д.) должны быть
открыты для расширения, но закрыты для изменения
Принцип открытости/закрытость дает понимание того, как оставаться
достаточно гибкими в условиях постоянно меняющихся требований.
Все классы, функции и т.д. должны проектироваться так, чтобы для
изменения их поведения, нам не нужно было изменять их исходный
код.
OCP - Принцип открытости/закрытости
class Logger {
public function Log($logText) { /* Save to file */ }
}
class SmtpMailer {
private $logger;
public function __construct() {
$this->logger = new Logger();
}
public function sendMessage($message) {
// Send
// Save to log
$this->logger->Log($message);
}
}
OCP - Принцип открытости/закрытости
class DbLogger {
public function Log($logText) { /* Save to Db */ }
}
class SmtpMailer {
private $logger;
public function __construct() {
$this->logger = new DbLogger();
}
public function sendMessage($message) {
// Send
// Save to log
$this->logger->Log($message);
}
}
OCP - Принцип открытости/закрытости
interface LoggerInterface {
public function Log($logText);
}
class Logger implements LoggerInterface {
public function Log($logText) { /* Save to file */ }
}
class DbLogger implements LoggerInterface {
public function Log($logText) { /* Save to file */ }
}
OCP - Принцип открытости/закрытости
class SmtpMailer {
private $logger;
public function __construct(LoggerInterface $logger) {
$this->logger = $logger;
}
public function sendMessage($message) {
// Send
// Save to log
$this->logger->Log($message);
}
}
OCP - Принцип открытости/закрытости
Конкретизируя классы методом instanceof мы должны сразу понять, что наш
код начал "попахивать":
abstract class BaseEntity { }
class AcountEntity extends BaseEntity { }
class RoleEntity extends BaseEntity { }
class Repository {
public function save(BaseEntity $entiry) {
if ($entiry instanceof AcountEntity) {
// ...
} else if ($entiry instanceof RoleEntity) {
// ...
}
}
}
OCP - Принцип открытости/закрытости
1. "Открыт для расширения":
поведение может быть расширено
путем добавления новых объектов,
реализующих новые аспекты
поведения;
2. "Закрыт для модификации": в
результате расширения поведения
исходный код объекта не может быть
изменен.
LSP - Принцип замещения Лисков
Формулировка №1: eсли для каждого объекта o1 типа S существует объект
o2 типа T, который для всех программ P определен в терминах T, то
поведение P не изменится, если o1 заменить на o2 при условии, что S
является подтипом T.
LSP - Принцип замещения Лисков
Формулировка №1: eсли для каждого объекта o1 типа S существует объект
o2 типа T, который для всех программ P определен в терминах T, то
поведение P не изменится, если o1 заменить на o2 при условии, что S
является подтипом T.
Формулировка №2: подтипы должны быть заменяемы базовыми типами.
LSP - Принцип замещения Лисков
Поведение наследуемых классов не должно противоречить поведению,
заданному базовым классом, то есть поведение наследуемых классов
должно быть ожидаемым для кода, использующего переменную базового
типа.
interface CollectionInterface {
public function get($index);
public function count();
}
class MyCollection implements CollectionInterface {
public function get($index) { }
public function count() {}
}
$myCollection = new MyCollection();
if (1 == $myCollection->count()) {
$firstItem = $collection->get(0); // Exception, null
}
LSP - Принцип замещения Лисков
• Следовать этому принципу очень важно при проектировании новых типов
с использованием наследования.
• Этот принцип предупреждает разработчика о том, что изменение
унаследованного производным типом поведения очень рискованно.
Пример рассмотрен в книге Роберта Мартина «Быстрая разработка
программ» в разделе «Принцип подстановки Лискоу. Реальный пример»
ISP - Принцип разделения интерфейса
Формулировка: клиенты не должны зависеть от методов, которые они не
используют
Как и при использовании других принципов проектирования классов мы
пытаемся избавиться от ненужных зависимостей в коде, сделать код легко
читаемым и легко изменяемым.
ISP - Принцип разделения интерфейса
interface IItem {
public function applyDiscount($discount);
public function applyPromocode($promocode);
public function setColor($color);
public function setSize($size);
public function setCondition($condition);
public function setPrice($price);
}
ISP - Принцип разделения интерфейса
interface IItem {
public function setCondition($condition);
public function setPrice($price);
}
interface IClothes {
public function setColor($color);
public function setSize($size);
public function setMaterial($material);
}
interface IDiscountable {
public function applyDiscount($discount);
public function applyPromocode($promocode);
}
ISP - Принцип разделения интерфейса
class Book implemets IItem, IDiscountable {
public function setCondition($condition){/*...*/}
public function setPrice($price){/*...*/}
public function applyDiscount($discount){/*...*/}
public function applyPromocode($promocode){/*...*/}
}
class KidsClothes implemets IItem, IClothes {
public function setCondition($condition){/*...*/}
public function setPrice($price){/*...*/}
public function setColor($color){/*...*/}
public function setSize($size){/*...*/}
public function setMaterial($material){/*...*/}
}
DIP - Принцип инверсии зависимости
Формулировка:
• Модули верхнего уровня не должны зависеть от модулей нижнего уровня. Оба
должны зависеть от абстракции.
• Абстракции не должны зависеть от деталей. Детали должны зависеть от
абстракций.
DIP - Принцип инверсии зависимости
class OrderProcess {
public function CalculeteTotal(Order $order) {
$itemTotal = $order->getItemTotal();
$discountCalculator = new DiscountCalculator();
$discountAmount = $discountCalculator->calculateDiscount($order);
$taxAmount = 0;
if($order->getCountry() == "US") {
$taxAmount = $this->getTaxAmount($order);
} elseif ($order->getCountry() == "UK") {
$taxAmount = $this->getVatAmount($order);
}
return $itemTotal - $discountAmount + $taxAmount;
}
private function getTaxAmount(Order $order) { }
private function getVatAmount(Order $order) { }
}
DIP - Принцип инверсии зависимости
Причина, по которой проекты "стареют", заключается в том, что у
разработчиков нет возможности безболезненно менять код каких-то
компонентов без боязни нарушить работу других.
Дизайн таких систем можно охарактеризовать следующими признаками:
• Жесткость - изменение одной части кода затрагивает слишком много
других частей;
• Хрупкость - даже незначительное изменение в коде может привести к
совершенно неожиданным проблемам;
• Неподвижность - никакая из частей приложения не может быть легко
выделена и повторно использована.
DIP - Принцип инверсии зависимости
Перечислим все обязанности, которые выполняет класс OrderProcessor:
• Знает, как вычислить сумму заказа;
• Знает, как и каким калькулятором вычислить сумму скидки;
• Знает, что означают коды стран;
• Знает, каким образом вычислить сумму налога для той или иной
страны;
• Знает формулу, по которой из всех слагаемых вычисляется стоимость
заказа.
OrderProcess DiscountCalculator
DIP - Принцип инверсии зависимости
interface DiscountCalculatorInterface {
public function calculateDiscount(Order $order);
}
class DiscountCalculator implements DiscountCalculatorInterface {
public function calculateDiscount(Order $order) { }
}
interface TaxStrategyInterface {
public function getTaxAmount(Order $order);
}
class USTaxStarategy implements TaxStrategyInterface {
public function getTaxAmount(Order $order) { }
}
class UKTaxStarategy implements TaxStrategyInterface {
public function getTaxAmount(Order $order) { }
}`
DIP - Принцип инверсии зависимости
class OrderProcess {
/** @var DiscountCalculatorInterface */
private $discountCalculator;
/** @var TaxStrategyInterface */
private $taxStarategy;
public function __construct(DiscountCalculatorInterface $discountCalculator,
TaxStrategyInterface $taxStarategy) {
$this->discountCalculator = $discountCalculator;
$this->taxStarategy = $taxStarategy;
}
public function CalculeteTotal(Order $order) {
$itemTotal = $order->getItemTotal();
$discountAmount = $this->discountCalculator->calculateDiscount($order);
$taxAmount = $this->taxStarategy->getTaxAmount($order);
return $itemTotal - $discountAmount + $taxAmount;
}
}
DIP - Принцип инверсии зависимости
OrderProcess
DiscountCalculator
DiscountCalculatorInterface TaxStrategyInterface
USTaxStarategy UKTaxStarategy
DIP - Принцип инверсии зависимости
Принцип обращения зависимости - это очень мощный
инструмент, который в сочетании с другими SOLID-
принципами позволяет разрабатывать дизайн систем
так же легко, как если бы он собирался из
конструктора LEGO.
?

Weitere ähnliche Inhalte

Was ist angesagt?

Лекция 6_принципы ООП : инкапсуляция, наследование
Лекция 6_принципы ООП : инкапсуляция, наследованиеЛекция 6_принципы ООП : инкапсуляция, наследование
Лекция 6_принципы ООП : инкапсуляция, наследование
metaform
 
ук 03.001.02 2011
ук 03.001.02 2011ук 03.001.02 2011
ук 03.001.02 2011
etyumentcev
 
03_JavaBasicConstructionsAndDatatypes
03_JavaBasicConstructionsAndDatatypes03_JavaBasicConstructionsAndDatatypes
03_JavaBasicConstructionsAndDatatypes
dklenov
 
Релиз PHP7 - что нас ждет в октябре 2015
Релиз PHP7 - что нас ждет в октябре 2015Релиз PHP7 - что нас ждет в октябре 2015
Релиз PHP7 - что нас ждет в октябре 2015
Andrey Tokarchuk
 
C++ осень 2013 лекция 5
C++ осень 2013 лекция 5C++ осень 2013 лекция 5
C++ осень 2013 лекция 5
Technopark
 
Классы и объекты в Java
Классы и объекты в JavaКлассы и объекты в Java
Классы и объекты в Java
metaform
 
Шаблоны разработки ПО. Часть 3. Шаблоны GoF
Шаблоны разработки ПО. Часть 3. Шаблоны GoFШаблоны разработки ПО. Часть 3. Шаблоны GoF
Шаблоны разработки ПО. Часть 3. Шаблоны GoF
Sergey Nemchinsky
 

Was ist angesagt? (20)

Step 5
Step 5Step 5
Step 5
 
Java Core. Lecture# 2. Classes & objects.
Java Core. Lecture# 2. Classes & objects.Java Core. Lecture# 2. Classes & objects.
Java Core. Lecture# 2. Classes & objects.
 
Лекция 6_принципы ООП : инкапсуляция, наследование
Лекция 6_принципы ООП : инкапсуляция, наследованиеЛекция 6_принципы ООП : инкапсуляция, наследование
Лекция 6_принципы ООП : инкапсуляция, наследование
 
ук 03.001.02 2011
ук 03.001.02 2011ук 03.001.02 2011
ук 03.001.02 2011
 
C++ Базовый. Занятие 15.
C++ Базовый. Занятие 15.C++ Базовый. Занятие 15.
C++ Базовый. Занятие 15.
 
Java core-lect6-part3-annotation.ppt
Java core-lect6-part3-annotation.pptJava core-lect6-part3-annotation.ppt
Java core-lect6-part3-annotation.ppt
 
SOLID Principles in the real world
SOLID Principles in the real worldSOLID Principles in the real world
SOLID Principles in the real world
 
03_JavaBasicConstructionsAndDatatypes
03_JavaBasicConstructionsAndDatatypes03_JavaBasicConstructionsAndDatatypes
03_JavaBasicConstructionsAndDatatypes
 
C++ Базовый. Занятие 03.
C++ Базовый. Занятие 03.C++ Базовый. Занятие 03.
C++ Базовый. Занятие 03.
 
Релиз PHP7 - что нас ждет в октябре 2015
Релиз PHP7 - что нас ждет в октябре 2015Релиз PHP7 - что нас ждет в октябре 2015
Релиз PHP7 - что нас ждет в октябре 2015
 
java 8
java 8java 8
java 8
 
принципы ооп и программирование классов в C#
принципы ооп и программирование классов в C#принципы ооп и программирование классов в C#
принципы ооп и программирование классов в C#
 
C++ осень 2013 лекция 5
C++ осень 2013 лекция 5C++ осень 2013 лекция 5
C++ осень 2013 лекция 5
 
Java. Generic - шаблонные типы.
Java.  Generic - шаблонные типы.Java.  Generic - шаблонные типы.
Java. Generic - шаблонные типы.
 
Классы и объекты в Java
Классы и объекты в JavaКлассы и объекты в Java
Классы и объекты в Java
 
Стажировка-2015. Разработка. Занятие 8. Абстракции, именование,документирование
Стажировка-2015. Разработка. Занятие 8. Абстракции, именование,документированиеСтажировка-2015. Разработка. Занятие 8. Абстракции, именование,документирование
Стажировка-2015. Разработка. Занятие 8. Абстракции, именование,документирование
 
Java Core. Lecture# 3. Part# 1. Abstract classes.
Java Core. Lecture# 3. Part# 1. Abstract classes.Java Core. Lecture# 3. Part# 1. Abstract classes.
Java Core. Lecture# 3. Part# 1. Abstract classes.
 
Шаблоны разработки ПО. Часть 3. Шаблоны GoF
Шаблоны разработки ПО. Часть 3. Шаблоны GoFШаблоны разработки ПО. Часть 3. Шаблоны GoF
Шаблоны разработки ПО. Часть 3. Шаблоны GoF
 
C++ Базовый. Занятие 17.
C++ Базовый. Занятие 17.C++ Базовый. Занятие 17.
C++ Базовый. Занятие 17.
 
Ввведение в java
Ввведение в javaВвведение в java
Ввведение в java
 

Ähnlich wie SOLID

Yuri Trukhin - Software developement best practices
Yuri Trukhin - Software developement best practicesYuri Trukhin - Software developement best practices
Yuri Trukhin - Software developement best practices
beloslab
 
ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)
ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)
ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)
ZFConf Conference
 
Секрет производства: программный продукт, за который не будет стыдно
Секрет производства: программный продукт, за который не будет стыдноСекрет производства: программный продукт, за который не будет стыдно
Секрет производства: программный продукт, за который не будет стыдно
CUSTIS
 
Hacking PostgreSQL. Обзор исходного кода
Hacking PostgreSQL. Обзор исходного кодаHacking PostgreSQL. Обзор исходного кода
Hacking PostgreSQL. Обзор исходного кода
Anastasia Lubennikova
 
Rupyru2007 Rastyagaev Ruby
Rupyru2007 Rastyagaev RubyRupyru2007 Rastyagaev Ruby
Rupyru2007 Rastyagaev Ruby
emarkine
 
C++ осень 2012 лекция 9
C++ осень 2012 лекция 9C++ осень 2012 лекция 9
C++ осень 2012 лекция 9
Technopark
 

Ähnlich wie SOLID (20)

Refactoring
RefactoringRefactoring
Refactoring
 
Tdd php
Tdd phpTdd php
Tdd php
 
SOLID
SOLIDSOLID
SOLID
 
Yuri Trukhin - Software developement best practices
Yuri Trukhin - Software developement best practicesYuri Trukhin - Software developement best practices
Yuri Trukhin - Software developement best practices
 
Общие темы. Тема 02.
Общие темы. Тема 02.Общие темы. Тема 02.
Общие темы. Тема 02.
 
ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)
ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)
ZFConf 2011: Толстая модель: История разработки собственного ORM (Михаил Шамин)
 
Толстая модель. История разработки ORM
Толстая модель. История разработки ORMТолстая модель. История разработки ORM
Толстая модель. История разработки ORM
 
Cтиль программирования
Cтиль программированияCтиль программирования
Cтиль программирования
 
Чуть сложнее чем Singleton: аннотации, IOC, АОП
Чуть сложнее чем Singleton: аннотации, IOC, АОПЧуть сложнее чем Singleton: аннотации, IOC, АОП
Чуть сложнее чем Singleton: аннотации, IOC, АОП
 
Секрет производства: программный продукт, за который не будет стыдно
Секрет производства: программный продукт, за который не будет стыдноСекрет производства: программный продукт, за который не будет стыдно
Секрет производства: программный продукт, за который не будет стыдно
 
C# Desktop. Занятие 07.
C# Desktop. Занятие 07.C# Desktop. Занятие 07.
C# Desktop. Занятие 07.
 
Lecture 3
Lecture 3Lecture 3
Lecture 3
 
Спецкурс-2015. Занятие 03. Абстракции, именование, документирование.
Спецкурс-2015. Занятие 03. Абстракции, именование, документирование.Спецкурс-2015. Занятие 03. Абстракции, именование, документирование.
Спецкурс-2015. Занятие 03. Абстракции, именование, документирование.
 
Hacking PostgreSQL. Обзор исходного кода
Hacking PostgreSQL. Обзор исходного кодаHacking PostgreSQL. Обзор исходного кода
Hacking PostgreSQL. Обзор исходного кода
 
Rupyru2007 Rastyagaev Ruby
Rupyru2007 Rastyagaev RubyRupyru2007 Rastyagaev Ruby
Rupyru2007 Rastyagaev Ruby
 
msumobi2. Лекция 1
msumobi2. Лекция 1msumobi2. Лекция 1
msumobi2. Лекция 1
 
Document
DocumentDocument
Document
 
C++ осень 2012 лекция 9
C++ осень 2012 лекция 9C++ осень 2012 лекция 9
C++ осень 2012 лекция 9
 
Введение в Realm.io
Введение в Realm.ioВведение в Realm.io
Введение в Realm.io
 
особенности программирования на с++
особенности программирования на с++особенности программирования на с++
особенности программирования на с++
 

Kürzlich hochgeladen

CVE. The Fortra's GoAnywhere MFT [RU].pdf
CVE. The Fortra's GoAnywhere MFT [RU].pdfCVE. The Fortra's GoAnywhere MFT [RU].pdf
CVE. The Fortra's GoAnywhere MFT [RU].pdf
Хроники кибер-безопасника
 
Cyber Defense Doctrine Managing the Risk Full Applied Guide to Organizational...
Cyber Defense Doctrine Managing the Risk Full Applied Guide to Organizational...Cyber Defense Doctrine Managing the Risk Full Applied Guide to Organizational...
Cyber Defense Doctrine Managing the Risk Full Applied Guide to Organizational...
Ирония безопасности
 
ИСТОЧНИКИ ИННОВАЦИОННОСТИ КИТАЯ (ПО ВЕРСИИ DGAP) | The Sources of China’s Inn...
ИСТОЧНИКИ ИННОВАЦИОННОСТИ КИТАЯ (ПО ВЕРСИИ DGAP) | The Sources of China’s Inn...ИСТОЧНИКИ ИННОВАЦИОННОСТИ КИТАЯ (ПО ВЕРСИИ DGAP) | The Sources of China’s Inn...
ИСТОЧНИКИ ИННОВАЦИОННОСТИ КИТАЯ (ПО ВЕРСИИ DGAP) | The Sources of China’s Inn...
Ирония безопасности
 
СИСТЕМА ОЦЕНКИ УЯЗВИМОСТЕЙ CVSS 4.0 / CVSS v4.0 [RU].pdf
СИСТЕМА ОЦЕНКИ УЯЗВИМОСТЕЙ CVSS 4.0 / CVSS v4.0 [RU].pdfСИСТЕМА ОЦЕНКИ УЯЗВИМОСТЕЙ CVSS 4.0 / CVSS v4.0 [RU].pdf
СИСТЕМА ОЦЕНКИ УЯЗВИМОСТЕЙ CVSS 4.0 / CVSS v4.0 [RU].pdf
Хроники кибер-безопасника
 
2023 Q4. The Ransomware report. [RU].pdf
2023 Q4. The Ransomware report. [RU].pdf2023 Q4. The Ransomware report. [RU].pdf
2023 Q4. The Ransomware report. [RU].pdf
Хроники кибер-безопасника
 
Cyberprint. Dark Pink Apt Group [RU].pdf
Cyberprint. Dark Pink Apt Group [RU].pdfCyberprint. Dark Pink Apt Group [RU].pdf
Cyberprint. Dark Pink Apt Group [RU].pdf
Хроники кибер-безопасника
 

Kürzlich hochgeladen (9)

CVE. The Fortra's GoAnywhere MFT [RU].pdf
CVE. The Fortra's GoAnywhere MFT [RU].pdfCVE. The Fortra's GoAnywhere MFT [RU].pdf
CVE. The Fortra's GoAnywhere MFT [RU].pdf
 
Malware. DCRAT (DARK CRYSTAL RAT) [RU].pdf
Malware. DCRAT (DARK CRYSTAL RAT) [RU].pdfMalware. DCRAT (DARK CRYSTAL RAT) [RU].pdf
Malware. DCRAT (DARK CRYSTAL RAT) [RU].pdf
 
Cyber Defense Doctrine Managing the Risk Full Applied Guide to Organizational...
Cyber Defense Doctrine Managing the Risk Full Applied Guide to Organizational...Cyber Defense Doctrine Managing the Risk Full Applied Guide to Organizational...
Cyber Defense Doctrine Managing the Risk Full Applied Guide to Organizational...
 
Ransomware_Q3 2023. The report [RU].pdf
Ransomware_Q3 2023.  The report [RU].pdfRansomware_Q3 2023.  The report [RU].pdf
Ransomware_Q3 2023. The report [RU].pdf
 
ИСТОЧНИКИ ИННОВАЦИОННОСТИ КИТАЯ (ПО ВЕРСИИ DGAP) | The Sources of China’s Inn...
ИСТОЧНИКИ ИННОВАЦИОННОСТИ КИТАЯ (ПО ВЕРСИИ DGAP) | The Sources of China’s Inn...ИСТОЧНИКИ ИННОВАЦИОННОСТИ КИТАЯ (ПО ВЕРСИИ DGAP) | The Sources of China’s Inn...
ИСТОЧНИКИ ИННОВАЦИОННОСТИ КИТАЯ (ПО ВЕРСИИ DGAP) | The Sources of China’s Inn...
 
СИСТЕМА ОЦЕНКИ УЯЗВИМОСТЕЙ CVSS 4.0 / CVSS v4.0 [RU].pdf
СИСТЕМА ОЦЕНКИ УЯЗВИМОСТЕЙ CVSS 4.0 / CVSS v4.0 [RU].pdfСИСТЕМА ОЦЕНКИ УЯЗВИМОСТЕЙ CVSS 4.0 / CVSS v4.0 [RU].pdf
СИСТЕМА ОЦЕНКИ УЯЗВИМОСТЕЙ CVSS 4.0 / CVSS v4.0 [RU].pdf
 
2023 Q4. The Ransomware report. [RU].pdf
2023 Q4. The Ransomware report. [RU].pdf2023 Q4. The Ransomware report. [RU].pdf
2023 Q4. The Ransomware report. [RU].pdf
 
Cyberprint. Dark Pink Apt Group [RU].pdf
Cyberprint. Dark Pink Apt Group [RU].pdfCyberprint. Dark Pink Apt Group [RU].pdf
Cyberprint. Dark Pink Apt Group [RU].pdf
 
MS Navigating Incident Response [RU].pdf
MS Navigating Incident Response [RU].pdfMS Navigating Incident Response [RU].pdf
MS Navigating Incident Response [RU].pdf
 

SOLID

  • 2. Обо мне Alexander Nemanov alexander@asoft4web.com Skype: asoft4web FB: https://www.facebook.com/alexander.nemanov
  • 3. S.O.L.I.D. - принципы 1. Принцип единственности ответственности (SRP: Single Responsibility Principle) 2. Принцип открытости/закрытости (OCP: Open/Closed Principle) 3. Принцип подстановки Лисков (LSP: Liskov Substitution Principle) 4. Принцип разделения интерфейса (ISP: Interface Segregation Principle) 5. Принцип инверсии зависимостей (DIP: Dependency Inversion Principle)
  • 4. SRP - Принцип единственности ответственности Формулировка: Не должно быть больше одной причины для изменения класса Каждый объект должен иметь одну обязанность и эта обязанность должна быть полностью инкапсулирована в класс.
  • 5. SRP - Принцип единственности ответственности class Order { public function calculateTotalSum() {/*...*/} public function getItems() {/*...*/} public function getItemCount() {/*...*/} public function addItem($item) {/*...*/} public function deleteItem($item) {/*...*/} public function printOrder() {/*...*/} public function showOrder() {/*...*/} public function load() {/*...*/} public function save() {/*...*/} public function update() {/*...*/} public function delete() {/*...*/} }
  • 6. SRP - Принцип единственности ответственности 3 различный типов задач (3-и причины для изменения одного класса): • работа с самим заказом • отображение заказа • работа с хранилищем данных Решение: Сделать отдельные классы. Чтобы каждый класс занимается своей конкретной задачей и для каждого класса была только 1 причина для его изменения.
  • 7. SRP - Принцип единственности ответственности class Order { public function calculateTotalSum() {/*...*/} public function getItems() {/*...*/} public function getItemCount() {/*...*/} public function addItem($item) {/*...*/} public function deleteItem($item) {/*...*/} } class OrderRepository { public function load($orderID){/*...*/} public function save($order){/*...*/} public function update($order){/*...*/} public function delete($order){/*...*/} } class OrderViewer { public function printOrder($order){/*...*/} public function showOrder($order){/*...*/} }
  • 8. SRP - Принцип единственности ответственности Проблема: Задача валидации данных Первое решение: class Product { public function isValid() { return $this->price > 0; } } Решение: отдать ответственность за валидацию данных продукта другому объекту. Причем надо сделать так, чтобы сам объект продукта не зависел от конкретной реализации его валидатора. $validator = $this->get('validator'); $errors = $validator->validate($product);
  • 9. OCP - Принцип открытости/закрытости Формулировка: • программные сущности (классы, модули, функции и т.д.) должны быть открыты для расширения, но закрыты для изменения Принцип открытости/закрытость дает понимание того, как оставаться достаточно гибкими в условиях постоянно меняющихся требований. Все классы, функции и т.д. должны проектироваться так, чтобы для изменения их поведения, нам не нужно было изменять их исходный код.
  • 10. OCP - Принцип открытости/закрытости class Logger { public function Log($logText) { /* Save to file */ } } class SmtpMailer { private $logger; public function __construct() { $this->logger = new Logger(); } public function sendMessage($message) { // Send // Save to log $this->logger->Log($message); } }
  • 11. OCP - Принцип открытости/закрытости class DbLogger { public function Log($logText) { /* Save to Db */ } } class SmtpMailer { private $logger; public function __construct() { $this->logger = new DbLogger(); } public function sendMessage($message) { // Send // Save to log $this->logger->Log($message); } }
  • 12. OCP - Принцип открытости/закрытости interface LoggerInterface { public function Log($logText); } class Logger implements LoggerInterface { public function Log($logText) { /* Save to file */ } } class DbLogger implements LoggerInterface { public function Log($logText) { /* Save to file */ } }
  • 13. OCP - Принцип открытости/закрытости class SmtpMailer { private $logger; public function __construct(LoggerInterface $logger) { $this->logger = $logger; } public function sendMessage($message) { // Send // Save to log $this->logger->Log($message); } }
  • 14. OCP - Принцип открытости/закрытости Конкретизируя классы методом instanceof мы должны сразу понять, что наш код начал "попахивать": abstract class BaseEntity { } class AcountEntity extends BaseEntity { } class RoleEntity extends BaseEntity { } class Repository { public function save(BaseEntity $entiry) { if ($entiry instanceof AcountEntity) { // ... } else if ($entiry instanceof RoleEntity) { // ... } } }
  • 15. OCP - Принцип открытости/закрытости 1. "Открыт для расширения": поведение может быть расширено путем добавления новых объектов, реализующих новые аспекты поведения; 2. "Закрыт для модификации": в результате расширения поведения исходный код объекта не может быть изменен.
  • 16. LSP - Принцип замещения Лисков Формулировка №1: eсли для каждого объекта o1 типа S существует объект o2 типа T, который для всех программ P определен в терминах T, то поведение P не изменится, если o1 заменить на o2 при условии, что S является подтипом T.
  • 17. LSP - Принцип замещения Лисков Формулировка №1: eсли для каждого объекта o1 типа S существует объект o2 типа T, который для всех программ P определен в терминах T, то поведение P не изменится, если o1 заменить на o2 при условии, что S является подтипом T. Формулировка №2: подтипы должны быть заменяемы базовыми типами.
  • 18. LSP - Принцип замещения Лисков Поведение наследуемых классов не должно противоречить поведению, заданному базовым классом, то есть поведение наследуемых классов должно быть ожидаемым для кода, использующего переменную базового типа. interface CollectionInterface { public function get($index); public function count(); } class MyCollection implements CollectionInterface { public function get($index) { } public function count() {} } $myCollection = new MyCollection(); if (1 == $myCollection->count()) { $firstItem = $collection->get(0); // Exception, null }
  • 19. LSP - Принцип замещения Лисков • Следовать этому принципу очень важно при проектировании новых типов с использованием наследования. • Этот принцип предупреждает разработчика о том, что изменение унаследованного производным типом поведения очень рискованно. Пример рассмотрен в книге Роберта Мартина «Быстрая разработка программ» в разделе «Принцип подстановки Лискоу. Реальный пример»
  • 20.
  • 21. ISP - Принцип разделения интерфейса Формулировка: клиенты не должны зависеть от методов, которые они не используют Как и при использовании других принципов проектирования классов мы пытаемся избавиться от ненужных зависимостей в коде, сделать код легко читаемым и легко изменяемым.
  • 22. ISP - Принцип разделения интерфейса interface IItem { public function applyDiscount($discount); public function applyPromocode($promocode); public function setColor($color); public function setSize($size); public function setCondition($condition); public function setPrice($price); }
  • 23. ISP - Принцип разделения интерфейса interface IItem { public function setCondition($condition); public function setPrice($price); } interface IClothes { public function setColor($color); public function setSize($size); public function setMaterial($material); } interface IDiscountable { public function applyDiscount($discount); public function applyPromocode($promocode); }
  • 24. ISP - Принцип разделения интерфейса class Book implemets IItem, IDiscountable { public function setCondition($condition){/*...*/} public function setPrice($price){/*...*/} public function applyDiscount($discount){/*...*/} public function applyPromocode($promocode){/*...*/} } class KidsClothes implemets IItem, IClothes { public function setCondition($condition){/*...*/} public function setPrice($price){/*...*/} public function setColor($color){/*...*/} public function setSize($size){/*...*/} public function setMaterial($material){/*...*/} }
  • 25. DIP - Принцип инверсии зависимости Формулировка: • Модули верхнего уровня не должны зависеть от модулей нижнего уровня. Оба должны зависеть от абстракции. • Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.
  • 26. DIP - Принцип инверсии зависимости class OrderProcess { public function CalculeteTotal(Order $order) { $itemTotal = $order->getItemTotal(); $discountCalculator = new DiscountCalculator(); $discountAmount = $discountCalculator->calculateDiscount($order); $taxAmount = 0; if($order->getCountry() == "US") { $taxAmount = $this->getTaxAmount($order); } elseif ($order->getCountry() == "UK") { $taxAmount = $this->getVatAmount($order); } return $itemTotal - $discountAmount + $taxAmount; } private function getTaxAmount(Order $order) { } private function getVatAmount(Order $order) { } }
  • 27. DIP - Принцип инверсии зависимости Причина, по которой проекты "стареют", заключается в том, что у разработчиков нет возможности безболезненно менять код каких-то компонентов без боязни нарушить работу других. Дизайн таких систем можно охарактеризовать следующими признаками: • Жесткость - изменение одной части кода затрагивает слишком много других частей; • Хрупкость - даже незначительное изменение в коде может привести к совершенно неожиданным проблемам; • Неподвижность - никакая из частей приложения не может быть легко выделена и повторно использована.
  • 28. DIP - Принцип инверсии зависимости Перечислим все обязанности, которые выполняет класс OrderProcessor: • Знает, как вычислить сумму заказа; • Знает, как и каким калькулятором вычислить сумму скидки; • Знает, что означают коды стран; • Знает, каким образом вычислить сумму налога для той или иной страны; • Знает формулу, по которой из всех слагаемых вычисляется стоимость заказа. OrderProcess DiscountCalculator
  • 29. DIP - Принцип инверсии зависимости interface DiscountCalculatorInterface { public function calculateDiscount(Order $order); } class DiscountCalculator implements DiscountCalculatorInterface { public function calculateDiscount(Order $order) { } } interface TaxStrategyInterface { public function getTaxAmount(Order $order); } class USTaxStarategy implements TaxStrategyInterface { public function getTaxAmount(Order $order) { } } class UKTaxStarategy implements TaxStrategyInterface { public function getTaxAmount(Order $order) { } }`
  • 30. DIP - Принцип инверсии зависимости class OrderProcess { /** @var DiscountCalculatorInterface */ private $discountCalculator; /** @var TaxStrategyInterface */ private $taxStarategy; public function __construct(DiscountCalculatorInterface $discountCalculator, TaxStrategyInterface $taxStarategy) { $this->discountCalculator = $discountCalculator; $this->taxStarategy = $taxStarategy; } public function CalculeteTotal(Order $order) { $itemTotal = $order->getItemTotal(); $discountAmount = $this->discountCalculator->calculateDiscount($order); $taxAmount = $this->taxStarategy->getTaxAmount($order); return $itemTotal - $discountAmount + $taxAmount; } }
  • 31. DIP - Принцип инверсии зависимости OrderProcess DiscountCalculator DiscountCalculatorInterface TaxStrategyInterface USTaxStarategy UKTaxStarategy
  • 32. DIP - Принцип инверсии зависимости Принцип обращения зависимости - это очень мощный инструмент, который в сочетании с другими SOLID- принципами позволяет разрабатывать дизайн систем так же легко, как если бы он собирался из конструктора LEGO.
  • 33. ?