Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Hexagonal architecture

109 views

Published on

Hexagonal architecture with symfony

Published in: Software
  • Be the first to comment

  • Be the first to like this

Hexagonal architecture

  1. 1. Symfony and 
 Hexagonal Architecture
  2. 2. Software Developer, father, geek, PHP and Node.js expert. Open-source enthusiast, active contributor on GitHub and StackOverflow. Who am I? Alessandro Minoccheri Software developer @Flowing @minompi @AlessandroMinoccheri
  3. 3.
  4. 4. A real story ◆
  5. 5.
  6. 6. How do you usually start a new Symfony Project • Install Symfony skeleton project • Remove demo code • Autogenerate entities • Start coding from controllers or autogenerate those • Ready to develop the application
  7. 7. 6 months later… ◆
  8. 8.
  9. 9. How many points inside the code do you need to change to replace that service? ◆
  10. 10. 42 different places in all over the code-base. ◆
  11. 11. class PaymentController { public function payAction(Request $request, YourBankGateway $gateway) { $gateway->pay($request->get('amount'), false, false, 0, 'EUR'); } }
  12. 12. class Payment { public function pay(Request $request) { $gateway = new YourBankGateway(); $gateway->pay($request->get('amount'), false, false, 0); } }
  13. 13. class User { public function pay(Request $request) { $gateway = new YourBankGateway(); $gateway->pay($request->get('amount')); } }
  14. 14. Why does this situation exists? ◆
  15. 15. Problems when you are guided from the framework • Impossible to upgrade framework and vendors. • Cost of maintenance • Developers are not motivated because the stack it's very old for the reason of point 1. • Not maintainable application because everything is coupled. • A lot of technical debt • Impossible to change implementation easily.
  16. 16. So, what really matters in software? ◆
  17. 17.  What really brings value in software is the solution to the specific problem in the domain ◆
  18. 18. Hexagonal Architecture history ◆
  19. 19. The hexagonal architecture divides a system into several loosely-coupled interchangeable components, such as the application core, the database, the user interface, test scripts, and interfaces with other systems. 
 This approach is an alternative to the traditional layered architecture. (Wikipedia) ◆
  20. 20. Is it an over-engineer strategy? ◆
  21. 21. Coupled code namespace AppService; use SymfonyComponentHttpFoundationRequest; class Payment { public function doPayment(Request $request) { $gateway = new YourBankGateway(); $gateway->pay($request->get('amount'), false, false, 0); } }
  22. 22. Decoupled code interface GatewayProvider { public function pay(Money $amount): void; }
  23. 23. Decoupled code use AppValueObjectMoney; class YourBankGateway implements GatewayProvider { public function pay(Money $amount): void { //do stuff.. } }
  24. 24. Decoupled code class Payment { /** * @var GatewayProvider */ private GatewayProvider $gatewayProvider; public function __construct(GatewayProvider $gatewayProvider) { $this->gatewayProvider = $gatewayProvider; } public function doPayment(Money $amount) { $this->gatewayProvider->pay($amount); } }
  25. 25. Why is it important to decouple your code? ◆
  26. 26. Maintainable application • Changes in one part of an application should affect as few other places as possible • Adding features shouldn't require to touch any part of the code- base • Adding new ways to interact with the application should require as few changes as possible • Debugging should require as few workarounds • Testing should be relatively easy
  27. 27. Single responsibility for architecture:
 What changes for the same reason, should be grouped together ◆
  28. 28. Examples • Code related to the framework • Code related to the specific service • Code related to the domain
  29. 29. The important distinction from domain and infrastructure Domain • Models: entities, value object or others • interfaces for boundary objects Infrastructure • framework • implementations for boundary objects • Web controllers, CLI commands Application • Use cases
  30. 30. Why is it so important to have maintainable software? ◆
  31. 31. Why an Hexagon?
  32. 32. Ports ◆
  33. 33. Ports are like contracts They will not have any representation in the codebase. There is a port for every way a use case of the application can be invoked . There are input and output ports.
  34. 34. Input ports interface PayOrderHandler { public function handle(PayOrderCommand $command): void; }
  35. 35. Output ports interface UserRepository { public function save(User $user): void; public function findAll(): UserCollection; }
  36. 36. Adapters ◆
  37. 37. Adapters definition Adapters are the implementation of the ports because for each of these abstract ports we need some code to make the connection work.
  38. 38. Adapter example class MysqlUserRepository implements UserRepository { /** * @var Connection */ private $connection; public function __construct(Connection $connection) { $this->connection = $connection; } public function save(User $user): void {//do stuff...} public function findById(UserId $userId): User {//do stuff...} public function findAll(): UserCollection {//do stuff...} }
  39. 39. Directories structure example Src Payment Domain
 Application Infrastructure Cart Domain Application Infrastructure
  40. 40. Dependency inversion principle
  41. 41. Advantages of using hexagonal architecture ◆
  42. 42. increase testability 1
  43. 43. More unit tests 2
  44. 44. You can replace an implementation without affecting the domain 3
  45. 45. You can postpone the choice of 
 vendors, databases, servers, etc... 4
  46. 46. you can update vendors and framework without touching your domain code. 5
  47. 47. So you can create maintainable application 6
  48. 48. EXAMPLE
  49. 49. namespace AppUserInfrastructureController; use AppUserApplicationCreateUserService; use AppUserApplicationDTOCreateUserRequest; use SymfonyComponentHttpFoundationJsonResponse; use SymfonyComponentHttpFoundationRequest; class UserController { public function saveAction(Request $request, CreateUserService $createUserService) { $createUserRequest = CreateUserRequest::create($request->request->all()); $createUserService->createUser($createUserRequest); return new JsonResponse(); } }
  50. 50. namespace AppUserApplication; use … class CreateUserService { private UserRepository $userRepository; public function __construct(UserRepository $userRepository) { $this->userRepository = $userRepository; } public function createUser(CreateUserRequest $createUserRequest): CreateUserResponse { $user = User::create( $createUserRequest->getName(), $createUserRequest->getPassword() ); $this->userRepository->save($user); return CreateUserResponse::createFromUser($user); } }
  51. 51. When to use it? • When you have a new project • When you need to develop a new context into a legacy application • always? When to use it
  52. 52. How about legacy code without hexagonal architecture? ◆
  53. 53. Golden rule Boy scout rule: Leave your code better than you found it. When to use it
  54. 54. Where can you start from? • Using more interfaces • Using dependency injection • Practice with kata projects • Apply the architecture into a real project When to use it
  55. 55. Next improvements - DDD: Domain driven design - CQRS pattern (Command Query Responsibility Segregation) - Event sourcing - TDD - BDD When to use it
  56. 56. We are hiring!
  57. 57. Thank you! @minompi https://joind.in/talk/f6069

×