JAW Speak

Jonathan Andrew Wolter

Improving developers enthusiasm for unit tests, using bubble charts

with 12 comments

Reading time: 4 – 6 minutes

The Idea
Visualize your team’s code to get people enthused and more responsible for unit testing. See how commits contribute to or degrade testability. See massive, untested checkins from some developers, and encourage them to change their behavior for frequent, well tested commits.

Several years ago I worked with Miško Hevery, who came up with an unreleased prototype to visualize commits on a bubble chart. The prototype didn’t make it as an open source project, and Misko’s been so busy I don’t know what happened to it. I was talking to him recently, and we think there are lots of good ideas in it that other people may want to use. We’d like to share these ideas, in hopes it interests someone in the open source community.
This is a standard Flex Bubble Chart. This was a rich flash widget with filtering, sorting, and other UI controls.

  • Each bubble is a commit
  • The X axis is a timeline
  • The size of bubbles is the size of each checkin
  • The colors of bubbles are unique per developer
  • The Y axis represents the ratio of (test code / total code) changed in that checkin.

Size is measured in lines of code, an imperfect measure, but it proved useful for his internal use.

Interpreting It
We found that showing this to a few people generally got a big interest. All the developers wanted to see their bubbles. People would remember certain commits they have made, and relive or dispute with each other why certain ones had no test code committed.

testability-bubbles-big commits

Best of all, though, when used regularly, it can encourage better behavior, and expose bad behavior.


Using It
Developers often leave patterns. When reading code, I’ve often thought “Ahh, this code looks like so-and-so wrote it.” I look it up, and sure enough I’ve recognized their style. When you have many people checking in code, you often have subtly different styles. And some add technical debt to the overall codebase. This tool is a hard to dispute visual aid to encourage better style (developer testing).

Many retrospectives I lead start with a timeline onto which people place sticky notes of positive, negative, and puzzling events. This bubble chart can be projected on the wall, and milestones can be annotated. It is even more effective if you also annotating merges, refactorings, and when stories were completed.

If you add filtering per user story and/or cyclometric complexity, this can be a client friendly way to justifying to business people a big refactoring, why they need to pay down tech debt, or why a story was so costly.

While you must be careful with a tool like this, you can give it to managers for a mission control style view of what is going on. But beware of letting anyone fall into the trap of thinking people with more commits are doing more work. Frequent commits is probably a good sign, but with a tool like this, developers must continue to communicate so there are no misunderstandings or erroneous conclusions made by non-technical managers.

Some developers may claim a big code change with no test coverage was a refactoring, however even refactorings change tests in passing (Eclipse/Intellij takes care of the updates even if the developer is not applying scrutiny). Thus the real cause for the large commit with no tests deserves investigation.

Many other features existed in the real version, and a new implementation could add additional innovations to explore and communicate what is happening on your project.

  • Filter by user
  • Filter by size or ratio to highlight the most suspicious commits
  • Filter by path in the commit tree
  • Showing each bubble as a pie chart of different file types, and each of their respective tests.
  • Display trend line per team or per area of code
  • Use complexity or test coverage metrics instead of lines of code
  • Add merge and refactoring commit visualizations
  • Color coding commits to stories, and adding sorting and filters to identify stories with high suspected tech debt.
  • Tie in bug fixes and trace them back to the original commits’ bubbles

We hope some of you also have created similar visualizations, or can add ideas to where you would use something like this. Thanks also to Paul Hammant for inspiration and suggestions in this article.

Bookmark and Share

Written by Jonathan

July 16th, 2011 at 7:35 pm

Book: Power: Why Some People Have It-and Others Don’t

without comments

Reading time: 4 – 6 minutes

Power: Why Some People Have It-and Others Don'tPower: Why Some People Have It-and Others Don’t by Jeffrey Pfeffer
My rating: 3 of 5 stars

It is an easy read with interesting examples. If you dislike the title, consider how the world is political, and it is in you interest to know the power games other people will play.

