Main

March 03, 2008

ruby files as libraries or scripts

Listen to this article Listen to this article

Include the following snippet at the end of a Ruby file:

if $0 == __FILE__
    # do something
end

If you execute the file, the 'do something' block will run, but if you require the file, it won't. That way you can use the file as both a library and a script.

February 10, 2008

Classification does not equal prioritisation

Listen to this article Listen to this article

One of the classic mistakes that people make in planning agile software projects comes about when someone is asked to prioritise the stories to be done by the software team. The conversation usually goes like this:

Q: What do you think about Story A?
A: That's a priority one.

Q: Ok, what do you think about Story B?
A: That's a priority one as well.

At this point, the stories have not been prioritised. They have been classified into groups, where the group is named "Priority One". Whilst this may be a useful culling technique, do not fool yourself into thinking they are prioritised. What's worse for you is that, whether you like it or not, the stories will get done in some order. If the team is ready to start on a story and finds two of them that are both "Priority One", then they will pick one of them to do first. Sometimes, they will pick the wrong one.

Do your team a favour. Don't classify your stories. Prioritise them.

January 21, 2007

Why IntelliJ IDEA is a great IDE for Ruby on Rails

Listen to this article Listen to this article

JetBrains have just released the first beta of their IntelliJ IDEA Ruby Plugin. I've been using builds from the source repository for a while, and its my favourite environment for building Ruby on Rails applications. The strange thing is, I don't use it because I think it makes IntelliJ a great Ruby environment. I use it because IntelliJ is already a great environment for building HTML and CSS. When I'm building Rails apps, the framework allows my code to be so lean that I actually find myself spending more time working on the presentation of the system.

IntelliJ has been a great environment for HTML and CSS for years now. Its certainly very familiar to me from my Java web app development experience. The release of this plugin makes it at least an adequate environment for Ruby development. If history is anything to go by, JetBrains may well turn it into something which makes me wish I was forced to write more Ruby code in a Rails app :-)

January 19, 2007

Pragmatic requirements duplication

Listen to this article Listen to this article

Duplication in code is generally considered bad, because it violates the DRY principle. Probably the only commonly accepted exception to the rule is documented in Extreme Programming Explained by Kent Beck. He says that the one higher priority (than removing duplicate code) in simple design is to ensure that the system "must communicate everything you want to communicate". In other words, the readers of the code need to be able to understand what it is doing by reading it.

Requirements in the form of Use Cases are no different in this sense. The Use Cases should ideally have no duplication within them, but it is actually more important that the readers of the requirements understand what is being described within them. In other words, if putting some duplication in helps your readers better understand what is going on, that's a good thing.

The main difference between these cases is the skill of the reader. The people reading the code are (probably) trained in how to design and write it. The people reading the Use Cases however are probably not trained. In many projects, Use Cases have to be signed off by representatives of the business with no training or experience in them at all. In such cases, being pragmatic about duplicating some sections of requirements may be perfectly appropriate.

Oh - and by the way, Use Cases are not design. If you end up with duplicate code as a result of having duplicated requirements, beat your developers with a stick. They should know better.

January 07, 2007

Fixing a static method code smell

Listen to this article Listen to this article

Static methods are a clue that a piece of code might not be conforming well to object oriented design principles. Its probably not as well designed as it could be, or as reusable as it could be. Most of all, its probably not as testable as it could be. The contents of the method often belong on one of the objects being worked on, and sometimes belong in a whole new object unto themselves.

The first clue for how to fix it is to look at the parameters being worked on in the method. If it is, then you can convert the method to an instance method on that object. IntelliJ IDEA has a refactoring option called "Convert To Instance Method...", which will ask you which parameter to move the method to. If you're not using IntelliJ IDEA, you can move the method to the appropriate Object, delete the parameter, and use this instead.

public class AccountFunctions {
    public static void withdraw(Long amountInCents, Account account) {
        // ...
    }
}

becomes:

public class Account {
    public void withdraw(Long amountInCents) {
        // ...
    }
}

The second clue for how to fix it is to look at the local variables being used in the method. It's possible that the contents of the method belongs on one of them instead of one of the parameters. Maybe a singleton object is being accessed in the method for example. In this case, the solution is similar to the first option, except that the parameters all still exist.

