SlideShare uma empresa Scribd logo
1 de 27
Baixar para ler offline
Why Is CRUD a Bad Idea
Focus on Real Scenarios
Petr Heinz
More than 8 years of programming experience.
Loves clean code, regular expressions and
clever design.
Dedicated last year to developing the Shopsys
Framework, open source e-commerce
framework made with passion on Symfony 3.
✉ petr.heinz@shopsys.com
Typical CRUD
Create, Read, Update and Delete
Four basic functions of an persistent storage, often used as an API.
Can be mapped to SQL statements:
INSERT SELECT UPDATE DELETE
Can be mapped to HTTP methods (used in REST APIs):
PUT GET POST DELETE
Example: Article
class Article {
private $author, $text, $state, $published;
public function setAuthor(Author $author) {
$this->author = $author;
}
public function getAuthor() {
return $this->author;
}
public function setText($text) {
$this->text = $text;
}
// ...
}
class ArticleController {
public function create(...) {
// ...
}
public function update(...) {
// ...
$article->setAuthor($author);
$article->setText($text);
$article->setState($state);
$article->setPublished($published);
}
public function delete(...) {
// ...
}
}
Entities Must Follow Business Rules
Entities are often constrained by business rules and the consistency must be kept.
● Company customer must have VAT ID filled in his account.
● Sold out product must be hidden.
● Article in published state must have published date.
This is difficult to achieve in the previous example. That’s because all article
attributes can be changed independently. Developers are not restricted in the way
they interact with the object.
Example: Article without setters
class Article {
const STATE_UNPUBLISHED = 1;
const STATE_PUBLISHED = 2;
const STATE_DELETED = 3;
private $author, $text, $state, $published;
public function __construct(Author $author, $text, $state, DateTime $published = null) {
// ...
}
public function update(Author $author, $text, $state, DateTime $published = null) {
// ...
}
public function delete() {
$this->state = self::STATE_DELETED;
}
}
Example: Article without setters
class Article {
// ...
public function update(Author $author, $text, $state, DateTime $published = null) {
if ($this->state === self::STATE_DELETED) {
throw new ArticleIsDeletedException($this);
}
$this->author = $author;
$this->text = $text;
$this->state = $state;
if ($state === self::STATE_PUBLISHED) {
$this->published = $published ?: new DateTime();
} elseif ($state === self::STATE_UNPUBLISHED) {
$this->published = null;
}
}
}
What Is an Object Anyway?
Object Oriented Programming
Objects have both data (their properties) and behavior (their methods).
Objects model real-world behavior, concepts and relationships.
Encapsulation principle tells us to hide the details about the data and focus solely
on the behavior - the public methods of our objects (“Tell, Don’t Ask”).
In PHP it is easy to combine procedural and object-oriented programming.
Example: Bank Account Object
class BankAccount {
private $balance;
public function __construct(Money $balance) {
$this->balance = $balance;
}
public function deposit(Money $amount) {
$this->balance = $this->balance->add($amount);
}
public function withdraw(Money $amount) {
if ($this->balance->isLessThan($amount)) {
throw new InsufficientFundsException($balance, $amount);
}
$this->balance = $this->balance->subtract($amount);
}
}
Anemic / Rich Domain Model
Let’s Define Some Terms First
Domain: Most common definition: “A sphere of knowledge or activity.”
It’s basically the subject area of your application (eg. an online store or news site).
Domain Model: System of abstractions describing part of the domain that can be
used to solve problems. Simplification of the real world.
Domain Object: Object that is part of the domain model (eg. Product, Order, …).
Business Logic: High-level logic reflecting the real-world business rules.
Anemic Domain Model
No business logic in domain objects
Clearly separates logic and data
Violates object encapsulation
Works well for simple applications
Leads to procedural programming
Called an anti-pattern by M. Fowler
Business logic mainly in domain objects
Domain objects encapsulate inner data,
offer meaningful behavior
Data integrity kept by the encapsulation
Better choice for complex domain
models
Rich Domain Model
Anemic Domain Model Rich Domain Model
class Worker {
function getVelocity() {
return $this->velocity;
}
function setVelocity($velocity) {
$this->velocity = $velocity;
}
}
class WorkerService {
function work(Worker $w, Task $t, $time) {
$progress = $t->getProgress();
$progress += $w->getVelocity() * $time;
$t->setProgress($progress);
}
}
class Worker {
function __construct($velocity) {
$this->velocity = $velocity;
}
function work(Task $task, $time) {
$progress = $this->velocity * $time;
$task->makeProgress($progress);
}
}
The Problem Lies in Setters
Setters Do Not Exist in the Real World
Setters have no meaning in the real world:
● A writer does not set a “published” state to an article, he/she publishes it.
● Customers do not set a “paid” status to an order, they pay for it.
● Your happy boss does not set a higher salary to you, he/she raises it.
There is always a better, more expressive, alternative to a setter.
Expressive statements lead to more readable code.
Nobody Expects The Setters To Do Stuff
Similarly to adding logic to a CRUD
update, you might feel the need to add
some business logic to your setter.
The problem with this is that nobody
expects setters to do anything beside
setting the property.
An unexpected behavior leads to bugs.
class Order {
// ...
public function setStatus($status) {
if (!$this->isValidStatus($status)) {
throw new InvalidArgumentException();
}
$this->status = $status;
if ($status === self::STATUS_PAID) {
$this->mailService->sendOrderPaidMail(
$this->orderNumber, $this->customer
);
}
}
}
Nobody Expects The Setters To Do Stuff
Similarly to adding logic to a CRUD
update, you might feel the need to add
some business logic to your setter.
The problem with this is that nobody
expects setters to do anything beside
setting the property.
An unexpected behavior leads to bugs.
class Order {
// ...
public function pay() {
$this->status = self::STATUS_PAID;
$this->mailService->sendOrderPaidMail(
$this->orderNumber, $this->customer
);
}
public function cancel() {
$this->status = self::STATUS_CANCELLED;
}
}
An Update in CRUD Is Similar to a Setter
Generic update method in CRUD is similar to a setter:
● It does not have a real-world meaning.
● There are better alternatives based on real scenarios to be implemented.
For example, by “updating” an article we mean “rewriting” it and possibly
“publishing”, “unpublishing” or “deleting” it.
Conclusion and
Recommendations
Focus on Real Scenarios
By building your application around you domain objects and their behavior you
can get expressive code that is easier to understand, use and maintain.
Concept of “setting” or “updating” to too generic to be meaningful.
Your API should be focused on real scenarios, real use-cases. This will keep the
API clean and intuitive and it will help you keep the integrity of your data.
Think About the Way You Program
There is no best way, no silver bullet. And there probably never will be one.
Keep in mind the techniques of object-oriented programming, encapsulation
principle, focusing on the behavior.
Knowing about the two extremes will help you improve the design of your
application and choose the proper solution for your project.
Need CRUD methods? Add a Layer.
If you for some reason want to
allow classical CRUD methods,
you can build it on top of your
internal API.
You can use Adapter pattern for
this task.
class Article {
// ...
public function update(...) {
if ($this->state === self::STATE_DELETED) {
throw new ArticleIsDeletedEx($this);
}
$this->author = $author;
$this->text = $text;
$this->state = $state;
if ($state === self::STATE_PUBLISHED) {
$this->published = $published ?: new DateTime();
} elseif ($state === self::STATE_UNPUBLISHED) {
$this->published = null;
}
}
}
Need CRUD methods? Add a Layer.
If you for some reason want to
allow classical CRUD methods,
you can build it on top of your
internal API.
You can use Adapter pattern for
this task.
class ArticleCrudAdapter {
// ...
public function update(...) {
if ($this->article->isDeleted()) {
throw new ArticleIsDeletedEx($this->article);
}
$this->article->rewrite($text, $author);
switch ($state) {
case Article::STATE_PUBLISHED:
$this->article->publish($published); break;
case Article::STATE_UNPUBLISHED:
$this->article->unpublish(); break;
case Article::STATE_DELETED:
$this->article->delete(); break;
}
}
}
It Is About the Balance
Every way has its tradeoffs and, as always, it is about the balance.
Focusing on real-world use-cases helps to maintain integrity and usability.
Integration with other libraries or components is easier with generic methods.
When developing Shopsys Framework we try to keep that in mind, and take
inspiration from Rich Domain Model.
See for yourself, join closed beta: https://www.shopsys-framework.com
Thanks for listening!
Let’s get down to your questions!