A few highlights:

  • When Keith Ferrazzi (author, CMO, CEO) was offered a position at Deloitte, he insisted in seeing the “head guys.” He met the NYC chief, Loconto, over dinner and Keith said he would accept if the two  would have dinner once a year at the same restaurant.” This was a gutsy move, but gave him influence at a very high level. All because he asked. What could you have asked for?
  • Ishan Gupta is an entrepreneur from India who positioned himself with compiling a book of major Indian entrepreneurs. He had the founder of Hotmail, the Indian president Kalam, and over a dozen leaders contribute to the book. How? His pitch was as a fellow entrepreneur and IIT graduate, he appreciated their courage, and said no one would take a book by him seriously, he wanted their help to write just a few pages or hundred words with key advice. He packaged the request brilliantly, and almost all accepted. Asking for help is inherently flattering. He leveraged his experience to write something with a positive social implication. Then gained influence with very big hitters, and ‘jumped up a weight class.’
  • Confucius said, ‘Real knowledge is to know the extent of one’s own ignorance.’ While this seems somewhat out of place in this book, remember if you gain more power, you will change. It is best to not become full of yourself.
  • Stay focused on the outcomes you are seeking, and do not get hung up on people and their idiosyncrasies. You can not and will not please everyone.
  • Be able to act. As in acting, theatrics, Hollywood. If you are ‘angry’ don’t always really be angry, as you can act with emotion, skipping over facts, weaken you position, and alienate people. I have made my worst mistakes when acting out of emotion. You can use emotions effectively to lead a team; however, if you can have the passion of emotion, without the irrationality, it is much better. Thus, learn how to act. It disconnects the irrationality. When I worked at FeedBurner, Dick Costolo was CEO there and he came from 10 years of stand up comedy. Extremely useful for his outward influence (now CEO Twitter), and inward motivating employees.
  • Synchronize the ‘voice’ of a team’s many leaders. I have had huge team problems because the peer group of senior leaders all had different opinions about the vision and priorities. If one of us had suggested a simple, quick, weekly breakfast or lunch meeting next door, we would have been on sync. It would have boosted the team’s morale and effectiveness.
  • Oliver North vs Donald Kennedy’s congressional testimonies suggest theatrics (righteous anger vs shame and timidity) is a significant factor for how people are judged. This was an “aha” moment. Senior leadership is a lot of acting. CXO’s may not see some employees but once a year. The ability to turn on the energy and optimism (acting) is crucial to leave strong, lasting influences in people.
  • One comical specific claim was that “moving your hands in a circle or waving your arms diminishes how powerful you appear. Gestures should be short and forceful, not long and circular.” Probably true. How you carry yourself influences how you are viewed. Are you the carefree person, consistent worker, angry person, goofy one, solid leader, etc.?
  • Take you time in responding. Flustered or unsure people are marginalized. Related to acting. When choosing between emotions or a slower response, always choose the slower, more deliberate response. (My editorializing).

Not amazing, but short and I finished it. I think I can only read a
small number of these kinds of books a year. Now I am ready to read
more math books.

View all my reviews

Bookmark and Share

Written by Jonathan

May 20th, 2011 at 3:18 am

Book Review: The McKinsey Mind. Focusing on Mutually Exclusive Collectively Exhaustive thinking

with 5 comments

Reading time: 4 – 6 minutes

The McKinsey Mind: Understanding and Implementing the Problem-Solving Tools and Management Techniques of the World's Top Strategic Consulting FirmThe McKinsey Mind: Understanding and Implementing the Problem-Solving Tools and Management Techniques of the World’s Top Strategic Consulting Firm by Ethan M. Rasiel
My rating: 4 of 5 stars

Worth reading. Especially if you are in consulting. I like the beginning of the book especially, and will be turning back to some of those pages for reference.

Thinking logically
The book starts strong by introducing “MECE: Mutually Exclusive Collectively Exhaustive.” I use it often in my teams. Think of it as building a decision tree, where you cover every option, and none are overlapping. Each branch in the tree also has more MECE sub-branches. When deciding or investigating something, draw the tree on a whiteboard, and walk everyone through the options, and sub-tree options until you have a decision, or clear actions to take. Very logical. Be sure to encourage other people to contribute to the branches, and if you are leading it, ideally you team will volunteer the branches, and then they have more commitment to the options.

