Mark Needham

Thoughts on Software Development

Archive for the ‘Java’ Category

Coding Dojo #5: Uno

without comments

We ran our 5th coding dojo on Thursday night, writing the card game Uno in Java. We didn’t all know the rules so this video explained it – surely a parody but you never know!

The Format

We used the Randori approach again with 6 people participating for the majority of the session. Everyone paired with everyone else at least once and sometimes a couple of times.

We had the pair driving at the front of the room and everyone else further back to stop the tendency of observers to whiteboard stuff.

What We Learnt

  • Modeling games is really good for practicing design skills. Most people had played the game so we had domain experts who could use their knowledge to help drive out the API of the various classes. We didn’t get to the scoring part of the game in the time available but it was quite cool to see our code with all the terms detailed in Wikipedia’s entry on the term.
  • We managed to drive the design much more effectively than we have done on previous sessions. The flexibility to move between classes depending on where it made most sense to test from next was finally there and we didn’t end up with the problem we’ve had on previous sessions where we ended up with coarsely grained tests and then tried to code the whole application in one go.
  • It was quite painful for me personally having to manually perform operations on collections in Java rather than having the selection of functional operators that are available in C# 3.0.
  • It wasn’t a new learning but I’ve noticed in my project work that I’ve become a lot more keen to keep the steps really small – there is a bit of pressure on you to do this in a dojo situation and I think it’s just continued over from there. Every time I try to be too clever and take a big step something inevitably doesn’t work and I end up doing the small steps anyway. It’s also a lot of fun coding in this type of environment and watching how others approach problems and how they pair with each other. If you get a chance to attend a dojo I think it’d definitely be worthwhile.

Other Dojo Thoughts

  • Some ideas for future coding dojos that we discussed were:
    • Concurrency – using the Retlang/Jetlang libraries
    • Do some stuff with Web Driver
    • Modeling games
    • Taking an open source project and refactoring it
  • I notice there are a couple of sessions of coding/coding dojos planned for Jason Gorman’s Software Craftsmanship conference. It will be interesting to see how those work out, especially if there are high numbers of participants. We’ve always had a fairly small number of people involved which I think has helped to keep everyone involved. I’m not convinced it would be effective with many more participants.

Written by Mark Needham

January 8th, 2009 at 11:41 pm

Posted in Coding Dojo,Java

Tagged with

JUnit Theories: First Thoughts

with 9 comments

One of my favourite additions to JUnit 4.4 was the @Theory annotation which allows us to write parameterised tests rather than having to recreate the same test multiple times with different data values or creating one test and iterating through our own collection of data values.

Previously, as far as I’m aware, it was only possible to parameterise tests by using the TestNG library which has some nice ideas around grouping tests but had horrible reporting the last time I used it.

To create parameterisable tests using Theories we need to write some code like the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import org.junit.Test;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;
 
@RunWith(Theories.class)
public class SomeTest {
	@Theory
	public void testTheNewTheoriesStuff(int value) {
		// test which involves int value	
	}
 
	public static @DataPoints int[] values = {1,2,3,4,5};
}

The ‘testTheNewTheoriesStuff’ Theory is then executed with each of the values defined in the values array decorated with the @DataPoints annotation.

The error message reported for a failure is reasonably good and makes it quite easy to figure out which one of the data points causes the problem.

An example error message for an assertion which failed inside a theory might look like this:

org.junit.experimental.theories.internal.ParameterizedAssertionError: testTheNewTheoriesStuff(values[1])

It’s 0 indexed so this error message tells us that there was an error when running the theory with the 2nd data point, therefore allowing us to go and work out why that’s the case and fix it.

This approach is actually particularly useful for testing the scope in which classes we pull from a dependency injection container are available from in our application.

Another potential use for this would be to test the edge cases of our classes – perhaps this would work best if we can randomise the data it uses.

This seems to be more the approach Microsoft are taking with the the Pex framework, a similar idea in the .NET space.

Written by Mark Needham

December 12th, 2008 at 12:34 am

Posted in Java

Tagged with ,

Logging with Pico Container

without comments

One thing that we’ve been working on recently is the logging for our current code base.