Mais conteúdo relacionado

Mais procurados

Doctrine fixtures
Doctrine fixturesDoctrine fixtures
Doctrine fixtures
Bill Chang
 
Design Patterns in PHP5
Design Patterns in PHP5 Design Patterns in PHP5
Design Patterns in PHP5
Wildan Maulana
 

Mais procurados (20)

PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolve
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
 
Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)
 
Hacking Your Way To Better Security - Dutch PHP Conference 2016
Hacking Your Way To Better Security - Dutch PHP Conference 2016Hacking Your Way To Better Security - Dutch PHP Conference 2016
Hacking Your Way To Better Security - Dutch PHP Conference 2016
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et Pimple
 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technology
 
Doctrine fixtures
Doctrine fixturesDoctrine fixtures
Doctrine fixtures
 
Xlab #1: Advantages of functional programming in Java 8
Xlab #1: Advantages of functional programming in Java 8Xlab #1: Advantages of functional programming in Java 8
Xlab #1: Advantages of functional programming in Java 8
 
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
 
Lithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksLithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate Frameworks
 
Oops in php
Oops in phpOops in php
Oops in php
 
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
 
The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016
 
Design Patterns in PHP5
Design Patterns in PHP5 Design Patterns in PHP5
Design Patterns in PHP5
 