Or, as Wikipedia says:

[MECE] says that when data from a category is desired to be broken into subcategories, the choice of subcategories should be
1. collectively exhaustive — i.e., the set of all subcategories, taken together, should fully characterize the larger category of which the data are part (“no gaps”)
2. mutually exclusive — i.e., no subcategory should represent any other subcategory (“no overlaps”)

This is desirable for the purpose of analysis: mutual exclusivity avoids the risk of double counting information, and collective exhaustion avoids the risk of overlooking information.

Two areas for MECE thinking are in logic-trees and issue trees.

Logic trees help you identify components of a problem. Start at the 20,000 foot view and move progressively downward. You may want to build multiple trees, for instance by business unit (organizational hierarchy) and functionally (production, sales, marketing, etc.) to see which leads you to the next step, the hypothesis.

Form a hypothesis of what component of the logic tree may be causing the problem. Run it by the Quick and Dirty Test: ask what assumptions you are making that must be true. Are any false? If it passes the QDT, gather data and do analysis to disprove it. This is the same as the scientific method. If you fail to disprove it, you may be on to something. Predict what could happen if the identified root cause was changed.

Issue trees let you rigorously test the hypothesis. They are different from logic trees. Logic trees are a hierarchical grouping of elements. Issue trees are the series of questions or issues that must be addressed to support or disprove a hypothesis. It becomes you roadmap for analysis.

Present with the conclusion at the start. This was a good lesson. Do not use inductive reasoning to build up from details into a specific conclusion for your audience. They may already agree with it. You would then waste their time. Instead make you conclusion, and progressively drill into details, broadly covering each level before drilling down further. Stop/skip forward if they do not need the convincing. (A refresher on inductive/deductive reasoning).

Presentations are all about getting buy-in. It is important to “pre-wire” the meeting so that there are no surprises, and people already know your conclusions. The act of pre-wiring will identify gaps you need to work on, or build allies for you proposal.

Interviewing clients/stakeholders is a common activity I have done at ThoughtWorks. The authors advised scheduling time with people, and sending them an agenda. This lowers their apprehension of why consultants want to talk to them. Also at the end, during small talk before you walk out, ask “is there any thing else we did not cover that you think we should?” You’ve built rapport by now. Their answer can uncover important, previously unmentioned issues.

Note: as a software engineer, I appreciate the MECE thinking style for its logic. Also, it is the exact way we approach performance tuning an application. Think about the logic tree of slow spots. Build a hypothesis. Test it by profiling the running program under load. Let the data of time spent in each component show the root cause.

View all my reviews

Bookmark and Share

Written by Jonathan

May 1st, 2011 at 3:14 am

Book Review: The Unimaginable Mathematics of Borges’ Library of Babel

with 2 comments

Reading time: 1 – 2 minutes

This book is *awesome*! Why? The author takes a short story, “The Library of Babel,” by Jorge Luis Borges and analyzes it along many different mathematical dimensions. The results are stimulating and accessible to non-mathematicians. The story is about a library, which is composed of:

An indefinite number of … hexagonal galleries. In the center of each gallery is a ventilation shaft, bounded by a low railing. … Twenty bookshelves … line four of the hexagon’s six sides… One of the hexagon’s free sides opens onto a narrow sort of vestibule, which in turn opens to another gallery, identical to the first — identical in fact to all.

What’s the implication of this? The author, William Goldbloom Bloch, takes us through combinatorics, information theory, real analysis, topology and cosmology (a tough chapter), geometry and graph theory, and more combinatorics. He explains things in an easy to understand way, and then if you want more, has “Math Aftermath” sections that get more in depth.

In the end, he gives a long list of suggested readings. I have started a list here http://amzn.com/w/236UZ2PNNR3W2. What math books do you all suggest?

Bookmark and Share

Written by Jonathan

April 30th, 2011 at 12:38 pm

