Test it, for documentation sake!

By Conrad Hesse

One of the challenges of software development is to have up-to-date documentation of the system design. Knowing how your software works and having this knowledge in a concise and presentable form is crucial. It enables you to communicate on your current situation, about your planned changes, about your problems … and it allows you to pass this knowledge on to new team members. Unfortunately, system documentation is one of the most neglected topics in the enterprise software world.

Why this?

The general view of developers and architects is that there is no value in documentation, since it never reflects the current state of the software. Keeping the documentation current is way too expensive, perhaps even impossible. Therefore, the common reasoning is that working on documentation is a waste of time and energy.

Based on this real life experience, the agile community derived some key points when it comes to documentation. The most outstanding are:

  • document late
  • document only stable things
  • document lean and sufficient, just barely good enough

Those points have a common goal: to reduce the costs by minimizing documentation or avoiding it when things are in flux. But is this really the right way to tackle the problem?

The point is about communication

The whole point in documentation is communication. So what are the odds that you need to communicate about something that probably won’t change anymore? Actually, what are the chances that some part of the system won’t change anymore anyhow? My guess is that the answer to both questions is: not very high.

Instead of focusing on documentation that is irrelevant, we should be focusing on creating documentation that supports us in our daily communication. It should be helping us during the development process and the associated costs should be minimal.

The basic idea

I have been tinkering around with the following idea:
I always found that unit tests are a great way to understand how a class should be used and how it works. Why not extend this concept and create high-level tests specifically for documenting the system design? Since those tests are part of the code they share all the benefits of the regular development process: they can be changed and refactored along with the system so they always reflect the current state. But the best part of this is: since they are runnable tests, they can be used to record runtime information and display it in a presentable form like a sequence or class diagram.

Based on this idea, I created a simple prototype. Let me show you how it works:

Suppose we are building a new online auction system. The system has auction engine class that enable users to place their bids. Lets assume that we have a JUnit test in place for the auction engine:


public class AuctionEngineTest {
@Test
public void placeSucessfulBidTest() {
AuctionEngine auctionEngine = new AuctionEngine();
BidData bid = new BidData(auctionId, userId, maxBid);
BidResult bidResult = auctionEngine.placeBid(bid);
assertEquals(BidResult.OK, bidResult);
}
}

Now this is a nice test that runs a very important part of our application. It probably is the typical example for the code that you want to have a good overview about what is going on.

Binding documentation to the test

We have our integration test in place. What we do now is to add an annotation that enables the appropriate tracking of the test along with some JavaDoc:


/**
* This test shows the basic flow when placing a successful bid. Notice that before the transaction is started a quick sanity
* check is perfomed.
*
* {@sequence}
*/
@Test
@Track(classes="com.auctions.*")
public void placeSucessfulBidTest() ...

When we run this test the @Track annotation is evaluated and a “flight recording” is started. When the test is done the recorded data is dumped to a file. Afterwards, a custom doclet is used to create the HTML JavaDoc along with the sequence diagram of the test. The result looks like this:

And there you go: a documentation of your system design that stays current with your code as long as you keep your tests running.

The Dark Side of Modern Test Frameworks

By Conrad Hesse

How can you tell that your software is in bad shape? How do you know that your system architecture is in desperate need for a refactoring session? Sure enough, there are lot of indicators, metrics and tools you can use to get a better insight. Nevertheless, I think that there are two key aspects that are very common when things start to smell fishy: excessive dependencies between components and bad separation of concerns. Normally, the place were you will start noticing these problems is in your unit tests. It will become quite difficult to get your classes and all its dependencies in a testable state if you are solely relying on a traditional framework like JUnit. But if you are using a modern mock framework like EasyMock or jmockit, you can still write sensible tests with a reasonable amount of work. And this is supposed to be a good thing, right? Don’t be fooled: The quick and easy path leads to the dark side!

Lets look at a simple example at an imaginary flight booking web site written in Java. This application has a class “Itinerary” which holds a list of flights and has a method to calculate the total price of the itinerary:


public class Itinerary {
List flights;

public String calculatePrice(HttpServletRequest request) {
MyPrincipal user = (MyPrincipal)request.getUserPrincipal();

 if (user.isVIP()) {
// calculate Price for VIPs
}
if (request.getParameter("promotionCode") != null) {
// calculate Price with promotion code
}
...
}
}

