Code Duplication

October 1st, 2004

Benjamin makes some good comments about code duplication and software design. I think by and large I agree with him though I do think that less code duplication implies better design, it’s just that there are also other factors which may be more important as well.

The critical thing about eliminating duplicated code is to identify duplicated code based on it’s requirements, not on what it looks like. For instance, today I added a new method to our UIUtils class (GUIs are the most common place where duplicate code is created unnecessarily), the method took as parameters an OK button and a Cancel button, created a panel and put them in it in the appropriate order for the platform. It’s about 5 lines of code all up and it’s duplicated all over the place when it should not have been.

In many cases, when this code is duplicated, it doesn’t actually look the same - it might use different layout managers, be mixed in with other code or a wide range of variations. However, the requirement is extremely clear cut:

On Macintosh the cancel button is on the left and the ok on the right, on all other systems the ok is on the left and the cancel is on the right. The buttons are separated by a gap of 4 pixels.

Regardless of where ok and cancel buttons are used or how they are implemented, that requirement must be upheld. Once I re-factored it out into a utility method it also became apparent that OK and Cancel buttons also have to have their preferred size set in a specific way - something we had another utility function for already since the behavior is similarly well defined. So a call to the sizing function is added to the layout function and we have a standard library function that gives us an ok and cancel button pair ready for adding to a dialog.

There are other things that need to be set about ok and cancel buttons (for instance their action listeners are almost always identical because of the way we write our code) but that’s getting too big for a static utility method and it’s not always common to every ok and cancel button. Having said that, I really should re-factor out the cancel listener because I can’t think of a cancel button that has different requirements plus it has to be used for the escape key and a bunch of other places. Getting rid of the extra class files the anonymous listeners create would probably save us a hundred k or so.

Coming back on topic, the design used isn’t correct in terms of object oriented programming, in fact it’s almost aspect oriented programming as it forms a cross cutting concern across all GUI dialogs, however it is extremely effective, has an extremely clearly defined purpose and is short and simple to understand even at a glance. Possibly the biggest indicator that a utility method should be used is that if the requirements for one dialog’s layout of the ok and cancel buttons changes - the requirements for every dialog will also change. The need for consistency in implementation is a big red flag that there should be a single implementation. So of course now if we ever support a new system that orders the ok and cancel buttons like Mac OS does or perhaps some other layout, we only have to make the change in one place.

Essentially, I think Benjamin and I are saying the same thing in slightly different ways, except that I don’t class code that should behave different as duplicated code - only code that has the same requirements is duplicated.

On a side note, Benjamin used the phrase:

bad design that comes about from prematurely reusing common-looking code

Prematurely doing anything is always asking for trouble (including prematurely suggesting that something will cause trouble). It’s amazing how many people (myself included) still fall into the prematurely doing stuff trap either for reusing code, optimization, writing code, writing a design and the most common: prematurely shipping the product.

What’s Your Biggest Code Smell?

October 1st, 2004

What’s the thing that most stands out as “gee, this is going to bite me later” code?

For me it’s without a doubt code duplication. I really hate seeing duplicate code even if it has slightly different behavior (it should put the common behavior into a parent class or utility methods etc and then just have different code where the behavior is actually different). Every time I see code duplicated I just know that a bug will turn up in it at some point and it will wind up only being fixed in one of the copies.

I also tend to design using generic plugins a lot. Sometimes I probably take it a bit too far but most of the time the generic approach winds up being much more flexible and robust, plus it’s usually easier to understand generic plugin style designs because they separate out functionality a lot more clearly - this plugin does this, that plugin does that. Of course, generic non-plugin type designs tend to have the opposite effect. There’s also this really messy middle ground between a plugin style design and a non-plugin design where things just wind up coming out ugly. Usually you get into that area when the functionality hasn’t been split up carefully enough or when the desired functionality is different enough to require separate functionality.

One of the areas I haven’t found a design I’m happy with yet is for menu and toolbar code - particularly when the menu and toolbar is configurable. It’s exceptionally clumsy to manually create each menubar and toolbar as if they were completely different things (they’re not - they’re just buttons of different styles that wind up firing an event) but it can also get very messy if you try for an MVC approach because the behaviors can become disturbingly complex (think submenus, comboboxes, toggle buttons, radio buttons, enabled and disabled etc). I’ve tried out a number of ways to handle this and I’m not quite happy with any of them. I’d like to try out a design where each menu is created from a particular definition (a set of properties that describe how it behaves) but that there are separate categories for the different types - so there’d be a toggle button MVC, a plain button MVC, a sub menu MVC, radio button MVC etc all integrated somehow (an overarching MVC kind of pattern?). I don’t know, I’ll have to find a project that will let me put it into code at some point and see what comes out of the concept.

Apple And Java 1.5

October 1st, 2004

Sun released Java 1.5 (or 5.0 or something) yesterday and today suddenly there’s a whole bunch of people complaining that Apple hasn’t yet ported it to Mac OS X. What the? People do realize that porting the JVM takes time right? Apple don’t get the final source code from Sun until Sun finish it (oddly enough) and Sun only just finished it. Sure Apple has had access to prerelease builds from Sun (and similarly Apple Select and Premiere developers have access to a seed release of Java 1.5). It will take time to for Apple to port the JVM and add in all the extra little details they provide (where little amounts to an entire L&F plus more). Then it has to go through QA (you do want it tested right?) and then it will be released. Daniel Brookshier” leads the charge with the whining. Of particular note is the comment:

Versions of Java 5.0 are released for Linux, Solaris, and MS. When will Apple release 5.0? Not really sure, but the rumors are that the sometime next year when Apple releases their next release of OS X. That’s a long wait for someone that needs to be building products with the latest and greatest.

Firstly, versions of Java 5.0 have been released by precisely one vendor (Sun) for the platforms that they support. When will Apple release 5.0? When they’ve had a chance to work on it. Secondly, “needs” to be building products with the latest and greatest?? Exactly what feature is present in Java 5.0 that you absolutely have to have? Sure there’s a lot of nice stuff and I can understand the desire to want to use it, but need to use it? I think not. Besides which, right now there are effectively zero users out there with Java 5.0 installed - it hasn’t even come through the automatic update system for me yet. Most developers still aren’t crazy enough to install Java 5.0 on their main dev boxes and anyone speaking Arabic or other RTL languages definitely won’t be upgrading (big thanks to Igor for the work around on that one). Take a deep breath people, calm down and use some common sense. Now is the time when you should start considering dropping Java 1.3 support if you haven’t already and doing testing on Java 1.5 to make sure your product runs on it correctly. In 6-12 months when the new release has stabilized and been deployed widely you might start thinking about dropping support for Java 1.4 and taking advantage of Java 1.5. There’s no rush, it’s not going to suddenly disappear and leave you stuck behind. However nice the features might be, you’ve survived without them this long right?