Luciano Queiroz
Backend Engineer @ HelloFresh
Vaughn Vernon, Implementing Domain Driven Design (Perason Education, Inc: 2013), 172.
View
Controller
Model
Database
Data
Data
Data
<?php
App::uses('AppController', 'Controller');
class CustomersController extends AppController {
public function add() {
if ($this->request->is('post')) {
$this->Customer->create();
if ($this->Customer->save($this->request->data)) {
$this->Flash->success(__('The customer has been saved.'));
return $this->redirect(array('action' => 'index'));
} else {
$this->Flash->error(__('The customer could not be saved. Please, try again.'));
}
}
}
public function edit($id = null) {
if (!$this->Customer->exists($id)) {
throw new NotFoundException(__('Invalid customer'));
}
if ($this->request->is(array('post', 'put'))) {
if ($this->Customer->save($this->request->data)) {
$this->Flash->success(__('The customer has been saved.'));
return $this->redirect(array('action' => 'index'));
} else {
$this->Flash->error(__('The customer could not be saved. Please, try again.'));
}
} else {
$options = array('conditions' => array('Customer.' . $this->Customer->primaryKey => $id));
$this->request->data = $this->Customer->find('first', $options);
}
}
}
<?php
App::uses('AppController', 'Controller');
class CustomersController extends AppController {
public function add() {
if ($this->request->is('post')) {
$this->Customer->create();
if ($this->Customer->save($this->request->data)) {
$this->Flash->success(__('The customer has been saved.'));
return $this->redirect(array('action' => 'index'));
} else {
$this->Flash->error(__('The customer could not be saved. Please, try again.'));
}
}
}
public function edit($id = null) {
if (!$this->Customer->exists($id)) {
throw new NotFoundException(__('Invalid customer'));
}
if ($this->request->is(array('post', 'put'))) {
if ($this->Customer->save($this->request->data)) {
$this->Flash->success(__('The customer has been saved.'));
return $this->redirect(array('action' => 'index'));
} else {
$this->Flash->error(__('The customer could not be saved. Please, try again.'));
}
} else {
$options = array('conditions' => array('Customer.' . $this->Customer->primaryKey => $id));
$this->request->data = $this->Customer->find('first', $options);
}
}
}
"So what does the architecture of your application scream? When you look at the top level directory structure, and the source files in the highest level package; do they scream: Health Care System, or Accounting System, or Inventory Management System? Or do they scream: Rails, or Spring/Hibernate, or ASP?"
Uncle Bob
[Evans, Ref, p.16]
User Interface
Application Layer
Layered Architecture
Infrastructure
Domain Layer
Application Layer
Domain Layer
Layered Architecture
Infrastructure
Application Layer
Domain Layer
Layered Architecture
Infrastructure
Layered Architecture
Application
Domain
Infrastructure
Layered Architecture with DIP
Domain
Entity
Value Object
Application
Infrastructure
Alistair Cockburn.
Domain
Application
Infrastructure
Http
Persistence
AMPQ
Console
Http
Request
Command
Handler
ServiceBus
Entities
Value Objects
Http Land
Domain Land
<?php
class RegisterCustomer {
private $name;
private $email;
private $username;
private $customer;
public function __construct(
$name, $email, $username
)
{
$customer = Customer::fromPersonAndUser(
Person::fromName($name),
User::fromUsernameAndEmail(
Username::fromString($username),
Email::fromString($email)
)
$this->$customer = $customer;
)
}
public function customer()
{
return $this->customer;
}
}
<?php
class RegisterCustomerHandler {
private $customerRepository;
public function __construct(
ICustomerRepository $repository
)
{
$this->customerRepository = $repository;
}
public function handle(
RegisterCustomer $registerCustomer
)
{
$customer = $registerCustomer->customer();
return $this->repository->store($customer);
}
}
MySqlRepository
MongoDB
MySQL
Domain Land
Persistence Land
MongoDBRepository
InMemoryRepository
CacheRepository
Redis
IRepository
Handler
<?php
interface ICostumerRepository {
public function store();
public function ofId($id);
}
<?php
class MySqlCustomerRepository implements ICustomerRepository {
private $entityRepository;
public function __construct(EntityRepository $entityRepository)
{
$this->entityRepository = $entityRepository;
}
public function store(Customer $customer)
{
$this->entityRepository->em->persist($customer);
$this->entityRepository->em->flush();
}
public function ofId(CustomerId $customerId)
{
return $this->entityRepository->findBy(['id' => $customerId]);
}
}
Implementing Domain Driven Design - Vaughn Vernon.
Domain-Driven Design: Tackling Complexity in the Heart of Software - Eric Evans.
Principles of Package Design - Mathias Noback.
Clean Code Episode VII - Architecture, Use Cases, and High Level Design - Uncle Bob.
http://alistair.cockburn.us/Hexagonal+architecture
@luciianoqueiroz
luciiano.queiroz@gmail.com
By Luciano Queiroz
Slide para o MeetUp do PHP Pernambuco
Backend Engineer @ HelloFresh