advertisement

SOLID

50 %
50 %
advertisement
Information about SOLID
Technology

Published on March 13, 2014

Author: alexandernemanov

Source: slideshare.net

Description

S.O.L.I.D. - Принципы объектного проектирования классов
advertisement

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.

?

Add a comment

Related presentations

Presentación que realice en el Evento Nacional de Gobierno Abierto, realizado los ...

In this presentation we will describe our experience developing with a highly dyna...

Presentation to the LITA Forum 7th November 2014 Albuquerque, NM

Un recorrido por los cambios que nos generará el wearabletech en el futuro

Um paralelo entre as novidades & mercado em Wearable Computing e Tecnologias Assis...

Microsoft finally joins the smartwatch and fitness tracker game by introducing the...

Related pages

Home - !Solid

ÜBER SOLID. Willkommen in der Welt von Solid - eine der coolsten Marken Europas für modebewusste Männer zwischen 18-30. Wir produzieren Mode für unsere ...
Read more

linksjugend ['solid] | sozialistisch, antifaschistisch ...

Im Netz kursieren bereits viele Parodien auf die neue aggressive Bundeswehr-Rekrutierungs-Kampagne. Wir tragen diese Parodie jetzt in das Real Life.
Read more

dict.cc | solid | Wörterbuch Englisch-Deutsch

Übersetzung für solid im Englisch-Deutsch-Wörterbuch dict.cc.
Read more

Solid Bikes Europe

SOLID BIKES Europe. Image 01. Image 02. Image 03. Image 04. Image 05. Image 06. Warenkorb. 0 Artikel. Ihr Konto; Zur Kasse; Anmelden; Bikes; Rahmenkit ...
Read more

Solid Online-Shop | Solid Mode versandkostenfrei bei Zalando

Solid Online-Shop bei Zalando | Große Auswahl, kostenloser Versand & kostenlose Servicehotline unter 0800 2401020. Jetzt Solid bei Zalando bestellen!
Read more

Solid - Wikipedia, the free encyclopedia

Solid is one of the four fundamental states of matter (the others being liquid, gas, and plasma). It is characterized by structural rigidity and resistance ...
Read more

Ladeverbund FrankenPlus

Gesellschafter. Die Gesellschafter der solid GmbH sind: N-ERGIE Aktiengesellschaft, infra fürth gmbh, Erlanger Stadtwerke AG, Stadtwerke Schwabach GmbH ...
Read more

Home - !Solid

the denim journey! The Solid Gang on the Denim Journey! Once upon a time in the late 19th century some young men from the small town of Waekefield, USA ...
Read more

Duden | so­li­de | Rechtschreibung, Bedeutung ...

Definition, Rechtschreibung, Synonyme und Grammatik von 'solide' auf Duden online nachschlagen. Wörterbuch der deutschen Sprache.
Read more

solide – Wiktionary

Nebenformen: solid. Worttrennung: so·li·de, Komparativ: so·li·der, Superlativ: am so·li·des·ten. Aussprache: IPA: [zoˈliːdə], Komparativ ...
Read more