Slimmed Down Software – A Lean, Groovy Approach Part 4 – Defer Commitment
September 13th, 2010This article originally appeared in the July 2010 edition of GroovyMag, the Groovy and Grails magazine. Parts 5 and 6 are currently available for download from the magazine’s site, and more will come each month. Previous articles in this series are on the Canoo website: Part 1: Eliminate Waste, Part 2: Build Quality In, and Part 3: Create Knowledge. Lastly, if you like this, you may want to check out some of my older blog posts from my personal site under the “craft” category. Enjoy!
The Groovy Programming Language advertises itself as an “agile and dynamic Language for the JVM”, but what does this mean exactly? This series of articles explains Lean Software Development, and shows how your choice of programming language can make your entire process remain nimble and adaptive. Each months article will cover one of the seven Lean Software Development principles and explain how Groovy and the associated ecosystem help eliminate waste, defer commitment, and build quality into your product.
About this Series
Groovy is an agile programming language. In order to explain what this means, these articles are structured around the seven principles of Lean Software Development. The previous installments included a short introduction to Lean, explained how an expressive language can eliminate waste in unit testing, showed how the easyb Behavior Driven Development framework and Groovy Builders can build quality into your life-cycle, and demonstrated how the Spock Testing Framework can create project knowledge. In later months we’ll explore how metaprogamming allows you to deliver fast, and see how Groovy’s Grapes module system, alongside modules like Groovy Web Services, streamline interactions between development and other groups like operations and QA (an important aspect of respecting people). Finally, we’ll look at optimizing the whole by applying Groovy to domains that cross department boundaries: how Gradle improves the build process and easyb serves as a collaboration mechanism between different organization roles. The series will end with a discussion on the best practices of mixing Java and Groovy.
Some of the code examples are basic while others are advanced. The articles explore why the features of Groovy are important rather than the mechanics of any one Groovy feature. Hopefully you’ll leave with some new ideas about how to use Groovy, how to convince your team that Groovy is worthwhile, or most importantly, how to increase your productivity.
Lean Revisited
Part 1 of this series c ontained a more indepth explanation of Lean, and I won’t repeat it here. But as a quick refresher here are the 7 lean principles along with a summary for those principles covered previously:
1. Eliminate Waste – Reduce work in progress and half done work
2. Build Quality In – Instead of settling for finding defects, optimize your process to create fewer defects
3. Create Knowledge – Create fast feedback cycle and encode project information in executable form
4. Defer commitment
5. Deliver Fast
6. Respect People
7. Optimize the Whole
Principle 4 – Defer Commitment
Deferring commitment is about keeping your options open. It may seem wise to make decisions early, and it does lead to a comforting illusion of progress. But decisions can be costly to unmake, and oftentimes new information will become available that affects the choices you’re willing to make. The best time to make a decision is at the “Last Responsible Moment”: the point in time where not making a decision eliminates an important alternative. By delaying decisions we are ensured that when new information does becomes available then we can factor it into our project. Just be sure not to wait too long because at some point a lack of decision will force your hand.
One of the most interesting agile family members to arrive recently is the Real Options community, which grew out of an understanding of financial risk management models. Given the recent world banking crisis, following the advice of financial risk modelers may seem as foolish as looking to oil giant BP for a good decision making framework. It is better to think of Real Options as a methodology based on both mathematical models and the basic principle of many agile processes: the freedom to choose.
As software developers, decisions are what we do: they are pervasive. We code decisions into unit tests and production code. We encode them into acceptance tests and test plans. And oftentimes, we discuss, rehash, and duplicate them endlessly in a merry-go-round of meetings and requirements documents. Of course, from the system analyst’s perspective the flow of value is reversed: decisions are made during analysis and the outcomes are duplicated and perverted by the developers in a merry-go-round of bug fixing. Regardless of your role, there are three types of decisions: a right decision, a wrong decision, and no decision. Real Options is about harnessing the power of “no decision”, which can be the best decision to make because it allows us to defer commitment until we have more information available. A better informed decision is a better decision and more likely to be right. There is a big value difference between making a premature decision today, making an informed decision tomorrow, and not making a decision at all and having an opportunity pass you by.
The fictional Doctor House from television is a master of leveraging the value of no decision. When faced with a mysteriously ill patient, his team masterfully narrows down the illness possibilities to either avian monkey pox, swine sars, or some other terminal infection; either way the patient will die in 24 hours. The important plot point is that treating an avian monkey pox patient with swine sars medicine results in immediate death, and treating a swine sars patient with avian monkey pox medicine also results in immediate death. Clearly, there is no good decision. Guessing the wrong illness could kill the patient (and end the show 30 minutes too early). So what do they do? They wait. And wait. And wait until more information is available. Their decision timebox is 24 hours, so they can spend 23 hours waiting before a decision must be made. Meanwhile, they poke, prod, and test the patient, trying to determine the true illness. Eventually they work to create knowledge, discover a new diagnosis, administer the penicillin, and end the show.
Real options are about the flow of information arrival; remember how developing software was a knowledge creation process? Creating knowledge in the system, and deferring decisions until this knowledge is available, leads to better decisions… making the “right decision” more frequently. We need information to arrive before making commitments, and we push out decision making until the last responsible moment. As the authors state, “The last responsible moment is after which execution of an option is too late. The option no longer exists or you’re not able to execute it any more.”[1].
Options contain three important aspects:
1. Options have value
2. Options expire
3. Never commit early unless you know why
In the case of House, deferring the decision to create swine sars was a valuable option: it left the patient alive. But that option expires: swine sars is deadly after 24 hours. By not committing to a possibly deadly treatment, House kept the patient alive until the proper treatment could be found. If there is no reason to make a commitment then do not make it.
This might sound like common sense. But it is very difficult to follow because of the psychology surrounding decision making. People hate uncertainty, so they naturally drive to make decisions early. This is even more evident in big meetings, where leaders need to be seen leading and progress needs to be made. Not only are big meetings costly, but they can lead to premature decisions, thus further driving the cost of business up. Counter-act this aversion to uncertainty by timeboxing decisions: pick an exact date or conditions to be met before making a decision. Replace the phrase, “We should not make a decision on this” with either “We should not make a decision until after the next iteration on Tuesday” or “We should not make a decision until after the prototype of Plan B is finished.” Giving people certainly over the time frame of a decision balances the natural angst of deferring the decisions. And as you can guess, keeping an up-to-date issue log visible in the team area is a best practice.
For more information on Real Options, download the free “Real Options at Agile 2009″ comic book by Chris Matts[4]. The illustration is rough, but the content, humor, and ambition are top notch. Now let’s get back to programming.
Do you remember the original Java white paper in 1995 from James Gosling[3]? Me neither, but you can find it on the Internet if you search hard enough. It contains a prescient passage on the value of both deferring commitment and dynamic languages like Groovy:
“Very dynamic languages like Lisp, TCL and Smalltalk are often used for prototyping… [One] reason given for these languages being good for prototyping is that they don’t require you to pin down decisions early on. JAVA has exactly the opposite property: it forces you to make choices explicitly.”
Perfectly well said, except that Groovy is missing from the list of good dynamic languages and JAVA is now written Java, as enforced by the divine writ of the Sun/Oracle legal department. As Java programmers, we are used to making commitments: up front and not deferred. We are asked by the compiler to make them early and make them often. I never noticed this until after I had spent a considerable amount of time in a dynamic language. Now, when programming Java, I feel that I’m constantly being asked the same question: what is the name of type you are using? It’s easy to notice this within the methods and code you write. Statements like “List<String> list = new ArrayList<String>();” are surely repetitive, but both IDEs and future Java versions are addressing this. A bigger problem is the repetition of types across unit tests. With Java, the compiler ensures that you commit to types in your API. If your “UserView” is a GUI for User objects, then the compiler is going to make darn sure that only User objects are allowed to be passed to it. Yet, in your test code for UserView, you must also make sure that Users are being passed; you’re being asked to commit to this type a second time, even though the compiler already enforces it! Have you ever refactored a production class only to find that a handful of unit tests now fail to compile, forcing you to update all the references before being able to run the system or run the tests? If so, welcome to premature commitment.
Groovy offers another way out. With Groovy, you can leave things dynamically typed and flexible for as long as you’d like, move them to be optionally typed when the need and commitment arises, or even convert them to Java and static typing. Consider the unit test example in Listing 1, which tests an imaginary UserView object, a user interface over a list of users.
public void testUserView() {
def userList = [
[getId: { 111 }],
[getId: { 222 }],
[getId: { 333 }],
]
def view = new UserView(userList)
assert view.rowCount == 3
view.remove(userList[1])
assert view.rowCount == 2
}Listing 1: Testing without duplicated types
This is the test for the aforementioned UserView.Users can be added to and removed from the UserView, a behavior this test confirms. Does the UserView work off of Users? Or some sort of generic interface? Who cares. That information is specified in the production code, and there is no need to duplicate it in the test code; this would only serve to make your tests more fragile. How you decide to refactor is your own business. The only detail we have committed to is that the objects the UserView expects must have a getId() method. This test is flexible enough to withstand however you want to refactor your production types. As Taiich Ohno, inventor of Lean says, “The sturdier the human spine, the more easily it bends.” The same is true with unit tests. Break dependencies and maintain options with Groovy’s optional typing. If there is good reason to commit to types then do so. If not, then don’t. Groovy, and agile, are both about keeping options open.
How exactly does this example show the dynamic typing? The example’s userList object is a list of Maps, each entry is created using the [key: value] notation, and in this case is a map from String to Closure. In Groovy, a Map of type <String, Closure&rt; is a shorthand for implementing an interface. As long as the code being called is flexible enough then any method calls to getId() will be dispatched into this Map’s getID closure. This is a very handy way to implement partial objects for wide interfaces. As a word of warning, an API expecting User objects will require you to declare this partial interfaces as Users using the “as User” keyword. This requires only a small change and keeps coupling to a minimum.
What I like about dynamically typed unit tests is it allows me to focus on the outputs of a system instead of the inputs. Is the value of an IT system in the inputs or the outputs? Can you name a single IT system with value that has no inputs? The value is always in the outputs of a system; we need to make commitments on system output because that drives business value, but we need to not make commitments on inputs because that leaves the system flexible. On a programming level, being able to forget about static types for testing input can be a great aide in developing faster without any real loss of value.
Groovy helps you defer commitment and stay agile, at the “expense” of accepting a dynamically typed language. For a lot of organizations, the decision to use a dynamic language is a big one, and not to be taken lightly. Limiting dynamic languages to testing is a great way to introduce your group to these new ideas. The test tree is a place to experiment while having minimal impact on your production system. Should you eventually decide not to embrace Groovy, it is much easier to rip out Groovy tests than it is production code! Using Groovy in test is yet another way to defer commitment: it is an easily undo-able decision. However, I doubt you’ll end up doing that.
Sidebar: Structural vs. Nominative Typing
There is more to the debate than just whether a dynamically typed or statically typed language is better! Java developers are already familiar with Nominative typing: a type must be given a name, and two objects share the same type if they share the same name. Structural typing, on the other hand, does not require names. A type has a certain form, or structure. It does not matter what you name a type, if two objects share the same method or function signatures then they are of equivalent types.
Nominative typing can be crude and inflexible. Using a language with closures for any time will make you wonder why we have the types Runnable, Callable, Action, Command, Listener, and a host of other types that could all be replaced with a single, good function object.
Duck typing in dynamic languages grew out of this dissatisfaction with nominative types. If your method requires an object with an execute() method then you can pass it any old object you want, as long as execute() is present. This check happens at runtime, and only the part of the object invoked is checked for the proper structure. In comparison, languages with better structural typing like ML, OCaml, and F# will make this check at compile time and require that the entire structure be identical, not just the part that is invoked at runtime.
Groovy achieves flexibility by moving away from static, nominative typing and lives in a middle zone where both duck typing and optional typing are supported.
Next Steps
Put options thinking to work in your next meeting. Recognize when a premature decision is being made and then make like Doctor House and follow these steps to delay the commitment:
1. Identify the options and alternatives available
2. Identify when the option expires: when a commitment must be made
3. Identify concrete steps to seek new options until the expiry date
4. Wait to make decisions… and wait… and wait… until the conditions are correct
5. Finally, decide quickly and act with confidence, knowing you have made the best informed decision possible
This may require keeping an active, visible issue list and being accountable for options. But you can prevent premature decisions by strategically delaying and then tracking when decisions actually do need to be made.
Next Month: Deliver Fast
Delivering fast is about delivering less. Not just less code but also less features. Next month we’ll discuss how Groovy enables you to focus on small batches of features and avoid both big bang integrations and the typically resulting scheduling setbacks. This is available today from GroovyMag, the Groovy and Grails magazine. Other articles about agile and software craftsmanship can be found on my personal site under the “craft” category.
Learn More
Several references were made in this article, and all are enjoyable, informative reads in their own right:
[1] “Real Options” Underlie Agile Practices – http://www.infoq.com/articles/real-options-enhance-agility
[2] Implementing Lean Software Development – Poppendieck
[3] “Java: an Overview” – James Gosling, February 1995
[4] Real Options at Agile 2009 – http://www.lulu.com/product/paperback/real-options-at-agile-2009/5949485
Also, the MEAP pre-release for “Groovy in Action 2nd Edition” does not yet (at the time of this writing) contain an updated treatment of optional typing, but it should be coming out shortly.
Thanks for listening.
Posted by Hamlet

