Contact info.
 
My Secret Life as a Spaghetti Coder
home | about | contact | privacy statement
Here's a 35 minute recording of the presentation which I gave to houstonrb on February 21, 2012. It is a practice run I did before the live presentation, so you won't get the discussion, but hopefully you'll find it useful anyway.

How to avoid becoming a formerly-employed Rails developer standing in line at the OOP Kitchen from Sammy Larbi on Vimeo.



You can find the slides here: Slides for the Rails OOP presentation

There is also reference to a project whose purpose is to eventually be a full-scale demonstration of the techniques: Project for the Rails OOP presentation

Let me know what you think in the comments below.

Updated to use HTML5 player at Vimeo.

Hey! Why don't you make your life easier and subscribe to the full post or short blurb RSS feed? I'm so confident you'll love my smelly pasta plate wisdom that I'm offering a no-strings-attached, lifetime money back guarantee!



I'm writing a Client of FooServer which is reliant upon a rather clunky library whose functionality I'd like to encapsulate in a wrapper library to make the usage less clunky.

My first thought is to choose FooServer as the name of what will likely be the most used class in the library. That way, when I want to get some property of the server or tell it to perform some action I can do something like:

FooServer foo = FooServer.findById(12);
string property = foo.property;
foo.performAction();

That seems innocent enough. But my fear is that by calling the class FooServer, it may violate the principle of least surprise because it does not fully implement a Foo server, nor would it be of use in implementing a Foo server.

I also dislike tagging it with "Wrapper" or something of the sort, because reading that in the client code doesn't seem right either.

I know I'm probably over-thinking it, but names are important to me, because they are the start of clean, readable code that does what it says and says what it does. So that's why I come to you, dear reader.

What would you name the class?


This is the eight in a series of answers to 100 Interview Questions for Software Developers.

The list is not intended to be a "one-size-fits-all" list. Instead, "the key is to ask challenging questions that enable you to distinguish the smart software developers from the moronic mandrills." Even still, "for most of the questions in this list there are no right and wrong answers!"

Keeping that in mind, I thought it would be fun for me to provide my off-the-top-of-my-head answers, as if I had not prepared for the interview at all. Here's that attempt.

Though I hope otherwise, I may fall flat on my face. Be nice, and enjoy (and help out where you can!).

More...


Last week, hgs asked,
I find it interesting that lots of people write about how to produce clean code, how to do good design, taking care about language choice, interfaces, etc, but few people write about the cases where there isn't time... So, I need to know what are the forces that tell you to use a jolly good bodge?
I suspect we don't hear much about it because these other problems are often caused by that excuse. And, in the long run, taking on that technical debt will likely cause you to go so slow that that's the more interesting problem. In other words, by ignoring the need for good code, you are jumping into a downward spiral where you are giving yourself even less time (or, making it take so long to do anything that you may as well have less time). More...


This is a story about my journey as a programmer, the major highs and lows I've had along the way, and how this post came to be. It's not about how ecstasy made me a better programmer, so I apologize if that's why you came.

In any case, we'll start at the end, jump to the beginning, and move along back to today. It's long, but I hope the read is as rewarding as the write.

A while back, Reg Braithwaite challenged programing bloggers with three posts he'd love to read (and one that he wouldn't). I loved the idea so much that I've been thinking about all my experiences as a programmer off and on for the last several months, trying to find the links between what I learned from certain languages that made me a better programmer in others, and how they made me better overall. That's how this post came to be. More...


Since the gift buying season is officially upon us, I thought I'd pitch in to the rampant consumerism and list some of the toys I've had a chance to play with this year that would mean fun and learning for the programmer in your life. Plus, the thought of it sounded fun. Here they are, in no particular order other than the one in which I thought of them this morning: More...


At the O'Reilly ONLamp blog, chromatic pointed out that we should "program as if [our] maintenance programmer were not a barely-competent monkey," quoting a paragraph from Mark-Jason Dominus.

Mark was describing the idiocy of programming-by-superstition, where you might put parentheses if you are unsure of the order of operations operator precedence (or, to help barely-competent monkeys know the order precedence), rather than re-defining that order as opposed to using them to change the "normal" precedence. More...


The next few days in Houston are busy for programming technophiles. A couple of quick reminders:

BarCampHouston 2 is this Saturday, August 25, 2007 beginning at 9:00 AM at Houston Technology Center. Update: I had the map wrong since it was wrong on the BarCampHouston wiki page. I hope no one went to the wrong place. Here is the correct one: HTC. I also decided to take the day off and chill out instead of heading up there. My apologies to anyone who had planned to say hello!

HouCFUG is hosting a ColdFusion 8 release party on Tuesday, August 28 from noon to 1:00 PM at Ziggy's Healthy Grill where they'll be giving away a licensed copy of CF 8.

Finally, Agile Houston is hosting a session with Robert Martin, object mentor on Tuesday as well. It's at 6:30 PM in PGH 563 on the University of Houston Campus.

I should be at both BarCamp and at Robert's presentation, but I'll be in class during HouCFUG's meeting.


We could all stand to be better at what we do - especially those of us who write software. Although many of these ideas were not news to me, and may not be for you either, you'd be surprised at how you start to slack off and what a memory refresh will do for you.

