My Secret Life as a Spaghetti Coder
home | about | contact | privacy statement
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...

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!



From a project I was working on recently I ran into this problematic and fairly complex boolean expression (pseudocode):

if not arguments.pending and arguments.umoneyamount is 0 and aname.agencyname is arguments.agencyname
    do something
elseif ((aname.agencyname is arguments.agencyname and arguments.pending) or (session.id is 1 or (isdefined("session.realid") and session.realid gt 0)) or (not arguments.pending and arguments.umoneyamount is 0 and local.isMyClient)) and (session.id is 1 or arguments.pending)
    do something else
else
    do the other thing
end

Or alternatively,

local.isMyClient = aname.agencyname is arguments.agencyname
local.isPending = arguments.pending
local.isAdmin = session.id is 1 or (isdefined("session.realid") and session.realid gt 0)
local.canAddUtilities = not arguments.pending and arguments.umoneyamount is 0 and local.isMyClient
local.allow_edit = (local.isMyClient and local.isPending) or local.isAdmin or local.canAddUtilities

if local.canAddUtilities
    do something
elseif local.allow_edit and (session.id is 1 or arguments.pending)
    do something else
else
    do the other thing
end

Which do you prefer, and why?


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...


Something I haven't thought much about, but am beginning to (want to) get into is the auto-generation of reports. Autogenerating forms, validation, and operations for CRUD is quite simple - the approach I've used simply gets what metadata it can from the database, and dynamically builds around it. So, NOT NULL fields become required, datetimes build different form fields from nvarchars, and validate as such (as do other types), and field maxlengths are honored on the HTML side based on the DB metadata (among other things). That is incredibly useful by itself, but not useful enough for a real, production quality application (should the user really be required to remember the categoryID?) More...


There are a couple of drawbacks (or some incompleteness) to scaffolding being truly useful. The one that seems to be most often cited is that normally (at least in Ruby on Rails, which seems to have popularized it) it looks like crap (it is only scaffolding though). Of course, most who make that complaint also recognize that it is only a starting point from which you should build.

Django has been generating (what I feel is) production-quality "admin" scaffolding since I first heard about it. It looks clean and professional. Compare that to the bare-bones you get by default in Rails, and you're left wondering, "why didn't they do that?" Well, as it happens, it has been done. In particular, there are at least 4 such products for use with Rails: Rails AutoAdmin (which professes to be "heavily inspired by the Django administration system"), ActiveScaffold (which is just entering RC2 status), Hobo, and Streamlined (whose site is down for me at the moment). More...


Back in December, I had a post about why closures are useful. In particular, I mentioned what I called the "generalized Template Method" pattern as a benefit: basically, you have a function where, when the user calls it, you want them to be able to change its behavior in some way.

I was short of practical examples, but today I came across one. I've got a list() function that behaves identically for each object it is called on. Basically, it figures out what properties the object has that should be listed, and creates a table that lists them for some query result set. Normally, this just outputs the variable's value on a cell with a white background. The slight change in this case was that depending on the value, the list should set a background color to one particular cell. More...


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...


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...


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...


(and functions with arguments can take more than the defined amount)

This may be well known, but I haven't seen a lot (or anything) on it. Of course, as always, I may just be missing something.

In any case, the other day as I was looking over some old code, I (re)discovered this marvelous fact. Now, you may be wondering why on Earth I'd want to use arguments in a function where none were defined. But, I have at least one case where I think it's valuable: suppose you are following the Active Record Pattern, or really writing any ORM. Basically, you want to abstract the query process. Now, that's certainly a noble goal. But, what happens when you want to provide a filter? For instance, you might have a function find_by_id(), a which finds a record based on the id you pass in. That's easy enough. You might even provide methods to find_by_other_columns_even_in_combinations(). More...


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...


This morning I was going through some code that my team and I wrote a couple of weeks ago. We had violated DRY in an attempt to show a client (who wanted to show a venture capitalist) our progress (sort of by faking it, I guess). It seemed necessary at the time (and I still think it was), and it worked fine.

In any case, I promised myself that before this iteration was over, I would refactor the code, because I didn't want it to become a nightmare to maintain. I started out trying to get the whole thing in one go. When I was almost done, I suddenly noticed "there's no way this is going to work." I had removed some code that was needed for another piece to work, and couldn't remember what the code was - I just noticed it was missing.

It was Javascript as well, so it's not like it would have been incredibly easy to figure out what the problems were, had I continued along my path.

Anyway, I started over, taking baby steps - one small bit at a time, while ensuring what existed still worked. It helped a bunch.

So, the lesson is: As while coding in general, it is important to take baby steps when refactoring.