public class CartFunctions {
    public static void addItemToCart(Long itemId) {
        Cart cart = Cart.getInstance();
        List items = cart.getItems();
        items.add(itemId);
    }
}

becomes:

public class Cart {
    public void addItem(Long itemId) {
        // ...
    }
}

The third clue for how to fix it is to create a completely new class just for the static method. The parameters on the method become instance variables, and a constructor should be created that takes them as parameters. The method itself becomes an instance method on that class that uses the instance variables instead of having parameters to it.

public class DatabaseFunctions {
    public static String buildSelectStatement(String tableName, Collection columns, 
                                              Collection conditions, Collection orderBys) {
        // ...
    }
}

becomes:

public class Query {
    private String _tableName;
    private Collection _columns;
    private Collection _conditions;
    private Collection _orderBys;

    public Query(String tableName, Collection columns, Collection conditions, Collection orderBys) {
    }

    public String toSql() {
        // ...
    }
}

December 13, 2006

Easy Access Training

Listen to this article Listen to this article

Cogent Consulting is trying a new idea next year called Easy Access Training. The idea is simple. Training courses often run over multiple weekdays, and can be quite expensive. That can make them inaccessible to people who either can't get the time off work, or don't have budget support from their boss to pay for it. So Cogent is offering one day courses on a weekend, and the seats are auctioned off, so it is possible to get one reasonably cheap.

Steve Hayes is running the first course in late January, and I'm going to to try and come along as well. Check out the EAT site to see the latest bids if you're interested.

June 22, 2006

ant build speed with ivy

Listen to this article Listen to this article

I work on a project with a *big* build. It has over 100 inter-dependant components, each with their own Ant build file. Developers need to build them all on their local machines as part of their normal build process. I won't go into why its like that for now. Needless to say, I think its way to big and would love to get the opportunity to simplify it.

We use Ivy to manage the build and make sure everything gets built in an order that satisfies the dependencies. Up until a week ago, a full build took about 45 minutes. Then I happened to stumble across a thread on the ant-user mailing list discussing performance of various ant tasks. It basically says that using the subant task or the antcall task is expensive, because it constructs a new ant project under the covers. Using subant is the way Ivy calls all of the sub-builds, so we had some usage of it in our main build.

I re-factored our build to minimise the use of subant, and also cleaned up a few antcall's that we had. Our build went down from 45 minutes to 35 minutes. Thats an enormous gain for the project when you have over 30 developers running it every day.

May 12, 2006

Silent letters in domain names

Listen to this article Listen to this article

I've been using wrytradesman.com for a couple of years now as my primary domain. At the time I registered it, I thought it was cool to have a domain that was an anagram of your name. Pretty soon though, I discovered the pain of having silent letters in your domain name. Every time I told someone what my website or email address was, I had to spell it for them.

Recently, I registered martyandrews.net, and I'm in the process of changing across to it as my primary domain. My blog has moved across, as well as my email address. The old domain and email address will continue to work for a while. My old rss feed is now pointing to the new blog location as well. If you've got any links though, please move them across. Mum - that probably only means you...

March 29, 2005

Expectations on test speed

Listen to this article Listen to this article

Unit testing

Tests single classes only.

  • Hundreds - thousands of tests should be able to run in the order of seconds to get very fast feedback on changes.
  • The speed is facilitated by using mocks to provide expected behaviour from other services nearby.
  • The use of mocks is facilitated by dependency injection techniques.

A side effect of this technique is that design has very low coupling. A code base that achieves this is likely to have many interfaces. Developers are often confident to refactor code or otherwise make changes quickly given that they have a large safety net. They will usually run unit tests many times per day on their development machines.

Integration Testing

Test groups of classes or components working together.

  • Hundreds of tests should be able to run in the order of minutes

These tests are usually at least run as part of the continuous build. Sometimes developers will also run them on their development machines based on their judgment about whether their work may impact groups of components working together.

System Testing

Test the system as a whole.

  • Tens of tests should run in tens of minutes or hours.