Here are (briefly) 10 ways to improve your code from the NFJS session I attended with Neal Ford. Which do you follow? More...


Often when we make a change to some code, if it is not properly designed, the result is that cascading changes need to be done throughout the application because bugs will ripple through the system. That's one of the ideas behind why we want to have low coupling between classes. We also have unit testing to combat the effects of this, but let's just suppose we haven't written any, and haven't used JUnit Factory to create regression tests.

Given that there is a lot of code out there that isn't quite perfect, wouldn't it be nice to have a tool that could analyze changes and where they would affect other code? I can imagine how such a tool might work, but I haven't heard of one before now (that I recall, anyway).

So the point of it all: I heard something about BMC and IBM teaming up on such a tool (my understanding is that BMC started it, and IBM later joined the project). I'm assuming it'd be in Java, but does anyone have information on this? Can anyone confirm or deny the story I heard?


Peter Bell's presentation on LightWire generated some comments I found very interesting and thought provoking. (Perhaps Peter is not simply into application generation, but comment generation as well.)

The one I find most interesting is brought up by several people whose opinions I value - Joe Rinehart, Sean Corfield, Jared Rypka-Hauer, and others during and after the presentation. That is: what is the distinction between code and data, and specifically, is XML code or data (assuming there is a difference)? More...


Robert "Uncle Bob" Martin has put together a post about just what SOA is. It's very easy to understand (especially for web developers / CF programmers, since we're always talking about MVC). So if you've ever wondered "WTF is SOA?" (like me), I'd recommend giving it a read.

Demystify SOA for yourself.


This post at Worse Than Failure made its rounds today on the Yahoo pragprog group and CFCDev mailing list, and I had a response to one of the emails that I also thought was worth blogging. On pragprog, the discussion was turning into the question, "where do you draw the line on knowing when to eliminate literals?" (not a direct quote) Someone brought up the idea to use YAGNI and DRY as guiding factors: "If you need the number in just one place, just use the number there. YAGNI," and "If you find the number being repeated so that you would have to change it in several places, then externalise it so that I change in just one place is needed. DRY." More...


One of the great benefits of using a framework (in the general sense) is the freedom in portability it often gives you. Rather than writing your own Ajax routines which would need to handle browser incompatibilities, you can rely on Prototype/Scriptaculous, AjaxCFC, Spry, or a seemingly infinite number of Ajax frameworks available. We see the same phenomenon in our use of ColdFusion, which uses Java to be cross-platform. And, you can get the benefit for databases by using a framework like Transfer or Reactor or ActiveRecord in Ruby (all also have a slew of other benefits). In general, we're simply seeing an abstracting away of the differences between low-level things so we can think at a much higher level than "oh crap, what if they're using Lynx!" (Ok, I'm doubting any of those Ajax frameworks fully support Lynx =), but you get the picture) More...


Yesterday I was working on a little Java program that, when given a table, a "possible" candidate key (which could be composite), and some non-key columns would check to see if the table was in 1st, 2nd, or 3rd normal form(s). One constraint is that this program needs to be procedural in style (or rather, all of my code must reside in the file that contains the main() function).

I started out with the pseudocode programming process in psvm. My listing started to look like: More...


Our second meeting of the UH Code Dojo was just as fun as the first. This time, we decided to switch languages from Java to Ruby. And although we started quite slowly (we came unprepared and undecided on a problem and a language), we pretty much finished the anagram problem.

Now, I mentioned it was slow at first - because we were trying to decide on a problem. I'm guessing we spent about 30-45 minutes just looking over Ruby Quiz and then moving on to Pragmatic Dave's Code Kata. We learned from our experience though, and resolved to determine before-hand what we would do in the future. In any case, we finally decided on anagrams as our problem, and one of us mentioned something to the effect of "I don't know about you all, but I use Java too much at work." Of course, there's not much you can say to an argument like that - Ruby it was!

Since we found ourselves violating YAGNI at the first meeting, we decided to do a little more discussion of the problem before we started coding. One of the initial paths we explored was looping over each letter and generating every possible combination of letters, from 1 to n (n being the length of the input). We then realized that would need a variable number of nested loops, so we moved on to recursion. After that, we explored trying to use yield in conjunction with recursion, in an isolated environment. I don't recall the reasoning behind it, but whatever it was, we were starting to discover that when we passed that fork on the road a few minutes back, we took the path that led to the cannibals. (As a side note, if you're unfamiliar: yield sits in a function, which takes a closure as an argument, and runs the code in the closure -- I think that's a simple way of putting it, anyway).

After smelling the human-stew awaiting us, we backtracked a little and started looking for another idea. Enter idea number two: I'm not sure how to describe it in words, so I'll just show the code now and try to explain it afterwards:

char_count = Array.new(26).fill(0)
dictionary = ['blah', 'lab', 'timmy', 'in', 'hal', 'rude', 'open']

word = "BlAhrina".downcase

word.each_byte { |x| char_count[x - ?a] += 1 }

dictionary.each do |entry|
   char_count2 = char_count.clone
   innocent = true
   entry.each_byte do |letter|
     index = letter - ?a
     if char_count2[index] > 0
       char_count2[index] -= 1
     else
       innocent = false
       break
     end
   end
   puts entry if innocent
