Category: Object Oriented Programming

Lightwire versus Coldspring

Though the holidays have been upon us, my deadlines (including the unrealistic ones) stand firm as does my desire to stay strictly OO on my latest ColdFusion project.  So far, so good.  Now that some major milestones have been reached, I'm able to start testing some of my services beyond the simple unit tests I had conducted up to this point and I found the results troubling.

The more my application ran and the more in-browser testing I conducted, I found that my application response time was slowing down over time.  Not dramatically, especially considering I was the only one hitting the application.  But it was noticeable and it would certainly be a problem at production time.  I began conducting slow-going, manual "process of elimination" tests to see if I could identify the problem.  I started by doing a side by side compare of the small script I was running in two versions: with Coldspring for dependency injection or handling dependencies by hand.  The latter, in an effort to produce identical circumstances (i.e. dependencies of dependencies would have to be instantiated) took a considerable amount of code!  It's no wonder these frameworks are used!

I learned, as you might have guessed, the app was definitely faster without Coldspring.  I understand that, it's less overhead.  But the difference was very significant, especially in regards to transient objects.  So, I switched to Lightwire to see if it made a difference.  And wow... it sure did.

Lightwire appears to be a much lighter weight choice if all you need to do is identify your transients and singletons and set their dependencies on instantiation.  In doing some research to see if there was a way to get Coldspring to handle transients more effectively, I did read that others have had similar problems that they've chosen to solve with Lightwire as well.

Check out Lightwire

OO in ColdFusion Keeps UI Options Open

My first official OO ColdFusion project found it's way "on the grid" as it were with a sudden business need to have it completed ASAP.  That works for me!  But would all the sudden meetings and new people in the mix require me to refactor what I've developed so far?  As it turns out, no!

I am probably about 85% complete writing my ColdFusion objects and their DAO components.  From there, I'll move on to their validation objects which I intend to use to ensure all business requirements are met before records are saved or updated.  I intend to implement my validators by overriding my save() method where validation is required.  When this is complete, I'll have complete functionality available to me without any implementation of a user interface.  My options are open in that respect.  I can integrate into an existing application via web services.  I can write a whole new UI from scratch as a standalone app.  Or, I can do a combination of both.

When the folks at work begin scheduling urgent meetings to discuss their needs, I was concerned.  Would my weeks of silent effort be overturned due to suddenly new and urgent needs that would require code rewrites?  I attended these meetings with anticipation and planned to scribble notes furiously.  Sure enough, questions flew about wildly and other people answered these questions with ideas.  They'd drop an idea on the table and look at me cautiously, asking, "Can we do that?"

They wanted reports, scheduled alerts, options for batch uploading in addition to single file uploading, "ticklers," integration within the existing front office application, and more, all of which were items specific to what I'm referring to as the "service" layer of UI layer.  The data access layer and object structures currently developed remain in tact.  The good news was I didn't have to change a single thing.  I love you, Object Oriented Programming!

On another note, I've been able to breeze through my development by drafting my model and its dependencies BEFORE writing any code.  Admittedly, I used old school tools like Excel to do this due to my lack of familiarity on Visio, but I got a good primer on how to do things more traditionally thanks to a quick tutorial from Micky.  He's since elaborated on his blog with a very thorough walkthrough on application design that I highly recommend.

Mixing OO with Procedural in ColdFusion

My current OO project began as a dark secret -- one that I would reveal when the time was right, when enough of my own personal time had been invested that my employer would find deploying it attractive (cheap).  Then a discussion about the product it was meant to replace came about and I revealed what I had been writing, with little fanfare.  Then, a high profile meeting was called where I was brought in to discuss what I could do with this enhanced bit of code to a handful of executives.  My secret was officially out.  Unfortunately, my new audience doesn't know anything about or have any professional interest in the meaning of object oriented programming... but that's ok... for now.

What did come out of the meeting was that my other big secret intention of using Flex for the front end would not happen.  The VPs want this software to integrate directly into our existing front office application, which is ColdFusion powered but procedural to the core.  At first, this bugged me deeply, but with more thought it became clear that very little has to change.

I'll continue to proceed with the OO nature of the development.  I had planned to expose CFCs as services for the Flex layer, and I can continue to do that as intended with slight modifications to provide integration with the existing CF app instead.  This allows me to keep my model purely OO, separating my business logic into its own layer, and then instead of creating a new UI layer, simply adding on to an existing one.  No big deal at all, right?  Right?  God, I hope not!

Unit Tests Save Lives

