Mistaeks I Hav Made http://nat.truemesh.com/ http://nat.truemesh.com//logo.jpg/logo.jpg Mistaeks I Hav Made http://nat.truemesh.com/ "Good judgement is the result of experience ... Experience is the result of bad judgement." — Fred Brooks en-us 2008-06-26T15:07:05+00:00 Throw Defect http://nat.truemesh.com/archives/000739.html Defects Sign

While I'm on the subject of exceptions, let me share another exception idiom I've used a lot on recent projects... the Defect exception.

The Java compiler is very strict. It will complain about missing code paths that you, the programmer, know should never be followed at runtime. This is especially common when using APIs that throw checked exceptions to process data that will always be correct unless the programmer has screwed up..

For example, loading and parsing template from a resource that is compiled into the application should never fail, but throws a checked IOException.

Template template;
try {
    template = new Template(getClass().getResource("data-that-is-compiled-into-the-app.xml"));
}
catch (IOException e) {
    // should never happen
}
...

If an IOException is caught, something is seriously wrong with the application itself, because of something the programmer has done. The application has been built incorrectly, perhaps, or the template is syntactically incorrect. If the application continues running it will fail with confusing errors later on. The error will be difficult to diagnose.

So, the catch block must throw another exception. It can't throw a checked exception. Because it has caught a programming error, it should throw some kind of RuntimeException. RuntimeException itself is a bit vague, and there isn't a subclass of RuntimeException that really fits the bill for this situation. Therefore, I like to define a new exception type to report programmer errors. I first called it StupidProgrammerException, but now, as suggested by Romilly, I call it by the less confrontational name of Defect:

public class Defect extends RuntimeException {
    public Defect(String message) {
        super(message);
    }

    public Defect(String message, Throwable cause) {
        super(message, cause);
    }
}

When the compiler asks me to write code paths that should never happen, I throw a Defect. For example:

Template template;
try {
    template = new Template(getClass().getResource("data-that-is-compiled-into-the-app.xml"));
}
catch (IOException e) {
    throw new Defect("could not load template", e);
}
...

Image by Jonas B, distributed under the Creative Commons Attribution license.]]> Design and Architecture npryce 2008-06-26T15:07:05+00:00 Generic Throws: Another Little Java Idiom http://nat.truemesh.com/archives/000738.html throw.jpg

A seemingly little known fact about Java generics is that you can write generic throws declarations by declaring a type parameter that extends Exception. For example, the following interface defines a generic finder that looks up a value of type T, returns null if it is not found,or may report that the lookup failed completely by throwing an exception of type X:

public interface Finder<T, X extends Exception> {
    @Nullable
    T find(String criteria) throws X;
}

Different implementations can fail in different ways. A finder that performed an HTTP query can fail with an IOException. A finder that queries a database can fail with a SQLException. And so on.

A Cunning Idiom for Classes That Cannot Fail

But what about queries that cannot fail? You might want to implement the query in-memory, with a HashMap or something. You don't want to declare that find throws a checked exception. Therefore bind X to RuntimeException. The compiler will ignore the throws clause and you don't even need to include it in implementing classes:

public class InMemoryFinder<T> extend Finder<T, RuntimeException> {
    private final Map<String,T> entries;

    public InMemoryFinder(Map<String,T> entries) {
        this.entries = entries;
    }

    @Nullable
    T find(String criteria) { // No need for a throws clause
        return entries.get(criteria);
    }
}

Generic throws can remove a lot of boilerplate code to pass checked exceptions through interfaces by wrapping them in more abstract checked exceptions. Hopefully one day Java will provide anchored exceptions so we can avoid all this generics jiggery-pokery.

Generic Throws and Polymorphism

Wrapped exceptions are still necessary when an interface must be used polymorphically. A type that declares generic throws is generic but not polymorphic: an interface T<IOException> cannot be used wherever a T<SQLException> is acceptable.

If necessary, an interface with generic throws can be converted by an Adaptor into a version that throws wrapped exceptions and can be used polymorphically.

public class PolymorphicFinder<T,X> extend Finder<T, FinderException> {
    private final Finder<T,X> implementation;

    public PolymorphicFinder(Finder<T,X> implementation) {
        this.implementation = implementation;
    }

    @Nullable
    T find(String criteria) throws FinderException {
        try {
            return implementation.find(criteria);
        }
        catch (X x) {
            throw new FinderException("query failed", x);
        }
    }
}

Wishful Thinking

Imagine if the Iterable and Iterator interfaces were parameterised by exception type:

public interface Iterator<T, X extends Exception> {
    boolean hasNext() throws X;
    T next() throws X;
}

public interface Iterable<T, X extends Exception> {
    Iterator<T,X> iterator();
}