end

That's it: quite simple. First we initialize an array with a cell corresponding to each letter of the alphabet. Each cell holds a number, which represents the number of times that letter is used in out input, called word. These cells are set by using the line word.each_byte {...}.

Then for each entry in the dictionary, we do something similar: loop through each letter. If the total count for each letter goes to 0, we have a match (and in our case, simply print it to the standard output device). It's really a simple, elegant solution, and I think we're all glad we didn't go down the painful path of recursion. It would be fairly trivial to add a file which contained a real dictionary, and loop over that instead of each word in our array, but we didn't have one handy (nor did we happen to notice that Dave had provided one). And it would have been just an extra step on top of that to find all the anagrams in the dictionary.

I know this is just a silly little problem that you're not likely to encounter in real life, but it shows how even the simplest of problems can be tough without some thought, and I found it to be great practice. In particular, one problem we had was with trying to use TDD. Although we spent some time looking for tests we could write, and ways to test, and we even wrote an empty test thinking about what to put in there - none of us seemed to find anything to test. Now that we see the solution, it's fairly easy to figure out how to test it, but trying to drive the design with the test was proving fruitless for us. Dave alluded to this on the Kata page:
Apart from having some fun with words, this kata should make you think somewhat about algorithms. The simplest algorithms to find all the anagram combinations may take inordinate amounts of time to do the job. Working though alternatives should help bring the time down by orders of magnitude. To give you a possible point of comparison, I hacked a solution together in 25 lines of Ruby. It runs on the word list from my web site in 1.5s on a 1GHz PPC. It’s also an interesting exercise in testing: can you write unit tests to verify that your code is working correctly before setting it to work on the full dictionary.
I didn't read that before we had started (in fact, it wasn't until we had finished that anyone noticed it), but as you can tell, this exercise performed as promised. Our solution was under 25 lines, and while we didn't test it on his word list, I think our results would have been comparable (in fact, I wouldn't be surprised if we had the same basic solution he did).

Thoughts anybody?


I can't remember the last time I used anything resembling a stack or queue (other than what I'm about to blog about). Of course, I've used lists and arrays, but not with the same intent you often see in the use of a typical LIFO or FIFO mechanism. I did have occasion to use the concept in the last couple of updates to cfrails, however, so I thought I'd bring it up in case anyone else came across the same use as I have. Let me explain how I arrived at the need (which also doubles as a little documentation):

Using cfrails, to make a model you simply go into your project and create a CFC that extends cfrails.model in the model folder. Assuming that file has the same name as a table in your database, you've now got an object (after it is instantiated, of course) with all the basic CRUD methods. The case is similar for the view or controller, where you'd be in the appropriate directory, but name it modelname_view.cfc or modelname_controller.cfc. There is a way to change the name of the table if you don't want the model name to match the table for some reason, but I'll not go over it here, as it's an "undocumented feature" at the moment. More...


I'm in the middle of reading Steve McConnell's Code Complete 2 (website, Amazon), and it is chock-full of good advice (no wonder its considered a must-read classic for software developers). There's been plenty in it I've wanted to share and blog about, particularly the parts about design and class construction, and when I find the time, I certainly will. It just so happened that this time, my computer was already on so the barriers to blogging were low.

In any case, I'm in the chapter where he's talking about the "Pseudocode Programming Process." The idea is that you write precise pseudocode in English (or really, I suppose any human language that your audience will be reading in), and in doing so, you get a clear description of the intent behind the method. Of course, you shouldn't write a novel - the statements should be concise and to the point. He specifies that it should be written "at a low enough level that generating code from it will be automatic," but it should be written at the level of intent. Intent here means that you should talk about the meaning, not how the code will be implemented. The added bonus of course, is that you now have useful comments for your code. More...


On Monday (Jan. 29, 2007) we had our first meeting of the UH Code Dojo, and it was a lot of fun. Before we started, I was scared that I'd be standing there programming all by myself, with no input from the other members. But, my fear was immediately laid to rest. Not only did everyone participate a lot, one of the members, Matt (I didn't catch his last name), even took over the typing duties after about 45 minutes. That turned out to be a good thing - since I still can't type worth a crap on my laptop, and he was much faster than me.

Now, it had only been a couple of months since I last used Java - but it still amazes me how little time off you need to forget simple things, like "import" for "require." I found myself having several silly syntax errors for things as small as forgetting the semicolon at the end of the lines.

Overall, we started with 7 people, and had 5 for most of the meeting. We finished with four because one person had tons of homework to do. It seemed like those five of us who stayed were genuinely enjoying ourselves.

In any case, we decided to stick with the original plan of developing a tic-tac-toe game. You would think that a bunch of computer scientists could develop the whole game in the two hours we were there. But, you'd have been wrong.

I came away from the meeting learning two main points, which I think illustrate the main reasons we didn't complete the game:
  1. YAGNI is your friend
  2. Writing your tests first, and really checking them is very worthwhile
More...


