SlideShare une entreprise Scribd logo
1  sur  34
Télécharger pour lire hors ligne
SPECIFICATION
A Software Design Pattern
Problem solver,

Architect, Leader
Robert Šorn
SPECIFICATION
A Software Design Pattern
— DISCLAIMER —
— WHAT IS A SPECIFICATION? —
Design pattern
used to codify business rules
that state something about an object
Cheap to
WRITE

MAINTAIN
Complex
LOGIC
Easy to
TEST
To encapsulate a business rule which does not belong inside entities or value, but is applied to it.
— WHY TO USE A SPECIFICATION? —
To make a business rule explicit in the codebase.
To make a business rule a first-class citizen of your codebase - domain.
Assertion
Build
to order
Selection
— HOW TO USE A SPECIFICATION? —
— ASSERTION —
interface CustomerSpecification
{
public function isSatisfiedBy(Customer $customer) : bool;
}
final class CustomerIsPremium implements CustomerSpecification
{
private $orderRepository;
public function __construct(OrderRepositoryInterface $orderRepository)
{
$this->orderRepository = $orderRepository;
}
public function isSatisfiedBy(Customer $customer) : bool
{
return $this->orderRepository->countFor($customer) > 3;
}
}
$customer = $customerRepository->findById(42);
$spec = new CustomerIsPremium($orderRepository);
$spec->isSatisfiedBy($customer);
— ASSERTION - COMPOSITE - AND —
final class AndSpecification extends AbstractSpecification implements SpecificationInterface
{
/** @var AbstractSpecification */
private $one;
/** @var AbstractSpecification */
private $two;
/**
* @param AbstractSpecification $one
* @param AbstractSpecification $two
*/
public function __construct(AbstractSpecification $one, AbstractSpecification $two)
{
$this->one = $one;
$this->two = $two;
}
/**
* @param mixed $object
*/
public function isSatisfiedBy($object) : bool
{
return $this->one->isSatisfiedBy($object) && $this->two->isSatisfiedBy($object);
}
}
— ASSERTION - COMPOSITE - OR —
final class OrSpecification extends AbstractSpecification implements SpecificationInterface
{
/** @var AbstractSpecification */
private $one;
/** @var AbstractSpecification */
private $two;
/**
* @param AbstractSpecification $one
* @param AbstractSpecification $two
*/
public function __construct(AbstractSpecification $one, AbstractSpecification $two)
{
$this->one = $one;
$this->two = $two;
}
/**
* @param mixed $object
*/
public function isSatisfiedBy($object) : bool
{
return $this->one->isSatisfiedBy($object) || $this->two->isSatisfiedBy($object);
}
}
— ASSERTION - COMPOSITE - NOT —
final class NotSpecification extends AbstractSpecification implements SpecificationInterface
{
/** @var AbstractSpecification */
private $spec;
/**
* @param AbstractSpecification $spec
*/
public function __construct(AbstractSpecification $spec)
{
$this->spec = $spec;
}
/**
* @param mixed $object
*/
public function isSatisfiedBy($object) : bool

{
return !$this->spec->isSatisfiedBy($object);
}
}
— ASSERTION - COMPOSITE —
$specAnd = new AndSpecification(
new CustomerIsPremium($orderRepository),
new CustomerHasOverdueInvoices($invoiceRepository)
);
$specAnd->isSatisfiedBy($customer);
$specOr = new OrSpecification(
new CustomerIsPremium($orderRepository),
new CustomerHasOverdueInvoices($invoiceRepository)
);
$specOr->isSatisfiedBy($customer);
$CustomerIsNotPremium = new NotSpecification(
new CustomerIsPremium($orderRepository)
);
$specNot->isSatisfiedBy($customer);
— ASSERTION - COMPOSITE - PIPE IT BABY —
abstract class AbstractSpecification
{
/**
* @param AbstractSpecification $other
* @return SpecificationInterface
*/
public function andSpecification(AbstractSpecification $other)
{
return new AndSpecification($this, $other);
}
/**
* @param AbstractSpecification $other
* @return SpecificationInterface
*/
public function orSpecification(AbstractSpecification $other)
{
return new OrSpecification($this, $other);
}
/**
* @return SpecificationInterface
*/
public function notSpecification()
{
return new NotSpecification($this);
}
}
Build
to order
Assertion Selection
— SELECTION —
— SELECTION —
interface SqlSpecification
{
/** @return string */
public function asSql();
}
final class CustomerIsPremium implements CustomerSpecification, SqlSpecification
{
// ...
/** @return string */
public function asSql()
{
return "SELECT * FROM customers LEFT JOIN orders ON ...";
}
}
— SELECTION —
interface RepositoryCompatibleSpecification
{
public function applyToRepository(SpecificationReceivableRepository $repo);
}
interface RepositoryCompatibleSpecification
{
public function getRecordsMatching(RepositoryCompatibleSpecification $spec) : array;
}
— SELECTION —
EXAMPLE OF SPECIFICATION USED FOR SELECTION WITH DOCTRINE
https://github.com/Happyr/Doctrine-Specification
— SELECTION - COMPOSITE - PIPE —
Build
to order
Assertion Selection
— BUILD TO ORDER —
— BUILD TO ORDER —
API BasketEvents
— BUILD TO ORDER —
Ad TransactionBasket
— BUILD TO ORDER —
Entity vs Value
— BUILD TO ORDER —
final class Basket
{
private $products = array();
private $amount = 0.0;
public function __construct(array $products = array())
{
foreach ($products as $product) {
$this->products[$product->getProductId()] = $product;
$this->amount += $product->getPrice();
}
}
public function hasProduct(Product $product)
{
return isset($this->products[$product->getProductId()]);
}
public function getAmount()
{
return $this->amount;
}
public function getProducts()
{
return $this->products;
}
}
— BUILD TO ORDER —
class BasketOperationService
{
public function addProductToBasket(Basket $basket, Product $product)
{
$products = $basket->getProducts();
$products[$product->getProductId()] = $product;
$newBasket = new Basket($products);
return $newBasket;
}
public function removeProductFromBasket(Basket $basket, Product $product)
{
$products = $basket->getProducts();
unset($products[$product->getProductId()]);
$newBasket = new Basket($products);
return $newBasket;
}
}
— BUILD TO ORDER —
class ProductIsInBasketSpecification
{
public function isSatisfiedBy(Basket $basket, Product $product)
{
return $basket->hasProduct($product);
}
}
— BUILD TO ORDER —
class BasketCanBeBoughtSpecification
{
public function isSatisfiedBy(Basket $basket, User $user)
{
if ($basket->getAmount() <= $user->getCurrentBalanceAmount()) {
return true;
}
return false;
}
}
— BUILD TO ORDER —
final class TriedToAddProductToBasketEvent
{
private $basket;
private $product;
private $user;
public function __construct(Basket $basket, Product $product, User $user)
{
$this->basket = $basket;
$this->product = $product;
$this->user = $user;
}
public function getProduct()
{
return $this->product;
}
public function getBasket()
{
return $this->basket;
}
public function getUser()
{
return $this->user;
}
}
— BUILD TO ORDER —
— BUILD TO ORDER —
class TriedToAddProductToBasketEventSubscriber
{
public function onTriedToAddProductToBasketEvent(TriedToAddProductToBasketEvent $event, EventDispatcher $dispatcher)
{
$basket = $event->getBasket();
$product = $event->getProduct();
$user = $event->getUser();
$communicatorService = $dispatcher->getFrontendCommunicatorService();
$productIsInBasketSpecification = new ProductIsInBasketSpecification();
if ($productIsInBasketSpecification->isSatisfiedBy($basket, $product)) {
$communicatorService->showError('Product already in basket!', $product);
} else {
$basketOperationService = new BasketOperationService();
$newBasket = $basketOperationService->addProductToBasket($basket, $product);
$basketCanBeBoughtSpecification = new BasketCanBeBoughtSpecification();
if ($basketCanBeBoughtSpecification->isSatisfiedBy($newBasket, $user)) {
/* ... Replace $basket with $newBasket in DIC for further events to use it ... */
$communicatorService->showProductInBasket($product);
$communicatorService->setTotalPrice($newBasket->getAmount());
} else {
$communicatorService->showError('Not enough funds!', $product);
}
}
}
}
— BUILD TO ORDER —
— BUILD TO ORDER —
— FURTHER READING —
“THE BLUE BOOK”
https://www.amazon.com/gp/product/B00794TAUG/
EXAMPLE OF SPECIFICATION USED FOR SELECTION WITH DOCTRINE
https://github.com/Happyr/Doctrine-Specification
BLOG POST 4 QUICK PEEK
http://marcaube.ca/2015/05/specifications
MARTIN FOWLER
https://www.martinfowler.com/apsupp/spec.pdf
“THE YELLOW BOOK”
https://leanpub.com/ddd-in-php?a=Ug88MJbcykCAu8AEAWNjDA
Q&A
Robert Šorn
COO @ TRIKODER
robert.sorn@trikoder.net
ks, ks, BTW, Trikoder is hiring! ;)
Head of PM, PHP developers, Java developers, UX/UI specialist, …
work@trikoder.net
THANK YOU
Robert Šorn
COO @ TRIKODER
robert.sorn@trikoder.net