Collections could implement Iterable<T,RuntimeException> and appear no different from the way they are now. However, I/O streams, SQL result sets and other streams of data read from the program's environment could be represented as Iterable objects and the for-each loop could be used to iterate over their contents.

For example, BufferedReader could implement Iterable<String,IOException>, which would let you write:

try {
    BufferedReader reader = new BufferedReader(...);
    for (String line : reader) {
        ... do something with the line
    }
}
catch (IOException e) {
    ... iteration failed
}

Unfortunately, it's probably too late to make this change because it would break backward compatibility.

Photo by Wildcat Dunny, distributed under a Creative Commons license.

]]>
Design and Architecture npryce 2008-06-25T16:55:57+00:00
Evolving an API: Programmers are People Too http://nat.truemesh.com/archives/000732.html By popular (e.g. one) demand, here are the notes to the lightning talk I gave at the last Google Open-Source Jam on my experiences in API design.

A User Interface for Programmers

An API is a user interface for programmers. That means you have to develop it like a user-interface: iteratively, adapting to how the users actually use and misuse the interface in real life. In an open-source project we can't afford to run usability experiments, hiding behind one-way mirrors observing how users work with our software. Instead we have to react to explicit user feedback, bug reports and feature requests on our project's mailing lists, forums and issue trackers. Because programmers are passive aggressive and love to moan about things, they'll post negative feedback on their blogs instead of discussing it on the mailing lists. Google Blog Search is an excellent tool for finding out what programmers really think about your API.

But... programmers focus on solutions, not goals, so their feature requests will be worded in terms of how they think they would change the API to support whatever it is they want to do. You have to engage in a lot of arduous back-and-forth to find out what they are trying to achieve, rather than what they think they would change in your code. Often you (and they) discover that their goal can be achieved with the current API but they haven't noticed because of their solution myopia. If it turns out your API does not do what they want, you will be better placed to work out the correct way of extending the API or push back on the request because it would violate the API's conceptual integrity.

Conceptual Guide

An API encapsulates a conceptual model for representing and solving problems in the API's application domain. It guides programmers towards what the API designer considers to be the "right" way of doing things and away from the "wrong" way.

But... although programmers know there are no silver bullets, they love their golden hammers! They've learned your API and now they want to apply it to problems that are unrelated or only vaguely related. They'll submit bug reports, feature requests and patches aplenty as they encounter difficulties. To steal a colleague's joke: "if all you have is a hammer, everything looks like a thumb". You have to be willing to push back on requests that would violate the conceptual integrity of your API, otherwise it turns into an inconsistent mess that cannot communicate any useful understanding about the problem domain. It seems a strange idea to some programmers, but just because they use your API doesn't mean that they cannot not use another API at the same time.

System of Names

A clear and consistent system of names help people understand the conceptual model. For an API, the names should be chosen to make the calling code as readable as possible, even if it makes the implementation of the API less readable. It's really useful to discuss naming ideas on the mailing lists before adding new features to find out if what you think is easy to understand actually confuses people.

But... people often don't take notice of names or understand their meaning, especially when they speak a different language from the API implementors. I wrote an example class in Java that was called UnsafeHackConcreteClassImposteriser. I'd have thought that the phrase "unsafe hack" in the name was enough to warn programmers away from using it as anything more than an example, but apparently not. Someone still used it in their project and complained that it didn't work exactly as they wanted.

Extensibility

Users will always want to adapt your (object-oriented) API to their needs.  If you don't define clear plug-in points they will adapt your API by inheriting your classes and overriding internal methods.  That is brittle: it will increase your support overhead or reduce your ability to change the code. Define plug-in interfaces to be focused on one thing, so that they remain stable. For example, the Hamcrest Matcher interface has only two methods and has not significantly changed since it was first defined over 8 years ago. To ensure that code that uses the API is as readable as possible, plug-in points should be seamless: code that plugs user defined objects into the API should not look different than code that uses the built-in objects.

But... if you provide extension points, programmers will want you to maintain their extensions for them. Your users will contribute loads obscure extensions that make sense in their projects but don't have a wide applicability. If you adopt every contributed extension you will end up with an enormous maintenance overhead. Therefore, find out which are the most popular plug-in points and keenest users. Spin off libraries of extensions as external projects and get your keen users to maintain them. E.g. the Hamcrest matchers used to be part of the jMock project but now they're maintained by Neil and Joe. Thanks chaps!

Diagnostics

Error messages are part of the API. Take notice of the errors that confuse users the most (using the mailing lists, issue tracker and blog searches) and improve error messages to reduce confusion. This will reduce the support load in the long term.

But... there is a tension between error diagnostics and generalisation. The more generic and pattern-tastic is your implementation, the harder it is to determine what the user was trying to do that caused an error, and so the harder it is to generate error messages that make sense to the user. Sometimes you have to sacrifice generality for better error messages.

