In diesem Artikel werden wir kurz auf die Theorie eingehen und in der Praxis herausfinden, wie eine Legacy-Anwendung in eine hexagonale Architektur übersetzt werden kann. Die Erzählung wird im Kontext des Symfony-Frameworks und von PHP 7.4 sein, aber die Syntax der angegebenen Beispiele ist so einfach, dass Sie leicht verstehen können, wie Sie dasselbe in Ihrer Programmiersprache tun (wenn es OOP unterstützt).
Während meiner Karriere habe ich an vielen Symfony-Projekten gearbeitet. Eines der häufigsten Probleme, mit denen Kunden unser Unternehmen anrufen, ist, dass ihre Software durch eine alte Version des Frameworks "gesperrt" wird oder unbeaufsichtigt ist, weil sie gefunden und repariert wird Bugs ist zu teuer.
Normalerweise versuche ich ein gutes Verständnis dafür zu bekommen, warum sich diese Legacy-Projekte in diesem Zustand befinden. Und oft fand ich ein gemeinsames Muster: Das Team zu Beginn des Projekts muss schnell eine Anwendung von Grund auf neu erstellen, da die Fristen eng sind.
Ihr Entwicklungsprozess beginnt ungefähr so:
- Installieren Sie das Symfony-Skeleton-Projekt mit Composer
- Demo-Code entfernen
- automatische Generierung von Modellen
- automatische Generierung von Controllern
- Jetzt ist alles bereit für die Entwicklung von (Geschäftslogik-) Anwendungen
, - , - .
, 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
, .