We all know (or should know) that it's a good idea to keep your methods short. I've seen it recommended that they should be more than 7 ± 2 lines (Update: Although I still have seen it recommended they should be that short, I didn't mean to imply that I haven't seen other recommendations. Steve McConnell's Code Complete 2 says 50, I think, as Peter Bell alluded to in the comments below). The goal, of course, is simply to manage complexity, so as long as you've accomplished that, you're ok.

I've generally just created methods for three purposes that I can identify (in no particular order):
  • Follow the DRY Principle: Refactor common code out into one method.

  • Create an interface for a class

  • Reduce complexity: Sometimes, I see some code that is hard to understand or is a long related block (such as setDefaultVariablesScope()), so I'll put it into a method so I don't have to think about it while I'm working on something else.
More...


Looking at the code Joe Rinehart provided in this post on why it's a good idea to use XML configuration in Model-Glue, I think I would probably prefer the XML. (And that's saying something!)

But, I also think that the code as it stands could be better abstracted, so that the end-programmer wouldn't need to create all those objects. One strategy to abstract the complexity out of that could be to allow the programmer to just create a config object, and use that API to create other objects. I haven't thought through that idea completely, but it seems preferable to me on its face. I'm sure there are many other strategies as well.

In the comments to that post, Teddy R. Payne mentioned, "a generation script that auto generates your code and writes XML for you would seem like creating an abstraction on top of an abstraction. It seems that would introduce another layer of complexity." More...


At times, I like to push the limits of the languages I work in, just to see what I can learn. A while back, I got the idea of using structs as objects in Coldfusion, since instantiating objects is so slow. Of course, this would only be useful if you had tons of objects, and if it was substantially quicker than creating real objects. Anyway, I decided to see what I could come up with.

Unfortunately, I don't think this would be any more efficient (and possibly less), because I need to do three file operations. But, I thought I'd share what I came up with regardless.