Examples

To save time, make documentation extensible so that you can grow it piecemeal without it obviously being under construction. It's easiest to generate reference documentation with Javadoc.

But... programmers don't always want reference documentation. Javadocs are not useful for people trying to learn an API. Programmers want canned solutions and concrete examples that they can copy into their project and adapt to their needs. The best form of documentation for both you the implementor and your users is HOWTO documents, cookbook recipes and FAQs. The more flexible and extensible the API, the more useful recipes and HOWTOs are because applying the API may require some lateral thinking to understand how the features of the API are used to solve problems.

]]>
Design and Architecture npryce 2008-02-29T16:57:06+00:00
Allowing tests to drive development http://nat.truemesh.com/archives/000729.html Witches

I have noticed teams who are new to TDD reach for ever more sophisticated tools to help them test their code rather than refactor their code to make it more testable. By doing so, they lose one of the major benefits of TDD: the feedback it gives on internal design quality.

Code is difficult to test when classes are tightly coupled, are entangled by hidden dependencies like static methods or singletons, or don't clearly distinguish between internal implementation details and peer objects (dependencies, policies or notifications). To unit-test classes like this, it can be tempting to use tools that use clever class loader tricks and bytecode manipulation [1, 2] to break the tight dependencies. But by using tools like this you lose one of the major benefits of unit-testing in the TDD process: rapid feedback on the internal quality of the software.

TDD is not merely about testing — that is, about verifying the external quality of the software: whether it is reliable enough, accurate enough, fast enough, etc. It also gives you feedback about its internal quality: how well designed the code is, such as how loosely coupled and cohesive the classes are, whether dependencies are explicit or hidden, whether information hiding is being used appropriately. And that translates into feedback about how maintainable the code is: how easy it is to extend, change or correct its behaviour over its lifetime.

If you use unit-testing tools that let you side-step poor dependency management in the design, you lose this valuable source of feedback and, when you find that you do need to address these design issues because you have to modify the production code, it will be much harder to do so. The poor structure will have influenced the design of other parts of the system that rely upon it. The programmers responsible for the change will not understand the code as well as those who wrote it (even if they are the same people). It's far easier to nip these design issues in the bud as you discover them than let them remain to affect the design of the rest of the code.

I therefore use a simple rule of thumb when choosing technologies to help me write unit tests:

Break dependencies in unit tests only with techniques that would be acceptable in the production code.

Would I use classloader magic and bytecode manipulation to set dependencies in production code? No. Would I use reflection to modify private fields in production code? No. Would I refactor to introduce an interface between objects? Yes. Would I refactor an object to get a dependency through its constructor instead of from a global variable? Yes.

Following this rule of thumb ensures that code is always easy to change. There are no nasty surprises late in the project when new functionality requires massive changes to the design and developers are pressured to hack the change in because the estimated costs of doing it the right way are too high.

]]>
Test-Driven Design npryce 2008-01-06T13:00:00+00:00
Tricks with Test Data Builders: Refactoring Away Duplicated Logic Creates a Domain Specific Embedded Language for Testing http://nat.truemesh.com/archives/000728.html Builder and Customer

Test Data Builders remove a lot of duplication from test code, but there can often still be duplicated logic at the point at which the built objects are used. Many different tests will have very similar code that creates an object using a builder and then passes it to the code under test. We can address this duplication by factoring out test scaffolding that works with builders, not system objects. Doing so produces a higher level testing API that more clearly communicates the intent of the test and hides away unimportant details of how the system is being tested.

For example, consider a system to process orders. Orders are sent into our system and processed asynchronously. To perform an end-to-end system test, the test must must create an order, send the order to our system and track the processing of the order by waiting for correlated events to appear on the system's monitoring topic and driving the client through its user interface. That would look something like the following (where the requestSender and progressMonitor do lots of behind the scenes magic with JMS connections, sessions, message producers and consumers, message properties and correlation IDs).

@Test public void reportsTotalSalesOfOrderedProducts() {
    Order order1 = anOrder()
        .withLine("Deerstalker Hat", 1)
        .withLine("Tweed Cape", 1)
        .withCustomersReference(1234)
        .build();

    requestSender.send(order1);
    progressMonitor.waitForConfirmation(order1);
    progressMonitor.waitForCompletion(order1);

    Order order2 = anOrder()
        .withLine("Deerstalker Hat", 1)
        .withCustomersReference(5678)
        .build();

    requestSender.send(order2);
    progressMonitor.waitForConfirmation(order2);
    progressMonitor.waitForCompletion(order2);

    TotalSalesReport report = gui.openSalesReport();
    report.displaysTotalSalesFor("Deerstalker Hat", equalTo(2));
    report.displaysTotalSalesFor("Tweed Cape", equalTo(1));
}

