PHP Software Architecture Part 3: Extensible Architecture
When I first started using this architecture, I had no name for it. But having a name will make it easier for us to remember it. Let’s call it the “Extensible Architecture”. That is because, it is basically an extension to MVC. We just added new design patterns and layers to bring shape to this architecture.
[Domains]: Domain specific code/Business logic eg. getFlightAvailability()
[Adapters w/ or w/o Interfaces]: Third party code/APIs separation. eg. Flight Booking API
[Services]: Common application/business logic goes here. eg. log()
[Repositories]: Persistence logic goes here. eg. saveData()
[MVC : Model, View, Controllers] : Three basic layers of separation
Now let’s go for an in-depth understanding of each layer.
Domains are classes that act as a glue to our various layers in the application. It contains all our domain/business logic. It directs what API we need to call and where we need to save our data. In our flight application code in Part 1 of our series, we had all our domain code in the “getFlightAvailability” method of the Controller. All those belong instead in a domain layer, which we call as a domain. There are no interfaces here, just plain old php classes.
Adapter is actually a design pattern. It is a special class that is used as a bridge between two different interfaces. We usually use an Interface class which the Adapter class will adhere to. But I say this is not required in all cases. If you are not sure if the API is going to be a fit, you can always write an Interface for it. I usually do not see any need for extra layer of Interfaces even for Adapters.
Services are one of the most overused terms in PHP community. People use it for various reasons, and there is no clear definition of the term due to that.
For me Services are application logic that usually are cross-referenced from different domain classes. It can also be domain logic that is too big for the domain itself. If some domain logic needs to be cross-referenced from different classes, then that usually is separated to its own Service class.You could further subdivide them into Application Services and Domain Services if needed. But in a medium sized app, I think they can co-exist under the same umbrella “Services”.
Keep in mind, we are not talking about Laravel Service Providers here. They are completely different beasts. They are services which are used by the framework itself, or that are needed globally throughout the application.
A repository is the persistence layer that retrieves and stores data. It usually retrieves them from the ‘Model’ which is the Eloquent Model in Laravel. Repositories are essential to keep all the persistence logic out of our main Domain layer. They help act as a bridge between our internal code and the Model. This way no SQL or Eloquent queries can creep in to our business logic. It also makes easy to switch our persistence layer, we would just rewrite our repository instead of having to touch our domain layer.
Now, I am not advocating that we should never allow anyone to write their business logic in a controller. If a feature is small, by all means go ahead and write them in a controller. You can also directly reference your Model there, if the db call is just one liner. Just keep in mind that, if ever you need to change the persistence layer, you would need to refactor it into a Repository. The main point behind our simple architecture is to be quick and only refactor when it is actually needed. And further, only refactor the part you need to change.
Also these layers are not all you can add. If you need an extra layer between your View and your Repository/Model, you can use a Decorator pattern. In Clean Architecture by Uncle Bob, he uses a similar pattern called ViewModel. You can use that to do all the decorating logic before you pass it to a view.
Another layer that has been useful for me is the Translator layer. It sits before the Adapter layer. It processes the data that comes through an external API, then it passes it to the Adapter. Translators do manual conversion from XML/JSON structure to native objects. In case of PHP that would be plain native PHP objects.
In an application where there are two or more than two user facing interfaces, let’s say front-end and back-end, we can share the services, adapters and repositories. The flowchart above shows us the overview.
Anyways, this is it for Part 3. We will finally refactor the code we wrote in the first part, next. We will use our Extensible Architecture for that purpose.
Please don’t forget to give a clap, on this article. And I’ll see you in the next part. :)
PHP Software Architecture Part 4: Refactoring
All right. Let’s go over and refactor our code from part one.
Check out my other series at: