Convert guard clauses to value objects

Consider this method which registers a visitor to an event.

public class Event {
    public void registerVisitor(String name, String phoneNumber) {
        if (name == null || name.trim().isEmpty()) 
             throw new IllegalArgumentException("Name was empty");
        if (!PHONE_NUMBER_PATTERN.matcher(phoneNumber).matches())
             throw new IllegalArgumentException("Number invalid");
        // Do actual registration...
    }
}

As a good member of society, it uses guard clauses to verify its pre conditions, because:

  • It protects the method from sloppy callers.
  • It communicates what we expect and makes for a crude form of documenting pre conditions.
  • It helps us discovering bugs early and makes sure we do not fill our events with bogus visitors.
  • In fact, even security may depend on this, as we can use guard clauses to protect us from various forms of injection attacks.

That’s all good.

Duplication is the root of all evil

At least everything would have been good if the above example would have been the only place were we had to use these guard clauses. But of course, there are other methods through which these name and phoneNumber values pass. Each of these other methods also want to verify their pre conditions and make sure they are properly called. The solution? Simple, we add guard clauses to these methods as well!

That’s were things start to go south.

Rather quickly, we live in a soup of guard clauses as we duplicate them over and over again.

Well, we’ve got a solution for that, don’t we? After all, we know the DRY principle and have even memorized the Extract Method short cut. We’ll simply extract each guard clause to a separate method and reuse these methods where they are needed. (And we’ll just put them in that “util” class which we’ve got laying around anyway.) Problem solved!

public class Event {
    public void registerVisitor(String name, String phoneNumber) {
        Util.verifyNameNotEmpty(name);
        Util.verifyPhoneNumberIsValid(phoneNumber);
        // Do actual registration...
    }
}
public class Util {
    // Remember to use these wherever names or phone numbers
    // needs to be validated!
    public static void verifyNameNotEmpty(String name) {
        if (name == null || name.trim().isEmpty()) 
            throw new IllegalArgumentException("Name was empty");
    }
    public static void verifyPhoneNumberIsValid(String phoneNumber) {
        if (!PHONE_NUMBER_PATTERN.matcher(phoneNumber).matches())
             throw new IllegalArgumentException("Number invalid");
    }
}

Problem solved? Well, not quite.

Sure, we got rid of some of the duplication – but not all. We still have to invoke these guard clause methods. So we still have the validation spread out everywhere. And that is assuming we remember to add them at all! Subtle security bugs may arise because we forgot to add a single guard clause in a single place.

That’s not very good.

Thankfully, we can do much better.

Understanding the problem

To get there, we’ll start by thinking about the code that we are duplicating. Why do we have to put the “name not empty” guard clause all over the place? What does the places where we add it have in common? The answer is quite simple; they all have a name parameter.

The pain we’re feeling is actually a symptom of that we’ve separated logic from data. Because after all, where would be a more obvious place for the name validation logic than together with the name?

Unfortunately, the name is currently just floating around anonymously in a String, so we cannot move the method to the data. (The static guard methods are a sign of that.) But we can solve that!

Value objects to the rescue

The solution is to introduce a value object Name which can hold both the data and the validation logic (and the same for PhoneNumber). It would look like this.

public class Event {
    public void registerVisitor(Name name, PhoneNumber phoneNumber) {
        // Do actual registration...
    }
}
public class Name {
    public Name(String name) {
        if (name == null || name.trim().isEmpty()) 
            throw new IllegalArgumentException("Name was empty");
        this.name = name;
    }
    //...
}
public class PhoneNumber {
    public PhoneNumber(String phoneNumber) {
        if (!PHONE_NUMBER_PATTERN.matcher(phoneNumber).matches())
             throw new IllegalArgumentException("Number invalid");
        this.phoneNumber = phoneNumber;
    }
    //...
}