Sukrupa in Bangalore, an AMAZING organization, and ThoughtWorks

with one comment

Reading time: 3 – 5 minutes

I’ve been living in Bangalore since October. First training at ThoughtWorks University (TWU), now working for a UK client. The people and work has been amazing. Best of all is what we have done with Sukrupa.

Six years ago next month I was in Bangalore, volunteering with the non profit Sukrupa, a slum school founded by the amazing Krupathala Martin Dass. [1] And in January this year ThoughtWorks began working for the school in rebuilding their website and launching a student records project. I’m very proud for ThoughtWorks for investing with many dozen people to work on this, and for the honor to enable such a wonderful, high impact activity. This is part of the culture here. What a great place.

Below is a write up from TWU XX, which completed in February, and compiled by my colleague Pallavi from Australia.

TWU XX project for Sukrupa went live Feb 17 – Release 1 consisted of a redesign of the Sukrupa website www.sukrupa.org and a Student Record System.

Who is Sukrupa?
Sukrupa is a Bangalore-based NGO that works to transform the lives of children from the slums and integrate them into mainstream society. Heard enough and want to help? You can donate or explore volunteer opportunities at Sukrupa.

What did TWU-XX do?

  • We met the most amazingly talented children, who made us realize that every child deserves an opportunity to shine no matter where they come from.
  • We revamped and rebranded www.sukrupa.org to showcase the great work done by Sukrupa.
  • We enabled online donations and are looking for ThoughtWorkers to QA our online donation widget. Any volunteers? ;-)
  • We created an offline donations guide that offers the donor a variety of options to maximize donation.
  • We produced an events summary to help track the many events hosted by Sukrupa (events are an avenue to showcase the talents of the children, and also to increase visibility with sponsors/donors).
  • We are proud to say that we successfully delivered software in a one-click-deploy environment!
  • We got completely upstaged by the Sukrupa children in ‘TWU’s Got Talent (or not!)’, witnessed by Roy, Trevor, Dan and Dave. Stay tuned for embarrassing videos and pictures.

In Closing

  • Sukrupa needs your help! Please donate and/or volunteer!
  • This project with Sukrupa will continue with future TWU batches.
  • ThoughtWorks’ involvement with Sukrupa is set to grow, with Rohit exploring other opportunities for us to help – Thank you Rohit.
  • TWU XX has been an incredibly rewarding experience. Not only did it prepare us to be consultants but it also enabled us to carry forward ThoughtWorks values in our very first project.
  • A big thank you to our trainers and clients for their endless patience.
  • Thank you to the Bangalore office for hosting us and particularly the Admin Team.

My backstory on Sukrupa
[1] Back in 2005, a friend and I were on a five week project to have an art camp with several non profits in India. We attempted to film a documentary and capture children’s answer to “what do I want to be when I grow up.” We met with many non profits and schools in Chennai and Bangalore. You can read the old blog here, ArtView India. Sukrupa was one the organization that left a deep impact on me and I returned in 2007, as well as have worked with Krupa from the US in grant writing and publicity. I’ve been directly involved since 2010, connecting her with ThoughtWorks.

Sukrupa children

Bookmark and Share

Written by Jonathan

April 18th, 2011 at 2:49 pm

Posted in career, thoughtworks

Web Caching Design: Cache keys should be deterministic

without comments

Reading time: 2 – 2 minutes

Following up on my previous post on Session State, there are a few conceptual ways to think about caches that I want to cover.

Cached items can be placed in session. That may be the easiest, but soon it will expose limitations. For instance, session may be serialized as one big blob. If so, you won’t be able to have multiple concurrent threads populating into the same cache. Imagine when logging in, you want to have a background asynchronous thread lookup and populate data.

The key with cache is the keys that are cached need to be independent. A session may be okay to store as a serialized object graph. But cache keys could be primed in multiple synchronous threads, so a single graph could involve locking or overwriting parts of session. If cache entries are deep in a graph, you’re almost certain to have collisions and overwritten data.

