Rich Model And Layered Architecture in SF2 Application
Upcoming SlideShare
Loading in...5
×
 

Rich Model And Layered Architecture in SF2 Application

on

  • 2,811 views

Presentation for Symfony Camp UA 2012.

Presentation for Symfony Camp UA 2012.
* What are Rich Model, Service Layer & Layered Architecture
* Layered architecture in Sf2 Application
* Integration with 3rd party bundles

Statistics

Views

Total Views
2,811
Views on SlideShare
2,371
Embed Views
440

Actions

Likes
6
Downloads
15
Comments
0

7 Embeds 440

http://2012.symfonycamp.org.ua 374
https://twitter.com 43
http://makedev.org 13
http://www.sfexception.com 5
https://si0.twimg.com 3
http://2013.symfonycamp.org.ua 1
http://www.docshut.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

CC Attribution-NonCommercial LicenseCC Attribution-NonCommercial License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Rich Model And Layered Architecture in SF2 Application Rich Model And Layered Architecture in SF2 Application Presentation Transcript

  • RichModelAnd Layered Architecture Kirill chEbba Chebunin (Creara.ru) iam@chebba.org
  • Rich Model. ??? http://www.vexinthecity.com/2010/10/estee-lauder-christmas-collection-pure.html © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. Who? Martin Fowler – Anemic Domain Model – Domain Model – Transaction Script Eric Evans – Domain-Driven Design Benjamin Eberlei – Building an Object Model: No setters allowed © Kirill chEbba Chebunin. Creara 2012 View slide
  • Rich Model. What? About business objects – Entities Data + Logic instead of pure Data (Anemic Model) Real encapsulation Consistent state Business methods instead of Setters Low level validation © Kirill chEbba Chebunin. Creara 2012 View slide
  • Rich Model. How?class Project{ const STATUS_NEW = new; const STATUS_ACTIVE = active; const STATUS_BLOCKED = blocked; private $name; private $status; public function setName($name) { $this->name = $name; } public function getName() { return $this->name; } public function setStatus($status) { $this->status = $status; } public function getStatus() { return $this->status; }} © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. How?class Project http://rober-raik.deviantart.com/art/Fuck-You-263589802{ const STATUS_NEW = new; const STATUS_ACTIVE = active; const STATUS_BLOCKED = blocked; private $name; private $status; public function setName($name) { $this->name = $name; } public function getName() { return $this->name; } public function setStatus($status) { $this->status = $status; } public function getStatus() { return $this->status; }} FUCK YOU, SETTERS! © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. How?class Project class Project{ { const STATUS_NEW = new; const STATUS_NEW = new; const STATUS_ACTIVE = active; const STATUS_ACTIVE = active; const STATUS_BLOCKED = blocked; const STATUS_BLOCKED = blocked; private $name; private $name; private $status; private $status; public function setName($name) public function __construct($name) { { $this->name = $name; $this->name = trim($name); } $this->status = self::STATUS_NEW; } public function getName() { public function getName() return $this->name; { } return $this->name; } public function setStatus($status) { public function getStatus() $this->status = $status; { } return $this->status; } public function getStatus() { public function activate() return $this->status; { } if ($this->status === self::STATUS_BLOCKED) {} throw new LogicException( Can not activate blocked project); } $this->status = self::STATUS_ACTIVE; } } © Kirill chEbba Chebunin. Creara 2012
  • rdRich Model. 3 Party? © Kirill chEbba Chebunin. Creara 2012
  • rdRich Model. 3 Party? Doctrine2 – Persistence Layer – Same as Serialization Symfony2 Form – Data Binder – Born to use Accessors – Data Transformers? Symfony2 Validation – External Validation – Heavyweight for Internal Validation © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. Doctrine Side Effects $entity = $this->em->find($className, $id); try { $this->update($entity, $data); // Failed, no update was executed } catch (ValidationException $e) { // Do stuff on fail } // ................................. $entity->link($anotherEntity); $this->em->flush(); // Old invalid updates will be executed © Kirill chEbba Chebunin. Creara 2012
  • rdRich Model. 3 Party? © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. Solution. Isolated Persistence Layer Transactional Operations Rich + Anemic Objects (DTO) Service Layer (Facade) © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. DTO.class ProjectData{ /** * @AssertNotBlank * @AssertRegex(pattern="/[a-z0-9_]+/i") */ private $name; public function setName($name) { $this->name = $name; return $this; } public function getName() { return $this->name; }} © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. Domain Interface.interface Project{ const STATUS_NEW = new; const STATUS_ACTIVE = active; const STATUS_BLOCKED = blocked; /** * Get project name * * @return string */ public function getName(); /** * Get project status * * @return string STATUS_* constant */ public function getStatus();} © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. Service Layer.interface ProjectService{ /** * Create new project * * @param ProjectData $data * * @return Project * @throws ValidationException */ public function createProject(ProjectData $data);} © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. Example.class ProjectManager implements ProjectService{ /* ... */ public function createProject(ProjectData $data) { $this->validate($data); $project = new EntityProject($data->getName()); $this->em->persist($project); $this->em->flush(); return $project; }} © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. Example.class ProjectController extends Controller{ public function createAction(Request $request) { $data = new ProjectData(); $form = $this->createForm(new ProjectType(), $data); $form->bind($request); if ($form->isValid()) { return $this->projectService->createProject($data); } return $form; }} © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. Solution. Client Code Controller, Command, etc. DTO Domain Interface Service Interface Persistence Layer © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. Profit? © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. Profit? © Kirill chEbba Chebunin. Creara 2012
  • rdRich Model. 3 Party Bundles. Anemic Model Managers Direct ObjectManager Manipulation © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. FOSUser. © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. FOSUser. Problems. User – Property Setters – Unnecessary Functions Manager – Low Level Methods © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. FOSUser. Solution.Delegation instead of Inheritancehttp://thevanwinkleproject.blogspot.com/2011_02_01_archive.html http://www.halloweencostumes.com/sweet-daddy-pimp-costume.html © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. FOSUser. Delegation.class UserWrapper implements FOSUserInterface{ private $user; private $email; private $enabled = false; public function __construct(DomainUser $user = null) { if ($user) { $this->setUser($user); } } public function setUser(DomainUser $user) { $this->user = $user; $this ->setEmail($user->getEmail()) ->setEnabled($user->getStatus() == DomainUser::STATUS_ACTIVE) ; } // Other UserInterface methods} © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. FOSUser. Delegation.class FOSUserManager implements FOSUserManagerInterface{ public function updateUser(UserInterface $wrapper) { $user = $wrapper->getUser(); $userService = $this->userService; // User registration if (!$user) { $user = $userService->registerUser($wrapper->getRegistrationData()); // Update simple fields } else { $user = $userService->updateUser($id, $wrapper->getUserData()); } $wrapper->setUser($user); } // Other UserManagerInterface methods} © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. SonataAdmin.http://southpark.wikia.com/wiki/File:ScauseForApplause00031.png © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. Admin Architecture. SonataAdminBundle – Base CRUD View Functions – Dashboard, Menu, etc. – Interfaces for Storage Implementations ORM/ODM/... Bundles – Storage Implementations registered in Admin – Direct Object Manager Manipulation © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. Admin Interfaces.We have interfaces! Implement them!class CustomModelManager implements ModelManagerInterface{ /* ... */ /** * {@inheritDoc} */ public function modelTransform($class, $instance) { // Method is not used in Admin } /** * {@inheritDoc} */ public function getParentFieldDescription($parentAssociationMapping, $class) { // Method is not used in Admin }} © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. Admin Interfaces. © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. Admin.Custom Model.interface Model{ /** * Create mew object instance * * @return mixed */ public function createInstance(); /** * Save new object * * @param object $object * * @throws RuntimeException */ public function create($object); /** * Update existing object * * @param $object * @throws RuntimeException */ public function update($object); // Some other methods} © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. Admin.Custom Model.class UserModel implements Model{ public function createInstance() { return new UserWrapper(); } public function create($wrapper) { $user = $this->userService->registerUser( $wrapper->getRegistrationData() ); $wrapper->setUser($user); } public function update($wrapper) { $user = $this->userService->updateUser( $wrapper->getUserData() ); $wrapper->setUser($user); } // Some other methods} © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. PROFIT! © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. Summary. Object Logic in Object Class Separate Domain Objects from View Object Isolated Business Layer (Service Layer) Delegation instead of Inheritance Read 3rd Party Code © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. Pros & Cons. OOPed (KISS, DRY, Patterns, blah, blah, blah) Pros: – Less side effects – Less code duplication – Less chances to shoot your leg – Easy serialization – Easy API creation – Etc, etc, etc. Cons: – More code – Codebase required – Hi shit sort out level © Kirill chEbba Chebunin. Creara 2012
  • Rich Model. Questions? © Kirill chEbba Chebunin. Creara 2012