Now we’re in a much better place!

  • The registerVisitor() method reads much cleaner. It is absolutely clear what the indata is, and we can go straight to understanding the actual domain logic without being distracted by guard clauses.
  • Each guard clause has a single place to call home. It no longer needs to be spread out all over the system, nor does it have to live in some “util” class. It can live together with its data, as it should.
    • This point becomes even more important if the validation logic is more complex than in this rather simple example.
  • You do not have to remember validating the incoming data. You know that the data you get is sound. Save for the use of black magic (reflection), it is simply impossible to create a Name or PhoneNumber object in an invalid state.
  • The new value objects are excellent places to put any logic regarding these concepts that might show up in the future.
    • And for “usual suspects” such as toString(), equals(), hashCode(), and compare().
  • You can control whether and in what ways the object can be mutated. In this case, we used an already immutable String, but in other scenarios the underlying data structure may very well be mutable.
  • We’ve made previously implicit concepts explicit. No longer is the meaning of “name” and “phone number” some fuzzy things that we all think we share common definitions of. Instead, they are explicitly defined concepts, clear and self-validating.

The only possible drawback I can think of is generating more objects which might occupy more memory. However, for every case where you haven’t got a profiler in front of me telling me it’s a real world problem that particular situation, I’ll argue it’s worth it.

What do you say?

Thanks to Daniel Deogun whose talk on writing secure code triggered the writing of this post.

How to write robust tests

Many unit tests are  brittle. As soon as the code is changed, the test breaks and has to be changed too. We don’t want that. We want robust tests.

A robust test is a test which does not have to change when the code it is testing is changed as long the change preserves the intended functionality.

A robust test does not break when the code is refactored. You don’t have to remove or change a robust unit test when you fix a bug. You just add a new one to cover the bug.

If you want to start writing more robust tests, here are a few things you can consider.

  • Test on a slightly higher level. Tests on a lower level often have to be removed or rewritten completely because there is much volatility in low-level class design. They require more significant changes when a large refactoring comes around, while higher-level classes tend to get by with smaller changes.
  • Choose which classes to test. Not every class needs its own test class. Especially, consider not writing separate tests for small private helper classes which are tightly coupled with a larger public class. If a certain class is very complex, selectively target that class with tests even though you don’t give its less complex sibling classes the same treatment.
  • Don’t fake or mock too much. Tests that fake or mock too much become less robust because they know too much about how the unit performs its work. If the unit finds another way to do the same work, the test will fail.
  • Focus on the important functionality. A robust test verifies functionality rather than implementation. It is focused on the parts of the unit’s interface which are truly important while it ignores the parts of the unit’s interface (or internals!) that should be allowed to change. Put differently, it knows the difference between “intentional” and “accidental” functionality.
  • Test in the language of the domain. By expressing your tests in the language of the domain, i.e. using concepts relevant to your business or application, you naturally create tests which depends on the wanted functionality, but not on too many implementation details.

Robust tests lead to “functionality unit” pattern

All of these guidelines together favor a certain type of design pattern. We can call it “functionality unit”. It means that any piece of (non-trivial) low level functionality is performed by a primary class, optionally supported by a few secondary helper classes. The primary class is often the only publicly visible one and acts as a façade for the functionality performed by the secondary classes. The tests focus their efforts on the primary class and seldom tests the helper classes individually, unless there is a special reason such as high algorithmic complexity. They are expressed in the language of the business functionality the primary class is supposed to perform.

Designing and testing in this way makes robust unit tests possible because it:

  • Focuses on a level low enough to unit test effectively while high enough to be reasonably stable.
  • Doesn’t require mocking since unit tests see the helper classes as internals of the primary class.
  • Focuses on functionality performed by the primary class rather than the secondary ones.
  • Creates tests which “make sense” because they are expressed in domain language.

Let us look at an example

In this example the functionality in question is to parse a certain type of document. We have a primary class Parser which is quite big. It has over 1000 lines of code and is rather hard to understand so we decide to split it up. The good part is that it is well unit tested with multiple test classes testing from different angles. To make the code clearer we figure out that extracting the two secondary classes Foo and Bar would be a good idea. It looks like this.

Depending on how you structure your test, they may be more or less robust.

Depending on how you structure your test, they may be more or less robust.

The question then becomes, what do we do with the tests?

First, we should note that the existing tests help us making the refactoring safely. They will (hopefully) break if we actually change the functionality of the Parser class. But what about after the refactoring? Should we keep the tests as they are or should we split them up into separate unit tests for each class? As always, the answer is “it depends”.