Contenu connexe

Tendances

Gravity Forms Hooks & Filters
Gravity Forms Hooks & FiltersGravity Forms Hooks & Filters
Gravity Forms Hooks & Filtersiamdangavin
 
WordPress overloading Gravityforms using hooks, filters and extending classes
WordPress overloading Gravityforms using hooks, filters and extending classes WordPress overloading Gravityforms using hooks, filters and extending classes
WordPress overloading Gravityforms using hooks, filters and extending classes Paul Bearne
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosDivante
 
Oop php 5
Oop php 5Oop php 5
Oop php 5phpubl
 
Dutch php a short tale about state machine
Dutch php   a short tale about state machineDutch php   a short tale about state machine
Dutch php a short tale about state machineŁukasz Chruściel
 
11. CodeIgniter vederea unei singure inregistrari
11. CodeIgniter vederea unei singure inregistrari11. CodeIgniter vederea unei singure inregistrari
11. CodeIgniter vederea unei singure inregistrariRazvan Raducanu, PhD
 
WordCamp Denver 2012 - Custom Meta Boxes
WordCamp Denver 2012 - Custom Meta BoxesWordCamp Denver 2012 - Custom Meta Boxes
WordCamp Denver 2012 - Custom Meta BoxesJeremy Green
 
Unbreakable Domain Models - DPC13
Unbreakable Domain Models - DPC13Unbreakable Domain Models - DPC13
Unbreakable Domain Models - DPC13Mathias Verraes
 
