Download - From silex to symfony and viceversa
The reality• Lack of discipline
• Time pressures
• Long release cycles
• Short release cycles
• New features every day
• Bugs and hot fixes
Some of the implications…
• Infiltration of business logic into the delivery mechanism (or the user interface)
• Untestable systems
• Bad written tests
• Delayed projects
“Create a new layer in the architecture…
With the promise that this time…
really and truly,
no business logic will be put into the new layer”
• If we don’t have a mechanism to detect when a violation of that promise occurs…
• Then… in a few development cycles, the new layer is cluttered with business logic and the old problem has reappeared
Ports and Adapters• Makes the application domain model central to the
system
• Cleanly decouples and isolates the application domain model from the system's technical infrastructure
• Define its relationships with the outside world in terms of application domain concepts ("ports")
Application
HTTP/S
WS/S
Raw Sockets
Tests
CLI
Adapters
IPC
Persistence
Messaging/Queues
Reporting/Tracking
–Vaughn Vernon. “Implementing Domain-Driven Design”
“Anything that can help us give more emphasis to the Core Domain and less
to technology will likely drive out
more value for the business and help it achieve an even greater competitive
advantage.”
Let’s start
• By building something small
• By building something testable
• By building something easily interchangeable
• With hard boundaries
• With single responsibility everywhere
Building something testable
User
Acceptance Tests Unit
Tests
In-AppPurchases
Integration Tests
Persistence
HTTP Adapter
FunctionalE2E Tests
Acceptance Tests• It is a validation activity – Did we build the right
thing?
• Can instantiate and exercise the domain model without instantiating any of the technical plumbing that connects it to the external resources in the real system
• Can be described in plain English
Acceptance Tests
• Ports & Adapters makes it possible to run acceptance tests directly against the application domain model
An acceptance can instantiate and exercise the domain model without instantiating any of the technical plumbing that connects it to the external resources in the real system.
http://www.natpryce.com/articles/000786.html
The opposite: instantiate the adapters without the domain model of the real application. Rather than connecting the adapter to an object from the real domain model, the test connects it to a fake implementation
http://www.natpryce.com/articles/000786.html
With hard boundaries
User In-AppPurchases
Feature Y
Feature X
Game
Analytics
Kernel
Unit Of Work
Event Publisher
HTTP AdapterSilex
Service Locator
HTTP AdapterSymfony
Container Event Dispatcher
LoggerLogger
Tracker
Container
• You shouldn't start a new project with microservices, even if you're sure your application will be big enough to make it worthwhile – @martinfowler
• http://martinfowler.com/bliki/MonolithFirst.html
Ports and Adapters• Ports and Adapters is a coarse-grain OO design
pattern
• It decouples the object model of a system's application domain from the object models of its technical domains
• Among other benefits, this lets you write acceptance tests against the application domain model directly
Ports and Adapters
• Says nothing about distribution between processes, machines and/or organizations.
• It's concerned with how we structure our objects within each process
Modules
• Ports&Adapters promotes a loosely coupled architecture, with functionality broken down into independent modules
Emerald
• Highly opinionated library following the architectural principles described here
• Not open source yet, but we can see some code later
Principles• Broken down into independent modules
• Modules don’t interact with other modules
• Modules don’t share runtime services (by their self) with other modules
• There is no access to global state, or a global “container” of services
Principles• Modules don’t know anything about the rest of the
world
• They don’t even know that they are running together with other modules
• Modules don’t interact with other modules
• They have very limited knowledge of what’s going on in the rest of the system
Interacting with the rest of the world
• Modules either receive commands or queries from the outside world (adapters)
• This promote CQRS
• Modules publish events, and could react to other events in the system, but without coupling to other modules
The big picture
User In-AppPurchases
Feature Y
Feature X
Game
AnalyticsKernel
Command
Query
POST /alliance/123
AllianceCreateCmd { id :123, name: “PHP”, }
GET /alliance/123/
AllianceMembersQuery { id :123
Controllers• POPOs, only have access to the application Kernel
and have only the following responsibilities:
• convert request in queries or commands
• dispatch control to the kernel
• convert back the response to a suitable representation
Container, Event Dispatcher, etc…
• We need clear separation between all the layer, better to have them separated
• Application has it own service locator and event publisher
Conclusions
• Do not let any (web) framework guide your architecture
• Try to solve your problem first, then chose delivery mechanisms, persistence, etc…
• This kind of architecture can be applied in any programming language/stack
References• Hexagonal architecture
http://alistair.cockburn.us/Hexagonal+architecture
• Growing Object-Oriented Software Guided by Testshttp://www.growing-object-oriented-software.com/
• Visualising Test Terminology http://www.natpryce.com/articles/000772.html
• Ports and Adapters With No Domain Modelhttp://www.natpryce.com/articles/000786.html
• http://martinfowler.com/bliki/MonolithFirst.html