(Consider hiring Doug to instruct you and your team in the ways of OO!)
I've been hearing the term 'Service Layer' everywhere for at least the past year and a half, as I'm sure most of my peers have as well. Whether it's seen in blog posts, heard during casual conversation at conferences, found in articles, or woven throughout almost any discussion at all concerning OO and Coldfusion...the term is quite prevalent and common these days. But I had a problem: the term held absolutely ZERO connotation in my mind. No picture was ever conjured up when I came across it, no corresponding 'Doug Boude' translation was found in my internal lexicon; I felt quite out of the loop. Ah, but recently that has all changed, as the phrase itself has not only come to life for me, but found an absolute and permanent place in all that I do, technically speaking; an epiphany, if you will. I just figured there were others out there who, like myself, may still be kinda grasping for a way to think about the term, so what follows is my personal definition/explanation of what a Service Layer really is. Please feel free to append, addend, flip, and twist it to your heart's content until it's as whole as it ever can be.
SERVICE LAYER
This is not NEARLY as gray and ambiguous a term as you might think. Picture if you will, a man sitting comfortably on his sofa. In one hand is the remote for his very large plasma TV; in the other hand is a remote for his home theater system. The two remotes and the man are all objects, and all three come pre-built with things they can do. In the kitchen is the man’s wife; let’s think of her as the calling application. She barks out the order to the husband object, “START THE MOVIE, YOU IMBECILE!”. The husband object just happens to have a startTheMovie method, and begins to execute it. First, he manipulates the objTVRemote object, calling its “tvOn” method. Then, he manipulates the objDVDRemote object, calling it’s “dvdOn” and “dvdPlay” methods. Now he manipulates the objTVRemote again, calling the “inputSRC” method and switching the tv to receive the dvd input. Tada! Movie is playing now!
Pretty clear scenario, eh? Well, in this illustration, the
Doug out.
You are not logged in, so your subscription status for this entry is unknown. You can login or register here.
Them: "SELECT * FROM Cust".
Me: You may WANT a list of all customers, but this is the list that I'm going to GIVE you:
SELECT * FROM Cust
INNER JOIN Security
ON Security.CustID=Cust.CustID
WHERE UsrID=#You#
Actually, no, a service layer is not an object factory at all...two different animals. An object factory is itself and object whose job it is to create instances of other objects for you. So, instead of writing 'createObject("component","model.user")', you'd instead ask your object factory for it with something like 'cfset myNewUserObj = objFactory(objToMake="user") . Make sense?
Why would you want to do this, you might ask? Well, you might want to do this in order to simplify your object creation process and lessen the amount of code needed throughout the rest of your app. There are a myriad of other possible reasons to do it, as well, but that's content for a blog post all its own.
Hope this helps some.
We build an app that manages medical benefits. In order to perform a simple task such as "change my medical coverage", there are actually several underlying object calls needed, and thus a "benefitServiceLayer" object. Now our home office mentions during a status meeting that they'd like to be able to leverage that same business logic in an app they're building, and they'd like to do it via web services. The only object that needs exposing as a web service is our benefitServiceLayer object...all of the other objects live below that one and are not accessed directly from the home office. So, from this scenario, it's absolutely clear that our service layer objects are JUST as much a part of our 'domain' as any other object containing business logic, and thus the service layer objects must belong within our MODEL directory.
That's what it looks like from where I'm standing, anyway.
There might be people who say that the service layer should be created from the start, and I wouldn't have a solid argument against that except that it's creating more work than necessary to get your code out of the door.
I'm done rambling now.
In essence, the controller's job is strictly to act as liaison between view templates and the model. The model is where all the action is; the business rules, db access...everything! As a courier, or liaison, the controller then should have his job kept as simple as possible. Some people call this "keeping your controller thin", etc. But what it means to me is that when I'm writing a controller, my goal is always to have it do as LITTLE as possible...basically doing nothing more than receiving incoming values, perhaps doing a little "fix up" on them, passing them in to the model, and then taking whatever the model returns and putting it where the views can get to it.
Now, down in the model, where all the action is...that's where the service layer objects reside. Their duties tend to be more complex than other model objects, performing actions that require a little more "thinking", broader reaching methods, and (this is the key for me) the manipulation of other model objects. Anytime I find myself writing a method that needs to talk to, manipulate, or otherwise access other model objects, that CFC becomes a candidate as a service layer object. Not all model objects who interact with other model objects are service layer objects, but I would say the majority are. It really comes down to what kind of role the object plays as to whether or not it rises up as a service layer object.
Back to the controller and its job, though, my strict opinion is that when I look at the code a controller is executing, it should be EXTREMELY simple and "thin". If you had to change frameworks tomorrow and all you were allowed to take with you was your model...would you find yourself having to rewrite a lot of code? If so, you may want to consider thinning out your controllers.
It seems like a service object method should coordinate 1 or more domain object's activities (Husband::turnOnTv() = Tv::on() + SurroundSound::on() + Remove::switch()), and at the same time provide the application layer with a well-defined list of things it can do with/to the model. I'm curious to know where fairly simple single object actions, like updating a domain object's properties, or deleting a domain object, would fit.
For instance, let’s say for your user object there are effectively three kinds of properties: personal information (name, email address, nickname, and favorite animal), password, and preferences. Would the User Service object implement upatePersonal, updatePassword, and upatePreferences methods, and the controller would take the client's input and pass it along to the service layer methods? Or would the User Service object implement an "updateProperties" method, and the controller would effectively "decide" what properties to pass it? Is the answer "either is OK, as long it's in your User Service object, and the choice depends on how you want to draw your applications boundaries?"
Many thanks in advance for any advice.