Nearly all the objects in our system are being created by Pico Container so we decided that writing an interceptor that hooked into Pico Container would be the easiest way to intercept and log any exceptions throw from our code.

Our initial Googling led us to the AOP Style Interception page on the Pico website which detailed how we could create a static proxy for a class that we put in the container.

The code to do this was as follows:

1
2
3
4
5
6
7
8
        DefaultPicoContainer pico = new DefaultPicoContainer(new Intercepting());
        pico.addComponent(Interceptable.class, ConcreteInterceptable.class);
        Intercepted intercepted = pico.getComponentAdapter(Interceptable.class).findAdapterOfType(Intercepted.class);
        intercepted.addPreInvocation(Interceptable.class, new InterceptableReporter(intercepted.getController()));
        intercepted.addPostInvocation(Interceptable.class, new InterceptableReporter(intercepted.getController()));
 
        Interceptable a1 = pico.getComponent(Interceptable.class);
        a1.methodThatThrowsException();
1
2
3
public interface Interceptable {
    void methodThatThrowsException();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
    private static class InterceptableReporter implements Interceptable {
        private Intercepted.Controller controller;
 
        public InterceptableReporter(Intercepted.Controller controller) {
            this.controller = controller;
        }
 
 
        public void methodThatThrowsException() {
            System.out.println("error happened");
 
        }
    }

While this approach works, the problem is that we need to define an individual proxy for every class that we want to intercept. It works as a strategy if we just need to intercept a few classes but not on a larger scale.

Luckily it is possible to create a dynamic proxy on the container so that we can intercept all the objects without having to create a static proxy for each one.

The code to do this was as follows:

1
2
3
4
5
        DefaultPicoContainer pico = new DefaultPicoContainer(new LoggingAwareByDefault());
        pico.addComponent(Interceptable.class, ConcreteInterceptable.class);
 