It is tempting pull this duplication into a "helper" method that builds and uses an object. For example:

@Test public void reportsTotalSalesOfOrderedProducts() {
    submitOrderFor("Deerstalker Hat", "Tweed Cape");
    submitOrderFor("Deerstalker Hat");

    TotalSalesReport report = gui.openSalesReport();
    report.displaysTotalSalesFor("Deerstalker Hat", equalTo(2));
    report.displaysTotalSalesFor("Tweed Cape", equalTo(1));
}

void submitOrderFor(String ... products) {
    OrderBuilder orderBuilder = anOrder()
        .withCustomersReference(customersReference++);

    for (String product : products) {
        orderBuilder = orderBuilder.withLine(product, 1);
    }

    Order order = orderBuilder.build();
    
    requestSender.send(order);
    progressMonitor.waitForConfirmation(order);
    progressMonitor.waitForCompletion(order);
}

private int customersReference = 1;

However, this refactoring leaves us with the same difficulties that we encountered with the Object Mother when we have to vary data in different tests. We will need to submit orders with different properties and submit different kinds of events — orders, order amendments, order cancellations, etc. The helper method has the very same problems we found with the Object Mother, and that we avoided by using builders to create our test data.

void submitOrderFor(String ... products) { ... }
void submitOrderFor(String product, int count) { ... }
void submitOrderFor(String product, int count, String otherProduct, int otherCount) { ... }
void submitOrderFor(String product, double discount) { ... }
void submitOrderFor(String product, String giftVoucherCode) { ... }
... etc ...

Instead, we can pass an order builder to the method that sends an order into the system, just as we do when combining builders. That method can add properties through the builder before building the order sending it into the system.

@Test public void reportsTotalSalesOfOrderedProducts() {
    sendAndProcess(anOrder()
        .withLine("Deerstalker Hat", 1)
        .withLine("Tweed Cape", 1));
    sendAndProcess(anOrder()
        .withLine("Deerstalker Hat", 1));
    
    TotalSalesReport report = gui.openSalesReport();
    report.displaysTotalSalesFor("Deerstalker Hat", equalTo(2));
    report.displaysTotalSalesFor("Tweed Cape", equalTo(1));
}

void sendAndProcess(OrderBuilder orderDetails) {
    Order order = orderDetails
        .withDefaultCustomersReference(customersReference++)
        .build();
    
    requestSender.send(order);
    progressMonitor.waitForConfirmation(order);
    progressMonitor.waitForCompletion(order);
}

private int customersReference = 1;

Finally, a bit of judicious renaming can change the language of the test so that it communicates more about what behaviour is being tested than how the system implements that behaviour.

@Test public void reportsTotalSalesOfOrderedProducts() {
    havingReceived(anOrder()
        .withLine("Deerstalker Hat", 1)
        .withLine("Tweed Cape", 1));
    havingReceived(anOrder()
        .withLine("Deerstalker Hat", 1));
    
    TotalSalesReport report = gui.openSalesReport();
    report.displaysTotalSalesFor("Deerstalker Hat", equalTo(2));
    report.displaysTotalSalesFor("Tweed Cape", equalTo(1));
}

@Test public void takesAmendmentsIntoAccountWhenCalculatingTotalSales() {
    Customer theCustomer = aCustomer().build();

    havingReceived(anOrder().from(theCustomer)
        .withCustomerReference(10)
        .withLine("Deerstalker Hat", 1)
        .withLine("Tweed Cape", 1));
        
    havingReceived(anOrderAmendment().from(theCustomer)
        .withCustomerReference(10)
        .withLine("Deerstalker Hat", 2));

    TotalSalesReport report = gui.openSalesReport();
    report.displaysTotalSalesFor("Deerstalker Hat", equalTo(2));
    report.displaysTotalSalesFor("Tweed Cape", equalTo(1));
}

Test Data Builders are a foundation upon which we can define higher-level testing APIs that better communicates the intent of our tests in a language that is closer to that used by non-technical project stakeholders and so greatly help communication within the project.

Update: Thanks to David Peterson and Michael Hunger for helpful feedback. I've fixed typos in the test code and improved the test names. Hopefully the code is easier to follow now.

]]>
Test-Driven Design npryce 2007-12-21T08:30:00+00:00
Tricks with Test Data Builders: Emphase the Domain Model with Factory Methods http://nat.truemesh.com/archives/000727.html Construction of the 'gherkin' building

Tests that use Test Data Builders can be made less noisy by combining builders. This still leaves some noise in the test: the test code overly emphasises how the tests are building objects at the expense of what they are building. A future reader of the test will be far more interested in what objects are being used than in the way that those objects are constructed.

We can de-emphasise the builders further by instantiating them in clearly named factory methods:

Order order = 
    anOrder().fromCustomer(
          aCustomer().withAddress(
              anAddress().withNoPostcode())).build();

When we do this, the naming convention we've used for builder methods up to now gets in the way instead of making things clearer. The builder code looks better if we rename the methods to reflect the relationship between objects only, and not include the type of object at the far end of the relationship:

Order order = 
    anOrder().from(aCustomer().with(anAddress().withNoPostcode())).build();

This relies on Java's method overloading and so only works for properties that have unique, user-defined types. Longer method names are necessary for primitive types, or if the built object has different relationships with the same type of object. For example, most of the fields of an Address are Strings, and so the builder methods must be explicitly named after the field. However, the post code is strongly typed and so can be passed to an overloaded method:

Address aLongerAddress = anAddress()
    .withStreet("222b Baker Street")
    .withCity("London")
    .with(postCode("NW1", "3RX"))
    .build();
]]>
Test-Driven Design npryce 2007-12-16T18:21:00+00:00
Tricks with Test Data Builders: Combining Builders http://nat.truemesh.com/archives/000726.html Three Builders

If an object built with a Test Data Builder contains other objects built with other Test Data Builders, you can pass one builder to another to save keystrokes and reduce noise, making tests easier to read. For example, instead of:

Invoice invoice = new InvoiceBuilder()
    .withRecipient(new RecipientBuilder()
        .withAddress(new AddressBuilder()
            .withNoPostcode()
            .build())
        .build())
    .build();

You can write:

Invoice invoice = new InvoiceBuilder()
    .withRecipient(new RecipientBuilder()
        .withAddress(new AddressBuilder()
            .withNoPostcode())))
    .build();

The result is significantly easier to read.

]]>
npryce 2007-12-13T23:00:00+00:00
Tricks with Test Data Builders: Defining Common State http://nat.truemesh.com/archives/000724.html A builder with a plan

Using separate Test Data Builders to construct objects with common state leads to duplication and can make the test code harder to read and maintain. For example:

Invoice invoiceWith10PercentDiscount = new InvoiceBuilder()
    .withLine("Deerstalker Hat", new PoundsShillingsPence(0, 3, 10))
    .withLine("Tweed Cape", new PoundsShillingsPence(0, 4, 12))
    .withDiscount(0.10)
    .build();

Invoice invoiceWith25PercentDiscount = new InvoiceBuilder()
    .withLine("Deerstalker Hat", new PoundsShillingsPence(0, 3, 10))
    .withLine("Tweed Cape", new PoundsShillingsPence(0, 4, 12))
    .withDiscount(0.25)
    .build();

Instead, you can initialise a single builder with the common state and then repeatedly call its build method after defining values that apply only to the built objects:

InvoiceBuilder products = new InvoiceBuilder()
    .withLine("Deerstalker Hat", new PoundsShillingsPence(0, 3, 10))
    .withLine("Tweed Cape", new PoundsShillingsPence(0, 4, 12));

Invoice invoiceWith10PercentDiscount = products
    .withDiscount(0.10)
    .build();

Invoice invoiceWith25PercentDiscount = products
    .withDiscount(0.25)
    .build();

This can make tests much easier to read because there is less code and you can give the builder a descriptive name.

However, you have to be careful if the built objects need different fields to be initialised. Because the withXXX methods change the state of the shared builder, objects built later will be created with the same state as those created earlier unless it is explicitly overridden. For example, in the following code, the second invoice has both a discount and a gift voucher, which is not what the code appears to communicate at first glance.

InvoiceBuilder products = new InvoiceBuilder()
    .withLine("Deerstalker Hat", new PoundsShillingsPence(0, 3, 10))
    .withLine("Tweed Cape", new PoundsShillingsPence(0, 4, 12));

Invoice invoiceWithDiscount = products
    .withDiscount(0.10)
    .build();

Invoice invoiceWithGiftVoucher = products
    .withGiftVoucher("12345")
    .build();

A solution is to add a method or copy constructor to the builder that copies state from another builder:

InvoiceBuilder products = new InvoiceBuilder()
    .withLine("Deerstalker Hat", new PoundsShillingsPence(0, 3, 10))
    .withLine("Tweed Cape", new PoundsShillingsPence(0, 4, 12));

Invoice invoiceWithDiscount = new InvoiceBuilder(products)
    .withDiscount(0.10)
    .build();

Invoice invoiceWithGiftVoucher = new InvoiceBuilder(products)
    .withGiftVoucher("12345")
    .build();

Alternatively, you could add a factory method to the builder that returns a new builder with a copy of the builder's state:

InvoiceBuilder products = new InvoiceBuilder()
    .withLine("Deerstalker Hat", new PoundsShillingsPence(0, 3, 10))
    .withLine("Tweed Cape", new PoundsShillingsPence(0, 4, 12));

Invoice invoiceWithDiscount = products.but().withDiscount(0.10)
    .build();

Invoice invoiceWithGiftVoucher = products.but().withGiftVoucher("12345")
    .build();

The safest option is to make every with method create an entirely new copy of the builder instead of returning this.

]]>
Test-Driven Design npryce 2007-12-12T17:35:00+00:00
XTC has moved http://nat.truemesh.com/archives/000723.html XTC logo

For the last eight years or so, London's famous Extreme Tuesday Club (XTC) has been meeting every Tueday to share ideas about XP, "agile" software development, test-driven development and otherwise waffle philosophise about software development over fine ale and microwaved, puff-pastry pies (being in the UK, the beer is much better than the food).

The last few years, we have met in the Old Bank of England pub on the Strand. From now on we'll be in the Counting House pub on Cornhill, near Bank tube station.

Lots of great ideas and collaborations have spun out of the XTC, among them the XP Day family of grass-roots conferences, the mock objects technique and the jMock library for test-driven development of object-oriented code, the First International Conference on Postmodern Programming, the Jester mutation testing tool, the Extreme Lego workshop and other training games, and lots more.

An interesting aspect of XTC is that it is completely anarchic. There is no central organising committee. There is no formal membership. What happens is entirely up to whoever turns up and gets involved. This year we will be spending some of the income from XP Day on regularly hosting more formal presentations and rerunning the most popular sessions from XP Day to make them available to a wider audience. But for the rest of the time, the informal get-together style will prevail.

So, if you're interested in the future direction of software development techniques and practices, do please come along the Counting House and join in. The beer is the same but the pies are better, I've been told.

]]>
Agile Development npryce 2007-12-02T15:50:20+00:00
Designing an API to work with the IDE http://nat.truemesh.com/archives/000722.html In a recent blog post, Lou Franco describes how Microsoft's LINQ syntax is designed so that the Visual Studio IDE can easily autocomplete identifiers as the programmer writes queries. He asks:

The idea of language features being designed for the IDE leads to the question of whether API's should be designed for the IDE as well.

I think they should. Steve and I designed the jMock API to work well with IDEs. The chained method "Embedded DSL" API of jMock 1 was designed so that the IDE's autocompletion would act as a "wizard", guiding the programmer through the process of creating complex expectations. However, using strings for method names did not work so well with refactoring IDEs.

The new jMock 2 API works well with refactoring IDEs, but does not have as many chained methods and so is not quite as good at using autocompletion as an expectation wizard. It can also confuse some automatic code formatting tools. However, you can autocomplete on the names of mocked methods, which was not possible in jMock 1.

Like any design, an API must trade different constraints off against one another. Overall, I think, the jMock 2 API is an improvement and works better with features that are common in Java IDEs, if not yet in Microsoft's tools.

]]>
Design and Architecture npryce 2007-11-09T20:11:00+00:00
The XP Day Review Process http://nat.truemesh.com/archives/000719.html For the last few years XP Day has had an open review process. Anyone who submits a session also becomes a reviewer. Reviews are written on the website, are attributed and can be read by any other submitter/reviewer.

This year, this process had an interesting effect: people started reviewing sessions as soon as they appeared on the site, before the review phase started of the submission process started. This meant that the earlier a presenter submitted a proposal, the more time they had to improve it in response to the reviewers' feedback. Some really interesting sessions were invented on the website as reviewers and presenters bounced ideas back and forth.

Our review process accidentally stumbled onto an essential aspect of Agile software development: the earler you get feedback the more time you have to fix problems.

Maybe next year we shouldn't have a review phase at all. The submission deadline could be just before the meeting when the programme is put together. Presenters could submit as early (or as late) as they wished. The earlier they submitted the more feedback they would get, the more they could improve their submission, and the more they could be involved in the review process. The later they submitted the less feedback they would get but also the less reviews they would be able to write, which would count against their submission.

]]>
Agile Development npryce 2007-10-25T09:28:00+00:00
European XP Days http://nat.truemesh.com/archives/000718.html This year XP Day is bigger and better than ever before. There are now six (count 'em!) tracks of sessions, which has allowed the conference to both grow a little larger and have more focused sessions.

I will be running an introductory tutorial with Romilly Cocking and Steve Freeman on Test-Driven Development with JUnit and jMock 2. Although introductory, the tutorial will go beyond the basics and explain how use TDD to guide object-oriented design and how to recognise and avoid common misuses of TDD and mock objects.

I will also be at XP Day Benelux where I will be running a tutorial with Steve Freeman on "Sustainable Test Driven Development". This is a more advanced, hands-on, experiential tutorial that shows how to write tests that are easy to read and so clearly explain what a codebase does and why.

