Monday, June 23, 2008

programming problem solving

I have been working on my little developers application, with the intention of implementing pure OO techniques and coldSpring. I am also implementing machii framework version1.6. I will start to exploit the new machii features later in this process. For now, its more about proper modeling of classes or components. Keeping things where they belong. I mean keeping the model layer agnostic of the application that is using it, keeping bus logic in the service or model layer. Keeping validation logic in the beans, avoiding anemic bean syndrome.

Initially, i put the object creation code in the service for its dependent dao and gateway objects, got that working, then plugged coldSpring into the machii framework, ensured that was ok by creating the pointer object into the coldSpring bean factory (the CS black box). Once that worked, i added the acual bean creation code to the services.xml file (thats the one cs consumes to read your component definitions. I defined the service, DAO and Gateway components in the services xml file, with the DOA and Gateway as ref. objects within the services object. I then added the setxxx methods to the service object and finally removed the code from the init method in the service.

Once that was working, yea! I ran across a blog where someone mentioned creating a utility debugger and using it to dump from within a cfscript block. I probably read something like this before, but i was not ready to grok it. Now, i groked it. I set up a utility cfc and registered it in the coldSpring container (services.xml) and referenced it from the bootstrapper object, Application.cfc. I created a application scope on it, so i could reference it from any objects in the model. Ive used it a couple times already, and find it very useful. Brilliant!

Think of coldSpring as an attachment to the model layer. At application start, there has to be some instruction that says reference and scope the beans that are defined by the coldSpring framework in the services.xml file. This does create a thin layer of coupling between the application and the model layer, but its contained to a single bootstrapper object that has the knowledge of the coldspring framework.

Think abstraction. The more abstraction, the better. Abstraction = less knowledge of the collaborating entities. There will always be some coupling, but it is favored to reduce that coupling to its purest form.

Tuesday, June 17, 2008

framework OO design debugging

I got my developer app working today. This is my new app. that is utilizing pure OO techniques. It is still a shift for me, as i struggle, i see this more. Think in terms of objects, encapsulated objects, that contain their own data. Pass around a reference to this object, rather than passing along pieces of data by value. How does the object serve the application? Does the object know anything about what application is using it (lets hope not). Let the object take care of itself, keeping its own state and not reaching out to other objects (loosely coupled).

Its not ok to create just tiered applications anymore. I am thinking now more about objects and their state, relationships and bus. logic (which object should it belong, bean, service, DAO/Gateway) and even if i need a bean or service for an object. Could the entity be served by an existing object. I *should have less services than actual beans, as the application progresses. Its ok to start with the 4:1 (entity in your domain has bean, service, DAO, Gateway) - but this is a guide,not a rule! As Sean Corfield said, dont create an anti- pattern.

Anther problem i was running intois the mach-ii framework masking the errors (that i created first in my listener, then in my service, then in my DAO). The experience of stepping through the event flow is always valuable, but the framework was not helping by reporting a very unhelpful message. Is the framework really to blame for masking my mistakes? I think without a framework, i would have at least had a better path to follow regarding where CF was failing (in the listener, service, DAO/Gateway or somewhere else.

Anyway, i have worked my way through the problem. I have a listener that is handing off to a service. The service method requires a struct(listener passing in event.getArgs() ), takes the arguments passed in and calls a private method in the service that instantiates a new object and used the setter methods on that object to update with the arguments passed in from the listener. When the private method is complete creating and updating the object, it passes it back to the main method, who then calls the DAO to it its work. The resulting object reference passed back by the helper method is used as an arg to the DAO. Passing by reference, not value.

This is a big leap for me. I am not passing around a bunch of data, but rather an object reference that is resp. for keeping its own data. Object = encapsulation of its own methods AND its own data.

Im still not sure if my service is real smart, but i am passing by reference now. In my DAO create method, i will keep the validation logic around the actual SQL insert. This is keeping with the fat bus. ready object (non anemic).

Saturday, June 14, 2008

Design Patters (official)

Gleaning from Sean Corfield presentation.

Pattern: Composite View
A composite view is a view that includes other views

Patterns have four parts:
• Name - the common vocabulary
• Problem - “forces” that determine when the
pattern is applicable
• Solution - a template for solving the problem
• Consequences - “pros and cons”

APPLICATION / onApplicationStart()
is a singleton pattern (once entity accessible from one place)

problem (trade off) is breaks encapsulation when object x needs to reference some application scoped variable. A solution is to use something like CS, that injects object X at instantion with the application scoped variable (which is no longer application scoped at this point).

A common problem

I have components that make up my user
security logic but I don't want to expose them to
other code, in case I want to change how its implemented.

Create a new component that has a simple
API that calls the security components.

Think in terms of trade / offs (pros and cons) a pattern has both!
For example

Application code no longer needs to know about the
internals of your security system (+)

Application code can still get at the “low-level”
components if it needs to (+/-)

Some redundancy of methods between the API and
the underlying components (-)


Pattern - Facade ( common very helpful)
Problem - as a subsystem grows, it becomes more
complex with a large number of smaller objects

Solution - introduce a single component that
provides a simple API to the set of components
within the subsystem

Consequences - shields clients from the inside of the
subsystem, reducing complexity and coupling; does
not prevent access to subsystem if needed

Often only one instance of a facade is needed(singleton)

Pattern Name: Front Controller
- like fusebox or machii or global index, each of these frameworks is a front controller pattern.

Problem - need to apply consistent logic across all
requests in an application (security, layout etc)

Solution - route all requests through a single file that
decides how to process the request

Singleton and Facade refer to objects, most design patterns are focused on OO design

Consequences - centralized control, easy to change
how requests are handled in a consistent manner,
moves logic out of individual pages into controller
(which can become complex)

cfinterface specifies the methods a component provides (API) but not how they behave. cfcomponent *implements* the interface to specify the behavior. An interface can have many implementations. But duck typing is more powerful and appropriate for
ColdFusion - onMissingMethod() lets you implement any methods dynamically.

-- Sean Corfield

However, this is starting at the wrong end. When you
learn patterns by focusing on the solutions they
present, it makes it hard to determine the situations in
which a pattern applies. This only tells us what to do
but not when to use it or why to do it.”
-- Alan Shalloway

Creational patterns
Abstract Factory, Builder, Factory Method,
Prototype, Singleton
Structural patterns
Adapter, Bridge, Composite, Decorator, Facade,
Flyweight, Proxy
Behavioral patterns
Chain of Responsibility, Command, Interpreter,
Iterator, Mediator, Memento, Observer, State,
Strategy, Template Method, Visitor

Frameworks are designed to solve common problems
• Application frameworks usually implement several patterns
• Front Controller - everything goes through index.cfm
• Model-View-Controller - segregation of the presentation and
business tiers

ColdSpring
• Chain of Responsibility - each “aspect” calls methods on the next
“aspect” until the underlying business object is reached
• Identity Map - cache of objects accessed by “id” (bean name)
• Proxy - same API as your business objects but intercepts method
calls to execute before, after or around “advice”

Friday, June 13, 2008

MachII 1.5

When we upgrade our machii framework code to version 1.5 (released a year ago) there are several changes to note.

First, our existing code should not be effected. Although when i tried this briefly a couple weeks ago, i had a problem with one of the application controllers that was using a .dot notation in the event names. For example; in one of our sub-app controllers, most of the event names look like this;

event-handler event="somename.somethingelse.somethingelse" access="..."/

I have posted this question in the machii google group to see if any known problems with this notation exist.

Also, i have been running across the concept of a "bootstrapper" file or process in a number of blogs recently. The bootstrapper is the start-up routine or file that is responsible for doing application startup configuration. In the old school, no framework world, this would be the index.cfm file. I used to call this the driver, from my days as a procedural programmer. CF also has long supported the notion of an Application.cfm file, work done here has the application scope. With machii, there is the concept of the Application.cfc file and the index.cfm file. Prior to version 1.5 or machii, there was often setup code in the index.cfm file, including the include of the actual framework. In mach1.5, this goes away and no code lives in the index.cfm file, it all goes in the Application.cfc, which is actually extending the machii framework.

When we upgrade the machii framework code to 1.5, we will have to be careful to move that important bootstrapper info from the index.cfm file to the Application.cfc file.

When looking critically at this new bootstrapper file, think in terms of these areas:

application wide properties
machII specific properties
public functions, like
onRequestStart

Once this is done, we should not have too many other issues, then we can start taking advantage of the new 1.5 features, like the include functionality, that will allow us to break up the controllers into smaller pieces.

Where to put listeners and model code

I ran across a blog discussion today about best practices regarding locations of mach-ii listeners -vs- model code.

A summary.

Listeners are not part of your model layer, so keep them separate from the model code.

Put listeners into a /listeners folder.

Put model code in a /model folder.

In the model layer, some suggested organizing the cfcs like this:

/model/Beans
/model/Services
/model/DOA
/model/Gateway

This is know as grouping by functionality.

Most of the expert opinion (Matt Woodward, Peter Farrell) favored this approach for the model layer.

/model/busObject/

where the bean, service, DAO and Gateway objects were grouped by type. Since these objects comprise the abstract concept of a package, store them as a package. This seems more intuitive, as other programmers come into the application, they will take the approach of what bus objects are there and see what pieces of that package exist.

This is a quote from P Farrell "Otherwise, you are breaking objects into
directories based on object type (pattern/functionality of the object)
instead of the object's purpose (having to do with "user" stuff). This
is counter-intuitive as a developer would have to scan through a
"beans", "gateways", "services" and "daos" directories to see if the
User (bean) has a corresponding service, dao, gateway, etc.. Much
easier (and it makes more sense in the long run) to group by object
group instead of object type (pattern/function). "

Wednesday, June 11, 2008

A ColdSpring conversation between Mex and Lex

A hypothetical conversation between, a lesser experienced developer, Lex, and a more experienced developer Mex.

Lex, "what the heck is coldspring?"

Mex, "a framework that helps manage the model layer of your application"

Lex, "whats a model layer"

Mex, "the part of your programming that contains the bus. logic used in the program"

Lex, "how do i know if i have a model layer? and what is the bus. logic"

Mex, "does your application follow the MVC design pattern?"

Lex, "whats MVC?"

Mex, "a way of building your application so the view code is separated from the database and bus. logic code"

Lex, "i think we follow that, i have only really worked on the view side, thats coldfusion .cfm files, right?"

Mex, "yes, cfm files are usually a big part of the view layer, if your using ColdFusion. The model layer which contains your bus. logic are stored in coldFusion files called CFCs. The CFCs are the classes, like in Java."

Lex, "so what does ColdSpring do again?"

Mex, "Coldspring managers the model layer and helps with the relationships, or dependencies that exist between CFCs that collaborate in your model layer".

Lex, "You mean like a service or manager CFC that uses a DAO or Gateway CFC?"

Mex, "exactly like that. The service component or CFC is dependent on the DAO and Gateway to do its job. The way that is typically handled is when the service object is created, it has an init method or function that is called that creates the other objects it needs. In a larger application that has lots of services, this can become a big headache to keep track of."

Lex, "I think i heard some of the other programmers i work with complaining about this and how you have to open a bunch of files to track down what is being created and where."

Mex, "right, CS reduces that complexity by putting all that object create code into a single file or container. That file is responsible for defining all singleton objects in the application."

Lex, "instead of putting create object code in the init method of the service for the DAO and Gateway, you put it in a coldspring file? I could do that for all the services in the application in this one file?"

Mex, "yes and yes"

Lex, "Is the coldspring file magic?"

Mex, "sort of, seriously, its just a xml style file, its really not that complicated, once you understand what its doing"

Lex, "ok, im in, lets get down to some nitty gritty"

Mex, "i thought you would never ask"

Mex.....

CS is a framework, a black box, with a lot of code that you never touch, you simply use it. If you are using a framework like mach-ii, fusebox or model-glue, you have specific "plug ins or hooks" that connect CS to your model. Mach-ii has a plug-in architecture that connects CS to your application.

You write a little code upon application start that executes and creates an object pointer to the black box (CS). Then you use the CS object passing into it the file path to your bean definition file to load the definitions. Each of the beans (objects) is loaded in the application scope. This is really the only file that CS interacts with.

If the object that you are creating has no dependencies, its very simple to create the object with a xml style notation. If the object needs arguments passed in upon instantiation, use the arguments parameter to pass that data along. If the object has dependencies on other objects, use the tag to inject the dependency into the parent dependent object. Think of this as an "inner-bean". If the injected object is only used by the parent object, then define the collaborating objects like this:

bean id="someService" class="somepath.someService"
property name="someGateway"
bean id="someGateway" class="somepath.someGateway"
/property
/bean

When someService is created, it is injected with the someGateway object. The someGateway object is only available to the someService object. Sometimes, the object needs a more global scope, so other objects can reference it as an injection.

If the object being injected is already defined, use this notation to inject:

bean id="someService" class="somepath.someService"
property name="someGateway"
ref bean="someGateway"/
/property
/bean


The difference is that you are not injecting a new object


property name="someGateway"
bean id="someGateway" class="somepath.someGateway"
/property

but are injecting an existing object

property name="someGateway"
ref bean="someGateway"/
/property


ya dig?

More to follow.

Tuesday, June 10, 2008

Anemic Domain Model

I was reading an article by Sean Corfield in Fusion Authority today. I have read this article before, but my brain was not ready to grok it, today, it grokked.

The main concept is that too often we load up bus. logic in the service object instead of the bean or value object where it belongs. If you think critically on this, it makes sense that since the data and methods of an object are encapsulated into the value or bean object, so too should the bus. rules around it.

The anemic model is one where the value beans are just containers with state and getter and setter methods - not much else, the bus. rules are stored in the service object.

Sean makes a good point that many of our web applications are getting record sets, presenting in a collection, hiding detail, proving details about one record when requested, not alot of bus. logic to fill up our value beans. But, a good candidate is validation logic when dealing with single or groups of recs, rather than putting that logic in the service, leave it in the value bean - let it live along with the data and methods that it works on.

I recently completed grokking why bus. logic should be in the service and not the listener (model layer, not the application). I supplemented my understanding by going through a few of the older listeners and moving bus. logic out of and into related service object. Perhaps i will iterate again, moving small amount of logic from the services into the beans.

Lets turn those anemic value objects into rich domain objects!

Friday, June 6, 2008

hard core refacoring

I have spent the past 2 days retooling the model layer of a mach-ii application.

I have renamed numerous listeners and moved then into a new listeners folder. I am really trying to promote the idea of model and application autonomy.

/listeners/ objectNameLister1, ... objectNameListerx

/model/objectName/ service, bean, DAO, Gateway

Each time i renamed a listener, i did a careful search of the controller to update all instances of the old listener name. In some cases, this was only a couple instances, in others, there were many. This also gave a sense of what parts of the application are more widely used.

In a few cases, i renamed a manager that was really a listener, moved it into the listener folder and created a new service cfc. The new listener should only speak to its registered service, so i had additional refactoring to do in the listener. I updated methods that had knowledge of the DAO and Gateway moving that into the respective service. This supports best practices of the listener being coupled to the application and bus. logic living in the model layer, not the listener.

Think about the model layer as application agnostic. Your model layer should be usable by another application. Imagine there is no mach-ii framework with listeners to invoke services. Another application may want to use the objects in your model layer. I moved ALL knowledge of DAO, Gateway and other services from the listeners into their service. The service is the king of the jungle, not the listener. The listener just passes things along.

There were a few listener methods where i left bus. logic in place, but that logic is dealing with announcing of events, making it application logic, which belongs in the listener NOT the service.

Changing the location of the listeners required me to update the path in one place, the mach-ii listeners configuration. If i changed the location of the model classes, i had to change the path of the object invocation (init) method in the service, DAO and Gateway. After doing this a few times, i really stated to see the beauty of the coldSpring layer, which encapsulates this type of change into a single entity, the coldSpring.xml file. I also saw that some of the objects are not taking advantage of the coldSpring framework. These are candidates for coldSpring.

When i encountered listeners and services that had an empty configuration or init method, at least in terms of object creation, and i would see pointer references in class methods, i knew those pointers were defined somewhere, who would have knowledge of such pointers? I also noticed a set method that accepted the object itself at the bottom of those classes. Each of these things is a clear indicator that there is an object management framework in play.

I am still getting my head around how coldSpring is doing things, i thought i would deploy all these changes first, then work on a coldSpring deployment separately.

Things are jelling now, jellin like a felon, architecturally speaking.

Wednesday, June 4, 2008

Evolution of a MVC application

I have been tasked the honor of bringing others into or up to speed with a big MVC application. That's ok, i used to be a teacher and trainer, part of my brain enjoys the mentoring role.

I have been studying the architecture of the application, doing some reverse engineering for awhile and have a little summary i would like to share. Blogging this stuff helps me internalize and forces me to think more critically.

In the beginning our application did not use services. Most entities were created following the

Bean
Manager
DAO
Gateway

design patten. Which is fine, except the managers are actually the listeners, they are extending the mach-ii framework listener. All of these files are located in the root of the application in the model folder. Object instantiations to the DAO/Gateway occur in the managers (listener) constructor. The manager is trying to act like a manager (service) by creating its dependency objects (DAO, Gateway) in its constructor. Thats fine, good practice.

As the application grew, real managers started appearing, but not in the model folder (that should just be listeners) in a org. path. The idea of the org. path is to promote the concept that the model or bus. layer is application agnostic. It should not live in the same file structure as the applications listeners. Ill buy that.

The managers, playing the service role, live in the org path along with the other depenency objects, DAO, gateway and Bean (value bean). The managers (services) are responsible for instantiating their dependency objects (DAO, Gateway and bean). The listeners in the model path are only instantiating their manager or service object.

As sub applications start appearing, listeners are where they should, in the model layer and in a couple cases, the related bus. logic (bean, service, DAO, Gateway) appear in a folder beneath the model layer. This is ok, but does not seem to promote the idea of reusable model layer components or agnostic model layer.

In most cases, the listeners are instantiating their service object in their constructors while the service is instantiating their dependent objects in the init functions.

Eventually, ColdSpring was introduced to start managing all these object and dependency object creation. ColdSpring is a framework that abstracts the knowledge of dependencies from the actual objects. Ill study more on this as it appears some objects are not yet utilizing this feature.

Most of the application is following OO practices, meaning that object references are being passed along to service and DAO funtions that are requiring them and using the reference to the bean to handle updating or persistence requirements. Gateway functions are typically accepting values, not references and returning queries.

Some of the application functionality, like the stuff i wrote, is using object wrappers but is too often using procedural pass by value and not object reference. It was not until recently that i really started looking critically at this and reading in blogs why this is problematic.

As i continue to stretch my brain and teach others about this application architecture, i will continue to re-factor and implement OO practices.

Refactoring with on eye on patterns

I have been looking with a different eye at existing code in our applications. Refactoring code is an important part of any programmers job. I hear the stats about 75% of programmers time is spent maintaining existing systems. That seems about right to me. I have spent a lot of time the past month studying design patterns and best practices for CF developers, since the excellent CF Objective conference in May.

I have been looking at listeners in our mach-ii application and their managers (services) with an eye for moving bus. logic out of the listener and into the service. We actually had a cfc that was named a manager, but was actually a listener, it was extending the machii listener framework and was referencing event args. but did not have a service layer at all. I have been refactoring, renaming the manager to listener and creating a service layer between the listener and DAO/Gateway. It has taken me a long time to really get my head around why we would need all these layers, but i think its finally starting to jell.

I have spent lots of time in blogs, tutorials, books and existing code, learning from the experts, standing on the shoulders of giants, as my former co-worker liked to say.

I will continue looking at the listener and moving bus. logic out and into the service layer repeating the mantra "the listener only passes data to the service layer", its a traffic cop, not a problem solver. The listener can contain logic that directs the flow of the application, but not any logic that pertains to the bus. objects. The bus. objects are application agnostic!

I woke up this am thinking and repeating this to my 11 year old son.

"The bean is a container, that holds data and instructions about something, an object". When the application needs to reference the data or behaviors of the bean, it asks the service layer to do it. The service layer instantiates the bean and passes references to the bean into DAO which will operate on the bean." In others words, a reference to the bean is passed along to service who then passes where it needs to. Any functions that manipulate the data stored in the bean do so by reference. A DAO method requires a object be passed in and references the attibutes of the object via the argument reference passed in."

We are no longer passing values around from one function to another, but rather passing references to a bean.