Tuesday, August 17, 2010

ColdFusion Developer Fantasy Football League!

I just created a Yahoo Fantasy Football league just for you ColdFusion developers out there!  Its at http://football.fantasysports.yahoo.com/league/coldfusiongeeks.  For bragging rights only, but what great bragging rights they are.


The rosters, rules and scoring are all set to the league defaults.  The draft will be an auto-pick draft so you don't need to be there to get your team, just set your draft order and forget about it.  


Please shoot me an e-mail or hit me up on twitter @bittersweetryan if you are interested in participating and I'll send you the password.  



Thursday, August 12, 2010

Intro To the CFInterface Tag With A Real World Example

One of the most confusing things I encountered while learning OO concepts was the concept of interfaces.  Definitions of interfaces was were abundant but I couldn't find much information on how they were used in an actual application.   This post will focus on a real world example of using an interface in an application and hopefully help clarify how they can be used to create more flexible objects. Also, please feel free to leave me a comment and tell me where I'm way off here, I'm always learning and willing to listen to any good constructive criticism.  

At a very high level interfaces are types, just like components are types and can be passed around similar to components.  The difference between an interface and a component is that an interface has no implementation code (code that actually does something) inside of the function definition.   All an interface does is define functions and their signatures.  A function's signature is its name plus unique combination of arguments.   Lets take a look at  an example of an interface that defines a "Document" in a system that I am currently working on.

interface  hint="I represent either a binary or xml document"
{
     public any function GetDocumentData()
     hint="I send back document data" output="false";

}

Pretty simple looking, right?  The main thing to note here is that there is no implementation code, the function is just a skeleton.  This interface is a contract for any component that implements it saying that the component must have a method called GetDocumentData that returns the type of "any".  Its up to the implementing component to actually do stuff within the GetDocumentData function.

For the application I'm currently working on a Document object can represent either a Binary document such as a Word or Excel document or an XML document.   Since the handling of binary data is different than the handling of XML data I needed to create seprate components to handle each type of document. Here is the code for the  BinaryDocument Component:

component displayname="BinaryDocument" implements="IDocument" hint="I represent a binary document (word, excel, etc)" output="false"
{
     variables.documentData = ToBinary('');

     public void function SetDocumentData(binary documentData){
          variables.documentData = arguments.documentData;
     }

     public any function GetDocumentData()
     hint="I send back document data" output=false
     {
          return variables.documentData;
     }
}

You can see that the GetDocumentData function now returns variables.documentData which defaults to an empty Binary object and is set by the SetDocumentData function. The XMLDocument component is very similar, except the document data is stored as a string:

component displayname="XMLDocument"  implements="IDocument" hint="I represent a XML document (word, excel, etc)" output="false"
{
 variables.documentData = "";

 public void function SetDocumentData(string documentData){
  variables.documentData = arguments.documentData;
 }
 
 public any function GetDocumentData()
 hint="I send back document data" output=false
 {
  return IsXml(variables.documentData)?XMLParse(variables.documentData):false;
 }
}