XP Day always sells out early, so if you want to attend you'd better book soon.

Update: XP Day London has now sold out. However, if you want to attend you can join our waiting list to be informed if a place becomes available.

]]>
Presentations npryce 2007-10-24T11:52:08+00:00
Test Data Builders: an alternative to the Object Mother pattern http://nat.truemesh.com/archives/000714.html The traditional view of a builder

If you are strict about your use of constructors and immutable value objects, constructing objects in a valid state can be a bit of a chore.

Usually in application code, such objects are constructed in few places and all the information required by the constructor is at hand, having been provided by user input, obtained from a database query or received in a message for example. In tests, on the other hand, you have to provide all those constructor arguments every time you want to create an object, whether to test its behaviour or to create a value to use as input to the code being tested.

Invoice invoice = new Invoice(
    new Recipient("Sherlock Holmes",
        new Address("222b Baker Street", 
                    "London", 
                    new PostCode("NW1", "3RX"))),
    new InvoiceLines(
        new InvoiceLine("Deerstalker Hat", 
            new PoundsShillingsPence(0, 3, 10)),
        new InvoiceLine("Tweed Cape", 
            new PoundsShillingsPence(0, 4, 12))));

The code to create all those objects makes tests messy and hard to read and fills the tests with lots of unnecessary information that has nothing to do with the behaviour being tested. It also makes tests brittle: changes to the constructor arguments or the structure of the objects will break many tests.

The Object Mother pattern is one attempt to avoid this problem. An Object Mother is a class that contains a number of (usually static) Factory Methods that create objects for use in tests. For example, we could create an Object Mother for invoices we want to use in tests:

Invoice invoice = TestInvoices.newDeerstalkerAndCapeInvoice();

An Object Mother helps keep tests readable by moving the code that creates new objects out of the tests themselves and giving clear names to the objects being constructed. It also helps maintain the test data by gathering the code that creates new objects together into the Object Mother class and allowing it to be reused between tests.

However, the Object Mother pattern does not cope at all well with variation in the test data. Every time programmers need some slightly different test data they add another factory method to the Object Mother.

Invoice invoice1 = TestInvoices.newDeerstalkerAndCapeAndSwordstickInvoice();
Invoice invoice2 = TestInvoices.newDeerstalkerAndBootsInvoice();
...

Over time, the Object Mother becomes bloated, messy and hard to maintain. Either programmers add new factory methods without refactoring, in which case the Object Mother becomes full of duplicated code, or programmers refactor diligently, in which case the Object Mother becomes full of many, many fine-grained methods that each contain little more than a single new statement.

A solution is to use the Builder Pattern. For each class you want to use in a test, create a Builder for that class that:

  1. Has an instance variable for each constructor parameter
  2. Initialises its instance variables to commonly used or safe values
  3. Has a `build` method that creates a new object using the values in its instance variables
  4. Has "chainable" public methods for overriding the values in its instance variables.

For example, a builder of Invoice objects might look like:

public class InvoiceBuilder {
    Recipient recipient = new RecipientBuilder().build();
    InvoiceLines lines = new InvoiceLines(new InvoiceLineBuilder().build());
    PoundsShillingsPence discount = PoundsShillingsPence.ZERO;

    public InvoiceBuilder withRecipient(Recipient recipient) {
        this.recipient = recipient;
        return this;
    }

    public InvoiceBuilder withInvoiceLines(InvoiceLines lines) {
        this.lines = lines;
        return this;
    }

    public InvoiceBuilder withDiscount(PoundsShillingsPence discount) {
        this.discount = discount;
        return this;
    }

    public Invoice build() {
        return new Invoice(recipient, lines, discount);
    }
}

Tests that don't care about the precise values in an Invoice can create one in a single line:

Invoice anInvoice = new InvoiceBuilder().build();

Tests that want to use specific values can define them inline without filling the test with unimportant details:

Invoice invoiceWithNoPostcode = new InvoiceBuilder()
    .withRecipient(new RecipientBuilder()
        .withAddress(new AddressBuilder()
            .withNoPostcode()
            .build())
        .build())
    .build();

I've used Builders for creating test data on a couple of projects now and I've found that, compared to Object Mothers, they make it much easier to create test data in-line in the test code without making tests brittle or creating lots of duplication. Tests are isolated from those aspects of the objects' structure that have no bearing on the test. For example, code that creates the invoice with no postcode needs to know that an invoice has a recipient, that has an address, that has a postcode, but has no further dependencies on the structure of invoices, recipients and addresses. You can add constructor arguments without breaking tests at all. Removing constructor arguments is easy as well with modern refactoring IDEs.