Obviously, there are some bad things happening here. There is this nasty dependency on HttpServletRequest. And it is questionable if Itinerary should do price calculations. From the software design point of view it is desirable to refactor this class so that it is more focused on its real concerns. Now, if you start writing a JUnit test for calculatePrice(), you would automatically tend to do these refactorings right away since there is no other way to get the Itinerary class in a testable state. You would probably cut the HttpServletRequest parameter and push “principal” and “promotionCode” into calculatePrice(). Chances are that you would start thinking about creating a dedicated PriceCalculator class to house the price calculation logic. The process of writing a test is quite essential since it forces you to reflect about the usage of Itinerary: how easy is it for a developer to utilize its “services”? How can it be striped down to its core dependencies?

On the other hand, what would you do if you had access to Mockito? Probably you would end up with a test like this:


@Test
public void calculatePriceTest() {
HttpServletRequest req = mock(HttpServletRequest.class);
given(req.getParameter("promotionCode")).willReturn("123XYZ");

MyPrincipal principal = mock(MyPrincipal.class);
given(principal.isVIP()).willReturn(true);
given(req.getUserPrincipal()).willReturn(principal);

 String price = itinerary.calculatePrice(req);
assertEquals(price, "1024,24");
}

The biggest advantage of mocking frameworks is certainly that you are able to write a test for your crappy class without the need to do any refactorings. However, on the long run, it could hurt if the essential design problems are not addressed. Since there is no pressure to change anything, most developers choose to keep the code as it is. They don’t take the second step and clean up the class.

So don’t be seduced by the quick path – it might lead to the dark side!

Fair Play Teamwork

By Conrad Hesse

Ok, I’m going to come out straight with this one: What most people don’t realize is that teamwork only works good if it’s fair. And teamwork can only be fair if the performance of individual members are recognized. If you are a project manager and you want to get the best results from your team you should be paying attention to this.

As a developer you might know this situation: You work hard to produce good code and to meet the deadlines. But one of your colleagues doesn’t quite manage it … ever. So although he is a nice guy his professional skills are below average (to put it nicely). What happens? Well, because the team has to succeed, other team member start helping out by fixing, enhancing or cleaning up bits of his/her code whenever they stumble upon it. Or they simply start implementing part of his modules.

On the long run this kind of behaviour is bad. Management will probably fail to see that one member is not on par with the skills of the others. Poor work slips into the project. Other developers will start to feel bad about constantly doing the work of others for the project’s sake. And when the going gets tough this can doom the whole plan.

An opposite opinion about this is described in The Boy Scout Rule of 97 Things Every Programmer Should Know. The synopsis of this rule is:

What if we followed a similar rule in our code: “Always check a module in cleaner than when you checked it out.” No matter who the original author was, what if we always made some effort, no matter how small, to improve the module. What would be the result?

I have very mixed feelings about this. Actually, as a developer what I want is to be able to concentrate on my work without cleaning up the dirt that someone else left behind. And if I have the feeling that some part of the code needs an overhaul, I prefer that this is done in some kind of planed and communicated way. Playing “garbage collector” will not encourage others to produce clean code! Chances are you will think that teamwork is unfair.

Keeping track of the performance of individuals is a management task. Good managers will take appropriate action according to the findings. Strangely enough, this can actually be a real problem in many organisations.

Specification Killed The Innovation

By Conrad Hesse

This is how innovative and game changing ideas are not born:

Most companies think of their IT as being of strategic importance. So how does it come that this strip is reality for most of us working in the SW-business?

Now this is how it is supposed to be:

I think that the main reasoning behind this is that the specification document should not be used as a driving force in the development process, but as a mere way of documentation. The driving forces are the vision of the client and the ideas of the developer. Getting those together is a major management task of software projects. The developers in turn should structure and process the clients information and be creative. If your managers or developers can’t cut it you might just as well get this spec to an offshore software house.

Bring Them In!

By Conrad Hesse

In Germany it is quite common to work with independent contractors to get current IT projects done. Most of the time, they are hired on a project basis and help the company with the necessary man-power. They work on-site and get payed per time and materials.

I have been doing business in this kind of environment for 10 years now and I know that there are some good reasons to work with external developers from a management and accounting point of view. But I think that there are also some excellent “soft”-reasons to work with them that are just not mentioned very often.

So I will do it here now:

  1. They bring in new knowledge, ideas and ways of thinking and share this with the employees of the company.
  2. They are more free to talk about problems and things that are not working right.
  3. They don’t have any prejudice and in consequence they are perceived as being more impartial than the fellow co-worker.

So, independent contractor can bring in some “fresh blood” into the company and can kick off important changes. I think it is a great way to keep the company lean from the accounting perspective but agile and rich in knowledge. The company and its employees profit because they can adopt those qualities and continue to use them after the external contractors have left.

Now I think it is important to state that this works only if the contractor is on site and somehow fits into the culture of the company.  In this context it is interesting to note that some companies try to manage their costs and risks by contracts with fixed deliverables and fixed prices. While on a general basis I can understand the reasoning behind this, I think that IT companies shouldn’t be outsorcing their software development offsite and with basically no integration back into their core business. If you are in the process of making a decision like this you should ask yourself the following question: If this piece of software is part of my expertise, why is it better to let someone build it for me than to do it in house? If the aswer is that it is cheaper or faster to do it so, you should quickly start reviewing your assets before you go out of business.

Our new old software dinosaur

By Conrad Hesse

Everybody seems to be concerned about the complexity of software development these days. Despite our efforts to keep programming languages and frameworks simple we feel like everything is getting more and more complicated and difficult to understand.

There is an IDC study that says that in fact software is becoming more complex as a result of multicore processing, Web 2.0 and service oriented architectures (SOA) and the complexity is also driving up the original costs of development.

I must say that I feel somehow uncomfortable when I think about the future: All these big software systems written today using the latest and greatest buzzword-killer-technology and uber-framework-libraries… who will mantain them in say 5, 10 or 20 years? Will we be able to understand how they work after some time? If I look at the pace that technology evolves my bet is that these will be the COBOL mainframe nightmares of tomorrow – but without COBOLs simplicity.

So I was thinking: If you start a big project today and you are planing for this systems to last for the next decades … what is the best technology approach that you should take? Are there any golden rules so you don’t end up maintaining an unmaintainable/unexpendable codebase that no one ever will have the guts to replace with something new?

Hence, here they are, my 3 principles to ease the development of your future vintage system:

  1. Depend on the language and not on frameworks, libraries and tools
    Why: The language will be the last thing to change. Everything else will be out-dated by tomorrow.

    Looking into my last mid-sized Java Project, I see about 70 JAR files in my lib folder. And I am not countig all the other tools like the build, integration and testing systems. Now this is actually a wonderful thing, since nowadays you can build upon a myriad of functionality out of the box. The problem is, that most of this stuff will be utterly out-dated in the years to come, and no one will know what this was all about and how it is supposed to work – or work together. And your software is depending upon every single one of it.

    While I am not saying that you should custom build everything you need, I do think that for a long lasting system it will be better to avoid 3rd party software. Custom build libraries have the advantage that you only need to code what you really need and the way you need it. This eases complexity by avoiding general and overweight frameworks.

  2. Design for modularity and interface stability
    Why: Modular design allows you to replace part of your software with minimal impact on other parts.

    Lets face it: Inevitably you will get to a point where you will need to replace part of the software by something new. If you can do it without refactoring everything else you are in a good position to continuously update you system. And that’s exactly what you want.

    The key to a modular design is interface stability. The big question is: how do you keep your module interface stable while adding new features? There is no simple solution to this problem, but one recognized approach is to “freeze” your interface once it is published. The only way to change it is by extending it or by adding a new interface. Dependend modules will continue to work and you can gradually update them to use the new interface.

  3. Code extensive unit and integration Tests
    Why: They are your up to date system documentation.

    This is a very typical scenario: You have this old software running and all the developers who originally implemented it are gone! There is a system documentation laying around on some network drive, but it is inconsistent and out-dated. How does a new developer learn how the system works? Coded tests are an excellent way to document this. Chances are, that a developer can get into the software faster if he has some running sample (test) code. And the good news is: This documentation is always up to date as long as you keep your tests working.

Do you think that this will keep our new little software dinosaur happy?

A Word Of Warning

By Karl Banke

The one language facility that I really miss