The alternative to the left represents keeping the tests more or less as they are. We save time by reusing existing tests. We test in the language of the domain. We avoid mocking because ParserTest doesn’t try to isolate Parser from Foo or Bar. To the right we have the other alternative where we rewrite most of the tests to test each individual class. This also has benefits. We follow the very straight-forward and intuitive pattern of having one test class per implementation class. Problems in the Foo or Bar classes might be even simpler to find with focused tests.

However, regarding robustness, we can ask one very important question. In which of the two alternatives would the tests survive a major implementation code refactoring? Say that we merge Bar back into Parser, or split Foo into Apple and Banana. Such a scenario would require much work with the tests in the right-hand alternative, while most likely none at all in the left-hand alternative. This is a major strength of the left-hand alternative, as well as the “functionality unit” pattern outlined above. By sometimes viewing a small group of highly related classes as a a unit rather than an individual class, we get more robust tests.

Moving logic and data together [example]

I’ve talked about extracting logic and moving it elsewhere and I want to give an example of how doing so can improve the code. By necessity it is a rather short example, but hopefully the idea will be clear.

Lets say we have a method called activateContract() which will activate something called a Contract for a User. Understanding exactly how it works is not necessary for this example, but the code is complex enough that we have decided it deserves its own class. The method we’re going to work with at looks like this.

public void activateContract(Contract contract, User user) {
    int requiredStreamCount = 0;
    for (Service service : contract.getServices()) {
        if (service.isEnabled()) {
            requiredStreamCount += service.getRequiredStreamCount();
        }
    }
    if (requiredStreamCount > user.getAvailableStreamCount()) {
        throw new ActivationFailedException();
    }
    // Perform actual activation...
}

Let’s go through this code.

It seems that it is a method to activate a contract for a user. Before it starts with the actual activation (which I’ve ignored here), it seems to verify something which has to do with counting streams. It is not required to know what that means, but by looking at the code we can figure out that there are there is a contract to be activated for some user, that contracts consists of services, that services require a number of streams, and that the intent of the first few lines is to ensure the user has enough streams to cover all services on the contract to be activated.

The problems

However, there are some problems with this code.

  1. The purpose of the code is not immediately clear. The unfamiliar reader will have to look through the code in some detail to understand what the purpose of the code is. The code is not expressed in concepts relevant to activating a contract, but is focused on implementation details such as iterating and summing. In this example, the code is quite clear and it doesn’t take too long to figure out what the intent is, but it is easy to imagine a more complex example.
  2. Knowledge is spread out over the system. If any other programmer needs to perform this check, she gets no help and most likely ends up reimplementing this logic. With a bit of bad luck, she forgets to check if the services is “enabled” and thereby creates a bug.
  3. It is more procedural than than object oriented. The code does not make good use of object orientation and is very self centered – it is all “me”, “me”, “me”. “Give me the information I need so I can do what I want!” It would be much better of asking other objects to do some of the work for it.

Extracting method to clarify intent

So how can we improve this situation? Well, to fix the first problem and help clarify the intent of the code, we can create a separate method for the validation. We use the IDE’s refactoring Extract method to do the work for us. That would look like this.

public void activateContract(Contract contract, User user) {
    validateUserStreamCount(contract, user);
    // Perform actual activation...
}
private void validateUserStreamCount(Contract contract, User user) {
    int requiredStreamCount = 0;
    for (Service service : contract.getServices()) {
        if (service.isEnabled()) {
            requiredStreamCount += service.getRequiredStreamCount();
        }
    }
    if (requiredStreamCount > user.getAvailableStreamCount()) {
        throw new ActivationFailedException();
    }
}

That is better. Now we have moved unnecessary details about validation away from the method which is supposed to perform activation. The code is still is very procedural, and although we’ve taken one step towards a reusable method, we’re not quite there yet.

Extracting method again to prepare for reuse

So I keep looking for ways to split this code up. One thing that makes this method less than ideal for reuse is that it trows an exception – another class might want to handle the situation differently. Therefore I would like to get the logic of the method away from throwing the exception. I extract another method.

private void validateUserStreamCount(Contract contract, User user) {
    if (!canBeActivatedFor(contract, user)) {
        throw new ActivationFailedException();
    }
}
private boolean canBeActivatedFor(Contract contract, User user) {
    int requiredStreamCount = 0;
    for (Service service : contract.getServices()) {
        if (service.isEnabled()) {
            requiredStreamCount += service.getRequiredStreamCount();
        }
    }
    return requiredStreamCount <= user.getAvailableStreamCount();
}

