Tag: refactoring

Presenting interface-it

I’m proud to introduce to you a new tool I created. It’s called interface-it, and it’s an open source project hosted on Github designed to help Java developers to create better test fixtures and to refactor procedural code more easily. More specifically, it’s designed to replace the use of static imports by the use of “mixin” interfaces.

What’s a “mixin”?

A mixin is basically a special kind of class which allows multiple inheritance without potential for unresolvable ambiguity or cycles in the inheritance hierarchy. It provides not just inheritance of the type but also of the implementation. Another word for “mixin”, used in the Scala language, is “trait”.

Before version 8, Java did not allow mixins, but now in Java 8 you can create an interface with default method implementations. Oracle does not especially encourage the use of default method implementations in interfaces – it’s a feature which was added in order to retrofit existing API’s with lambdas (as explained here). However, default methods can be quite useful in certain specific cases.

What’s wrong with static imports?

The site javapractices.com encourages us to “use static imports rarely” because they can make the code more difficult to understand. I’ve even worked in a team which had IDE settings to forbid the use of static imports. When you read code, it’s nice to know whether a method call is defined in the calling class or in another class, and whether it’s a static method or non-static. Static imports hide this information.

Use cases for interface-it

  • Test fixtures

There are tools like Mockito and AssertJ which encourage the use of many static calls in unit test code. You can either use static imports for these and hope your IDE’s auto-completion is up to the task of dealing with them. Or you can wrap the classes with these static methods using interface-it to create mixins used by your test class. In that case, you have no need for a static import (instead you have “class MyTestClass implements Mockito, AssertJ”), and you call methods of these tests tools as though they belong to your test class, because they do belong to it.

Before Java 8, to build a complex test fixture, you needed to create a superclass with all the functionality you might need in your tests, or a hierarchy of fixture classes with added layers of functionality in each subclass. In Java 8 you can use mixins to separate out different functionalities needed for different types of tests, and you can pick and choose which ones each test class needs to implement. Maybe some tests need to implement AssertJ but not Mockito, for example.

The interface-it tool can be used to create mixins for test fixture classes. You can also just copy and paste the example source code for Mockito and/or AssertJ generated by interface-it.

For interface-it’s own test fixtures, I’ve been “eating my own dog food”, so you can see an example of this in the DelegateMethodGeneratorTest class, which “implements AssertJ, Mockito, JUnitAssert” (note that I had to resolve a name conflict between AssertJ and JUnit – the method fail() –  by overriding one of the mixin methods – not a big deal in this case, but I also could have chosen to rename one of the fail() methods in the mixin source code if I had needed to call both methods).

  • Refactoring procedural legacy code

Static methods are not object-oriented. A static call enforces tight coupling, which constrains your design. You can replace an object by another object without modifying the code that uses the object, but a static call links one class to another which can not be replaced (note that some tools like Powermock can use some class loading voodoo to allow you to replace a static call in a test, but that does not fix the inherent design flaw).

In test fixtures, some procedural code is okay, because the tests are generally not reusable objects. Common functionality of different tests can be factored up, but unit tests are largely procedural in nature : setup (“given”), followed by invocation of the unit under test (“when”), followed by validation of results and post-conditions (“then”).

In production code, it’s better to avoid procedural code apart from some factory functionality (where you construct the graph of objects). There’s a lot of legacy production code in the world where a static method is called many times in many different classes. In this case, it’s quite painful to get rid of all these calls at once. Following the Boy Scout Rule, if you need to add one of these calls in the code that you’re working on, or if you are refactoring a class which makes procedural static calls, consider using interface-it to create a mixin which you can use to replace the static call in one place at a time. It’s also useful if you need to write a unit test before doing a more complete refactoring, because the mixin can be mocked in a test. In production code, you don’t necessarily have to have your legacy class implement the mixin as in the test fixture use case. You can simply treat the mixin as the interface of a collaborating object and pass it into the constructor or into specific methods where it’s needed. Where you need to instantiate it in production code, you can create an anonymous subclass, as in “new MyMixin() {}”.

Example usage in refactoring of legacy code:

Imagine we have a supply system which makes online credit card purchases automatically, and the call which does this is a static procedural call.  We want to add flexibility to the design and add unit tests so we can more easily manage code quality and refactorings, but we have these unavoidable static calls everywhere.  We have to start somewhere, so let’s fix SupplyMonitor‘s trackAndProcurePencils() method which checks the inventory of pencils against the number of employees and buys new pencils accordingly:

public void trackAndProcurePencils() {
    int targetPencilCount = this.currentEmployeeCount * TARGET_PENCILS_PER_EMPLOYEE;
    int currentPencilCount = inventory.getItemCount(PENCIL_ITEM_CODE);
    if (currentPencilCount < targetPencilCount) {
        SupplySystem.buy(new PurchaseOrder(PENCIL_ITEM_CODE, targetPencilCount -                  
            currentPencilCount), new CreditCard(CREDIT_CARD_NUMBER));
    }
}

So let’s write a unit test:

@Test
public void should_order_pencils_when_undersupplied() {
    Mockito.when(inventory.getItemCount(SupplyMonitor.PENCIL_ITEM_CODE)).thenReturn(120);
    underTest.trackAndProcurePencils();
    // Oh, dear. Not only to I have no way to test what happened inside the
    // method under test, but I think I just bought 280 pencils with my credit card!!!!
}

Better not commit that – it could get expensive.

We’re going to fix this by generating a wrapper interface which delegates to SupplySystem. In a Windows command-line we type:

C:\dev\eclipsews>java -cp SupplyProject\bin;interface-it\target\interface-it-0.7.0.jar org.interfaceit.ui.commandline.CommandLineMain -n SupplySystemWrapper -c org.legacy.SupplySystem -p org.legacy -d Katas\src\org\legacy -s SupplyProject\src\org\legacy\SupplySystem.java

…and see:

Wrote file: C:\dev\eclipsews\SupplyProject\src\org\legacy\SupplySystemWrapper.java

Now we have our generated wrapper interface. We update the test to look like this:

@Test
public void should_order_pencils_when_undersupplied() {
    Mockito.when(inventory.getItemCount(SupplyMonitor.PENCIL_ITEM_CODE)).thenReturn(120);
    underTest.trackAndProcurePencils();
    Mockito.verify(supplySystem).buy(Mockito.argThat(orderMatcher ), Mockito.any());
}

Note that we could also use interface-it to get rid of the “Mockito.” references in the test code (as previously demonstrated), but it’s better to focus one issue at a time.

Here are links to more complete code for the examples: before refactoring and after refactoring. The generated wrapper interface code can be found here.

Conclusion:

So that’s what interface-it can do for now.  I’ve already started work on improving usability by creating a custom Ant task that manages the generation and update of wrapper interfaces.  Since the jar is available on the Central Repository, anyone with Maven, Gradle or Ivy can easily pull the jar to create their own custom usability solution. If you’re looking for a project, you could use the interface-it jar to create a plugin for your favorite IDE (please leave a comment if you plan to do something like that). You can code whatever UI you want using the ClassCodeGenerator API, specifically by using an instance of DelegateMethodGenerator.