So, the last couple of weeks I've been hard at work with school stuff, and also we've started a new (well, massively adding on to an existing one) project at work (and now another new one, as of last Wednesday). Because I seem to be so incredibly busy, and the projects need to be done "yesterday" (don't they all?), I built myself a little helper application that should increase my velocity by a ton - no more repetitive busy-work (well, it is greatly reduced anyway).

I've quite unimaginatively called it cfrails, since it was inspired by Ruby on Rails, and you can find it's project page at RIA Forge.

But first, you might want to read Getting Started with cfrails, so you can see how easily 0 lines of real code can create an interface to your database (the only lines are a couple of setup things, and cfcomponent creation).

I'd like to know what you think, so please leave a comment.


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...


Well, I guess I lied when I said xorBlog wouldn't be developed until I had caught up on my writing. I still haven't gotten caught up, but this morning I couldn't stand it any more - I had to have a way to categorize posts. Now, I didn't TDD these, and I didn't even put them in the right place. True to the name of the blog, I interspersed code where it was needed. I feel absolutely dirty, but I just couldn't spare the time at the moment to do it right, and I could no longer endure not having any categories. So, I took about 15 minutes, coded up a rudimentary category system, violated DRY in 2 places, and put a few comments like "this needs to be refactored into a CFC" throughout the code (as it needed).

At least I have some categories now (its not as gratifying a feeling as I thought it would be, however). I plan on refactoring this as soon as I have a chance. I'll write about it as well - it might make for some more interesting reading in the TDDing xorBlog series of posts.


In class on Wednesday Venkat explained so well, yet so succinctly, what I'm loving so much about Ruby: the signal to noise ratio is higher in Ruby than in most languages.

One of his examples was to take a program that does absolutely nothing in Java:

public class DoNothing
{
    public static void main(String[] args)
    {

    }
}

And compare it to this one in Ruby:




Notice the difference?

Incidentally, the high signal to noise ratio is also what I like so much about Coldfusion. To run a query, you just do it. You don't have to go through the hassle of creating connections, statements, and the like. Just type in your query and go. Of course the drawback in Coldfusion is that in many cases, there is a lot of noise. For example, to create an object I have to write <cfset someObj = createObject("component", "long.Path.To.CFC")>, and let's not mention the tag syntax (at least I can use <cfscript>, though I rarely do).

In any case, I find Java's database access so hard to work with, the last time I used it in any significant context I created a façade to do all the work for me. I'd just create an object of it, and pass in a query to run.

But, there's also a problem with building the queries in languages like Java and C#:

String theQueryString="select columnName from table" +
     " where someColumn = "
+ someValue +
     " and anotherColumn = " + anotherValue + " ... " +
     " order by " + orderBy;

Horrible! For long queries, that can get extremely unreadable. In Coldfusion if you need to create a multi-line string to keep it readable, you can simply do the following:

<cfsavecontent variable="theQueryString">
   put any text you want in here
   and as many lines as you
   want
</cfsavecontent>

And I was happy to find out you can do something similar in Ruby:

someVariable = <<DELIMITER_FOR_WHEN_YOUR_STRING_IS_DONE
   put any text you want in here
   and as many lines as you
   want
DELIMITER_FOR_WHEN_YOUR_STRING_IS_DONE

The next great surprise from Ruby? You can add methods to a class at run-time (there is no compilation) quite easily. Suppose I wanted the absolute value method to work on a string. I could just do:

class String
   def abs
      "absolute value of string"
   end
end

And no, it didn't overwrite the String class. So far, I am amazed. I know you can do the same thing in Coldfusion, but that doesn't make it any less awesome.


... 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'm either an idiot, or a moron. But, I have courage and that's what matters. Let me explain:

Ever since I started messing with inheritance with CFCs in Coldfusion, I have lamented the "fact" they didn't have a way to override a parent's method while retaining the functionality via a call to super.methodInQuestion(). I got so sick of it, in fact, I came up with this brilliant way to re-use code and not repeat myself - I'd have component Parent with methods foo(arg1, arg2) and theRealFoo(arg1, arg2) where foo() simply called theRealFoo() with the arguments it had been passed. Following me so far?

Then in component Child, when I needed to slightly modify the behavior of foo() and still use its code, I could simply do so by calling theRealFoo() within my Child version of the method. Sweet!

Of course I had tried using super, but I kept getting this strange error:

Error Occurred While Processing Request

Cannot invoke method method1 on an object of type coldfusion.runtime.Struct with named arguments.

Use ordered arguments instead.


What? I wasn't trying to invoke a method on a struct, was I? I thought this was just one of those random CF errors that get thrown which seem to have nothing to do with the problem, especially since it was right there in big bold letters. I never read the fine print.

Well, since then I had read that it did exist, and I tried again - but got the same error. I came to the conclusion that it became part of the language in version 7.0, since I don't yet have it. And lately I've been reading and writing with the Gurus on the CFCDev mailing list, and I finally decided to ask: Am I a moron or is there no super in CF6.1? Well, as it turns out, I am a moron. I should have read the fine print.



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 Cplusplus (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 (76)
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 (8)
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