        Interceptable interceptable = pico.getComponent(Interceptable.class);
        interceptable.methodThatThrowsException();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import org.apache.commons.logging.LogFactory;
import org.picocontainer.Characteristics;
import org.picocontainer.ComponentAdapter;
import org.picocontainer.ComponentMonitor;
import org.picocontainer.LifecycleStrategy;
import org.picocontainer.Parameter;
import org.picocontainer.behaviors.AbstractBehaviorFactory;
 
import java.util.Properties;
 
public class LoggingAwareByDefault extends AbstractBehaviorFactory {
    private static final String DO_NOT_LOG_NAME = "support-team-opt-out";
    public static final Properties DO_NOT_LOG = Characteristics
            .immutable(DO_NOT_LOG_NAME, Characteristics.TRUE);
 
 
    public <T> ComponentAdapter<T> createComponentAdapter(ComponentMonitor componentMonitor,
                                                          LifecycleStrategy lifecycleStrategy,
                                                          Properties componentProperties,
                                                          Object componentKey, Class<T> componentImplementation,
                                                          Parameter... parameters) {
        if (removePropertiesIfPresent(componentProperties, DO_NOT_LOG)) {
            return super.createComponentAdapter(componentMonitor, lifecycleStrategy, componentProperties, componentKey,
                    componentImplementation, parameters);
        } else {
            return new LoggingAware<T>(super.createComponentAdapter(componentMonitor,
                    lifecycleStrategy, componentProperties, componentKey,
                    componentImplementation, parameters));
        }
 
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import org.apache.commons.logging.Log;
import org.picocontainer.ComponentAdapter;
import org.picocontainer.ComponentMonitor;
import org.picocontainer.PicoContainer;
import org.picocontainer.behaviors.HiddenImplementation;
 
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
 
public class LoggingAware<T> extends HiddenImplementation {
    public LoggingAware(ComponentAdapter delegate) {
        super(delegate);
    }
 
    protected Object invokeMethod(Object componentInstance, Method method, Object[] args, PicoContainer container)
            throws Throwable {
        ComponentMonitor componentMonitor = currentMonitor();
        try {
            componentMonitor.invoking(container, this, method, componentInstance);
            long startTime = System.currentTimeMillis();
            Object object = method.invoke(componentInstance, args);
            componentMonitor.invoked(container,
                                     this,
                                     method, componentInstance, System.currentTimeMillis() - startTime);
            return object;
        } catch (final InvocationTargetException ite) {
            componentMonitor.invocationFailed(method, componentInstance, ite);
 
            // log the error
 
            throw ite.getTargetException();
        }
 
    }
}

From what I recall from looking at the source code I think in order to create a proxy around an object it needs to implement an interface otherwise the proxy will not be created.

Written by Mark Needham

November 11th, 2008 at 12:08 am

Posted in Java

Tagged with

Hamcrest Matchers – Make the error message clear

without comments

We have been making good use of Hamcrest matchers on my current project for making assertions, and have moved almost entirely away from the more traditional JUnit assertEquals approach.

There are several reasons why I find the Hamcrest matcher approach to be more productive – it’s more flexible, more expressive and when an assertion fails we have a much better idea about why it has failed than if we use a JUnit assertion for example.

This applies especially when we get a test failing as part of the build as compared to running a test from the IDE where the source code is close at hand and non descriptive error messages may not be such a problem.

It therefore makes sense when writing custom Hamcrest matchers to ensure that we do indeed provide a clear error message so that it is obvious how to fix the test.

The convention seems to be that we should first state the static method name of the matcher and then in brackets list the expected arguments.

To give an example from a matcher we wrote yesterday:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import org.hamcrest.Description;
import org.hamcrest.Factory;
import org.hamcrest.TypeSafeMatcher;
 
public class ContainsAllOf<T> extends TypeSafeMatcher<T> {
    private String[] messages;
 
    public ContainsAllOf(String... messages) {
        this.messages = messages;
    }
 
    public void describeTo(Description description) {
        description.appendText("containsAllOf(");
        for (String message : messages) {
            description.appendText(",");
            description.appendValue(message);
        }
        description.appendText(")");
    }
 
    @Factory
    public static <T> ContainsAllOf containsAllOf(String... messages) {
        return new ContainsAllOf(messages);
    }
 
    public boolean matchesSafely(T t) {
        return contains(t, messages);
    }
 
    private boolean contains(T t, String[] messages) {
        boolean containsAllMessages = true;
        for (String message : messages) {
            if (!t.toString().contains(message)) {
                return false;
            }
        }
        return containsAllMessages;
    }
 
}

If we call this in our test with a value that doesn’t exist:

assertThat("mark's cool message", containsAllOf("mark", "cool", "message", "notThere"));

Running the test results in the following error:

java.lang.AssertionError: 
Expected: containsAllOf(,"mark","cool","message","notThere")
     got: "mark's cool message"

We can easily see what the problem is and how to go about fixing it, which I feel is the most important thing when it comes to test assertions.

Written by Mark Needham

November 8th, 2008 at 2:46 am

Posted in Java

Tagged with ,

Keep Java checked exceptions in a bounded context

with 4 comments

One of the features that I dislike in Java compared to C# is checked exceptions.

For me an exception is about a situation which is exceptional, and if we know that there is a possibility of it happening and even have that possibility defined in our code then it doesn’t seem all that exceptional to me.

Having said that they do at least provide information which you can’t help but notice about what can go wrong when you make a call to a particular method.

The problem is that often these checked exceptions just get passed on – i.e. not handled – until we end up with an exception on the page the user sees which is completely irrelevant to the action they are trying to undertake.

To give an example, we have been using the OGNL library to hydrate some objects for testing using the builder pattern.

We have something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class FooBuilder {
    private String bar;
 
    public FooBuilder setBar(String bar) {
        this.bar = bar;
        return this;
    }
 
    public Foo toFoo() {
        Foo foo = new Foo();
        setValue(foo, "bar", bar);
        return foo;
    }
 
    protected void setValue(Object object, String propertyName, Object propertyValue) {
        try {
            OgnlWrapper.setValue(object, propertyName, propertyValue);
        } catch (OgnlException e) {
            throw new RuntimeException(e);
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import ognl.DefaultMemberAccess;
import ognl.MemberAccess;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
 
public class OgnlWrapper {
 
    public static void setValue(Object object, String propertyName, Object propertyValue) throws OgnlException {
        Ognl.setValue(propertyName, createOgnlContext(), object, propertyValue);
    }
 
    private static OgnlContext createOgnlContext() {
        MemberAccess memberAccess = new DefaultMemberAccess(true);
        OgnlContext ognlContext = new OgnlContext();
        ognlContext.setMemberAccess(memberAccess);
        return ognlContext;
    }
}

We can then build an instance of ‘Foo’ like so:

Foo foo = new FooBuilder().setBar("barValue").toFoo();

What is interesting here is not the OGNL library in itself but the checked ‘OgnlException’ which the ‘Ognl.setValue(…)’ method defines.

If I am using the FooBuilder I don’t care how the Foo object is created, all I care is that I get it. Therefore we don’t want to bubble the implementation details of how we are creating the object upwards.

I only care about the OgnlException if I am calling the OgnlWrapper and therefore that is where the exception should be caught and then rethrown as a Runtime exception.

I like to refer to this area of OgnlWrapper callees as being a bounded context – that exception should only be applicable in that particular area and beyond that it should not exist.

Doing this allows us more flexibility around the way we implement things. If I decide in the future to use a different library instead of OGNL to do the same job I don’t need to worry that the callees of FooBuilder will all need to be updated. I can just make the change inside FooBuilder and that’s it!

Written by Mark Needham

October 23rd, 2008 at 9:22 pm

Posted in Java

Tagged with ,

Tomcat – No caching of RESTlet resources for Firefox

with 3 comments

One problem that we’ve been trying to solve today is how to make a RESTlet resource non cacheable.

The reason for this is that when a user logs out of the system and then hits the back button they shouldn’t be able to see that page, but instead should see the login form.

After several hours of trawling Google and trying out various different suggestions we came across the idea of setting ‘cache-control’ with the value ‘no-store’ in the response headers.

The code to make this happen is as follows (use inside a class which extends Resource):

1
2
3
HttpResponse response = (HttpResponse) getResponse();
Series<Parameter> headers = response.getHttpCall().getResponseHeaders();
headers.add("cache-control", "no-store");

The important part in this example is the last line. As long as it’s added to the Http Response Headers that response should no longer be cached.

A bit of research revealed that Internet Explorer may change the ‘no-store’ value to ‘no-cache’ so I’m not sure if this will work for that browser.

Written by Mark Needham

October 22nd, 2008 at 10:00 pm

Posted in Java

Tagged with , ,

Java vs .NET: An Overview

with 5 comments

A couple of months ago my colleague Mark Thomas posted about working on a C# project after 10 years working in Java, and being someone who has worked on projects in both languages fairly consistently (3 Java projects, 2 .NET projects) over the last two years I thought it would be interesting to do a comparison between the two.

The standard ThoughtWorks joke is that you just need to remember to capitalise the first letter of method names in C# and then you’re good to go but I think there’s more to it than that.

The Language & Framework

There is really not much difference between the syntax of Java and C# and I’m not that interested in going into it it massive detail here. There are other websites which cover it in more detail.

Language features wise C# seems to be marginally ahead – the introduction of lambda expressions, implicitly typed local variables and extension methods in C# 3.0 is something not yet matched in Java.

From my experience C#/.NET has much better support for front end rich GUI applications (WinForms, WPF) while Java is probably better for back end work. When it comes to web applications Java probably holds a marginal edge although the soon to be production released ASP.NET MVC framework is a very nice piece of kit.

I have no data to justify saying that, merely thoughts based on experience, but from conversations with friends who work in investment banking I have learned that this is the way the two languages are used there as well.

Other language support

If you are looking for language support on the respective platforms beyond Java/C#, Java probably has a slight edge.

Groovy is a dynamic lanuage with a Java style syntax and should therefore be easier for Java developers to pick up. I’m not aware of a dynamic language with C# style syntax for .NET although Boo is an alternative which compiles to run on the Common Language Infrastructure.

If you need Ruby support Java has JRuby while .NET has IronRuby. JRuby is the more mature of the two options here. If Python is what you need then both contenders compete here too with Java’s offering of Jython and .NET’s IronPython.

Functional language wise .NET has a CTP release of F#, while Java has support for Scala.

Use of 3rd party APIs/Open Source Software

I’ve found that in the Java projects that I’ve worked on use significantly more open source software than the .NET ones. I’m yet to be convinced that this is necessarily a good thing although my Java colleagues are confident that it is.

To give an example, there are multiple different Java libraries for Xml parsing whereas in C# everyone just uses the default one that’s provided.

This provides the opportunity to learn new and better ways of doing things on the one hand, but the potential to spend serious amounts of time evaluating which tool to use instead of just getting on with it on the other.

From a Java perspective it certainly provides extra challenges in trying to get your applications integrated with the range of different application and web servers on the market. In .NET it would simply be a case of getting it to work on IIS – of course easier said than done!

IDEs

I think Java clearly leads in this area with IntelliJ out ahead of anything else I’ve ever worked with. Eclipse is a popular open source alternative but for me it is far less intuitive to use than IntelliJ.

Visual Studio only becomes usable once Resharper is installed but when that’s done it becomes better than eclipse if not quite as usable as IntelliJ. My colleague Pat Kua also listed some ideas to make it run even better. SharpDevelop is a free IDE for .NET development although I haven’t used it so I’m not sure how good it is.

Build and Deployment

Partly due to its better support of Ruby, Java has a much wider range of tools for working with the build.

In .NET NAnt is the only serious contender, and although msbuild is often used to handle the compiling of the code its verbosity of non intuitive approach means I can’t imagine recommending it for a whole build file.

Java wise we have Ant, Maven, a Groovy based wrapper around Ant called Gant, the Ruby based buildr and the dependency management tool Ivy.

Communities

From my experience the community around .NET is more accessible to your average developer than what I’ve noticed in the Java world.

The Alt.NET group is an initiative started last year by several of the leading lights in the .NET world and aims to make the world of .NET development a better and more productive place.

Java has the Java Community Process driving it forward from a community perspective and perhaps due to the lower reliance on the drag and drop tools which are encouraged by Microsoft tools, the standard of your average Java developer may in fact be higher.

When it comes to finding the answers to questions both are mainstream enough that this is fairly easy.

Overall

I’ve tried to cover some of the areas which I considered important when using these two approaches. I’m sure there are some comparisons I have missed out so it would be interesting to hear from others who have worked on both platforms.

This is all written from my knowledge (and a bit of research) so if I’ve missed anything please mention it in the comments.

*Updated*
The paragraph about ‘Other Language Support’ was updated to reflect Robin Clowers’ comments.

Written by Mark Needham

October 15th, 2008 at 12:09 am

Posted in .NET,Java

Tagged with , ,

Connecting to LDAP server using OpenDS in Java

with 4 comments

A colleague and I have spent the past couple of days spiking solutions for connecting to LDAP servers from Ruby.

We decided that the easiest way to do this is by using OpenDS, an open source directory service based on LDAP.

One option we came up with for doing this was to make use of the Java libraries for connecting to the LDAP server and then calling through to these from our Ruby code using the Ruby Java Bridge.

This post is not about Ruby, but about how we did it in Java to check that the idea was actually feasible.

The interfaces and classes we need to use to do this are not very obvious so it was a little bit fiddly getting it to work. The following code seems to do the trick though:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import org.opends.server.admin.client.ldap.JNDIDirContextAdaptor;
 
import javax.naming.directory.DirContext;
import javax.naming.NamingException;
import javax.naming.Context;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.InitialLdapContext;
 
import com.sun.jndi.ldap.LdapCtx;
 
import java.util.Hashtable;
 
public class OpenDs {
 
    public static void main(String[] args) throws NamingException {
        DirContext dirContext = createLdapContext();
        JNDIDirContextAdaptor adaptor =  JNDIDirContextAdaptor.adapt(dirContext);
 
        // do other stuff with the adaptor
    }
 
    private static DirContext createLdapContext() throws NamingException {
        Hashtable env = new Hashtable();
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, "ldap://localhost:389");
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        env.put(Context.SECURITY_PRINCIPAL, "cn=Directory Manager");
        env.put(Context.SECURITY_CREDENTIALS, "password");
 
        return new InitialLdapContext(env, null);
    }
}

Some points about the code:

  • Port 389 is the default port for the LDAP server so unless it’s in use this is probably the port you need to connect to.
  • ‘Directory Manager’ is the default ‘Root User DN’ that was setup when we installed OpenDS although there is more information on what this value may need to be on the official documentation.
  • We originally tried to connect using JNDIDirContextAdaptor.simpleBind(…) but it didn’t seem to work for us so we went with the JNDIDirContextAdaptor.adapt(…) approach.

Written by Mark Needham

September 29th, 2008 at 11:27 pm

Posted in Java

Tagged with , ,

My dislike of Java’s static import

with 8 comments

While playing around with JBehave I was reminded of my dislike of the import static feature which was introduced in Java 1.5.

Using import static allows us to access static members defined in another class without referencing the class name. For example suppose we want to use the following method in our code:

Math.max(1,2);

Normally we would need to include the class name (Math) that the static function (max) belongs to. By using the import static we can reference max like so:

import static java.lang.Math.max;
...
max(1,2);

The benefit of this approach is that it makes the code read more fluently but the disadvantage is that you can’t immediately tell where a method lives. I want to be able to tell what is going on in the code from looking at it and anything which prevents this is a hindrance.

The official documentation even suggests using this functionality sparingly:

So when should you use static import? Very sparingly! Only use it when you’d otherwise be tempted to declare local copies of constants, or to abuse inheritance (the Constant Interface Antipattern). In other words, use it when you require frequent access to static members from one or two classes.

On my last project we ended up saying that import static was allowed in test code because there were relatively few places the static methods could be imported from, but when it came to production code the fully qualified path was required.

Written by Mark Needham

September 24th, 2008 at 11:59 pm

Posted in Java

Tagged with , ,

Testing with Joda Time

with 6 comments

The alternative to dealing with java.util.Date which I wrote about in a previous post is to make use of the Joda Time library. I’m led to believe that a lot of the ideas from Joda Time will in fact be in Java 7.

Nevertheless when testing with Joda Time there are times when it would be useful for us to have control over the time our code is using.

Why would we want to control the time?

There are a couple of situations that come to mind where it may be useful to be able to control the time in a system:

  • There is a piece of code which only executes at a certain time of the day. To see if it executes correctly we need to be able to set the system time to be that time.
  • Date calculations – we want to do a calculation on a date and verify the result. We therefore need to be able to control the original date.

Given that, there are two approaches which I have seen to allow us to do this:

Freezing time

Joda includes a DateTimeUtils class which allows us to change the current time.

On the projects I’ve worked on we would typically wrap these calls in a more descriptive class. For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
import org.joda.time.DateTime;
import org.joda.time.DateTimeUtils;
 
public class JodaDateTime {
    public static void freeze(DateTime frozenDateTime) {
        DateTimeUtils.setCurrentMillisFixed(frozenDateTime.getMillis());
    }
 
    public static void unfreeze() {
        DateTimeUtils.setCurrentMillisSystem();
    }
 
}

This approach works better if DateTime is deeply engrained in the system and it is difficult for us to abstract dates behind another interface.

The benefit of taking this approach is that we can test for dates without having to change any of our code to add in another level of abstraction which leads to further complexity.

Time Provider

The alternative approach is to have a TimeProvider which we can pass around the system. This would typically be passed into the constructor of any classes which need to make use of time.

For example, we might have the following interface defined:

1
2
3
4
5
import org.joda.time.DateTime;
 
public interface TimeProvider {
    public DateTime getCurrentDateTime() ;
}

We can then mock out getCurrentDate() to return whatever date we want in our tests.

The advantage of this approach is that it allows more flexibility around the implementation – it could be used to sync system and local machine dates for example – although at a cost of adding extra complexity.

This approach is similar to the plugin pattern Martin Fowler details in Patterns of Enterprise Application Architecture in that we use one implementation of TimeProvider in our application and then a different version for testing.

I generally favour this approach if possible although if a quick win is needed then the first approach is fine.

Written by Mark Needham

September 24th, 2008 at 5:11 am

Posted in Java

Tagged with , , ,