The Beautiful Simplicity of ES2015
The Beautiful Simplicity of ES2015The Beautiful Simplicity of ES2015
The Beautiful Simplicity of ES2015Brandon Belvin
 
Writing Sensible Code
Writing Sensible CodeWriting Sensible Code
Writing Sensible CodeAnis Ahmad
 
Coding for Scale and Sanity
Coding for Scale and SanityCoding for Scale and Sanity
Coding for Scale and SanityJimKellerES
 
Taming forms with React
Taming forms with ReactTaming forms with React
Taming forms with ReactGreeceJS
 
Instant Dynamic Forms with #states
Instant Dynamic Forms with #statesInstant Dynamic Forms with #states
Instant Dynamic Forms with #statesKonstantin Käfer
 
50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 MinutesAzim Kurt
 
Form demoinplaywithmysql
Form demoinplaywithmysqlForm demoinplaywithmysql
Form demoinplaywithmysqlKnoldus Inc.
 
Learning the basics of the Drupal API
Learning the basics of the Drupal APILearning the basics of the Drupal API
Learning the basics of the Drupal APIAlexandru Badiu
 

Tendances (20)

Leveraging Symfony2 Forms
Leveraging Symfony2 FormsLeveraging Symfony2 Forms
Leveraging Symfony2 Forms
 
