Symfony y arquitectura hexagonal

En este artículo, repasaremos brevemente la teoría y, en la práctica, descubriremos cómo traducir cualquier aplicación heredada a una arquitectura hexagonal. La narración estará en el contexto del marco Symfony y PHP 7.4, pero la sintaxis de los ejemplos dados es tan simple que puedes entender fácilmente cómo hacer lo mismo en tu lenguaje de programación (si es compatible con OOP).







Durante mi carrera he trabajado en muchos proyectos de Symfony, y uno de los problemas más frecuentes con los que los clientes llaman a nuestra empresa es que su software está "bloqueado" por una versión antigua del framework o se ha desatendido porque está encontrando y arreglando bichos es demasiado caro.







Por lo general, trato de comprender bien por qué estos proyectos heredados se encuentran en este estado. Y a menudo encontré un patrón común: el equipo al comienzo del proyecto necesita crear rápidamente una aplicación desde cero, porque los plazos son ajustados.







Su proceso de desarrollo comienza algo como esto:







  • instalar el proyecto esqueleto de Symfony usando el compositor
  • eliminar el código de demostración
  • autogeneración de modelos
  • autogeneración de controladores
  • ahora todo está listo para desarrollar la aplicación (lógica empresarial)


, - , - .







, flow .







, , Symfony ( ) , ​​ , — «domain», .







, , , :







  • ,
  • ,


, , : .









- , -, 2005 .







, ​​, , , . . ()







, : ?







, , , , . , , .









, 10 , PHP, .







PHP , composer-, -, .







, .







— (not maintainable).







.







, , , -.







, . .







« » — , - .







, , , , , .







, , , .







, , , .







/ , , .







:









class Payment
{
  public function pay(Request $request): void
  {
     $gateway = new YourBankGateway();
     $gateway->pay($request->get('amount'));
  }
}

      
      





, :







  • pay Request, - HTTP. , , , - .
  • YourBankGateway , , , , .


:









interface GatewayProvider {
    public function pay(Money $amount): void;
}

class YourBankGateway implements GatewayProvider {
    public function pay(Money $amount): void
    {
        //do stuff..
    }
}

class Payment {
    private GatewayProvider $gateway;

    public function __construct(GatewayProvider $gateway)
    {
        $this->gateway = $gateway;
    }

    public function payThroughGateway(Money $amount): void
    {
        $this->gateway->pay($amount);
   }
}

      
      





, , .







: Payment - HTTP , Money ( DTO) Request.







, .











«» () .







— , () , .







— , , .







?







  • () -


, .











, : , :







  • ,
  • ,
  • , API


, : , .







:







  • : , …


:







  • ( )


:







  • , CLI


?



. “ -” .







, .







, .









, .







( UI, API ..), (, . .). .







— .







:









interface ProductRepositoryInterface
{
   public function find(ProductId $id): ?Product;
}

      
      





— , . , .









— , , .







.







:









class MysqlProductRepository implements ProductRepositoryInterface
{
    private $repository;

    public function __construct(ProductRepository $repository)
    {
        $this->repository = $repository;
    }

    public function find(ProductId $id): ?Product
    {
        return $this->repository->find(id);
    }
}

      
      





.













, CLI HTTP-, . .







, , , .







, PHP :













: Payment Cart.







, . , .







- ( , UUID ramsey/uuid).







, .







.







, .











, , .







, . .













, .







, .







.









, :







  • , , . unit-.
  • , , , .
  • composer-, , . ., . , .
  • , .




, , , .







?



, , , .







, Infrastructure Domain.







.







, , pull- .







legacy , , :







, .







Let’s Make Our Projects Great Again



:







  • DDD (Domain-driven design)
  • CQRS ( )
  • Event sourcing
  • TDD
  • BDD


, .








All Articles