IMHO, the most important thing is: Cache keys should be deterministic. For instance, if I want to cache all of a user’s future trips (and that is a slow call), I want to be able to look in the cache without first looking up the key to the cache in some other store. I want to say “Hey, given user 12345, look in a known place in the cache (such as “U12345:futureTrips”) to see if some other thread already populated the cache value.” This does mean you need to count more uniquely addressable cache locations in your application logic, but the extra accounting is well worth the flexibility it gives you. For instance, it allows background threads to populate that cache item, without overwriting anything else.

Bookmark and Share

Written by Jonathan

December 6th, 2010 at 4:20 am

Posted in architecture, code

Spring Slow Autowiring by Type getBeanNamesForType fix 10x Speed Boost >3600ms to <100ms

with 10 comments

Reading time: < 1 minute

We’re using Spring MVC, configured mostly by annotations, a custom scope for FactoryBeans so they don’t get created once per request, and autowiring by type. This makes for simple code, where the configuration lives right along where it is configured, however after a certain number of autowired beans, performance was abysmal.

Loading the main front page in Firefox, with firebug showing slowness:

Click on to read the full post.
Read the rest of this entry »

Bookmark and Share

Written by Jonathan

November 28th, 2010 at 4:25 am

Posted in code, java

Tagged with

Spring Bean Autowiring into Handler/Controller Method Arguments

with 7 comments

Reading time: 2 – 4 minutes

We request scope controllers in our Spring MVC web application, and then spring injects in collaborators. Each request builds up an object graph of mostly request scoped components, they service the request, and are then garbage collected. Examples of collaborators are Services, request-scoped objects like User, or objects from session. Declare these injectables as dependencies of your controller, and the IoC framework will resolve those instances for you. Using Spring’s FactoryBean, you can have custom logic around retrieving from a DB or service call. (Also, if you do request scoping for everything you will probably want to make your FactoryBeans caching, or create a custom scope, so Spring doesn’t recreate each FactoryBean, and make a remote call possibly, on every object injection.)

Instantiate a graph of request-scoped objects per request. Is that crazy? Not really, because garbage collection and object instantiation are very fast on modern JVM’s. I argue that it it helps you have cleaner and more maintainable code. Designs have better object orientation, tests don’t require as many mocks, and it’s easier to obey the single responsibility principle.

None of this is new, though. Here’s where it gets interesting for us. We have @RequestMapping methods on a controller, but only one of them needs the injected collaborator. If it is slow to retrieve the collaborator (such as a CustomerPreferences we get from a remote call), we don’t want to call it every time. Sometimes this means you need two controllers, other times you want to let any spring bean be injected into a handler method.

We extended Spring to inject any spring bean into a controller/handler’s @RequestMapping or @ModelAttribute annotated methods. You benefit with only injecting the bean into the handler method that needs it, possibly preventing remote calls to lookup said dependency if it were a field on a controller with multiple @RequestMapping’s.