Gravity Forms Hooks & Filters
Gravity Forms Hooks & FiltersGravity Forms Hooks & Filters
Gravity Forms Hooks & Filters
 
WordPress overloading Gravityforms using hooks, filters and extending classes
WordPress overloading Gravityforms using hooks, filters and extending classes WordPress overloading Gravityforms using hooks, filters and extending classes
WordPress overloading Gravityforms using hooks, filters and extending classes
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenarios
 
Oop php 5
Oop php 5Oop php 5
Oop php 5
 
Dutch php a short tale about state machine
Dutch php   a short tale about state machineDutch php   a short tale about state machine
Dutch php a short tale about state machine
 
11. CodeIgniter vederea unei singure inregistrari
11. CodeIgniter vederea unei singure inregistrari11. CodeIgniter vederea unei singure inregistrari
11. CodeIgniter vederea unei singure inregistrari
 
D8 Form api
D8 Form apiD8 Form api
D8 Form api
 
Rails <form> Chronicle
Rails <form> ChronicleRails <form> Chronicle
Rails <form> Chronicle
 
WordCamp Denver 2012 - Custom Meta Boxes
WordCamp Denver 2012 - Custom Meta BoxesWordCamp Denver 2012 - Custom Meta Boxes
WordCamp Denver 2012 - Custom Meta Boxes
 
Unbreakable Domain Models - DPC13
Unbreakable Domain Models - DPC13Unbreakable Domain Models - DPC13
Unbreakable Domain Models - DPC13
 
The Beautiful Simplicity of ES2015
The Beautiful Simplicity of ES2015The Beautiful Simplicity of ES2015
The Beautiful Simplicity of ES2015
 
Writing Sensible Code
Writing Sensible CodeWriting Sensible Code
Writing Sensible Code
 
Zend framework 04 - forms
Zend framework 04 - formsZend framework 04 - forms
Zend framework 04 - forms
 
Coding for Scale and Sanity
Coding for Scale and SanityCoding for Scale and Sanity
Coding for Scale and Sanity
 
Taming forms with React
Taming forms with ReactTaming forms with React
Taming forms with React
 
Instant Dynamic Forms with #states
Instant Dynamic Forms with #statesInstant Dynamic Forms with #states
Instant Dynamic Forms with #states
 
50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes
 
Form demoinplaywithmysql
Form demoinplaywithmysqlForm demoinplaywithmysql
Form demoinplaywithmysql
 
Learning the basics of the Drupal API
Learning the basics of the Drupal APILearning the basics of the Drupal API
Learning the basics of the Drupal API
 

Similaire à ZG PHP - Specification

Zend Framework and the Doctrine2 MongoDB ODM (ZF1)
Zend Framework and the Doctrine2 MongoDB ODM (ZF1)Zend Framework and the Doctrine2 MongoDB ODM (ZF1)
Zend Framework and the Doctrine2 MongoDB ODM (ZF1)Ryan Mauger
 
Migrating to dependency injection
Migrating to dependency injectionMigrating to dependency injection
Migrating to dependency injectionJosh Adell
 
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you needDutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you needKacper Gunia
 
Decoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDDDecoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDDAleix Vergés
 