These tests are run on a regular basis. Ideally this will be part of the continuous build, but sometimes this becomes difficult (tests might take too long, or full environments may not be available all the time). If this is the case, they may be run overnight, or on weekends. System tests can take the form of HttpUnit or JWebUnit tests for web applications, or testing technologies that interface with other protocols. Applications with thorough system testing should experience low regression figures.

December 14, 2004

Web Services from a Spring Enabled Web-App

Listen to this article Listen to this article

I spent some time recently working on an web-application using spring and webwork. (<tangent>this combination created the core of one of the cleanest architectures I've worked with</tangent>). Someone asked how easy it might be to expose some functionality as a web service, so I thought I'd give it a go.

Grabbing a copy of Apache Axis was my first step. It's documentation guided me most of the way, but the only missing bit was how to get at a spring-created bean from an axis-aware class. Here's what I did.

After putting the required libraries (axis-ant.jar, axis.jar, commons-discovery.jar, commons-loggin.jar, jaxrpc.jar, wsdl4j.jar, saaj.jar) on the classpath, I had to declare all of the appropriate axis stuff in my web.xml file.

<web-app>
    <listener>
        <listener-class>org.apache.axis.transport.http.AxisHTTPSessionListener</listener-class>
    </listener>

    <servlet>
        <servlet-name>axis</servlet-name>
        <servlet-class>org.apache.axis.transport.http.AxisServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>axis</servlet-name>
        <url-pattern>/services/*</url-pattern>
    </servlet-mapping>

    <mime-mapping>
        <extension>wsdl</extension>
        <mime-type>text/xml</mime-type>
    </mime-mapping>
</web-app>

The next step was to create a class which would be exposed as a web service by Axis:

public class TodoItemWebService {
    public String getTodoItemDescription(String title) {
        return "dummy description";
    }
}

To get the service to run, I also had to create a file named server-config.wsdd in the WEB-INF directory of my web application. I figured out what this looked like by going through the Axis tutorial which dynamically registers a service in your app. Statically creating the file works fine though too. Here's what mine looked like:

<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
    <handler name="LocalResponder" type="java:org.apache.axis.transport.local.LocalResponder"/>
    <handler name="URLMapper" type="java:org.apache.axis.handlers.http.URLMapper"/>
    <handler name="Authenticate" type="java:org.apache.axis.handlers.SimpleAuthenticationHandler"/>

    <service name="items" provider="java:RPC" style="wrapped" use="literal">
        <operation name="getTodoItemDescription" qname="ns1:getTodoList" returnQName="ns1:getTodoItemDescriptionResult"
            returnType="xsd:string" soapAction="" xmlns:ns1="http://wrytradesman.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            <parameter qname="ns1:TodoItemTitle" type="xsd:string"/>
        </operation>
        <parameter name="allowedMethods" value="*"/>
        <parameter name="className" value="com.wrytradesman.todolist.web.service.TodoItemWebService"/>
        <parameter name="wsdlTargetNamespace" value="http://wrytradesman.com/"/>
    </service>

    <transport name="http">
        <requestFlow>
            <handler type="URLMapper"/>
            <handler type="java:org.apache.axis.handlers.http.HTTPAuthHandler"/>
        </requestFlow>
        <parameter name="qs:list" value="org.apache.axis.transport.http.QSListHandler"/>
        <parameter name="qs:wsdl" value="org.apache.axis.transport.http.QSWSDLHandler"/>
        <parameter name="qs.list" value="org.apache.axis.transport.http.QSListHandler"/>
        <parameter name="qs.method" value="org.apache.axis.transport.http.QSMethodHandler"/>
        <parameter name="qs:method" value="org.apache.axis.transport.http.QSMethodHandler"/>
        <parameter name="qs.wsdl" value="org.apache.axis.transport.http.QSWSDLHandler"/>
    </transport>

    <transport name="local">
        <responseFlow>
            <handler type="LocalResponder"/>
        </responseFlow>
    </transport>
</deployment>

The service definition in bold is what I had to write to get the service running. All of the surrounding info is setup stuff that is just needed to configure axis. At this stage of the game, I could deploy my web application and hit a url http://localhost//services/items?wsdl to get the WSDL definition for my service. In the space of about 5 minutes, a cow-orker had used that WSDL to create a .NET based client which called the service and got my hard-coded response.

With my web service now up and running, the only remaining problem was to create a "real" implementation that used one of my spring managed objects instead of a hard-coded response. The trick here is to get a reference to the application context first. Everything from that point is easy. The simplest path to that is get a reference to the servlet from the Axis message context, then use the servlet context to get the application context from spring. Then just call your spring bean as per normal. Here's what my final code looks like:

public class TodoItemWebService {
    public String getTodoItemDescription(String title) {
        HttpServlet servlet = (HttpServlet) MessageContext.getCurrentContext().getProperty(
                HTTPConstants.MC_HTTP_SERVLET);
        ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servlet.getServletContext());

        Map beans = context.getBeansOfType(TodoListRepository.class, false, false);
        Iterator iterator = beans.values().iterator();
        TodoListRepository repository = (TodoListRepository) iterator.next();

        TodoItem item = repository.getTodoList().getItem(title);
        return item.getDescription();
    }
}

Thats it. Pretty straight forward really. There's a few corner cases to be covered off, but vertical slice is complete. The whole exercise took less than a days effort, which included learning about how Axis hangs together.

July 16, 2004

CI Demo Part 5 - Something to play with

Listen to this article Listen to this article

I've uploaded all of the artefacts for the continuous integration demo I've been working on, and put the details for how to run it on the articles section of the site. It includes examples of the things I've been blogging about recently so you can see them used in anger.

Please have a go if you're interested and have some time to spare. I'd love to get some feedback. Oh - and thanks to Mike Williams for all your help.

July 13, 2004

A faster alternative to batchtest with JUnit in Ant

Listen to this article Listen to this article

Want faster Ant build times? One of the most common culprits I've seen for slow builds is the use of batchtest under the junit task while it has fork="yes" set.

People end up in this state for a variety of reasons. The batchtest example in the Ant docs has fork="yes" set. So does the example in the cruise control docs. Perhaps they started not forking a VM, but got clashes with XML (or other) libraries, and that was the easiest fix. Whatever the reason, I've seen lots of people do it, and there is a better way.

Lets start with a typical example. Here's what your Ant test target might look like to start off with:

<target name="test">
    <junit fork="yes">
        <classpath refid="test.classpath"/>
        <formatter type="plain" usefile="false"/>
        <batchtest>
            <fileset dir="${test.classes.dir}">
                <include name="**/*Test.class"/>
                <exclude name="**/acceptance/**/*Test.class"/>
            </fileset>
        </batchtest>
    </junit>
</target>

The basic approach is to convert this Ant script which runs lots of tests into an Ant script that runs only one test. Several things need to happen though. Firstly, the virtual machine still needs to be forked, to make sure classpath issues are not re-introduced. Secondly, the test has to become a suite so that all of the tests will still be run. Finally, some sort of filter mechanism needs to be put into the suite that matches the fileset filtering mechanism in the batchtest

The Ant script now becomes a bit simpler. The batchtest section is gone, and a single test name is in its place: com.thoughtworks.todolist.AllTests.

<target name="test">
    <junit fork="yes">
        <classpath refid="test.classpath"/>
        <formatter type="plain" usefile="false"/>
        <test name="com.thoughtworks.todolist.AllTests"/>
    </junit>
</target>

To get the test suite to work as per batchtest, I use a utility from the JUnit Addons project. It dynamically builds up a test suite from a directory structure with custom filters to include or exclude classes. My test suite looks like this:

package com.thoughtworks.todolist;

import junit.framework.Test;
import junitx.util.DirectorySuiteBuilder;
import junitx.util.SimpleTestFilter;

public class AllTests {
    public static Test suite() throws Exception {
        DirectorySuiteBuilder builder = new DirectorySuiteBuilder();
        builder.setFilter(new SimpleTestFilter() {
            public boolean include(Class clazz) {
                return super.include(clazz) &&
                        !getPackageName(clazz).equals("com.thoughtworks.todolist.acceptance");
            }
        });
        return builder.suite("build/test/classes");
    }
}

The use of the DirectorySuiteBuilder class replaces the batchtest component of the Ant build script, and the use of the SimpleTestFilter replaces the need for the nested fileset element.

That's all there is to it. In my simple application that so far has a grand total of 11 unit tests, I managed to cut my build time from 4 seconds down to 2 seconds. Phew! Pretty quick huh? Well - maybe in my case it didn't matter so much, but I've seen this cut minutes of builds for "real" projects before. Let me know how it goes for you.

Oh yeah - as an added bonus, you now have a stand-alone JUnit test suite that will always be up to date with all of your unit tests. It has no dependancy on Ant, so you can run it by itself inside your IDE (or whatever environment you use for JUnit tests).

July 12, 2004

Decorating Test Suites with Jetty

Listen to this article Listen to this article

On previous web-based projects that I've worked on, the build script assumed that a web-container was running that it could deploy the application to for functional tests. In the continuous integration demo that I was working on recently, Mike showed me a cool technique that he had found to eliminate the dependancy.

He's beaten me to it though, and already written about how to decorate test suites with Jetty.

July 08, 2004

Maintainability in Ant build scripts

Listen to this article Listen to this article

I've worked on dozens of projects that used Ant build scripts, with team sizes ranging from just me to tens of developers. Big projects tend to have big Ant scripts, and they can be a maintenance nightmare. I've developed a structural style for scripts that I find easier to maintain and explain on larger projects.

Take the following Ant script as a typical example.

<project name="foo" basedir="." default="test">
    <target name="init" description="Prepare directories for build">
        ...
    </target>

    <target name="compile" depends="init" description="Compiles code">
        ...
    </target>

    <target name="test" depends="compile" description="Tests code">
        ...
    </target>
</project>

The script has only three targets in it. All targets have a description, and two of them have a dependancy on another target. Those descriptions and dependancies are scattered throughout the file. It is possible to discover the descriptions of targets publicly available by running ant -projecthelp, and the dependancies will be seen when the script runs, but neither are easily viewable at a glance. This is especially true when your Ant script has grown to hundreds of lines and tens of targets.

Here's the same script modified to follow my different convention

<project name="foo" basedir="." default="test">
    <target name="-init">
        ...
    </target>

    <target name="-compile">
        ...
    </target>

    <target name="-test">
        ...
    </target>

    <!-- Private targets used only for dependancies -->
    <target name="--init"    depends="-init"/>
    <target name="--compile" depends="-init,-compile"/>
    <target name="--test"    depends="--compile,-test">

    <!-- Public targets with description -->
    <target name="init"    depends="--init"    description="Prepare directories for build">
    <target name="compile" depends="--compile" description="Compiles code">
    <target name="test"    depends="--test"    description="Tests code">
</project>

Most of the targets in this script are now "private" targets. Basically - anything that starts with a hyphen can't be run on the command line by Ant, as it thinks you are passing a parameter to the Ant script rather than specifying a target. None of these private targets have any dependancies or descriptions.

All dependancies between targets can be seen at a glance in one section. They are again all listed on private targets, but these ones do no work other than describing dependancies.

All descriptions can be seen at a glance in one section. They are listed on public targets, and delegate to a single other private target which handles the dependancies for it.

Thats all there is to it really. The purist in me doesn't like it, because the test target really does depend on the compile target, so thats where it should be listed. My pragmatic side almost always wins though, and I've seen enough confusion in Ant scripts to adopt this pattern for all my new builds.

CI Demo Part 4 - A new start

Listen to this article Listen to this article

So I've finally found a bit of spare time to do some work on that continuous integration demo again. Mike Williams has been helping me out a bit, and we've made some good progress.

The app is pretty simple - it's a To-Do list. We built it using a slightly different set of technologies than I'd originally anticipated. They were:

  • Subversion
  • Java
  • Ant
  • JUnit
  • JCoverage
  • Simian
  • Jetty
  • JWebUnit
  • Cruise Control
  • WebWork
  • Velocity

There are a few noticeable differences from my original list here. Subversion was used for simplicity of setup on Windows. I anticipate that most people will set this up on Wintel boxes, and CVS caused a bit of frustration. Webwork I started trying it just to see what it was like, and became a fan so kept using it. Velocity is in the same boat.

No FIT (or FIT-like) tests are included yet. Thats on my To-Do to-do list (pun intended). I'm also not uploading it all yet, as I need to clean a couple of bits up. I will however describe some of the key features in other blog entries.

June 02, 2004

Code Coverage by EMMA

Listen to this article Listen to this article

I've had some pain in recent times trying to get code coverage reports working on my project. Some of it has been shared with Steve and Jon who have both been helpful, but unfortunately I could never quite get what I wanted to work.

The source of my pain comes from the complexity of my build process. I have two web applications being built, and they each use some code from a shared code base. Lets call the web-apps foo and bar, and the shared code base baz. Both foo and bar have some unit tests and some in-container tests. baz has only unit tests, but just to add a bit more complexity, we use a byte-code enhancing tool on some of its classes to help with our app.

Ok - now for me to get a test coverage report for foo as a whole, I have to get coverage results from foo's unit tests, foo's in-container tests and baz's unit tests. Then I have to merge them all together and generate a report. The same model has to be repeated with bar

When I started, there was two main Java code-coverage tools on the market - Clover and JCoverage. They both work in very similar ways. First, they enhance the byte-code of your classes. Then you run your unit tests, which causes a file with coverage information to be written to disk. Finally, you run a report tool which reads that information and generates a nice report for you.

Let the pain begin... JCoverage started out ok. It enhanced my classes by just being told where to find the class files on disk. The unit tests ran ok for foo and baz, as did the in-container tests. But the merge blew up. I dunno why, but it did.

Next stop is Clover. I didn't get very far at all this time. Clover enhances class files in your Ant build by hooking into the compile task and making changes as the byte code is originally created. The problem is, our own byte-code enhancing tool gets confused when it looks at Clover-enhanced classes. So I was stuck before I even began.

We had planned some time just this week to try to resolve some of these problems, but before we began I stumbled across a reference to EMMA. Its only just been released, but is making some strong claims about competing with Clover in its descriptions. The documentation looked fairly complete, so I gave it a go.

Everything just works. Fantastic! The byte-code enhancing is similar to JCoverage (just point it at your classes). The merge tool had no problems dealing with results from three different runs, and in fact I don't even need to use it. The report target can deal with multiple input files. Merging is really just for compressing results into a single file. The report is not as sexy as JCoverage or Clover, but I only really needed the numbers anyway.

So next time you're looking for some coverage results, give EMMA a go. It oozed goodness for me...

May 25, 2004

Angry Fruit Salad

Listen to this article Listen to this article

Intellij IDEA's default color scheme is ok, but I've never been a fan of white backgrounds for code editors. I find the glare to be too bright after a whole day cutting code. Instead, I prefer a deep blue background with light colors for text and keywords.

A friend from work came up with a scheme similar to the style I like (he has a black background though). Jon Eaves coined the term "Angry Fruit Salad" for its look. I like it so much I felt compelled to share it with you.

Java code looks a bit like this:

XML looks a bit like this:

Like it? If you want to use it, feel free to download Angry Fruit Salad. Just drop it into the "colors" directory under you IntelliJ IDEA installation and you're away...

February 17, 2004

CI Demo Part 3 - Maven Build

Listen to this article Listen to this article

At the Sydney Geek Night this week, I spent spent some time with Mike Cannon-Brookes putting a Maven build on my template application. Ok, I just sat back and watched while Mike did his thing, but in any case, I learned a bit about Maven.

Continue reading "CI Demo Part 3 - Maven Build" »

February 15, 2004

CI Demo Part 2 - Template Application

Listen to this article Listen to this article

I've started down the road to building my continuous integration demo by setting up a template application with some of the basic tools listed previously.

Continue reading "CI Demo Part 2 - Template Application" »

February 02, 2004

My CSS adventure

Listen to this article Listen to this article

I spent some time on the weekend learning about cascading style sheets and applying my new skills to my own website. The look is not that different, but lots of stuff has changed.

Continue reading "My CSS adventure" »

January 10, 2004

mock objects rock! Mock Objects suck!

Listen to this article Listen to this article

Developers using Mock Objects aren't getting better designed code. They're following the trend of the community to use Mock Object projects without understanding the mock philosophy (sic). Using mock objects is a design technique, but Mock Objects only provide a testing technique. If people use mock objects instead of Mock Objects, their designs will improve.

Continue reading "mock objects rock! Mock Objects suck!" »