Here’s a sample controller’s handler method. Before:

	@RequestMapping(value = Paths.ACCOUNT, method = GET)
	public String showAccount(Map model) {
	      model.put("prefs", customerService.getCustomerPrefs(session.getCustomerId()));
	      return "account";

There is an extension point WebAttributeResolver for you to add your own logic to resolve method parameters (such as autowire them as spring resolvable beans). After:

	@RequestMapping(value = Paths.ACCOUNT, method = GET)
	public String showAccount(Map model,
	          @AutowiredHandler CustomerPreferences customerPreferences) {
	      // the CustomerPreferences has a CustomerPreferencesFactoryBean which
	      // knows how to make a remote service call and retrieve the prefs.
	      model.put("prefs", customerPreferences)); // easier to test
	      return "account";

This lets you inject any spring bean into fields/methods annotated with @ModelAttribute or @RequestMapping.

Another very helpful way to do this is to automatically inject User or other request-specific objects.

References for further discussion/examples on the topic:

Bookmark and Share

Written by Jonathan

November 20th, 2010 at 4:13 am

Posted in code, java

Tagged with

Some Problems with Branch Based Development, And Recommendations

with 4 comments

Reading time: 3 – 4 minutes

As I have previously written, I dislike branch based development (especially when it involves subversion and long lived feature branches). Sometimes projects have multiple teams concurrently working in the same codebase, each on different release schedules. For example, team “Delta Force” will go live in a year, with some super top secret and amazing functionality. (Do not get me started on how bad an idea this usually is. I believe in short, frequent releases and rapid customer feedback). All the while, team “Alpha Squadron” is working on periodic releases into production every few weeks or months. Nothing from Delta can go live with Alpha’s releases. How do you enable these teams to cooperate? Some may suggest a long lived feature branch for Delta Force’s code. And then “just” merge the changes from Alpha down to Delta. I believe this is a Bad Idea.

But, if you’re forced into this scenario, at least explain to people the importance of frequently merging (i.e. on a daily basis). The longer you wait between merges, the greater the danger of increasing complexity and merge difficulties.

Rather than using a long lived branch, I suggest the following solution: Trunk Based Development. This means you do not create actual branches. Everyone is on the same trunk. As my colleague Paul Hammant phrases it, you Branch By Abstraction. My other colleague Martin Fowler calls this Feature Toggles. First, this enables refactoring, because everyone is working in one codebase. Second, as feature toggles become permanently turned on, you can remove them, and the conceptual divergence between the two “branches” drops. This is a Good Thing.


Once again, if you have a long lived branch, and even if you frequently merge, the divergence will grow as the not-reintegrated changes accumulate in the long lived branch. This divergence is RISK. It inhibits refactoring and encourages technical debt.

Prefer Trunk Based Development. It is not perfect, as there still is additional complexity in the codebase. But you can mitigate this with polymorphism instead of if conditionals, and have multiple continuous integration pipelines for all deployable feature toggle combinations.

By using Trunk based development, we make it easier to do the right thing. This is an example of the Boy Scout Rule. The Boy Scouts of America have a simple rule that we can apply to our profession. “Leave the campground cleaner than you found it.”

If we all checked-in our code a little cleaner than when we checked it out, the code simply could not rot. The cleanup doesn’t have to be something big. Change one variable name for the better, break up one function that’s a little too large, eliminate one small bit of duplication, clean up one if statement.

Long lived feature branches make this difficult, because any changes you make to one branch needs to be replicated, or you may have merge difficulties. This is especially a problem for a “long lived receiving” branch, which by it’s nature does not reintegrate its changes into the mainline. (Thus that branch is limited in what it can refactor).

Bookmark and Share

Written by Jonathan

November 7th, 2010 at 8:00 am

Subversion Branch Merging and Tree Conflicts

with 6 comments

Reading time: 2 – 4 minutes

I’ve written several times about how I recommend avoiding long lived feature branches. But, if you have to use these, you might run into a problem with subversion identifying unmergable tree conflicts. I think this has been fixed in current versions of subversion, but let me walk through a conceptual scenario of what was happening when you get this error message:

Error message:
svn: Attempt to add tree conflict that already exists
svn: Error reading spooled REPORT request response

(Using svn, version 1.6.4 (r38063) compiled Aug 7 2009, 03:47:20)

It starts when you have a branch and a cherry-picked merge from the branch to trunk.

Next, you want to merge all of the branch, to trunk. And you’re using subversion merge tracking.

Subversion really does two merges: one up to the cherry pick, one after the cherry pick.

But, if there were tree conflicts in both the merge before and after the cherry pick, subversion (as of an older version we used last year) would die. I hope this is out of date, and you can avoid the problem with newer versions.

I had to recompile subversion from source, hacking in some special logging and then forcing it to continue after the merge conflict. Read more on the mailing list here and search for jawspeak or paul_hammant. With my patch, it would log a special message, continue, and not die.


Resolve it by manually fixing the tree conflicts (some of these scripts might help you), and mark the conflicts as resolved.

Moral of the story? Use Trunk Based Development, and not feature branches.

Bookmark and Share

Written by Jonathan

November 6th, 2010 at 3:58 am

Posted in code

Tagged with ,