Another benefit is that the test code is easier to write and read because the parameters are clearly identified. Compare:

TestAddresses.newAddress(
    "Sherlock Holmes", 
    "222b Baker Street", 
    "London", 
    "NW1");

to:

new AddressBuilder()
    .withName("Sherlock Holmes")
    .withStreet("222b Baker Street")
    .withCity("London")
    .withPostCode("NW1", "3RX")
    .build();

Nothing in the first example will tell you that "London" has been accidentally passed as the second street line instead of the city name.

In some cases, Builders have so improved the code that they ended up being used in the production code as well.

Further techniques for using Test Data Builders:

Credits: builder picture from the Keep Scotland Beautiful campaign.

Update: thanks to Richard Hansen for pointing out a typo in the builder code, which is now fixed.

]]>
Test-Driven Design npryce 2007-08-27T18:36:00+00:00
Easy Java Bean Event Notification http://nat.truemesh.com/archives/000710.html Unlike C#, Java has no language support for event notification. Instead, Java classes usually follow a set of programming conventions, defined by the Java Beans framework, for defining notifications in terms of listener interfaces and methods for connecting and disconnecting event listeners and event sources.

In the Java Bean conventions, notifications are typed and grouped by "listener" interfaces. Each listener interface extends EventListener and defines a methods for each notification that is delivered through that interface. For example, the ContainerListener interface defines two notifications: componentAdded, announced when a component is added to the container, and componentRemoved, announced when a component is removed. Listener methods do not return results.

An object is declared as source of events of some type by implementing two methods, one to add a new listener to the event source and one to remove a listener from the event source. For example, a source of Sheep events would define the two methods:

  • void addSheepListener(SheepListener l) { ... }
  • void removeSheepListener(SheepListener l) { ... }

An object that wants to receive notifications must implement the listener interface that defines the notifications and then be added as a listener to the source of events. The source of events must maintain a collection of registered listeners. To announce an event it must call the appropriate notification method of all of the listeners that have been registered with it.

As you can see, writing a class that announces Java Bean events is not an insignificant effort. What is a one-line declaration in C# requires a lot of boilerplate code in Java. The Java Bean event conventions and Java's static type system do not make it easy to write notification code in a way that can be reused in many classes for different listener types. As a result, notification is not used as often as it could be in Java code. It is usually easier to pass a callback interface to an object's constructor than it is to define Java Bean events on the class.

The result is that classes are more tightly coupled than necessary. You must pass a listener to the constructor of the source of events even when there is no need to consume the notifications.

Worse, it becomes impossible to create the object and the listeners at different times and then connect them at a later time. This is a form of what I call "Temporal Coupling". The objects appear to be decoupled because they communicate through interfaces but there is an implicit, hidden coupling between the time at which the two objects can do things. In this case, the listener must exist before you create the source of events.

Luckily I have a trick up my sleeve. I have written a cunning class, Announcer, that uses the reflection API and Java 5 generics to implement the Java Bean event model for any listener interface. Although it still requires more than one-line, it makes it much easier to add Bean events to any class. Here's how it's used to make a class a source of Sheep events:

public class Sheep {
    private Announcer<SheepListener> sheepListeners = Announcer.to(SheepListener.class);
    
    ...

    public void addSheepListener(SheepListener  listener) {
        sheepListeners.addListener(listener);
    }

    public void removeSheepListener(SheepListener listener) {
        sheepListeners.removeListener(listener);
    }

    protected void announceSheepDipped() {
        sheepListeners.announce().sheepDipped(this);
    }

    protected void announceSheepSheared() {
        sheepListeners.announce().sheepSheared(this);
    }

    ...
}

Currently the Announcer class is sitting as an example in the jMock project. It's only one class (and a unit test), so I don't think it's worth giving it its own project and JAR file. I usually just copy it into whatever project I'm writing and move it into one of the project's packages. Feel free to do the same.

]]>
Design and Architecture npryce 2007-08-13T13:38:39+00:00
A Little Java 5 Idiom http://nat.truemesh.com/archives/000708.html In Java 5, an application's main function can be declared with varargs parameters instead of an array of Strings. For example:

public class Main {
    public static void main(String... args) {
        for (String arg : args) System.out.println(arg);
    }
}

Not a particularly astounding revelation: under the hood, varargs parameters are passed to the function as an array so the JVM sees no difference between a varargs main function and one declared to take a String array. However, it's easier to call a varargs main function from other Java code – in end-to-end tests for instance – and the resulting code is easier to read. For example:

private void runProgram() {
    Main.main("hello", "world");
}

instead of

private void runProgram() {
    Main.main(new String[]{"hello", "world"});
}

Because of this I've started declaring all my main functions with varargs parameters.

]]>
Design and Architecture npryce 2007-08-03T08:02:15+00:00