The new method takes care of the calculation and comparison, while the old method still makes the decision about what to do when the validation fails. Because I prefer my methods to have positive (in the boolean sense) names, I switched the boolean logic in the comparisons and negated the result of the function.

That is definitely one step in the right direction. This method, if we made it public, could actually be reused by other classes. The current class might not be the best place for such a method however, and we still haven’t dealt with the procedural nature of the code.

Move method to where it belongs

What we could do and what is often done, is making canBeActivatedFor() static and moving it to some kind of utility class. This solves the second problem since it is now easily reusable. This is how we would do it in C or Basic. Such a utility method is not always very easy to find though, and it does not solve problem three as it is still not taking advantage of object orientation.

Thankfully, the fix is rather simple. If we look at canBeActivatedFor() we see that it mostly deals with information related to Contract. In fact, it does not have anything to do with the class it currently lives in. Therefore, the most natural suggestion is to move it to Contract. Most IDEs have a Move method refactoring for this.

public void activateContract(Contract contract, User user) {
    validateUserStreamCount(contract, user);
    // Perform actual activation...
}
private void validateUserStreamCount(Contract contract, User user) {
    if (!contract.canBeActivatedFor(user)) {
        throw new ActivationFailedException();
    }
}
public class Contract {
    // ...
    public boolean canBeActivatedFor(User user) {
        int requiredStreamCount = 0;
        for (Service service : getServices()) {
            if (service.isEnabled()) {
                requiredStreamCount += service.getRequiredStreamCount();
            }
        }
        return requiredStreamCount <= user.getAvailableStreamCount();
    }
}

The result

Finally! The code is starting to look quite nice!

Depending on how the rest of the code looks, we might be able to deprecate or even remove the getServices() method. If we wanted, we could provide the canBeActivatedFor() with just the user’s “available stream count” instead of sending a User object. We could also further separate the counting from the comparison by extracting yet another method from canBeActivatedFor(), especially if that computation is needed elsewhere.

In any case, we have successfully dealt with the three problems identified with the original code and reached a number of benefits.

  • The code now reads much more clearly and the intent of the code is easy to understand.
  • The stream counting logic now lives where it conceptually belongs. It is simple to reuse if we need the it elsewhere. It is easy to discover since your IDE’s auto completion functionality will suggest it when you use a Contract object.
  • We are closer to coding in the language of the domain with method names that describe what they do, while the implementation details are hidden inside.
  • We make use of object oriented features and place logic and data together in smart objects.
  • Depending on the rest of the code, we might be able to completely hide the Services that are stored inside Contract.

There are more things that can be improved about the code above, but I definitely think we’ve moved in the right direction with the steps we’ve taken. Feel free to add comments on any suggestions or questions on the above.

Extract the logic (what’s left is glue)

 

Unit testing friendly code is code that has enough complexity and few dependencies. Therefore I would like to talk about a technique for massaging your code in that direction.

Separating logic from glue can make unit testing easier.Let’s say we have an important class with both high complexity and many dependencies. It is really in need of unit testing because of its complexity and importance, but is hard to isolate properly. Trying to unit test such a class typically leads to long tests that are hard to read and maintain, and that need a lot of complex set-up.

This is my “go to” method for handling this kind of situation.

  1. Extract the logic – move the pure, (mostly) dependency free code which performs the actual functionality of the system out into separate units. Unit test these new units as much as you want.
  2. What’s left is “glue” – the original code is now a “web” of dependencies that wire various units of logic together to perform what the user wants. Use integration or system tests to test this wiring.
  3. Improve the tests – write, modify, or delete tests as needed.

The result is code that follows a pattern that I call Logic+Glue.

Now, we will go through these steps in some more detail.

Extract logic

