October 31, 2014
A client came to us recently with a challenge. They wanted a working piece of software that could demonstrate modelling the year-on-year outcomes of complex financial contracts. Each contract contained various inter-related elements. There were various types of contract – the included elements varied from one to the other – but they all fell within the domain of oil exploration and production.
As the client revealed the nature of the contracts, the work started to look quite complex. For the demo version, we would have to model up to nine elements (including variants). The user would choose which elements to include when actually running the program, so each element may or may not appear in a contract, and may or may not be related to other included elements. This high density of dependencies made the potential for integration problems and cascading bugs quite high, but with enough time and a suitable test suite it seemed perfectly manageable.
“Oh, yes,” said the client, “and we need it in one week.”
The stark reality
Unfortunately that one-week deadline was immoveable, as the software was to be demoed at a conference. The challenge was therefore clear: we had to write rather a lot of complex code in a short time. We were obviously going to work in rapid prototyping mode, emphasising “getting it working” and forgetting about code quality and reusability.
By having two developers we could share the tasks and cut the development time, but that added an additional risk. While it was already a possibility that one developer would become bogged down by the complexity, having two developers would make that even more likely due to miscommunication and a lack of common understanding. Ending the week with a mass of indecipherable, non-working code was therefore a prominent probability.
We needed a strategy to prevent this.
Our strategy was two-pronged.
1. Use a design pattern.
The first thing we did was to choose a suitable design pattern. We settled on the visitor, a pattern which separates an algorithm’s structure from its implementation. Contract elements corresponded to elements in the pattern, and steps in the calculation corresponded to visitors. See the class diagram below for an example of how the price element is modelled.
This brought several advantages. First, it reduced the time spent on initial design almost to zero, a blessing for such a short schedule where every hour we could claw back was worth it. We chose a design we were already familiar with and then begin coding.
Second, the visitor pattern makes the addition of new elements easier because developers don’t need to consider the structure of the algorithm when adding new elements. They can simply add the new element to the existing structure without having to modify it. As a result, we could simply make a list of contract elements to be implemented and implement them one-by-one scrum-style.
Third, it is a maintainable approach, thanks mainly to the advantages inherent in the visitor design pattern.
2. Use code generation.
Everybody loves code completion. A couple of keystrokes… Ctrl+Space… BOOM! A whole line of code. Rinse and repeat, and before long you will have coded up a function in a fraction of the time.
The Eclipse IDE provides this time-saving trick and it helped on this project. But Eclipse also offers code generation. This doesn’t just help you generate a line of code; it will generate whole structures for you. When you ask for a new class, the IDE is clever enough to deduce the namespace, parent objects, methods and their signatures. For something like the visitor pattern, where the addition of new classes can be actually quite mechanical and laborious, this saved a lot of time.
Adding a new contract element typically went something like this:
- Add a reference to the new ContractElementA class into existing Contract class. But – oh no! – there’s a red squiggly line under ContractElementA, informing us that there’s a compile error because ContractElementA doesn’t exist.
- Hovering over the squiggly line brings up suggestions on how to fix this, including the one we want: Create class ContractElementA. Choosing this doesn’t just create an empty class, it creates a class in the right package with the right superclass and the required methods ready to be filled in.
- Next, add a new visit method for this element to the IContractVisitor interface. But – oh no! – there’s a red squiggly line informing us that the method isn’t implemented yet. Again, we follow Eclipse’s suggestion to create the new method for us, which it does.
- After several more squiggly line episodes like this, Eclipse has led you on a trail through the whole code structure and helped you add all the classes and methods required for the new contract element. You can now begin filling in the missing modelling logic – something no IDE can yet help you with.
Ultimately, we met our deadline. The demo program was completed and delivered within a week. In total, we had written about 2,000 lines in that time; a good proportion of it was automatically generated.
But there’s more. About three quarters of that code is the “business” functionality (i.e. the visitor pattern that carries out the actual contract modelling). While the rest is hastily-written I/O stuff that will probably be thrown away in the next stage, the business code is work we can reuse.
This is significant because creating prototypes and demos so often ends with throwing away all the code and starting again. This is not wasted effort – far from it, it’s a valuable learning exercise, albeit a potentially expensive one. However, if you have the opportunity to keep some of the code from a prototype, then why not do it? In this case, we can keep about 75% of our work and begin the next phase in possession of a tried and tested maintainable design, as well as one week’s head start.