Despite this rather intimidating definition, building a service layer is a straightforward process. Don't believe me? Focus your attention on the following class, which implements a service that works with generic entities: (MyApplication/Service/AbstractService.php) <?php namespace MyApplicationService; abstract class AbstractService /** /** /** /** /** /** As seen above, thanks to the “clever” (if that’s really the appropriate term) use of dependency injection, constructing an abstract service that runs CRUD operations on a few domain objects is a breeze. At first glance, the implementation of this additional abstraction layer seems to be somewhat redundant, especially when compared with the functionality already offered by the mapping layer -- but this is a misleading impression, trust me. In this case, the application’s concerns are quite trivial, reduced to fetching, saving and deleting entities from the database. But what if it’s necessary to do many other things, like interfacing with a different front-end, sending a newsletter or retrieving aggregated roots, like blog posts and their associated comments? Are we going to pollute our action controllers with all that stuff and suffer the side effects of code duplication nearly everywhere? That sounds lame, indeed. Undeniably, the best way to encapsulate all of this logic is behind a service layer. In the following segment I’ll be creating a user service, which naturally will be a derivative of the previous abstract parent. Now, move ahead and read the lines to come. Refining the earlier abstract parent class: implementing a user service Since the abstract service defined earlier already implements the logic required to run CRUD functions on generic entities, creating a subclass that works specifically with user objects is a straightforward process that can be accomplished in a few easy steps. If you still wonder how this user service will look, pay attention to the following class: (MyApplication/Service/UserService.php) <?php namespace MyApplicationService; class UserService extends AbstractService /** /** There you have it. As shown above, the implementation of a service that manipulates user entities was a simple, not to say simplistic process! To demonstrate how extendable such a layer can actually be, the service in question not only can fetch, save, and delete domain objects from the persistence layer, but it can also return user objects in XML format. Of course, I coded the “toXML()” method only for demonstration purposes; however, it should give you a clearer idea of how easy it is to encapsulate application logic behind a service, which can be consumed by several different clients layers without suffering the curse of code duplication. At this point, the good news is you've already learned what a service is and how it can be implemented using OOP. The bad news is that, to get it up and running, it’s necessary to create a slightly complex object graph. Final Thoughts In this fifth installment of the series, things took an exciting twist, as I finally managed to implement a fully functional user service. As you just saw, this additional layer uses the functionality of a mapper for running CRUD functions on user entities, as well as retrieving these domain objects in XML format. That's not too bad, considering that this is only an example that can be expanded and customized at will. Naturally, if you’re anything like me, at this moment you’ll want to see a script that shows how to put this service into action. Before we come to that point, though, we need to do a few more things. Construction of the entire service graph requires that we create a MySQL adapter, which is then injected into the mapper’s constructor. This collaborator is finally dumped into the service itself. So we need to build a basic dependency injection container that sets this object graph and returns it to client code in a valid state. That’s exactly what I’ll be doing in the upcoming tutorial, so don’t miss it!
blog comments powered by Disqus |
|
|
|
|
|
|
|