The IoC Hydra
The IoC HydraThe IoC Hydra
The IoC Hydra
 
When cqrs meets event sourcing
When cqrs meets event sourcingWhen cqrs meets event sourcing
When cqrs meets event sourcing
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
 
Symfony World - Symfony components and design patterns
Symfony World - Symfony components and design patternsSymfony World - Symfony components and design patterns
Symfony World - Symfony components and design patterns
 
Forget about index.php and build you applications around HTTP!
Forget about index.php and build you applications around HTTP!Forget about index.php and build you applications around HTTP!
Forget about index.php and build you applications around HTTP!
 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mocking
 

Semelhante a Why is crud a bad idea - focus on real scenarios

Semelhante a Why is crud a bad idea - focus on real scenarios (20)

Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Framework
FrameworkFramework
Framework
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
 
PHPSpec BDD Framework
PHPSpec BDD FrameworkPHPSpec BDD Framework
PHPSpec BDD Framework
 
Zend framework service
Zend framework serviceZend framework service
Zend framework service
 
Zend framework service
Zend framework serviceZend framework service
Zend framework service
 
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
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
 
Tidy Up Your Code
Tidy Up Your CodeTidy Up Your Code
Tidy Up Your Code
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
 
Как получить чёрный пояс по WordPress?
Как получить чёрный пояс по WordPress?Как получить чёрный пояс по WordPress?
Как получить чёрный пояс по WordPress?
 
Как получить чёрный пояс по WordPress? v2.0
Как получить чёрный пояс по WordPress? v2.0Как получить чёрный пояс по WordPress? v2.0
Как получить чёрный пояс по WordPress? v2.0
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5
 
Fatc
FatcFatc
Fatc
 
PHP Unit Testing
PHP Unit TestingPHP Unit Testing
PHP Unit Testing
 
PHPSpec BDD for PHP
PHPSpec BDD for PHPPHPSpec BDD for PHP
PHPSpec BDD for PHP
 
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
 
Multilingualism makes better programmers
Multilingualism makes better programmersMultilingualism makes better programmers
Multilingualism makes better programmers
 
4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk
4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk
4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk
 

Mais de Divante

eCommerce trends 2019 by Divante.co
eCommerce trends 2019 by Divante.coeCommerce trends 2019 by Divante.co
eCommerce trends 2019 by Divante.co
Divante
 

Mais de Divante (20)

The eCommerce Platforms in the Global Setup
The eCommerce Platforms in the Global Setup	The eCommerce Platforms in the Global Setup
The eCommerce Platforms in the Global Setup
 
eCommerce Trends 2020
eCommerce Trends 2020eCommerce Trends 2020
eCommerce Trends 2020
 
Async & Bulk REST API new possibilities of communication between systems
Async & Bulk REST API new possibilities of communication  between systemsAsync & Bulk REST API new possibilities of communication  between systems
Async & Bulk REST API new possibilities of communication between systems
 
Magento Functional Testing Framework a way to seriously write automated tests...
Magento Functional Testing Framework a way to seriously write automated tests...Magento Functional Testing Framework a way to seriously write automated tests...
Magento Functional Testing Framework a way to seriously write automated tests...
 
Die Top 10 Progressive Web Apps in der Modernbranche
Die Top 10 Progressive Web Apps in der ModernbrancheDie Top 10 Progressive Web Apps in der Modernbranche
Die Top 10 Progressive Web Apps in der Modernbranche
 
progressive web apps - pwa as a game changer for e-commerce - meet magento i...
 progressive web apps - pwa as a game changer for e-commerce - meet magento i... progressive web apps - pwa as a game changer for e-commerce - meet magento i...
progressive web apps - pwa as a game changer for e-commerce - meet magento i...
 
Customer churn - how to stop it?
Customer churn - how to stop it?Customer churn - how to stop it?
Customer churn - how to stop it?
 
eCommerce trends 2019 by Divante.co
eCommerce trends 2019 by Divante.coeCommerce trends 2019 by Divante.co
eCommerce trends 2019 by Divante.co
 
How to create a Vue Storefront theme
How to create a Vue Storefront themeHow to create a Vue Storefront theme
How to create a Vue Storefront theme
 
Game changer for e-commerce - Vue Storefront - open source pwa
Game changer for e-commerce - Vue Storefront - open source pwa Game changer for e-commerce - Vue Storefront - open source pwa
Game changer for e-commerce - Vue Storefront - open source pwa
 
Vue Storefront - Progressive Web App for Magento (1.9, 2.x) - MM18DE speech
Vue Storefront - Progressive Web App for Magento (1.9, 2.x) - MM18DE speechVue Storefront - Progressive Web App for Magento (1.9, 2.x) - MM18DE speech
Vue Storefront - Progressive Web App for Magento (1.9, 2.x) - MM18DE speech
 
How to successfully onboard end-clients to a B2B Platform - Magento Imagine ...
How to successfully onboard  end-clients to a B2B Platform - Magento Imagine ...How to successfully onboard  end-clients to a B2B Platform - Magento Imagine ...
How to successfully onboard end-clients to a B2B Platform - Magento Imagine ...
 
eCommerce trends from 2017 to 2018 by Divante.co
eCommerce trends from 2017 to 2018 by Divante.coeCommerce trends from 2017 to 2018 by Divante.co
eCommerce trends from 2017 to 2018 by Divante.co
 
Designing for PWA (Progressive Web Apps)
Designing for PWA (Progressive Web Apps)Designing for PWA (Progressive Web Apps)
Designing for PWA (Progressive Web Apps)
 
vue-storefront - PWA eCommerce for Magento2 MM17NYC presentation
vue-storefront - PWA eCommerce for Magento2 MM17NYC presentationvue-storefront - PWA eCommerce for Magento2 MM17NYC presentation
vue-storefront - PWA eCommerce for Magento2 MM17NYC presentation
 
Pimcore Overview - Pimcore5
Pimcore Overview - Pimcore5Pimcore Overview - Pimcore5
Pimcore Overview - Pimcore5
 
Pimcore E-Commerce Framework - Pimcore5
Pimcore E-Commerce Framework - Pimcore5Pimcore E-Commerce Framework - Pimcore5
Pimcore E-Commerce Framework - Pimcore5
 
The biggest stores on Magento
The biggest stores on MagentoThe biggest stores on Magento
The biggest stores on Magento
 
B2B Commerce - how to become successful
B2B Commerce - how to become successfulB2B Commerce - how to become successful
B2B Commerce - how to become successful
 
Budgeting in SCRUM by Divante
Budgeting in SCRUM by DivanteBudgeting in SCRUM by Divante
Budgeting in SCRUM by Divante
 

Último

pdfcoffee.com_business-ethics-q3m7-pdf-free.pdf
pdfcoffee.com_business-ethics-q3m7-pdf-free.pdfpdfcoffee.com_business-ethics-q3m7-pdf-free.pdf
pdfcoffee.com_business-ethics-q3m7-pdf-free.pdf
JOHNBEBONYAP1
 
Call Girls in Prashant Vihar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Prashant Vihar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort ServiceCall Girls in Prashant Vihar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Prashant Vihar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
VIP Call Girls Himatnagar 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Himatnagar 7001035870 Whatsapp Number, 24/07 BookingVIP Call Girls Himatnagar 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Himatnagar 7001035870 Whatsapp Number, 24/07 Booking
dharasingh5698
 
Thalassery Escorts Service ☎️ 6378878445 ( Sakshi Sinha ) High Profile Call G...
Thalassery Escorts Service ☎️ 6378878445 ( Sakshi Sinha ) High Profile Call G...Thalassery Escorts Service ☎️ 6378878445 ( Sakshi Sinha ) High Profile Call G...
Thalassery Escorts Service ☎️ 6378878445 ( Sakshi Sinha ) High Profile Call G...
Call Girls In Delhi Whatsup 9873940964 Enjoy Unlimited Pleasure
 
Low Sexy Call Girls In Mohali 9053900678 🥵Have Save And Good Place 🥵
Low Sexy Call Girls In Mohali 9053900678 🥵Have Save And Good Place 🥵Low Sexy Call Girls In Mohali 9053900678 🥵Have Save And Good Place 🥵
Low Sexy Call Girls In Mohali 9053900678 🥵Have Save And Good Place 🥵
Chandigarh Call girls 9053900678 Call girls in Chandigarh
 
📱Dehradun Call Girls Service 📱☎️ +91'905,3900,678 ☎️📱 Call Girls In Dehradun 📱
📱Dehradun Call Girls Service 📱☎️ +91'905,3900,678 ☎️📱 Call Girls In Dehradun 📱📱Dehradun Call Girls Service 📱☎️ +91'905,3900,678 ☎️📱 Call Girls In Dehradun 📱
📱Dehradun Call Girls Service 📱☎️ +91'905,3900,678 ☎️📱 Call Girls In Dehradun 📱
@Chandigarh #call #Girls 9053900678 @Call #Girls in @Punjab 9053900678
 
valsad Escorts Service ☎️ 6378878445 ( Sakshi Sinha ) High Profile Call Girls...
valsad Escorts Service ☎️ 6378878445 ( Sakshi Sinha ) High Profile Call Girls...valsad Escorts Service ☎️ 6378878445 ( Sakshi Sinha ) High Profile Call Girls...
valsad Escorts Service ☎️ 6378878445 ( Sakshi Sinha ) High Profile Call Girls...
Call Girls In Delhi Whatsup 9873940964 Enjoy Unlimited Pleasure
 
VIP Call Girls Pollachi 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Pollachi 7001035870 Whatsapp Number, 24/07 BookingVIP Call Girls Pollachi 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Pollachi 7001035870 Whatsapp Number, 24/07 Booking
dharasingh5698
 
在线制作约克大学毕业证(yu毕业证)在读证明认证可查
在线制作约克大学毕业证(yu毕业证)在读证明认证可查在线制作约克大学毕业证(yu毕业证)在读证明认证可查
在线制作约克大学毕业证(yu毕业证)在读证明认证可查
ydyuyu
 

Último (20)

Ganeshkhind ! Call Girls Pune - 450+ Call Girl Cash Payment 8005736733 Neha T...
Ganeshkhind ! Call Girls Pune - 450+ Call Girl Cash Payment 8005736733 Neha T...Ganeshkhind ! Call Girls Pune - 450+ Call Girl Cash Payment 8005736733 Neha T...
Ganeshkhind ! Call Girls Pune - 450+ Call Girl Cash Payment 8005736733 Neha T...
 
best call girls in Hyderabad Finest Escorts Service 📞 9352988975 📞 Available ...
best call girls in Hyderabad Finest Escorts Service 📞 9352988975 📞 Available ...best call girls in Hyderabad Finest Escorts Service 📞 9352988975 📞 Available ...
best call girls in Hyderabad Finest Escorts Service 📞 9352988975 📞 Available ...
 
Trump Diapers Over Dems t shirts Sweatshirt
Trump Diapers Over Dems t shirts SweatshirtTrump Diapers Over Dems t shirts Sweatshirt
Trump Diapers Over Dems t shirts Sweatshirt
 
pdfcoffee.com_business-ethics-q3m7-pdf-free.pdf
pdfcoffee.com_business-ethics-q3m7-pdf-free.pdfpdfcoffee.com_business-ethics-q3m7-pdf-free.pdf
pdfcoffee.com_business-ethics-q3m7-pdf-free.pdf
 
Busty Desi⚡Call Girls in Vasundhara Ghaziabad >༒8448380779 Escort Service
Busty Desi⚡Call Girls in Vasundhara Ghaziabad >༒8448380779 Escort ServiceBusty Desi⚡Call Girls in Vasundhara Ghaziabad >༒8448380779 Escort Service
Busty Desi⚡Call Girls in Vasundhara Ghaziabad >༒8448380779 Escort Service
 
Katraj ( Call Girls ) Pune 6297143586 Hot Model With Sexy Bhabi Ready For S...
Katraj ( Call Girls ) Pune  6297143586  Hot Model With Sexy Bhabi Ready For S...Katraj ( Call Girls ) Pune  6297143586  Hot Model With Sexy Bhabi Ready For S...
Katraj ( Call Girls ) Pune 6297143586 Hot Model With Sexy Bhabi Ready For S...
 
