The Concept of an Application Services Layer
I want to discuss a concept that I have been using for a while but have not been able to find it discussed on books or blogs I've read. I am talking about a formal layer of the application architecture that, for lack of any better name, I call "Application Services" layer.
Usually applications require some supporting functionality needed to perform their job but which is not part of the application's "business logic" per se. For example, you may be using something like Mailer.cfc to handle all outgoing mail from your application. Now, this component encapsulates some logic but it has nothing to do with the purpose of your application (well, assuming your application is not an email utility of some sort), and usually when you use this kind of tools you only require to have a single instance laying around maybe on the Application scope, or an instance that is passed around from object to object. This type of functionality is what I call an Application Service, and the collection of many of these services provide a layer of supporting functionality to the application. This layer of support is what can be called an Application Services Layer (do not confuse with Service Layer, which is something completely different)
Furthermore, these application services provide additional functionality to the application which may also be required by other layers; thus making it hard to fit this concept within any of the other layers of the application and reinforcing the idea of treating this collection of services as an application layer or tier on their own.
To better illustrate this, let's say we have a "bugTracking" component which should be called when exceptions are thrown so that errors are handled on a standard way. This service may do things like sending an email report to someone or writing to some specific log. Obviously calling this "service" would be very useful whenever an error occurs regardless of where it happens. Since the last thing we want is to be duplicating code, then we would end up needing to use this same service regardless if the error occurred while rendering a view on the presentation layer or applying a business rule on the domain model. Therefore the utility of an application service cuts across the traditional separation across application layer boundaries.
If we gather all these services that our application may need at some point and store instances of them on the Application scope, we can provide a support layer for our application that can be accessed from anywhere on our code; and since this is a layer of shared resources we are not really violating any rules of layer separation because these services are neither used (nor shall be) for outputting content to the browser or performing business logic.
Now, I imagine someone could argue that instead of having everyone invoking the Application scope to get to these services, they could be injected into the CFCs that require them via some form of dependency injection. However, in doing so we would be required to modify the interface of our components by adding a setter or an additional constructor argument for this specific service. The problem with this is that we would be forcing the object interface to be aware of this dependency which is not really related to the purpose of the object, complicating thus any future refactoring when the service may no longer be needed. At most to maintain a proper separation, we could have some sort of registry to handle the access to these services, but that can be discussed on a different post.
At the end, even if I am not using the correct name, I think it should be recognized the benefit of having an "Application Services Layer" to provide the supporting features needed for an application.
I can see the application service layer also as a web services registry, from where you are going at. However, I would probably view this as part of my domain model and treat it as an internal service that can be injected to the other services that would need mailing.
Again, that is my opinion
We have tons of legacy systems that we expose via service APIs that do everything from functionality tucked away in our systems to utility features like email, internal messaging, etc. When we build our applications (web or not), we traditionally use a 3 layered approach: Interface, business, and integration layer.
The integration layer re-exposes the service APIs we're going to use in the application via proxies or some form of fascade classes. The business layer is representative of the domain of the application as it applies to the execution of business rules and satisfaction of use cases. In this layer we utilize classes from the integration layer to satisfy the requirements of the software. In the interface layer, we construct our UI (via CF, Flex, whatever) or if we're building a service API we expose a service interface (via REST, SOAP, JMS, whatever) utilizing objects from the business layer.
It sounds like what you're calling your Application Service Layer is what we call our business layer. Like I said I may be completely off base, but this approach has been extremely beneficial to us (i.e. - easy to model in UML). When you get into really large systems, you end up sharing a domain, but what's done with each domain object is potentially very different in each application. Business layers amongst other things help to solidify what is done with those domain objects (usually via use cases and such) per application. We find ourselves duplicating a lot of design efforts, but the work is usually pretty simple and quick and contributes to that common domain model that we try to version.
We've had success applying this practice to our web tier and still used things like ColdSpring to speed up production time. If I am reading your post right, I think you're on the right track. If you ever want to talk more about this, just let me know.
Keep up the great ColdBox work!
I think I may have sounded too ambitious on my description of the application service layer; I was mainly describing something more akin to "libraries" of functionalities; like for example lets assume that there was no CFQUERY tag in ColdFusion, an application service could provide that type of functionality independently of what is the business logic of the application. Does that makes more sense?