Basically, what happens is that you tell pseudo_object.cfc what object you want to create, and it creates a fake object that behaves like a real one. It reads the CFC you tell it you want an object of. It creates a struct, finds the name of the variable you stored it in (multiple references won't matter, to my knowledge), rewrites the methods to use the scope+name of that variable, plus an extra this or variables scope to make up for variables named the same in different scopes within the CFC. Then, it attaches those methods to the struct and you now have a struct which behaves like an object. It won't work if you have any code outside of methods, however. Also, another problem may arise if you have something like this.variables.

Since I'm not entirely sure that made any sense, I'll share the code now: More...


Do you find yourself writing more classes in other languages than in Coldfusion? I do. For instance, I certainly develop more classes in Java than Coldfusion.

Is it due to the fact that I've developed bad habits in CF and haven't yet broken out of them (i.e., I'm just unable to spot needs for new classes) or is it because CF is so much more high-level than Java? A third option may be that the performance issues with instantiating CFCs contribute to me not wanting to break out? More...


I don't want to turn this into a mouthpiece for the code dojo at University of Houston, but I'm pretty excited about it since we've set the date of our first meeting. We're planning on doing it January 29, 2007 at 7:00 PM. Check the website for more details (such as the room). We have yet to decide on the first problem to solve / topic, but we will have that done by the end of next week. After that, I probably won't post much here about it, or I'll try not to anyway (I realize folks in China, for instance, could probably care less about it).


For those that don't know, cfrails is supposed to be a very light framework for obtaining MVC architecture with little to no effort (aside from putting custom methods where they belong). It works such that any changes to your database tables are reflected immediately throughout the application.

For instance, if you change the order of the columns, the order of those fields in the form is changed. If you change the name of a column or it's data type, the labels for those form fields are changed, and the validations for that column are also changed, along with the format in which it is displayed (for example, a money field displays with the local currency, datetime in the local format, and so forth). I've also been developing a sort-of DSL for it, so configuration can be performed quite easily programmatically (not just through the database), and you can follow DRY to the extreme. Further, some of this includes (and will include) custom data types (right now, there are only a couple of custom data types based on default data types). More...


Thankfully for me (and anyone who is interested in using his closures package), Sean Corfield reponded to my Beauty of Closures post and set me straight on a couple of issues.

First, he confirmed that there was indeed a bug when attempting to use a mapping to use the closures, and that in fact, it wasn't a CF 6.1 issue only.

Next, he dove right into the code. So, for easy reference, here is my original code: More...


The last couple of weeks I've been soliciting teammates and friends of mine to help on starting a code dojo at the University of Houston. Well, we got the go-ahead yesterday from the CougarCS organization, so now we're just trying to plan when we'll have our first meeting. If you go to UH or live around Houston (I don't think we'll be checking IDs or anything), I'd encourage you to come to one of our meetings. You can find more information at CodeDojo.org. Right now, as I said, we don't have a meeting schedule or anything, but you can follow the link to our google group and stay informed that way (of course we will be posting it on the webpage as well).

If you don't live in Houston, but want to start a dojo of your own, we also plan to provide a place for others to post information. We don't have the infrastructure set up yet, but if you contact me, I'll be glad to let you know when we do. Of course, you won't have to have our cheesy logo up there =).


There are plenty of uses for closures, but two of the most useful ones I've found (in general) are when you really want/need to encapsulate something, and when you want to implement the Template Method pattern. Actually, implementing the Template Method pattern using closures may be misusing it, or I may be mischaracterizing it. It's more of like a "generalized" template method (particularly since we're not following the pattern, but implementing the intent). I still don't understand all of the Gang of Four patterns, so have mercy on me if I've gotten it wrong. =) More on all this below.

So as I get ideas from other languages, I always wonder "how can I use that idea in language X." For instance, I like the way Coldfusion handles queries as a data structure - so I tried to implement something similar in Java (which, I will eventually get around to posting). I encountered closures for the first time in Lisp a few years ago in an Artificial Intelligence course, I'm sure. But it wasn't until more recently in my experience with Ruby that I started to understand them. Naturally, I thought "could this be done in Coldfusion?" More...


So, I was playing around a little in Ruby and noticed that DateTime is a subclass of Date, yet the method today is not defined for it. I asked Venkat about it (in an email), he inspected the source code (why didn't I think of that?), and he replied that
the culprit! is line 1261 in date.rb, within DateTime class
class << self; undef_method :today end rescue nil
I thought it was interesting: Certainly this violates LSP, yet certainly a DateTime shouldn't have the method today. So, are there instances where it makes sense to violate LSP, in favor of keeping up with the metaphor?

I wonder why Date isn't a subclass of DateTime, rather than the other way around? At least for this case, it would not have violated LSP. So, I posted about this on the Ruby-Talk mailing list - I'll update you when I hear back from that group.

Update: I just realized if we made Date a child of DateTime, we'd get a similar problem in that we'd be removing the time part from the class. How would you resolve it?

Update 2: After some thought and some help from the Ruby community, I'm not so sure this is a violation of LSP. You see, the method today can only be called on Date, not an object of Date. So therefore, there is no violation when an object of Date is replaced by one of DateTime. Robert Klemme chimed in with this, which of course I addressed above, but he said it much better than I did:
Once can certainly argue whether DateTime *is a* Date or rather *has a* Date. But it is definitively clear that Date *is not* a DateTime simply because it does not provide the same set of information that DateTime provides (date *and* time)
So in the end, it appears as if there is no problem at all. Sorry for being alarmist - I guess I should have tested it first, right? =).


Barry Beattie wrote recently on the CFCDev mailing list a question asking, "if it were Java/JSP, would you bother generating great sections of HTML within the java classes instead of leaving it to the JSP to take care of?"

It got me thinking again about my own use of HTML in CFCs.

At first, I thought it was a valid point - of course I would never consider using HTML in a Java class. But, the more I thought about it, the fuzzier the line got. As it turns out, I could go either way on the CFC/tag issue, depending on the specific case. More...


Now that we can insert posts, it is possible to update, select, delete, and search for them. To me, any one of these would be a valid place to go next. However, since I want to keep the database as unchanged as possible, I'll start with test_deletePost(). This way, as posts are inserted for testing, we can easily delete them.

Here is the code I wrote in xorblog/cfcs/tests/test_PostEntity:

<cffunction name="test_deletePost" access="public" returnType="void" output="false">
   <cfset var local = structNew()>   
   <cfset local.newID=_thePostEntity.insertPost(name="blah", meat="blah", originalDate="1/1/1900", author="yoda")>
   <cfset local.wasDeleted = _thePostEntity.deletePost(local.newID)>

   <cfset assertTrue(condition=local.wasDeleted, message="The post was not deleted.")>

   <cfquery name="local.post" datasource="#_datasource#">
      select id from post where id = <cfqueryparam cfsqltype="cf_sql_integer" value="#local.newID#">
   </cfquery>

   <cfset assertEquals(actual = local.post.recordcount, expected = 0)>
</cffunction>

And the corresponding code for deletePost():

<cffunction name="deletePost" output="false" returntype="boolean" access="public">
   <cfargument name="id" required="true" type="numeric">

   <cfset var local = structNew()>
   <cfset local.result = false>
   <cftry>
      <cfquery name="local.del" datasource="#_datasource#">
         delete from post where id = <cfqueryparam cfsqltype="cf_sql_integer" value="#id#">
      </cfquery>
      <cfset local.result=true>
   <cfcatch>
   
   </cfcatch>
   </cftry>
   <cfreturn local.result>
</cffunction>

Originally, I just left the test as asserting that local.wasDeleted was true. However, writing just enough of deletePost() in xorblog/cfcs/tests/PostEntity to get the test to pass resulted in the simple line <cfreturn true>. Since that would always pass, I also added a check that the inserted post no longer existed.

Now that we have some duplicate code, its definitely time to do some refactoring. More on that next time. (To be continued...)


We left off after writing the test for the insertPost() method. Now, we're going to make that test pass by writing the code for it. First you'll need to create PostEntity.cfc in the xorblog/cfcs/src directory, and make sure to surround it in the proper <cfcomponent> tags. What follows is that code:

<cffunction name="insertPost" output="false" returntype="numeric" access="public">
   <cfargument name="name" required="true" type="string">
   <cfargument name="meat" required="true" type="string">
   <cfargument name="originalDate" required="true" type="date">
   <cfargument name="author" required="true" type="string">
   
   <cfset var local = structNew()>
   <cftransaction>
   <cfquery name="local.ins" datasource="#variables._datasource#">
      insert into post
      (name, meat, originalDate, lastModifiedDate, author)
      values
      (<cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.name#">,
       <cfqueryparam cfsqltype="cf_sql_longvarchar" value="#arguments.meat#">,
       <cfqueryparam cfsqltype="cf_sql_timestamp" value="#arguments.originalDate#">,
       <cfqueryparam cfsqltype="cf_sql_timestamp" value="#arguments.originalDate#">,
       <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.author#">,
   </cfquery>

   <cfquery name="local.result" datasource="#_datasource#">
      select max(id) as newID from post
      where originalDate=<cfqueryparam cfsqltype="cf_sql_timestamp" value="#arguments.originalDate#">
      and name=<cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.name#">
   </cfquery>
   </cftransaction>
   <cfif local.result.recordcount is 0>
      <cfthrow message="The new post was not properly inserted.">
   </cfif>
   <cfreturn local.result.newID>
   </cffunction>

There isn't really anything special here, unless you are new to Coldfusion. If that's the case, you'll want to take note of the <cfqueryparam> tag - using it is considered a "best practice" by most (if not all) experienced Coldfusion developers.

The other item of note is that if you were to run this code by itself, it still wouldn't work, since we haven't defined variables._datasource. Many developers would do this in a function called init() that they call each time they create an object. I've done it as well.

I suppose if you were rigorously following the YAGNI principle, you might wait until creating the next method that would use that variable before defining it. I certainly like YAGNI, but my OCD is not so bad that I won't occasionally allow my ESP to tell me that I'm going to use something, even if I don't yet need it. With that said, I try only do it in the most obvious of cases, such as this one.

Now that we've written the code for insertPost(), its time to run the test again. Doing so, I see that I have two test that run green (this one, and our test_hookup() from earlier. We've gone red-green, so now it's time to refactor. Unfortunately, I don't see any places to do that yet, but I think they'll reveal themselves next time when we write our second test and second method in PostEntity. (To be continued...)


So we decided that blog software centers around posts and that for any other feature to be useful, we'd need them first. Therefore, we'll start with a model component for our posts, and we'll call it PostEntity. Before I create that file though, I'm going to go back into my test_PostEntity.cfc file and write a test or two for some functionality that PostEntity should provide.

Thinking of things we should be able to do regarding the storage of posts, it's easy to identify at least insert(), update(), and delete(). However, since you can't update or delete a post that doesn't exist, I figured I'd start with adding a post. I came up with the following test:

<cffunction name="test_insertPost" access="public" returntype="void" output="false">
      <cfset var local = structNew()>
      <cfset local.nameOfPost = "My Test Post" & left(createUUID(),8)>
      <cfset local.meatOfPost = "The meat of the post is that this is a test." & left(createUUID(),8)>
      <cfset local.dateOfPost = now()>
      <cfset local.author = "Sam #createUUID()#">

      <cfset local.newID=_thePostEntity.insertPost(name=local.nameOfPost, meat=local.meatOfPost, originalDate=local.dateOfPost, lastModifiedDate=local.dateOfPost, author=local.author)>

      <cfquery name="local.post" datasource="#variables._datasource#">
         select name, meat, originalDate, author
         from post
         where id = <cfqueryparam cfsqltype="cf_sql_integer" value="#local.newID#">
      </cfquery>

      <cfset assertEquals(actual=local.post.name, expected=local.nameOfPost)>
      <cfset assertEquals(actual=local.post.meat, expected=local.meatOfPost)>
      <cfset assertEquals(actual=local.post.author, expected=local.author)>

      <!--- dateCompare isn't working correctly, so we are testing each datepart --->      
      <cfset assertEquals(actual=month(local.post.originalDate), expected=month(local.dateOfPost))>
      <cfset assertEquals(actual=day(local.post.originalDate), expected=day(local.dateOfPost))>
      <cfset assertEquals(actual=year(local.post.originalDate), expected=year(local.dateOfPost))>
      <cfset assertEquals(actual=hour(local.post.originalDate), expected=hour(local.dateOfPost))>
      <cfset assertEquals(actual=minute(local.post.originalDate), expected=minute(local.dateOfPost))>
      <cfset assertEquals(actual=second(local.post.originalDate), expected=second(local.dateOfPost))>

      <!--- clean up --->
      <cfquery datasource="#_datasource#">
         delete from post where id = #local.newID#
      </cfquery>
   </cffunction>

You'll notice I used a UUID as part of the data. There's no real point to it, I suppose. I just wanted to have different data each time, and thought this would be a good way to achieve that.

You should also be uncomfortable about the comment saying dateCompare isn't working - I am anyway. It doesn't always fail, but occasionally it does, and for reasons I can't figure out, CFUnit isn't reporting why. For now, so I can move on, I'm assuming it is a bug in CFUnit. Since I can test each date part that is important to me individually and be sure the dates are the same if they all match, I don't feel too bad.

Another thing to note is the use of the var local. By default, any variables created are available everywhere, so to keep them local to a function, you need to use the var keyword. I like to just create a struct called local and put all the local variables in there - it just makes things easier.

Finally, some people might not like the length of that test. Right now, I don't either, but we'll see what we can do about that later. Others may also object to using more than one assertion per test. I don't mind it so much in this case since we really are only testing one thing. If you like, you could also create a struct out of each and write a UDF like structCompare() and do the assertion that way. I haven't tested this one personally, but there is one available at cflib. In either case, I don't see much difference, other than one way I have to write more code than I need.

Now I run the test file we created and find that, as expected, the test still fails. Besides the fact that we don't even have a PostEntity.cfc, we haven't yet instantiated an object of that type, nor have we defined _datasource and the like. Let's do that in the setUp() method.

<cffunction name="setUp" access="public" returntype="void" output="false">
   <cfset variables._datasource="xorblog">
   <cfset variables.pathToXorblog = "domains.xorblog">
   <cfset variables._thePostEntity = createObject("component", "#variables.pathToXorblog#cfcs.src.PostEntity").init(datasource=_datasource)>
</cffunction>

Now our tests still fail, because we have no code or database. So create the datasource and database with columns as needed:

id (int, primary key, autonumber)
name (nvarchar 50)
meat (ntext)
originalDate (datetime)
lastModifiedDate (datetime)
author (nvarchar 50)

Next time, we'll start coding and get our first green test. (To be continued...)


I've recently converted to using CFEclipse (whose website is down at the time of posting). I downloaded it sometime in September or October 2005 to use on my new laptop since I didn't have a license for Dreamweaver.

At the time, I only had 256 MB RAM in the laptop (now its 2 GB), so I quickly threw it away (CFEclipse, not the laptop) and started using Notepad for when I had to edit CF files, and generally shied away from doing any Coldfusion development on that machine.

Since that time, on my other home computer and the one at work, I've been using Eclipse for Java development (and more recently, the Ruby and RADRails plugins for Ruby and Rails development). So in the last couple of weeks I'd say, Dreamweaver has started to annoy me.

I was still using the first Dreamweaver MX version, so that might be the problem, but when doing anything with the file system it started to hang on me. And, since I had been using Eclipse more consistently for other languages, it was even worse because I had a constant reminder of how crappy Dreamweaver was. To be fair, I don't know if they've made the newer versions any better, but I'm not planning to try it unless someone tells me I just have to try it out.

In any case, because I was so sick of it, I got CFEclipse up and running. And is it ever awesome. The first thing I love about it is the Methods View, among other things listed at ColdFusion Developer's Journal. But that's not all! I've discovered two (probably unintended) "features" it offers:
  • When working on large files (I first noticed it on about one about 40 kilobytes), it gets slooooooow. Slow like "you could type 4 or 5 lines of code before it gets done with the first line" slow.
  • When working on even larger CFCs, the Methods View stops showing the methods and appears as it does in a .CFM file
So why is this good? Because if you are ever working on CFCs that large, your components quite likely have more than one responsibility. The annoyance is enough for you to hunt down the extras, pull them out, and make new components out of them. Design by Annoyance - whatever works, right?

And if you're thinking that its machine related, I'm on a 2.8 GHz CPU with 1 GB of RAM. Not bleeding edge, but certainly adequate.


... and having no automated tests.

Do you ever have those "what the $!*&# was I thinking?" moments? I had one this morning when working on some legacy code. My guess is that it was probably written six or more years ago, though someone touched it as late as two years ago. I guess technically it isn't legacy since it is still supported (I'm fixing it aren't I?), but you get the idea.

You see, it was noticed that an order from Portugal to be shipped to California was showing the customer that they would be charged sales tax, but it was not charging the tax, nor was it showing on the receipt. Can you believe that in all this time, not one customer has ever had that happen? (Me either)

So, I went to inspect the source to see what the problem was. Only it took me probably half an hour to find the problem. Why? Because obviously it's best if you can calculate the same thing in as many different places as possible.

And I'm not talking about something like having tax=calculateTax(someArgs) in one place and taxAmount=calculateTax(someArgs) in another because I forgot what I named the first variable and I was too lazy to scroll up 10,000 lines to see what it was. I'm talking "loop through the order to total it, check if the shipping state and billing state are both California, and if so apply tax calculation and add the result to the order total." In three different spots between two different files.

And the best part? As you can tell from the fact the receipts were saying one thing and the web page another, they didn't even follow the same rules. So, the first thing to do was to figure out what the correct rule was, and then implement it in all three spots.

Just kidding ... I put the code into one spot and reused it.


I know there is a general disdain for using CFCs to produce the view layer in applications, but I wanted to take the time to explain when I use it: in situations where several customers will be using the same application (hosted on the same server as well).

In my more inept days, long before CFCs were introduced, I just deployed different versions of the same application to the different directories that housed each client's specific version of the application. This was nice because it allowed customization, but of course it became a giant pain having to fix the same bugs in several different places. The same was true if there was an improvement which would benefit everyone.

Eventually, (still before CFCs) I had the idea to just keep a common code base and <cfinclude> the needed files in each client's own directory. I even built the application(s) such that they would <cfinclude> some custom code in spots that required customer-specific computations or outputs. As you might expect, it wasn't long before customers started asking for changes which couldn't be done in the "customer-specific" includes very easily. It became much easier just to write

<cfif customerID is theCustomerRequestingThisChange>
   ... do something ...
<cfelse>
   ... do something for everyone else ...
</cfif>

in the middle of the common code rather than do it correctly. Because of the problems with the different versions I mentioned above, I was very reluctant to "branch" clients into differing code bases - so the code became littered with <cfif>'s and got to be a nightmare to maintain.

Finally, along came CFCs. I could have a component and aggregate it into another or inherit from it in another, and only make the changes I needed to those methods which needed it for those clients who needed it. A silver bullet (almost) for all my problems! The werecode was killed!

But, everywhere I look I see everyone telling me not to use HTML in CFCs! So what do you do in the situation where one client's form has to differ slightly from the common code? For instance, you might have a form that has a name section, a contact information section, an address section (or two), and perhaps more. Suppose one client wants to track some other information specific to them, and they want it placed just below the name section and just above the contact information. Do you rewrite the form for that client? While you would be following "best practices," this can lead to similar situations as described above.

I've been placing the common code in CFCs - and with great results. Each section of the form can be its own function, to be called in a main displayForm() function. Then, if a client needs a new section, I simply have to rewrite displayForm() and write the new part of the form. If they need to change the order of some fields within a section, I only have to rewrite that section. Its really helped me cut down on duplicate code and helped me follow the DRY principle.

What do you do in similar situations?


Since I wanted to start this blog, I thought it would be good practice to write the software that runs it using test-driven development. I've used a bit of TDD recently for additions to existing applications, but I've not yet started writing an application using it from beginning to end. I'm getting sick of eating Italian microwaveable dinners when I have to maintain code. This is my chance to eat something else. So, without further ado, we'll jump right in.

The first thing I did of course, was to create my directory structure. For the time being, we have:

xorblog/cfcs/src

and

xorblog/cfcs/tests

I like to keep the tests separate from the source. I don't have a reason behind it, other than it helps keep me a bit organized.

Next, I thought about what a blog needs. We want to deliver items that have the highest business value first, and move on to things that are lower on the value scale later. In doing this, we get a working application sooner rather than later, and hence the blog can be used at the earliest possible moment in its development.

With that in mind, we probably shouldn't start with things like Comments or functionality that lets us get included in places like Technorati. Since you need content to make anything else useful, I thought I'd start with that. Indeed, the Post is the core part of a blog. Therefore, the first thing I did was create test_PostEntity.cfc under xorblog/cfcs/tests.

Now, I'm using CFUnit for my tests, and this assumes you already have it set up. If you need help on that, you can visit CFUnit on SourceForge.

The first thing I do in test_PostEntity.cfc is write test_hookup(), to make sure everything is working:

<cfcomponent extends="net.sourceforge.cfunit.framework.TestCase" output="false" name="test_PostEntity">
   <cffunction name="test_hookup" access="public" returntype="void" output="false">
      <cfset assertEquals(expected=4, actual=2+2)>
   </cffunction>
</cfcomponent>

Next, we need a way to see the status of and run our tests. For this we have test_runner.cfm, which for the most part just copies what you'll find at the CFUnit site linked above:

<cfset testClasses = ArrayNew(1)>
<cfset ArrayAppend(testClasses, "domains.xorblog.cfcs.tests.test_PostEntity")>
<!--- Add as many test classes as you would like to the array --->
<cfset suite = CreateObject("component", "globalcomponents.net.sourceforge.cfunit.framework.TestSuite").init( testClasses )>
<cfoutput>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
   <title>Unit Tests for xorBlog</title>
</head>
<body>
<h1>xorBlog Unit Tests</h1>
<cfscript>
   createobject("component", "globalcomponents.net.sourceforge.cfunit.framework.TestRunner").run(suite,'');
</cfscript>
</body>
</html>
</cfoutput>


Finally, we run that page in a browser to make sure the test runs green - and it does. Now that we have our test environment set up, we can start writing tests for our PostEntity that doesn't yet exist. (To be continued...)



Google
Web CodeOdor.com

Me
Picture of me

Topics
.NET (19)
AI/Machine Learning (14)
Answers To 100 Interview Questions (10)
Bioinformatics (2)
Business (1)
C and C++ (6)
cfrails (22)
ColdFusion (78)
Customer Relations (15)
Databases (3)
DRY (18)
DSLs (11)
Future Tech (5)
Games (5)
Groovy/Grails (8)
Hardware (1)
IDEs (9)
Java (38)
JavaScript (4)
Linux (2)
Lisp (1)
Mac OS (4)
Management (15)
MediaServerX (1)
Miscellany (75)
OOAD (37)
Productivity (11)
Programming (168)
Programming Quotables (9)
Rails (31)
Ruby (67)
Save Your Job (58)
scriptaGulous (4)
Software Development Process (23)
TDD (41)
TDDing xorblog (6)
Tools (5)
Web Development (7)
Windows (1)
With (1)
YAGNI (10)

Resources
Agile Manifesto & Principles
Principles Of OOD
ColdFusion
CFUnit
Ruby
Ruby on Rails
JUnit



RSS 2.0: Full Post | Short Blurb
Subscribe by email:

Delivered by FeedBurner