Call Girls in Prashant Vihar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Prashant Vihar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort ServiceCall Girls in Prashant Vihar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
Call Girls in Prashant Vihar, Delhi 💯 Call Us 🔝9953056974 🔝 Escort Service
 
VIP Call Girls Himatnagar 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Himatnagar 7001035870 Whatsapp Number, 24/07 BookingVIP Call Girls Himatnagar 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Himatnagar 7001035870 Whatsapp Number, 24/07 Booking
 
Thalassery Escorts Service ☎️ 6378878445 ( Sakshi Sinha ) High Profile Call G...
Thalassery Escorts Service ☎️ 6378878445 ( Sakshi Sinha ) High Profile Call G...Thalassery Escorts Service ☎️ 6378878445 ( Sakshi Sinha ) High Profile Call G...
Thalassery Escorts Service ☎️ 6378878445 ( Sakshi Sinha ) High Profile Call G...
 
Low Sexy Call Girls In Mohali 9053900678 🥵Have Save And Good Place 🥵
Low Sexy Call Girls In Mohali 9053900678 🥵Have Save And Good Place 🥵Low Sexy Call Girls In Mohali 9053900678 🥵Have Save And Good Place 🥵
Low Sexy Call Girls In Mohali 9053900678 🥵Have Save And Good Place 🥵
 
📱Dehradun Call Girls Service 📱☎️ +91'905,3900,678 ☎️📱 Call Girls In Dehradun 📱
📱Dehradun Call Girls Service 📱☎️ +91'905,3900,678 ☎️📱 Call Girls In Dehradun 📱📱Dehradun Call Girls Service 📱☎️ +91'905,3900,678 ☎️📱 Call Girls In Dehradun 📱
📱Dehradun Call Girls Service 📱☎️ +91'905,3900,678 ☎️📱 Call Girls In Dehradun 📱
 
20240507 QFM013 Machine Intelligence Reading List April 2024.pdf
20240507 QFM013 Machine Intelligence Reading List April 2024.pdf20240507 QFM013 Machine Intelligence Reading List April 2024.pdf
20240507 QFM013 Machine Intelligence Reading List April 2024.pdf
 
valsad Escorts Service ☎️ 6378878445 ( Sakshi Sinha ) High Profile Call Girls...
valsad Escorts Service ☎️ 6378878445 ( Sakshi Sinha ) High Profile Call Girls...valsad Escorts Service ☎️ 6378878445 ( Sakshi Sinha ) High Profile Call Girls...
valsad Escorts Service ☎️ 6378878445 ( Sakshi Sinha ) High Profile Call Girls...
 
(INDIRA) Call Girl Pune Call Now 8250077686 Pune Escorts 24x7
(INDIRA) Call Girl Pune Call Now 8250077686 Pune Escorts 24x7(INDIRA) Call Girl Pune Call Now 8250077686 Pune Escorts 24x7
(INDIRA) Call Girl Pune Call Now 8250077686 Pune Escorts 24x7
 
Dubai=Desi Dubai Call Girls O525547819 Outdoor Call Girls Dubai
Dubai=Desi Dubai Call Girls O525547819 Outdoor Call Girls DubaiDubai=Desi Dubai Call Girls O525547819 Outdoor Call Girls Dubai
Dubai=Desi Dubai Call Girls O525547819 Outdoor Call Girls Dubai
 
VIP Call Girls Pollachi 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Pollachi 7001035870 Whatsapp Number, 24/07 BookingVIP Call Girls Pollachi 7001035870 Whatsapp Number, 24/07 Booking
VIP Call Girls Pollachi 7001035870 Whatsapp Number, 24/07 Booking
 
Real Men Wear Diapers T Shirts sweatshirt
Real Men Wear Diapers T Shirts sweatshirtReal Men Wear Diapers T Shirts sweatshirt
Real Men Wear Diapers T Shirts sweatshirt
 
All Time Service Available Call Girls Mg Road 👌 ⏭️ 6378878445
All Time Service Available Call Girls Mg Road 👌 ⏭️ 6378878445All Time Service Available Call Girls Mg Road 👌 ⏭️ 6378878445
All Time Service Available Call Girls Mg Road 👌 ⏭️ 6378878445
 