Now this is were interfaces become useful.  My system also includes an Attachment component that can represent either a binary or XML document. The Attachment component has a Document property which is set using the SetDocument function.  Whats important to see here is that the argument type that the SetDocument function expects is IDocument.  This means that any component that implements the IDocument interface can be passed into this function.  Since we know that the IDocument interface defines a function called GetDocumentData we can call that function on the Document property to return the data from any type of document.   The code for the Attachment object is shown below (I've removed all the other properties from this function to keep things terse):

component displayname="Attachment" hint="I represent an attachment" output="false"
{
 property name="variables.Document" type="IDocument" setter="true";

 public IDocument function getDocument()
 {
  return Document;
 }

 public void function SetDocument( required IDocument Document )
 {
  variables.Document = arguments.Document;
 }

 public any function GetDocumentData()
  description="I return a documents data as defined by the Document object." output="false"
 {
  return variables.Document.GetDocumentData();
 }

}

The following code is shows how all of these components are put together to output different types of data:


 //create a new binary document
 BinaryDocument = new BinaryDocument();
 BinaryDocument.SetDocumentData(toBinary(''));
 
 //create a new XML document
 XMLDocument = new XMLDocument();
 XMLDocument.SetDocumentData('XML is it your friend or foe?');

 Attachment = new Attachment();
 Attachment.setDocument(XMLDocument);
 
 WriteDump(Attachment.GetDocumentData());
 
 Attachment.setDocument(BinaryDocument);
 
 WriteDump(Attachment.GetDocumentData());


This is what the preceding code outputs:


For additional reading on Interfaces check out Sun's Java Tutorials here: http://download.oracle.com/javase/tutorial/java/concepts/interface.html.  I'd also suggest you read http://www.artima.com/lejava/articles/designprinciples.html where Erich Gamma talks about why programing using interfaces is preferred over inheritance here .

Thursday, August 5, 2010

My MXUnit TDD Perspective in CFBuilder (or CFEclipse for that matter)

First things first, if you are not doing Test Driven Development yet you should at least give it a try. Sparing all the technical aspects of why its good, its just a fun way to code.

In order for you to understand why I have my perspective setup this way for TDD a quick explanation of what TDD is in order. The basic principal of  Test Driven Development is to write unit tests before you write your implementation code.  For instance, if I wanted to write a function in an Account object to test if a username existed I'd start by writing a test called something like "TestIsUsernameUnique" in a CFC Called TestAccount.cfc.  Once that test is written it is run and should fail since the IsUsernameUnique method has not been implemented yet. This is an important step in TDD, if that test passes there is certainly something wrong with the test itself.  Once you have seen the test fail the implementation code (the actual IsUsernameUnique function) is written and the test is run, and re-run until the test passes.  

One great way to learn TDD is to watch TDD Kata's.  These are screencasts of people doing live test driven development.  I've always learned best by example so watching TDD Kata's has been invaluable to my learning of TDD.

Now that I've gotten that out of the way lets talk about how I have my development environment setup for Test Driven Development.   When I'm doing TDD there are 4 things that are important to me: 1 - my UML diagram, 2 - the Test code, 3 - the implementation code, and 4 - my MXUnit view.   Additionally I like to have my outline and console views handy so I can get a quick glance of what functions are in in the code I've written.

The first step in creating my TDD perspective is to minimize the navigator view and get rid of every other view.  This might be a good place to point out that you can always reset your CFBuilder or CFEClipse perspective back to its default state by going to Window -> Reset Perspective. The following image shows what my default ColdFusion perspective looks like before I clean up the screen:


This is what my perspective looks like after I clean up my screen:


Now that I have a blank canvas lets get my workspace setup for Test Driven Development. Assuming that you have the MXUnit eclipse plugin installed, open it by either clicking on the MXUnit icon on the top toolbar, or by going to Window -> Show View -> Other -> MXUnit -> MXUnit.  By default this should open on the right side of the screen as shown:


This isn't the ideal location for TDD so I'll move it to the bottom of my screen by dragging the tab towards the bottom of the screen until the outline fills the width of the eclipse screen and dropping it there as shown here:


This is useful when using TDD for a few reasons.  First you get more real estate to read the "Tag Context" of the MXUnit view so you can see exactly why your tests are failing.  Second, as you'll soon see I need all the horizontal real estate as I can get for my code.  

Once I have my MXUnit view anchored on the bottom of my screen I'll also do the same process to add the Outline and Console views next to my MXUnit view on the bottom.  I add these tabs because I like to be able to see what functions are available in the file I am working on to make sure that the function names in my test code and in my implementation code are the same.  I also like to see what MXUnit is doing behind the scenes in the console.

Now for the important part, the code.   If you haven't already created your implementation and test cfc's, use the Navigator (which was minimized so you'll need to click on the Navigator icon on the left of the screen to see it) to create them.  Now you should now have two code editor tabs open in your editor, one for your implementation code and one for your test code.  The next step is to get both of these files to display right next to each other.  Personally I like my test code to be on the right and my implementation code to be on the left, but the order really doesn't matter.  To do this grab the tab for either your test code or your implementation code and drag it towards the left side of the screen until  the outline fills half of your editor area and drop it there. The final workspace should look something like this:


Now you can see your test code, test results, and implementation code all on the same screen and are ready to become a TDD ninja.

One last step is to save this perspective so it's readily available for your TDD development.  Go to Window -> Save Perspective As and enter a name for it.
Fork me on GitHub