Tartan is a command-driven service framework for ColdFusion. It was built to help produce the service layer within a larger application architecture which relies on strict separation or layering of functionality.
All access to the underlying business logic is controlled by public services which are available locally as CFCs and remotely via Flash Remoting and SOAP web services. A service can be composed of any number of commands, each of which implements a discreet operation within the application. These contain the core logic for the application. Commands can communicate with databases via DAOs, manipulate values received from the client, execute other commands and even communicate with services available on other remote servers.
At the center of Tartan are 6 Core classes : LocalServiceProxy, LocalService, Command, DAO, ValueObject and ExceptionHandler. They provide most of the functionality of the framework, and must be extended by the application developer.
Overview and Explanation
The driving need behind Tartan was a production application that needed to transfer data between 5 different databases and 3 different applications. There was a complex set of DAO classes and a faade class that provided access. Each fa ade class had a single public method called “execute” that would simply take arguments and return a result.
This concept worked well, but obviously had its limitations. So Tartan was created to be able to quickly and easily add new commands to services, and new services to the system.
Tartan is described as a “command-driven service framework.” What does that mean? In this context a “service” is a set of commands that have commonality, and a “command” is a method that executes any number of other methods and returns a result. It’s that simple. A service such as “televisionViewer” could include a command such as “getListings” which would, based on locality data provided either by a config file or a method argument, check local listings and return a collection of data regarding current television listings.
To further explain the concept of “commands,” we could offer that method a second argument such as “returnType” and return the listings as an array of structures, a CF query object, or an XML file. By adding commands from granular to broad, we can incorporate them into sequences. For instance, if we wanted to offer the findMyShow command, we could have it first execute getListings, then parse the resulting data and determine if our show is on soon or not.
By doing this carefully and with some planning, we develop a very simple interface between our application and any persistant storage mechanism and/or business objects, with the ability to filter, alter, or convert our results before they’re returned to the caller. If we start with granular and move to broad commands, we maintain the flexibility and encapsulation of an OO design, but gain the convenience and natural-thinking appeal of procedural programming.