My OO project, despite being for work, will only get attention from me in the evening hours for the time being.  I've got a bit of a backlog at the office due to my time away with whatever type of flu that was (swine?).  Nevertheless, I have it in front of me right now and am delighted to report that one of my unit tests failed!

In the previous post, I described a new process where I override the save function and call the isValidated() function in my validator.  My test save() failed.  Of course, this happened because my test required me to mock the Validator object which I hadn't done since modifying the process.  But I take a certain amount of comfort in this failure.  It lets me know that with proper testing, I can detect disasters before they make their way into production.  It also lets me know that I need to keep my tests up to date when I make changes which is easy to note if you can exercise discipline and run your tests before packaging an upgrade.

For those interested in looking under the hood, here is my revised test that passes now.

    <cffunction name="testDelegation" access="public" returntype="void">
        <cfset var user = CreateObject("component","com.model.User").init() />
        <cfset var mockBox = createObject("component","coldbox.system.testing.MockBox").init() />
        
        <!--- Mock a Dao and force a true save() to ensure delegation of save method --->
        <cfset userDao = mockbox.createMock(className="com.model.dao.UserDao") />
        <cfset userDao.$(method="save",returns="true") />
        <cfset user.setDao(userDao) />
        <cfset userValidator = mockbox.createMock(className="com.model.validators.UserValidator") />
        <cfset userValidator.$(method="isValidated",returns="true") />
        <cfset user.setValidator(userValidator) />
        <!--- This test will fail without setting a Dao/Validator --->
        
        <cfset assertTrue(user.save()) />
    </cffunction>

Validating Object Properties

Despite my newfound love affair with my ColdFusion project, my flu symptoms and the flu symptoms of our 8 month old have kept me away from the workstation and enjoying daytime television instead (dry heave).  I did manage to come across an issue before being immersed in sickness that I feel I have managed myself effectively.  However, I'll throw it out to the universe and explain it at a high level and see if it sticks.

All objects in my application that need to persist MUST be validated for required fields and various business logic.  No object will have the same validation requirements, so I've introduced the IValidator interface that is implemented by these objects.

These objects also extend a Base class which I have modified to include a getValidator() and setValidator() method, along with isValidated which will delegate to my new Validator object.  Base already included a save() method which delgated to the Dao, but I am overriding save() at the object level and will explain why. First, check out a snippet of Base with it's new validator getter/setter and it's existing implementation of save():

    <cffunction name="getValidator" returntype="com.interfaces.validators.IValidator" access="public">
        <cfreturn instance.validator />
    </cffunction>
    
    <cffunction name="setValidator" returntype="void" access="public">
        <cfargument name="myValidator" type="com.interfaces.validators.IValidator" required="true" />
        
        <cfset instance.validator = arguments.myValidator />
    </cffunction>
    
    <cffunction name="isValidated" returntype="boolean" access="public">
        <cfreturn getValidator().isValidated() />
    </cffunction>
    
    <cffunction name="save" access="public" returntype="boolean">
        <cfreturn getDao().save() /> 
    </cffunction>

A new class is created called WhateverValidator that implements my Validator interface and consists of the isValidated() method which returns boolean, along with a getter/setter for a property of ValidationMessage that will store a string that explains the results of a failed validation check.  I ensure that my object is always validated before a save by overriding save() at the class level.  This allows me to execute my validation check before circling back and actually saving.  In this example, I'm validating my Whatever class and include a new save function in my Whatever.cfc as follows:

    <cffunction name="save" returntype="boolean" access="public">
        <cfif isValidated()>
            <cfreturn super.save() />
        </cfif>
        
        <cfreturn false />
    </cffunction>

My WhateverValidator will contain all the unique validation checking on all of the Whatever properties in its isValidated() method.  I'm confident this will take place, because my Base class indicates that we are to delegate isValidated() to the isValidated() method in its Validator.  If my save returns a false response due to failed validation, I know that my controller can call Whatever.getValidator().getValidationMessage() to show the user why.  The IValidator Interface is below:

<cfinterface>
    <cffunction name="isValidated" access="public" returntype="boolean"> 
    </cffunction>
    
    <cffunction name="getValidationMessage" access="public" returntype="String">
    </cffunction>
    
    <cffunction name="setValidationMessage" access="public" returntype="void">
        <cfargument name="validationMessage" type="String" required="true" />
    </cffunction>
</cfinterface>

Of course, I failed to consult anyone who knows better than me before adopting this approach, so I'm open to any suggestions anyone has.  For now, this appears to be testing nicely.