Of course, simply “extracting the logic” isn’t quite as simple as it sounds, most of the time. As a help, here is a general outline of the process I use to do it.

  1. Inline current methods into one large method. Do this within reason. If a method is recursive, or already dependency free, it might be better left alone.
  2. Extract local variables for all method calls. Each method return value should be assigned to a new variable. We do this in order to make it clear what data is actually used in our code.
  3. Treat any non-locally created data as dangerous. This includes constants, static fields, instance fields, parameters, as well as any object returned by a method call to such an object. These “dangerous” variable assignments are what will become the “glue”.
  4. Try to make all local variables final. The following steps will be much easier if variables are not reassigned. For the same reason, the method should have as few return points as possible.
  5. Extract blocks of logic into methods. Look at the code – whatever is not “dangerous” variable assignments is the actual logic. Look for for loops, if statements, blocks of non-dangerous local variable assignments, and so on. Such a block should not contain any of the “dangerous” variable declarations (but may use the variables!). Generally, we want as large blocks of code as possible that use as few variables as possible. Also, the more primitive (as in, using primitive data types) the interface is, the better. Use the “Extract Method” refactoring feature of your IDE to “preview” potential methods. Experiment, extract, inline, and extract again, until satisfied.
  6. Move methods of logic into new classes. Look at the newly created methods. They should now hopefully contain “meaty” logic but few or no references to class variables. If you realize, by looking at such a method that it would naturally fit in an existing class, move it there. Especially, see if it could fit in one of the parameter or instance variable types. Otherwise, create new classes and move a method, or a group of related methods, into it. Try to turn any static methods into non-static methods on the new class.
  7. Refactor and clean up. While doing the above steps, the code may get a bit messy. Now is the time to clean up the code you’ve extracted.

Feel free not to follow these steps if you feel you have a better way to do it, they are simply meant to be a help to get started.

What’s left is glue

Whatever code that is left in the class you started with becomes the glue. Ideally, this is now nothing but a bunch of the “dangerous” variable declarations and some calls to your newly extracted methods.

  • Refactor and clean up the glue code. Feel free to inline some of the variables or extract methods if it improves readability. The glue initially has the same interface as the old complex class. You can change this if you see room for improvements.

One way to verify how well we managed to extract the logic is by looking at the import statements of the glue class compared to the logic classes. Most of the import statements should be in the glue code, often from multiple different packages, whereas the logic classes should have rather short and homogeneous import sections.

Improve the tests

Finally, it is time to look at the tests. You have two primary strategies, which can be combined if wanted.

  • Write new tests. If you did this refactoring because the tests original tests were bad or non-existing, go ahead and write better ones for the newly extracted logic.
  • Keep the old tests. If the old tests worked well, you can choose to keep them since the glue is acting as a protecting layer between the logic and callers. They then become slightly higher-level unit tests where the “unit” now is a group of classes rather than a single class.

By doing this kind of extraction, you’ve moved your code base one step closer to a more testable code base. (Most likely, more in line with fundamental object oriented principles as well.)

How unit testing changes your design

Lots of developers feel that unit tests are not only hard to write, but also are more of a hinder than a help when working with the code.

I think this comes largely from having code which is not “suitable” for unit testing, or put differently, that unit testing is not suitable for that code base. To get the promised value out of unit tests I think it helps to look at how unit testing effects the implementation code.

In my experience, whether some code is suitable for unit testing or not depends largely on two factors.

  • Does it have enough complexity so it is worth writing unit tests for?
  • Does it have few dependencies so that isolating it under test is simple?

While there are other factors that affect testability, I’ve found these to be the most important.

Enough complexity

The first major factor for testability deals with “is this code complex enough to need a test?” Not every line of code, every method, or even every class needs a separate unit test! This is, quite eloquently, summarized by Kent Beck, father of Test-Driven Development and JUnit.

”I try not to have more tests than I need.”
– Kent Beck

The typical example is a “getter”, a method which does nothing but returning a value of a variable. Does it need a separate test? I would say “no”. There are two primary reasons for this, in my mind.

  1. It is too simple to reasonably fail. In any case, the extremely occasional failure because of an invalid getter will most likely cost us much less than writing and maintaining unit tests for all getters.
  2. Other tests will cover that code. A getter rarely exists for itself. It is merely a method for some object to get information from another one. That information is then used for some computation or other purpose. The tests for that other code will test the getter “for free”.

Somewhat tongue-in-cheek, unit testing is like a grilling meat. There is no point in putting a bone without meat on the grill. (On the flip side, if you put too much meat on a weak grill, it won’t get properly done.)

