Decouple your framework now, thank me later

336 views

Published on

Frameworks give you a rich toolset to do complex tasks very easy and developers all love it. But then you need to update your framework from one version to another and things are falling apart because of the tight coupling with your business logic.

In this talk I show a couple of actual scenarios that went wrong when we moved from one framework to another and the solutions we applied to abstract business logic from framework logic. Even if you're not planning on migrating frameworks yet, decoupling is a good practice that will give you less headaches in the future.

Published in: Engineering
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
336
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
8
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Decouple your framework now, thank me later

  1. 1. DECOUPLE YOUR FRAMEWORK NOW, THANK ME LATER MICHELANGELO VAN DAM - @DRAGONBE
  2. 2. MICHELANGELO VAN DAM CEO at in2it Lead PHP architect Community leader Coach & mentor FOSS contributor Public speaker
  3. 3. FRAMEWORKS ARE GREAT! • They abstract common tasks like email, database connectivity, routing and a ton more… • They allow us to quickly develop complex applications • They offer good to great security and robustness
  4. 4. BUT… • Frameworks have a nasty aftertaste when building business logic • You need to use their database, log or cache adapter everywhere • View templates are requiring framework components like translations, escaping and other trivial purposes • Best practices require to use modules, bundles or features to separate business logic components
  5. 5. IMPROVEMENTS THROUGH STANDARDS • The PHP-FIG standards motivates frameworks to use great components to abstract functionality and ensure interoperability with other frameworks and tools • Major frameworks already offer this straight off the bat • But add their own “secret sauce” to link it within their framework, even when using Dependency Injection
  6. 6. WHAT ARE THE CHALLENGES?
  7. 7. UPGRADE (OR CHANGE) YOUR FRAMEWORK
  8. 8. UPGRADE TO THE LATEST PHP VERSION
  9. 9. BUSINESS LOGIC AND FRAMEWORKS MIXED Framework X Business Logic BL DB FW DB FW Logging FW Mail FW Service BL Logging BL Mail BL Services
  10. 10. APPLYING INTERFACES IN BETWEEN Framework X Business Logic FW DB FW Logging FW Mail FW Service BL DB BL Logging BL Mail BL Services DB Interface Logging Interface Mail Interface Service Interface
  11. 11. RESTAURANT PRINCIPLE
  12. 12. THE HOSTES WILL BRING YOU TO YOUR TABLE AND GIVES YOU THE MENU AND WINE LIST.
  13. 13. A WAITER WILL TAKE YOUR ORDER FOR DRINKS AND FOOD
  14. 14. BARTENDER WILL PREPARE YOUR DRINKS
  15. 15. KITCHEN WILL PREPARE YOUR MEAL
  16. 16. YOUR WAITER BRINGS YOUR DRINKS
  17. 17. YOUR WAITER WILL DELIVER YOUR FOOD
  18. 18. YOUR WAITER WILL GIVE YOU THE BILL WHEN DONE
  19. 19. YOUR WAITER • Interfaces with the hostess to get started • Interfaces with you to take your order • Interfaces with the bar for drinks • Interfaces with the cash register to present you a bill
  20. 20. YOUR WAITER • Receives notification you have arrived at your table • Receives your order from you • Receives drinks from the bartender • Receives food from the kitchen • Receives money from you
  21. 21. HOW DO WE DO THIS IN CODE?
  22. 22. INTERFACES DESIGN BY CONTRACTS
  23. 23. WHAT ARE INTERFACES • Interfaces define a requirement without concrete implementation • There’s no limit on interfaces implemented • Everyone understands the “contract” immediately • One interface per goal, feature or purpose
  24. 24. COMMON INTERFACES IN PHP • Countable • Iterator (and derivates) • See language.oop5.interfaces on php.net for more details!
  25. 25. CUSTOM INTERFACES interface TableGatewayInterface {     public function find(int $id): array;     public function fetchRow(         array $where = [],          array $order = []     ): array;     public function fetchAll(         array $where = [],          array $order = [],          int $count = 0,          int $offset = 0     ): array;     public function insert(array $data): int;     public function update(array $data, array $where = []): int; }
  26. 26. BONUS: VERY TESTABLE!!! • No need to implement concrete code, just use interfaces to guide your development • A class can implement multiple interfaces, testing can occur on a single interface functionality at a time.
  27. 27. EVENTS
  28. 28. WHAT ARE EVENTS? • Events allow us to run tasks in the background and call back when completed. • Implements the observer pattern (e.g. SplSubject & SplObserver) • One observer can have many subscribers • A subscriber can subscribe to many observer objects
  29. 29. EXAMPLE $memberService = new MemberService(); $memberService->attach(new DBObserver()); $memberService->attach(new LogObserver()); $memberService->attach(new EmailObserver()); $memberService->attach(new CacheObserver()); $memberService->attach(new SearchObserver()); $memberService->register(new Member('John', 'Doe', 'j.doe@example.com'));
  30. 30. EVENT OBSERVATION Register DB Log Email Cache Search Storing in DB Logging Sending email Write to cache Update indexes
  31. 31. EVENT OBSERVATION AFTER EVENTS Register DB Log Email Cache Search Storing in DB Logging Sending email Write to cache Update indexes
  32. 32. BENEFITS • Reusable logic • Runs in the background, so no delays • Scalable
  33. 33. GLUING ALL TOGETHER
  34. 34. Core Business Logic Silex Web Frontend Apigility API Phalcon Web Backend
  35. 35. Core Business Logic Slim Web Frontend Zend Expressive API Python Web Backend
  36. 36. GLUE CLASS TO INTERACT 1/3 class SilexServiceProvider implements ServiceProviderInterface {     public function register(Container $container)     {         $dsn = $container['cb_config_db.dsn'] ?: '';         $username = $container['cb_config_db.username'] ?: '';         $password = $container['cb_config_db.password'] ?: '';         $pdo = new PDO($dsn, $username, $password);         $authorTable = new AuthorTable($pdo);         $authorHydrator = new AuthorHydrator();         $author = new Author();         $bookTable = new BookTable($pdo);         $bookHydrator = new BookHydrator();         $book = new Book();                  $memberTable = new MemberTable($pdo);         $memberHydrator = new MemberHydrator();         $member = new Member();
  37. 37. GLUE CLASS TO INTERACT 2/3         $serviceLocator = new ServiceLocator();         $serviceLocator             ->set('CloudbooksAuthorModelAuthorTable', $authorTable)             ->set('CloudbooksAuthorModelAuthorHydrator', $authorHydrator)             ->set('CloudbooksAuthorEntityAuthor', $author)             ->set('CloudbooksBookModelBookTable', $bookTable)             ->set('CloudbooksBookModelBookHydrator', $bookHydrator)             ->set('CloudbooksBookEntityBook', $book)             ->set('CloudbooksMemberModelMemberTable', $memberTable)             ->set('CloudbooksMemberModelMemberHydrator', $memberHydrator)             ->set('CloudbooksMemberEntityMember', $member);     }
  38. 38. GLUE CLASS TO INTERACT 3/3         $container['cb_author_service'] = $container->factory(function () use ($serviceLocator) {             $serviceFactory = new AuthorServiceFactory();             return $serviceFactory->createService($serviceLocator);         });         $container['cb_book_service'] = $container->factory(function () use ($serviceLocator) {             $serviceFactory = new BookServiceFactory();             return $serviceFactory->createService($serviceLocator);         });         $container['cb_member_service'] = $container->factory(function () use ($serviceLocator) {             $serviceFactory = new MemberServiceFactory();             return $serviceFactory->createService($serviceLocator);         });     }
  39. 39. LET’S RECAP
  40. 40. https://github.com/sensiolabs-de/deptrac
  41. 41. THANK YOU!

×