I am programming professionally for more than ten years now. Nowadays, I call it design and architecture more often than not, but in regular intervals I need to hit the trenches of good old coding. I have been programming in Java almost since it hit the shelves. I watched it grow mature, and looked how a whole ecosystem grew around it.

The advance of Java5 and beyond saw a bunch of additions to the language that created much controversy. A lot of people still call autoboxing, annotations, variable argument lists etc. “syntactical sugar” and too some extent, I think they do have a point. But I don’t want to write about the feature of the language (or the runtime) that exists and that I would rather do away with. I instead want to point out a feature that I sorely miss in not only Java but most other programming languages I came across. I call it “A warning propagation method for the the Java Programming language”.

Why we need warnings

Warnings are required because of the very simple fact that in todays complicated computing systems things can slighty go wrong. A language like Java provides Exceptions of course, so your first guess might be, that a warning is not really a striking new feature as you have a facility to deal with problems. You might think, that warnings would be, well, really syntactical sugar. So let’s have a look at a – somewhat artificial – example. Consider a system that collects account data for a person from various financial institutions. A typical interface would look like this.

public interface AccountService {

public List getAccounts(Person person) throws AccountHandlingException;

}

The implementation of the getAccounts method would look something like this

public List getAccounts(Person person) throws AccountHandlingException {

Iterator banks;

while (bank.hasNext) {

Bank nextBank = banks.next();

try {

result.add(nextBank.getAccountsFor(person));

} catch (BankAccessException exc) {

// Now what do I do with you

}

}

}

So while we are retrieving the consolidated account list for John, something goes wrong querying the bank where John has his long term savings account. Clearly the list that we retrieved is still meaningful. It might be used, say, to do some checking transactions, to look into the account history and so on. But given the account list, it might be unwise to try and judge John’s credit rating.

So we end up with some meaningful data and the need to communicate to the caller that the data, while still meaningful, might have some problems attached to it. We might also want to apply some logic to our data without even considering that there is an error at that particular state. For example, we might compute an account grand total and apply some currency conversion to our result data. Clearly throwing an Exception from our catch block would break our functionality.

Another possible approach would be adding the desired functionality to the return types. So we might rewrite our code in the following form

public AccountList getAccounts(Person person) throws AccountHandlingException {

Iterator banks;

AccountList results;

while (bank.hasNext) {

Bank nextBank = banks.next();

try {

result.add(nextBank.getAccountsFor(person));

} catch (BankAccessException exc) {

result.addWarning(“Error reading accounts from bank ”+nextBank);

// Now what do I do with you

}

}

}

This most definitely works. We could use interfaces or abstract base classes for example AccountList extends WarningSupport. Yet we might still encounter problems when using third party classes that do not fit our desired inheritance hierarchy. True, using aspect technology and byte code manipulations we might be able to overcome the problem, but this does not look like a particularly simple or clean solution to me. Also there seems not to be to much flexibility in handling such errors.

A classic way of solving these problems is to pass around a context or to attach a context-like object to the current thread of execution. The problem with such solutions is again that they break at container boundaries and of course that there will most likely be problems with multi threaded executions. It is not easy to pass such a context through a remote method invocation. On the other hand, passing around a context clutters the method interfaces with plumbing code. Also passing a context around often results in pushing warnings down the call stack. This is usually not a good idea, since the called code should not be exposed to details from its callers where not desired.

As a syntactical idea, one could use the declarative syntax of exceptions for methods to declare warning types. Consider the following method declaration.

public List getAccounts(Person persons) throws AccessDeniedException
queues BankWarning

Such a declaration means that the method issues warnings of types BankWarning where BankWarning extends Warning, a base class for all warnings. Inside the method, the programmer can enqueue Warnings.

try {


} catch(BankAccessException exc) {
enqueue(new BankWarning(“Bank not accessible: ”+ exc.getBank() ));
}

Finally the calling code can handle the Warnings. Similar syntax checks than those for exceptions can be performed to ensure that there actually can be warnings of the unwind type on the call stack.

try {

} unwind (List warnings) {

// Do something with the warnings

}

With such a mechanisms you can care about warnings, yet you don’t have to. This is essentially analogous to the classical case of handling or ignoring the status code from a function call. It gives an easy paradigm of handling near-exceptional cases without artificially breaking the call stack. Because it is an integral piece of the programming language, it can be transparently handled across container boundaries.