If you develop using Test-Driven Development, you get this for free. Unless the getter is a major feature of your system, you probably won’t write code to tests that getter. You won’t do it because having that getter does not “drive” the design of the system, it is just an implementation detail.

Finally, it is not okay to keep a test for something that can’t reasonably break “just because”. It still takes time to maintain. If it doesn’t provide any real value, remove it!

Few dependencies

The second major factor for testability is about having few dependencies. It is so obvious it is often missed – the fewer dependencies, the easier to test.

As I said, it is really obvious. After all, the purpose of unit testing is testing a single unit. While doing so, we try to isolate that unit as much as possible. We want to test that unit, not the other next to it. This has lead to a big rise in the use of mocking frameworks such as Mockito and EasyMock.

But as I also said, it is so obvious that the real point is often missed. While we can fake dependencies during testing with frameworks, the best way to make isolating a unit easier is to reduce the number of dependencies it actually has! It doesn’t take a Mensa membership to figure that out, but for some reason (us being engineers, not philosophers) we forge ahead and try to solve the problem with clever tools without realising that we are solving the wrong problem.

Interestingly enough, fewer dependencies also means easier to reuse. Code with fewer dependencies is less tightly coupled to the specific application code, and instead deals with more general concepts in the model.

Implications on design

These two principles actually has some fundamental implications on the design of the code.

The classes in two code bases in which unit testing will be easy and hard, respectively, plotted on a graph with axes for “Number of dependencies” and “Code complexity” would look like this.

A graph displaying two possible code bases that are more or less easy to test.
Two possible code bases that are more or less easy to test.

As for the design and testing of a system, we see two clear trends.

  • Most complexity is in classes with few dependencies. Unit test this code as much as you want. Writing tests is easy because each unit is well isolated.
  • Most dependencies are in classes with low complexity. Test setup is hard for these classes. Consider not unit test these classes at all, instead focusing on automated integration tests.

Now I know that much (perhaps most) code doesn’t look this way. There is plenty of code which mixes complexity and dependencies. I believe this is unfortunate as it complicates unit testing and generally is harder to understand and work with. I think the two statements above are worth striving for. That will help a team to get true value out of their unit tests.

What, how, and why?

When I develop code, I find it helps to use the following rule of thumb:

What? Signature of the method
How? Body of the method
Why? Signature of the caller

That is, what a method does should be expressed clearly by its name or signature. The details of how this is done should be hidden inside the method’s body. Finally, the reason why the method was called should be given by looking at the caller.

What and how – information hiding

The perhaps most common mistake is to mix up the what and how. Common examples of this includes:

  • Throwing a low-level or vendor-specific exception from a high-level class, such as an SQLException from an entity manager or repository.
  • Unnecessarily returning a concrete implementation of an interface, e.g. ArrayList instead of List.
  • Excessive use of getters and setters, allowing the caller to “directly” modify the object, rather than providing methods to perform whatever the clients actually need.

This basically comes down to the principle of information hiding. In the above examples, the implementer has failed to hide implementation details from the caller and as a result it will be harder to change these methods’ implementation without also changing their signatures or callers.

What and why – reusability

Another common, although perhaps less so, problem is mixing what and why. I don’t think neither the method’s name nor body, should say attempt to answer the question why. That is, neither should not contain a reason, purpose, or justification for using it.

An example here is that we typically do not have separate classes named PersonList and CompanyList doing the same things with different kinds of data, but instead just a List<T>. Instead, it is up to each caller what the list is used for. (Unless of course a “person list” is an important concept in your domain, in which case it might be perfectly fine to have its own class.)

Letting a method specify why it should be called needlessly limits the applicability of the method and makes it less reusable. Different callers may use the method for different purposes (within reason) and that is perfectly fine. A method should just perform an action and let the caller worry about the reason for doing so.

A great example of the what and why separation, is the stack trace. Looking at a stack trace should in theory allow one to completely understand what is happening in a system. We know what was supposed to happen by looking at the currently executing method’s name and the exception. By then following the names on the stack all the way back to the root, a good stack trace allows us to understand why each step in the chain was taken. This actually applies to every level of the stack trace.