-
Notifications
You must be signed in to change notification settings - Fork 24
What is the distinction between Mach II Listeners and the service layer?
Since Mach-II is an application framework which strongly supports the MVC design pattern and architectural style, Mach-II applications are separated into three distinct layers: Model, View and Controller. This "separation of concerns" is a large part of what allows the flexibility and long term maintainability of Mach-II applications. To fully describe the role of listeners and services, we should preface the discussion with a brief overview of the responsibility of each of the three layers in an MVC system:
-
Model: The model is arguably the most important layer of your application, and is likely where most development time will be spent. It is where the core business rules are implemented within the system. The model is typically made up of Business Objects (beans), DAO's and Gateways, and a Service layer. Business Objects are often simple data containers which represent the "nouns" in the system, such as user or product. DAO and Gateway objects have the responsibility of communicating with external resources such as databases. Finally, the model's service layer acts as an API to the other objects in the model, providing the system with a simple point of access to the functionaliy in the model.
-
View: The view, also called the presentation layer, is the simplest of all three layers and is essentially "what the user sees." The view is typically made up of xhtml and css files, or a Flex front end.
-
Controller: The controller layer is responsible for application flow. It determines the flow of the request, such as which methods are called and which views are displayed. In Mach-II applications, the controller layer is made up of the Mach-II framework itself as well as Mach-II extended developer components such as Filters, Plugins, Listeners, and Properties.
Mach-II listeners are a part of the controller layer. As such, they are involved in application flow as they listen for events and take necessary actions as a result of the announcement of those events. This behavior often includes talking to other objects in order to ensure that the needs of the request are met as specified by the application. Specifically, Mach-II listeners serve as the "connecting tissue" between the controller layer and the model layer. Listeners accomplish this by interacting with service layer of the application's model. To illustrate, how this relationship typically works is the Mach-II config file will specify which method in a listener is called (via a notify or publish command), and that method in the listener will in turn call the necessary method in model's API (service layer), which will in turn may communicate with DAO's, Gateways, and other objects to fulfill the needs of the request. This architecture promotes a highly flexible and maintainable application as changes only impact a very specific part of the system and should not "bleed through" to other layers.
<event-handler event="showUserForm" access="public">
<notify listener="userListener" method="getUserById" />
<execute subroutine="doStandardLayout" />
</event-handler>
Note that the getUserById method in the listener is clearly framework aware as it is accepting a Mach-II event object as it's only argument.
<cffunction name="getUserById" access="public" returntype="model.User">
<cfargument name="event" type="MachII.framework.Event" required="true" />
<cfset var userId = arguments.event.getArg("userId") />
<cfreturn getUserService().getUserById(userId) />
</cffunction>
Unlike your Mach-II listeners, the service layer of your application is a part of the application Model, and thus should be completely unaware of the Mach-II framework. This allows the model to be completely reusable in the event that the view or controller layer of the application needed to change for any reason. This way, any external system could call the methods in the service layer (the model's API), and the model could respond without caring whether the calls were coming from a Mach-II application, a Flex application, a Web service request, or anything else.
Notice that the user service method below is not aware of the Mach-II framework, as it simply accepts a numeric ID in order to grab the correct user.
<cffunction name="getUserById" access="public" returntype="model.User">
<cfargument name="userId" type="numeric" required="true" />
<cfreturn getUserDAO().read(arguments.userId) />
</cffunction>
Both listeners and services are both objects which play the role of mediators communicating with various parts of the system. However, the listener is undeniably a part of the controller layer and is framework aware, whereas the service layer is part of the model layer, specifically serving as the API to the model, and is completely framework agnostic.
The bottom line is that a Listener is where the Mach-II framework interacts with your object model, while Service objects manage how objects in your object model interact with each other.
- For a more detailed discussion of Mach-II Listeners, please see our Introduction to Listeners
- For more information about other developer defined controller objects, please refer to introductions for Filters, Plugins, and Properties
- To see practical examples of common model objects such as Business Objects (beans), DAO's, and Gateways, please refer to Adrian Moreno's Mach-II Primer