在线制作约克大学毕业证(yu毕业证)在读证明认证可查
在线制作约克大学毕业证(yu毕业证)在读证明认证可查在线制作约克大学毕业证(yu毕业证)在读证明认证可查
在线制作约克大学毕业证(yu毕业证)在读证明认证可查
 
Pirangut | Call Girls Pune Phone No 8005736733 Elite Escort Service Available...
Pirangut | Call Girls Pune Phone No 8005736733 Elite Escort Service Available...Pirangut | Call Girls Pune Phone No 8005736733 Elite Escort Service Available...
Pirangut | Call Girls Pune Phone No 8005736733 Elite Escort Service Available...
 

Why is crud a bad idea - focus on real scenarios

  • 1. Why Is CRUD a Bad Idea Focus on Real Scenarios
  • 2. Petr Heinz More than 8 years of programming experience. Loves clean code, regular expressions and clever design. Dedicated last year to developing the Shopsys Framework, open source e-commerce framework made with passion on Symfony 3. ✉ petr.heinz@shopsys.com
  • 4. Create, Read, Update and Delete Four basic functions of an persistent storage, often used as an API. Can be mapped to SQL statements: INSERT SELECT UPDATE DELETE Can be mapped to HTTP methods (used in REST APIs): PUT GET POST DELETE
  • 5. Example: Article class Article { private $author, $text, $state, $published; public function setAuthor(Author $author) { $this->author = $author; } public function getAuthor() { return $this->author; } public function setText($text) { $this->text = $text; } // ... } class ArticleController { public function create(...) { // ... } public function update(...) { // ... $article->setAuthor($author); $article->setText($text); $article->setState($state); $article->setPublished($published); } public function delete(...) { // ... } }
  • 6. Entities Must Follow Business Rules Entities are often constrained by business rules and the consistency must be kept. ● Company customer must have VAT ID filled in his account. ● Sold out product must be hidden. ● Article in published state must have published date. This is difficult to achieve in the previous example. That’s because all article attributes can be changed independently. Developers are not restricted in the way they interact with the object.
  • 7. Example: Article without setters class Article { const STATE_UNPUBLISHED = 1; const STATE_PUBLISHED = 2; const STATE_DELETED = 3; private $author, $text, $state, $published; public function __construct(Author $author, $text, $state, DateTime $published = null) { // ... } public function update(Author $author, $text, $state, DateTime $published = null) { // ... } public function delete() { $this->state = self::STATE_DELETED; } }
  • 8. Example: Article without setters class Article { // ... public function update(Author $author, $text, $state, DateTime $published = null) { if ($this->state === self::STATE_DELETED) { throw new ArticleIsDeletedException($this); } $this->author = $author; $this->text = $text; $this->state = $state; if ($state === self::STATE_PUBLISHED) { $this->published = $published ?: new DateTime(); } elseif ($state === self::STATE_UNPUBLISHED) { $this->published = null; } } }
  • 9. What Is an Object Anyway?
  • 10. Object Oriented Programming Objects have both data (their properties) and behavior (their methods). Objects model real-world behavior, concepts and relationships. Encapsulation principle tells us to hide the details about the data and focus solely on the behavior - the public methods of our objects (“Tell, Don’t Ask”). In PHP it is easy to combine procedural and object-oriented programming.
  • 11. Example: Bank Account Object class BankAccount { private $balance; public function __construct(Money $balance) { $this->balance = $balance; } public function deposit(Money $amount) { $this->balance = $this->balance->add($amount); } public function withdraw(Money $amount) { if ($this->balance->isLessThan($amount)) { throw new InsufficientFundsException($balance, $amount); } $this->balance = $this->balance->subtract($amount); } }
  • 12. Anemic / Rich Domain Model
  • 13. Let’s Define Some Terms First Domain: Most common definition: “A sphere of knowledge or activity.” It’s basically the subject area of your application (eg. an online store or news site). Domain Model: System of abstractions describing part of the domain that can be used to solve problems. Simplification of the real world. Domain Object: Object that is part of the domain model (eg. Product, Order, …). Business Logic: High-level logic reflecting the real-world business rules.
  • 14. Anemic Domain Model No business logic in domain objects Clearly separates logic and data Violates object encapsulation Works well for simple applications Leads to procedural programming Called an anti-pattern by M. Fowler Business logic mainly in domain objects Domain objects encapsulate inner data, offer meaningful behavior Data integrity kept by the encapsulation Better choice for complex domain models Rich Domain Model
  • 15. Anemic Domain Model Rich Domain Model class Worker { function getVelocity() { return $this->velocity; } function setVelocity($velocity) { $this->velocity = $velocity; } } class WorkerService { function work(Worker $w, Task $t, $time) { $progress = $t->getProgress(); $progress += $w->getVelocity() * $time; $t->setProgress($progress); } } class Worker { function __construct($velocity) { $this->velocity = $velocity; } function work(Task $task, $time) { $progress = $this->velocity * $time; $task->makeProgress($progress); } }
  • 16. The Problem Lies in Setters
  • 17. Setters Do Not Exist in the Real World Setters have no meaning in the real world: ● A writer does not set a “published” state to an article, he/she publishes it. ● Customers do not set a “paid” status to an order, they pay for it. ● Your happy boss does not set a higher salary to you, he/she raises it. There is always a better, more expressive, alternative to a setter. Expressive statements lead to more readable code.
  • 18. Nobody Expects The Setters To Do Stuff Similarly to adding logic to a CRUD update, you might feel the need to add some business logic to your setter. The problem with this is that nobody expects setters to do anything beside setting the property. An unexpected behavior leads to bugs. class Order { // ... public function setStatus($status) { if (!$this->isValidStatus($status)) { throw new InvalidArgumentException(); } $this->status = $status; if ($status === self::STATUS_PAID) { $this->mailService->sendOrderPaidMail( $this->orderNumber, $this->customer ); } } }
  • 19. Nobody Expects The Setters To Do Stuff Similarly to adding logic to a CRUD update, you might feel the need to add some business logic to your setter. The problem with this is that nobody expects setters to do anything beside setting the property. An unexpected behavior leads to bugs. class Order { // ... public function pay() { $this->status = self::STATUS_PAID; $this->mailService->sendOrderPaidMail( $this->orderNumber, $this->customer ); } public function cancel() { $this->status = self::STATUS_CANCELLED; } }
  • 20. An Update in CRUD Is Similar to a Setter Generic update method in CRUD is similar to a setter: ● It does not have a real-world meaning. ● There are better alternatives based on real scenarios to be implemented. For example, by “updating” an article we mean “rewriting” it and possibly “publishing”, “unpublishing” or “deleting” it.
  • 22. Focus on Real Scenarios By building your application around you domain objects and their behavior you can get expressive code that is easier to understand, use and maintain. Concept of “setting” or “updating” to too generic to be meaningful. Your API should be focused on real scenarios, real use-cases. This will keep the API clean and intuitive and it will help you keep the integrity of your data.
  • 23. Think About the Way You Program There is no best way, no silver bullet. And there probably never will be one. Keep in mind the techniques of object-oriented programming, encapsulation principle, focusing on the behavior. Knowing about the two extremes will help you improve the design of your application and choose the proper solution for your project.
  • 24. Need CRUD methods? Add a Layer. If you for some reason want to allow classical CRUD methods, you can build it on top of your internal API. You can use Adapter pattern for this task. class Article { // ... public function update(...) { if ($this->state === self::STATE_DELETED) { throw new ArticleIsDeletedEx($this); } $this->author = $author; $this->text = $text; $this->state = $state; if ($state === self::STATE_PUBLISHED) { $this->published = $published ?: new DateTime(); } elseif ($state === self::STATE_UNPUBLISHED) { $this->published = null; } } }
  • 25. Need CRUD methods? Add a Layer. If you for some reason want to allow classical CRUD methods, you can build it on top of your internal API. You can use Adapter pattern for this task. class ArticleCrudAdapter { // ... public function update(...) { if ($this->article->isDeleted()) { throw new ArticleIsDeletedEx($this->article); } $this->article->rewrite($text, $author); switch ($state) { case Article::STATE_PUBLISHED: $this->article->publish($published); break; case Article::STATE_UNPUBLISHED: $this->article->unpublish(); break; case Article::STATE_DELETED: $this->article->delete(); break; } } }
  • 26. It Is About the Balance Every way has its tradeoffs and, as always, it is about the balance. Focusing on real-world use-cases helps to maintain integrity and usability. Integration with other libraries or components is easier with generic methods. When developing Shopsys Framework we try to keep that in mind, and take inspiration from Rich Domain Model. See for yourself, join closed beta: https://www.shopsys-framework.com
  • 27. Thanks for listening! Let’s get down to your questions!