Tuesday, July 22, 2014

Keep it Simple Stupid

It's one of the XP core values - simplicity.  Yet, we value the highly complex and complicated.  In enterprise environments, if we aren't working on multiple projects, hanging tough through adversity, fixing bugs, driving features in until the bitter end then we must not be working hard enough.

So, I'm here to dispel the myth that working effectively requires complexity.  In fact, I would say just the opposite is true.  Working effectively requires simplicity. 

Research in cognitive load theory (CLT) shows that humans have effective use of at most seven elements, but we use only two to four elements and that our short term memory effectively retains items for only twenty seconds unless there is something that refreshes the memory.   In software development, particularly in the enterprise, this can affect us in multiple ways.


Working on Multiple Projects


Juggling multiple projects can reduce a developer's effectiveness to a great degree, particularly if there are significant differences between projects.  Presumably, each project requires a different branch of code and may contain classes and files that have changed significantly from one release to another.  The developer must keep context of the desired change as well as the existing context of the overall codebase into account.  This is exacerbated when this is created by differing customer desires for the same feature.  

Project managers will also wrestle with the priorities across these projects which will cause the developer to go back and forth between the codebases, each time requiring a cognitive reset in order to recall from long-term memory the context of the codebase.

What is the remedy?


There may be several possibilities to consider here.  First, if there really is a need to keep separate codebases for different clients, consider how this could be done by keeping a team of developers dedicated to that client.  This increases the effectiveness of the developer by keeping her in the same branch of code.  The obvious downside is that you may have some duplication across branches, so make sure that there are ways to communicate across teams within the same discipline so that they can look for opportunities for reuse if it makes sense.  But, don't favor reuse for the sake of reuse knowing that it drives up complexity.

Second, consider whether you can have a single codebase.  This may be true in the case of moving to cloud services.  Or, you may have properties which configure the optional feature set.  The intent here would be to create a long-lived team which can handle a set of features.

Third, make sure that you are clear on priorities and drive down work in progress.  Focus on getting a few things done well in shippable form.  Any increase in work not completed creates complexity all the way across the value stream.

Dealing with Delays


Delays can have many ill effects - broken promises, problems with finding defects late in the cycle, added stress to the test team when they are blamed for everything being late.  But, it also creates cognitive stress as the team tries to balance competing work priorities.  Delays in the system enforces work reassignments immediately increasing work in progress which adds to the cognitive load of each member of the team that is affected by the delay.

This becomes a vicious cycle that leads to further delays in the system.  Delays affectively lead to complexity.

What is the remedy?


Aggressively attack those parts of your system that cause or increase delay.  This could be any number of problems, such as functional silos, long planning cycles, lack of customer interaction or not enough focus on early testing.

If you look at the problem from your customer's perspective, each of these delays causes them to wait.  For a time this could simply break the trust you have built with the customer, but in the long run they will turn angry or indifferent moving on to other suppliers.  A significant delay means that your solution will be behind the market and thus less meaningful for your customer.

Focusing on simplicity means having the mindset that keeping processes simple increases flow and throughput.  

Test First is Simpler

One of the practices we might want to adopt to simplify process would be test-first to reduce the need for longer debug cycles trying to sift through the code to find where the bugs where introduced.  Testing first increases the number of tests at the bottom of the test pyramid thus reducing the need for more complex combinatorial tests later in the cycle.  

Test first also creates a very tight feedback cycle.  It reduces the "hope and pray" tactics of manual testing efforts.  Most importantly, the reduced time means that context is not lost.  If a problem arises, it was only seconds or at most minutes after the bug was introduced.

Cross-functional Teams are Simpler

Cross-functional teams allow focused effort on a few items in the system at once.  There is shared context of the problem.  Even if you have a situation where there is not perfect knowledge across the team (and this is almost never achievable anyway), the shared context provides a tight feedback system that reduces overall complexity.  

Reduce work-in-progress however you are managing your process.  Keeping the whole team or a significant portion of the team on a single user story enforces collaboration and collectivism.  

Emergent Design is Simpler

Teams that come from a culture of waterfall built systems believe in identifying designs up front in order to reduce overall risk.  While this is still a good idea in general to think about system design up front, most knowledge is actually acquired as work is completed and shared so that many minds can reflect on the outcome.  Therefore, working in smaller batches identifying the need for design patterns and letting this emerge as a practice is the most beneficial to the system as it is shared knowledge and is proven through application.

Doing this the opposite way actually increases risk overall to the system since it is based on little understanding of the affect the feature set in the backlog will have on the system.  And, it drives up complexity as the understanding of the system is kept apart from the implementors. 

In the End

Focus on simplicity first if you want to improve overall outcomes.  There are many patterns and practices you can put into place other than what I have mentioned above.  Try something.  Inspect.  Adapt.  Communicate.  But, above all, keep it simple.