[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...
[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...
[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...Mateusz Zalewski
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodeSWIFTotter Solutions
 
Lessons learned from functional programming
Lessons learned from functional programmingLessons learned from functional programming
Lessons learned from functional programmingBryceLohr
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
 
Revisiting SOLID Principles
Revisiting  SOLID Principles Revisiting  SOLID Principles
Revisiting SOLID Principles Anis Ahmad
 
PHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersPHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersKacper Gunia
 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsSam Hennessy
 
Meet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
Meet Magento Sweden - Magento 2 Layout and Code Compilation for PerformanceMeet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
Meet Magento Sweden - Magento 2 Layout and Code Compilation for PerformanceIvan Chepurnyi
 
Android Design Patterns
Android Design PatternsAndroid Design Patterns
Android Design PatternsGodfrey Nolan
 
Laravel Design Patterns
Laravel Design PatternsLaravel Design Patterns
Laravel Design PatternsBobby Bouwmann
 
Practical Event Sourcing
Practical Event SourcingPractical Event Sourcing
Practical Event SourcingMathias Verraes
 
Key Insights into Development Design Patterns for Magento 2 - Magento Live UK
Key Insights into Development Design Patterns for Magento 2 - Magento Live UKKey Insights into Development Design Patterns for Magento 2 - Magento Live UK
Key Insights into Development Design Patterns for Magento 2 - Magento Live UKMax Pronko
 
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011Alessandro Nadalin
 

Similaire à ZG PHP - Specification (20)

Zend Framework and the Doctrine2 MongoDB ODM (ZF1)
Zend Framework and the Doctrine2 MongoDB ODM (ZF1)Zend Framework and the Doctrine2 MongoDB ODM (ZF1)
Zend Framework and the Doctrine2 MongoDB ODM (ZF1)
 
Migrating to dependency injection
Migrating to dependency injectionMigrating to dependency injection
Migrating to dependency injection
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
 
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you needDutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
 
Decoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDDDecoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDD
 
[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...
[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...
[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better Code
 
Lessons learned from functional programming
Lessons learned from functional programmingLessons learned from functional programming
Lessons learned from functional programming
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Patterns in PHP
Patterns in PHPPatterns in PHP
Patterns in PHP
 
Revisiting SOLID Principles
Revisiting  SOLID Principles Revisiting  SOLID Principles
Revisiting SOLID Principles
 
PHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersPHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4Developers
 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy Applications
 
Meet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
Meet Magento Sweden - Magento 2 Layout and Code Compilation for PerformanceMeet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
Meet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
 
Android Design Patterns
Android Design PatternsAndroid Design Patterns
Android Design Patterns
 
Laravel Design Patterns
Laravel Design PatternsLaravel Design Patterns
Laravel Design Patterns
 
Practical Event Sourcing
Practical Event SourcingPractical Event Sourcing
Practical Event Sourcing
 
Doctrine and NoSQL
Doctrine and NoSQLDoctrine and NoSQL
Doctrine and NoSQL
 
Key Insights into Development Design Patterns for Magento 2 - Magento Live UK
Key Insights into Development Design Patterns for Magento 2 - Magento Live UKKey Insights into Development Design Patterns for Magento 2 - Magento Live UK
Key Insights into Development Design Patterns for Magento 2 - Magento Live UK
 
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
 

Dernier

Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024Mind IT Systems
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfVishalKumarJha10
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...Health
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...OnePlan Solutions
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension AidPhilip Schwarz
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfproinshot.com
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnAmarnathKambale
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplatePresentation.STUDIO
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...kalichargn70th171
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesVictorSzoltysek
 

Dernier (20)

Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdf
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 

ZG PHP - Specification

  • 5. — WHAT IS A SPECIFICATION? — Design pattern used to codify business rules that state something about an object
  • 6. Cheap to WRITE
 MAINTAIN Complex LOGIC Easy to TEST To encapsulate a business rule which does not belong inside entities or value, but is applied to it. — WHY TO USE A SPECIFICATION? — To make a business rule explicit in the codebase. To make a business rule a first-class citizen of your codebase - domain.
  • 7. Assertion Build to order Selection — HOW TO USE A SPECIFICATION? —
  • 8. — ASSERTION — interface CustomerSpecification { public function isSatisfiedBy(Customer $customer) : bool; } final class CustomerIsPremium implements CustomerSpecification { private $orderRepository; public function __construct(OrderRepositoryInterface $orderRepository) { $this->orderRepository = $orderRepository; } public function isSatisfiedBy(Customer $customer) : bool { return $this->orderRepository->countFor($customer) > 3; } } $customer = $customerRepository->findById(42); $spec = new CustomerIsPremium($orderRepository); $spec->isSatisfiedBy($customer);
  • 9. — ASSERTION - COMPOSITE - AND — final class AndSpecification extends AbstractSpecification implements SpecificationInterface { /** @var AbstractSpecification */ private $one; /** @var AbstractSpecification */ private $two; /** * @param AbstractSpecification $one * @param AbstractSpecification $two */ public function __construct(AbstractSpecification $one, AbstractSpecification $two) { $this->one = $one; $this->two = $two; } /** * @param mixed $object */ public function isSatisfiedBy($object) : bool { return $this->one->isSatisfiedBy($object) && $this->two->isSatisfiedBy($object); } }
  • 10. — ASSERTION - COMPOSITE - OR — final class OrSpecification extends AbstractSpecification implements SpecificationInterface { /** @var AbstractSpecification */ private $one; /** @var AbstractSpecification */ private $two; /** * @param AbstractSpecification $one * @param AbstractSpecification $two */ public function __construct(AbstractSpecification $one, AbstractSpecification $two) { $this->one = $one; $this->two = $two; } /** * @param mixed $object */ public function isSatisfiedBy($object) : bool { return $this->one->isSatisfiedBy($object) || $this->two->isSatisfiedBy($object); } }
  • 11. — ASSERTION - COMPOSITE - NOT — final class NotSpecification extends AbstractSpecification implements SpecificationInterface { /** @var AbstractSpecification */ private $spec; /** * @param AbstractSpecification $spec */ public function __construct(AbstractSpecification $spec) { $this->spec = $spec; } /** * @param mixed $object */ public function isSatisfiedBy($object) : bool
 { return !$this->spec->isSatisfiedBy($object); } }
  • 12. — ASSERTION - COMPOSITE — $specAnd = new AndSpecification( new CustomerIsPremium($orderRepository), new CustomerHasOverdueInvoices($invoiceRepository) ); $specAnd->isSatisfiedBy($customer); $specOr = new OrSpecification( new CustomerIsPremium($orderRepository), new CustomerHasOverdueInvoices($invoiceRepository) ); $specOr->isSatisfiedBy($customer); $CustomerIsNotPremium = new NotSpecification( new CustomerIsPremium($orderRepository) ); $specNot->isSatisfiedBy($customer);
  • 13. — ASSERTION - COMPOSITE - PIPE IT BABY — abstract class AbstractSpecification { /** * @param AbstractSpecification $other * @return SpecificationInterface */ public function andSpecification(AbstractSpecification $other) { return new AndSpecification($this, $other); } /** * @param AbstractSpecification $other * @return SpecificationInterface */ public function orSpecification(AbstractSpecification $other) { return new OrSpecification($this, $other); } /** * @return SpecificationInterface */ public function notSpecification() { return new NotSpecification($this); } }
  • 15. — SELECTION — interface SqlSpecification { /** @return string */ public function asSql(); } final class CustomerIsPremium implements CustomerSpecification, SqlSpecification { // ... /** @return string */ public function asSql() { return "SELECT * FROM customers LEFT JOIN orders ON ..."; } }
  • 16. — SELECTION — interface RepositoryCompatibleSpecification { public function applyToRepository(SpecificationReceivableRepository $repo); } interface RepositoryCompatibleSpecification { public function getRecordsMatching(RepositoryCompatibleSpecification $spec) : array; }
  • 17. — SELECTION — EXAMPLE OF SPECIFICATION USED FOR SELECTION WITH DOCTRINE https://github.com/Happyr/Doctrine-Specification
  • 18. — SELECTION - COMPOSITE - PIPE —
  • 20. — BUILD TO ORDER —
  • 22. Ad TransactionBasket — BUILD TO ORDER — Entity vs Value
  • 23. — BUILD TO ORDER — final class Basket { private $products = array(); private $amount = 0.0; public function __construct(array $products = array()) { foreach ($products as $product) { $this->products[$product->getProductId()] = $product; $this->amount += $product->getPrice(); } } public function hasProduct(Product $product) { return isset($this->products[$product->getProductId()]); } public function getAmount() { return $this->amount; } public function getProducts() { return $this->products; } }
  • 24. — BUILD TO ORDER — class BasketOperationService { public function addProductToBasket(Basket $basket, Product $product) { $products = $basket->getProducts(); $products[$product->getProductId()] = $product; $newBasket = new Basket($products); return $newBasket; } public function removeProductFromBasket(Basket $basket, Product $product) { $products = $basket->getProducts(); unset($products[$product->getProductId()]); $newBasket = new Basket($products); return $newBasket; } }
  • 25. — BUILD TO ORDER — class ProductIsInBasketSpecification { public function isSatisfiedBy(Basket $basket, Product $product) { return $basket->hasProduct($product); } }
  • 26. — BUILD TO ORDER — class BasketCanBeBoughtSpecification { public function isSatisfiedBy(Basket $basket, User $user) { if ($basket->getAmount() <= $user->getCurrentBalanceAmount()) { return true; } return false; } }
  • 27. — BUILD TO ORDER — final class TriedToAddProductToBasketEvent { private $basket; private $product; private $user; public function __construct(Basket $basket, Product $product, User $user) { $this->basket = $basket; $this->product = $product; $this->user = $user; } public function getProduct() { return $this->product; } public function getBasket() { return $this->basket; } public function getUser() { return $this->user; } }
  • 28. — BUILD TO ORDER —
  • 29. — BUILD TO ORDER — class TriedToAddProductToBasketEventSubscriber { public function onTriedToAddProductToBasketEvent(TriedToAddProductToBasketEvent $event, EventDispatcher $dispatcher) { $basket = $event->getBasket(); $product = $event->getProduct(); $user = $event->getUser(); $communicatorService = $dispatcher->getFrontendCommunicatorService(); $productIsInBasketSpecification = new ProductIsInBasketSpecification(); if ($productIsInBasketSpecification->isSatisfiedBy($basket, $product)) { $communicatorService->showError('Product already in basket!', $product); } else { $basketOperationService = new BasketOperationService(); $newBasket = $basketOperationService->addProductToBasket($basket, $product); $basketCanBeBoughtSpecification = new BasketCanBeBoughtSpecification(); if ($basketCanBeBoughtSpecification->isSatisfiedBy($newBasket, $user)) { /* ... Replace $basket with $newBasket in DIC for further events to use it ... */ $communicatorService->showProductInBasket($product); $communicatorService->setTotalPrice($newBasket->getAmount()); } else { $communicatorService->showError('Not enough funds!', $product); } } } }
  • 30. — BUILD TO ORDER —
  • 31. — BUILD TO ORDER —
  • 32. — FURTHER READING — “THE BLUE BOOK” https://www.amazon.com/gp/product/B00794TAUG/ EXAMPLE OF SPECIFICATION USED FOR SELECTION WITH DOCTRINE https://github.com/Happyr/Doctrine-Specification BLOG POST 4 QUICK PEEK http://marcaube.ca/2015/05/specifications MARTIN FOWLER https://www.martinfowler.com/apsupp/spec.pdf “THE YELLOW BOOK” https://leanpub.com/ddd-in-php?a=Ug88MJbcykCAu8AEAWNjDA
  • 33. Q&A Robert Šorn COO @ TRIKODER robert.sorn@trikoder.net ks, ks, BTW, Trikoder is hiring! ;) Head of PM, PHP developers, Java developers, UX/UI specialist, … work@trikoder.net
  • 34. THANK YOU Robert Šorn COO @ TRIKODER robert.sorn@trikoder.net