It's Not Simple to Keep It Simple

February 15, 2013 — Posted by Al Shalloway

I often hear about the need to keep it simple.  However, people often talk about “simple” as if “simple” were simple. I would suggest “keeping it simple” is more complicated than many people perceive. Let’s take a simple example (pun intended).  I remember 30 years ago when I started writing accounting software on PCs and was making a special effort to have the software be simple.  It was quite obvious to me that the simplest way of entering financial information into the system was to let people enter the number and, if there were no cents, have the computer enter the trailing “.00”.  In other words, instead of forcing someone to type in “1.00” for 1 dollar, they’d just have to type a “1”.  What could be simpler? 

Well, this was great – for a while.  All of our clients loved it.  And then, I ran into an accounting company and they complained that every time they entered “100” for one dollar, they got 100 dollars.  They were used to entering in dollars and cents without the decimal point and having the calculator put the decimal point in for them.  I told them they just didn’t have to enter the trailing “.00” – that this was easier.  They told me that they were used to using calculators that added the digit and that “100” was “1.00” and that I had made things complicated. Simple to some, complicated to others.

The point is that something being “simple” or “complicated” is in the eyes of the beholder.

However, writing software that is simple and writing software that is simple to use is actually two different things.  There is a difference between a simple result and the process that achieved that result.  Very often it takes a lot of work to create a simple result. Steve Jobs said it this way – ““Simple can be harder than complex: You have to work hard to get your thinking clean to make it simple. But it’s worth it in the end because once you get there, you can move mountains.”

When we talk about simple code we are talking about having code that is easy to understand and to change.  We are wanting to avoid complex code as best as we can.  The process to achieve such code, however, may not be a simple process – note, however, that I am trying to say it has to be a complex process.  Again, let me provide an example.

More recently, I was helping a company with Lean-Agile team methods.  I was also concerned about the quality of the code they were writing, so I talked to them about object-orientation, coupling, cohesion and some other programming issues.  They assured me that they both understood these concepts and that they were following them.  I have heard this claim before where the code didn’t bear out he assertions.  I therefore asked to see some of their code and discovered something quite different.

What I saw was massive duplication throughout the code.  Not exactly copy-and-paste, but rather conceptually the same rule implemented in different, albeit similar, ways throughout the applications.  This was duplication of intention if not complete duplication of code.  This type of duplication is actually worse because it is virtually impossible to find with a search.  The challenge was that the rule for applying the discount varied according to four factors: location of client, type of client, order size and sales program the client had signed up for.  These values were stored in the following variables: ClientCountry, ClientType, OrderSize and ClientProgram, respectively.  The code for setting the discount was:

DiscountAmount= (

   ClientProgram == Premium ||

   ClientType== (ClientCounty== US) : SpecialUS, Special ||

   OrderSize > MinOrderForDiscount

   ) PremiumDiscount , 0;


Code Sample 1.

Before going on to my main point, I want to discuss an aside about what simple style might entail.  Some people, however, might consider the following to be simpler.

DiscountAmount= 0;

if (OrderSize > MinOrderForDiscount) DiscountAmount= PremiumDiscount;

else if (ClientCountry== US &&

   (ClientProgram == Premium || ClientType==SpecialUS) )

   DiscountAmount = PremiumDiscount;

else // note Special not SpecialUS

   if (ClientProgram == Premium || ClientType==Special)

   DiscountAmount= PremiumDiscount;



Code Sample 2.

Is one simpler than the other?  The first uses less code, the second is easier for to read for some.   The challenge is that if we don’t agree on what “simple” code means then a couple of things may happen:

  1. People won’t be trying to write code in the same manner – this will result in unclear code
  2. Methods that are natural for some may never become natural for others
  3. It may be difficult to see what is truly better code since a lot of thrashing will take place because people are changing each other’s code all with the intent of making it simpler

One challenge in writing “simple” code is that people often incorrectly (or I should say, partially) quote rules that actually do define simple reasonably well.  Many people recollect that eXtreme Programming (XP) defined simpler as having the smallest number of methods and classes.  I often hear folks talk about “this is simpler because it has fewer methods and/or classes.”  But that’s not actually what XP said. 

From the original XP Explained book, “simple” code was defined as:

  1. The system (code plus tests) clearly communicates everything that needs to be communicated at the current instant in its development. This means that it runs every existing test, and that the source code clearly reveals the intention behind it to anyone who reads it.
  2. The system contains no duplicate code, unless that would violate (1).
  3. The system contains the minimum number of classes possible without violating (1) or (2).
  4. The system contains the minimum number of methods possible, consistent with (1) (2) and (3).

There is clearly duplicate code here (shown in Code Sample 3 as bold text). 

DiscountAmount= 0;

if (OrderSize > MinOrderForDiscount) DiscountAmount= PremiumDiscount;

else if (ClientCountry== US && 

   (ClientProgram == Premium || ClientType==SpecialUS) )

   DiscountAmount = PremiumDiscount; 

else // note Special not SpecialUS

   if (ClientProgram == Premium || ClientType==Special) ) )

   DiscountAmount= PremiumDiscount;



Code Sample 3.

One could argue that both clauses are completely redundant at the conceptual level.  That is, the  clause ‘ClientType==SpecialUS’ and ‘ClientType==Special’ are both testing exactly the same thing – is the ClientType special?

Of course, the point of whether the code is simpler or not is not really important.  What is important is is the code easy to understand and change?  I suppose there is an underlying assumption here that simple code is easier to understand and change – but again, what does simple mean?

From the above definition we’d have to say code sample 1 is simpler than code sample 2. But we’re getting ahead of ourselves.  Let’s see what happened – how we went down the wrong path. The reality is that they didn’t start with the discount calculation above.  They had a simple rule – provide a discount for orders over a certain amount.  It seemed silly to have a one-line function because it didn’t save any typing and what was the point?  It was clearer to see the code in-line and not have to see what geTDiscount( OrderSize) meant.    The problem was that at some point the way to calculate the discount changed.

Now the programmers had a dilemma.  We could change all of the duplicate code, or we could just change the place where the new rule applied.  I’ll let you guess which route they took.   The mistake, however, hadn’t happened here, it had happened the moment someone decided to copy the rule instead of making the function.  I am not faulting the original mandate, but it is somewhat easy to understand what happened. Statement #2 says not to contain duplicate code unless having duplication communicates better.   Ah, well, didn’t we think it did?  The point, I think, is we forgot the intention of having simple code – that it be simple to change.  Besides the possibly ambiguous intention of statement #2 above, talking about minimum number of classes and methods leaves one after reading this with minimum more in one’s head than no duplication.

 Now, when the rule needed to change, it needed to be changed in many different places.  Developers working with time pressure (and I think this last phrase is redundant) will do what is expedient.  But even this wasn’t quite what happened.  Very often, the code needed to only change in one place – because it was an additional rule for the special case. The idea that we were specifying a rule at the conceptual level (what was intended) hadn’t really hit the coders for the application.  Different variations of the discount rule were needed in different places.  The focus was on code that was simple, easy to understand at the place it was used.  Adding methods didn’t seem to help.

I like the changes Kent made in the 2nd Edition of Extreme  Programming Explained by modifying the four requirements to:

XP teams prefer simple solutions where possible.  Here are four criteria used to evaluate the simplicity of a design:

  1. Appropriate for the intended audience. It doesn't matter how brilliant and elegant a piece of design is; if the people who need to work with it don't understand it, it isn't simple for them.
  2. Communicative. Every idea that needs to be communicated is represented in the system. Like words in a vocabulary, the elements of the system communicate to future readers.
  3. Factored. Duplication of logic or structure makes code hard to understand and modify.
  4. Minimal. Within the above three constraints, the system should have the fewest elements possible. Fewer elements means less to test, document, and communicate.

The focus on avoiding duplication is a bit clearer and the focus on minimal is lessened.  The problem with the original statement is that many folks remembered to minimize the number of classes and methods but didn’t quite get that that was within the context of eliminating all kinds of redundancy (code, logic and structure).  

This set of rules starts discussing the purpose of simplicity – we want to avoid what makes code hard to understand and modify.  This is more important than minimal.   What we need to remember is that we’re trying to write simple code, we’re not necessarily trying to follow a simple process.  Minimal, in our process, only makes sense within the context of factored.

However, I prefer to take this one step further.  Duplication of logic or structure makes code hard to understand and modify.“  I somewhat restate Kent’s intent with Shalloway’s law – “when N things need to change, and N > 1, Shalloway will find at most N-1 things” (for a full explanation as to how I came to this law see the further learnings at the end of this blog).  Shalloway’s law provides an easy way to determining if there is duplication.  If something changes that causes you to change more than one thing, then you have duplication. In some cases, some people call this coupling (and it is).  But I would suggest coupling is always due to a duplication of a concept in more than one place.   The solution to avoid redundancy is to follow Shalloway’s principle – “avoid situations where Shalloway’s law applies.”  At first glance it sounds like you must make N equal 1.  But another way to avoid Shalloway’s law is to make it so the compiler and/or linker can find duplication for you (that is, use methods to encapsulate an implementation).

I think this slant on Shalloway’s Law and Principle is useful because it gets us looking at using abstraction as a way of avoiding duplication that is hard to find.  By encapsulating all of the rules for a discount in one place, even though the code in that one place may be more complicated than a few simple lines, it is easier to understand because the total set of rules is all in one place (a quality we call focus).  This is a way of using abstraction to create simple code, where simple here means simple to change..

As stated earlier, this all could have been avoided if the original test for a discount were encapsulated in a function.  It is not a coincidence that one of the most useful practices (and a cornerstone of XP) is programming by intention. If the original developer had used programming by intention, it is likely the simple function would have been put in a function and as it evolved, had the variation of the rules been contained in it.  This points out an interesting parallel between  XP practices and design patterns.  One of the mandates of design patterns is to ”find what varies and encapsulate it.”  (<<<ADD PAGE NUMBER>>).  “What varies” is often taken to mean what varies in our design right now. But in the Agile world, I take it to mean what will vary over time. Hence, I would say that encapsulating the variation of a business rule in a method is following the thought process of design patterns – even though no design pattern per se is present.

One last point.  What is being suggested here is to find what is varying and encapsulate it in a method.  This is one of the three fundamental thought patterns that are the essence of thinking in patterns.  In our pattern oriented design course we summarize the advice from the Gang of Four:

  • Design to interfaces
  • Favor object delegation over class inheritance
  • Consider what should be variable in your design … and “encapsulate the concept that varies”    

(Gamma, Helms, Johnson, Vlissides: The authors of Design Patterns: Elements of Reusable Object-Oriented Design)

We are basically suggesting the same thing here, although in reverse order.  We are identifying that our discount rule may vary.  We are putting it in a function that will be called (delegating the responsibility to the function, and the method encapsulating this variation will be referenced via a method interface.  This may be a surprising result for some – that the thought process of design patterns and XP are the same.

Summary

Writing simple code is not always simple.  The process and the result are two different things.  Our code must be appropriate, communicate, be properly factored to avoid duplication and be minimal.  When considering these qualities we must remember that the qualities are sequenced – meaning minimal is after the first three qualities.

Setting up code to be able to be changed simply does not mean to avoid  methods, it means to not add what is not needed.  Perhaps surprising for some, the approach that XP espouses is very compatible with that of design patterns.

Simple code is not necessarily code written in the simplest manner, but rather code that can be most simply changed when it needs to be.

It is important to remember that simple may mean different things to different people.  In software development, we should focus on simple as a result, not a method.  Simple to change our code, simple to understand our code may be different from how we write code in a simple fashion.  When writing simple code we must also remember that the guidance we are given in to apply different rules within the context of each other.  While we may want to have fewer methods and classes, that is after we have considered avoiding redundancy.

Please provide feedback on our Lean Programming user group.

As always, if you think we can be of any assistance, please contact me at alshall AT netobjectives.com

Al Shalloway, CEO, Net Objectives

If you found this blog useful and want to learn more, we suggest the following:

Talk by Rich Hickey: Simple Made Easy

Upcoming Webinars: Essential Skills for the Agile Developer

Books

Past Webinar to view

Websites

Courses

Subscribe to our blog Net Objectives Thoughts Blog

Share this:

About the author | Al Shalloway

Al Shalloway is the founder and CEO of Net Objectives. With 45 years of experience, Al is an industry thought leader in Lean, Kanban, product portfolio management, Scrum and agile design. He helps companies transition to Lean and Agile methods enterprise-wide as well teaches courses in these areas.



        

Blog Authors

Al Shalloway
Business, Operations, Process, Sales, Agile Design and Patterns, Personal Development, Agile, Lean, SAFe, Kanban, Kanban Method, Scrum, Scrumban, XP
Cory Foy
Change Management, Innovation Games, Team Agility, Transitioning to Agile
Guy Beaver
Business and Strategy Development, Executive Management, Management, Operations, DevOps, Planning/Estimation, Change Management, Lean Implementation, Transitioning to Agile, Lean-Agile, Lean, SAFe, Kanban, Scrum
Israel Gat
Business and Strategy Development, DevOps, Lean Implementation, Agile, Lean, Kanban, Scrum
Jim Trott
Business and Strategy Development, Analysis and Design Methods, Change Management, Knowledge Management, Lean Implementation, Team Agility, Transitioning to Agile, Workflow, Technical Writing, Certifications, Coaching, Mentoring, Online Training, Professional Development, Agile, Lean-Agile, SAFe, Kanban
Ken Pugh
Agile Design and Patterns, Software Design, Design Patterns, C++, C#, Java, Technical Writing, TDD, ATDD, Certifications, Coaching, Mentoring, Professional Development, Agile, Lean-Agile, Lean, SAFe, Kanban, Kanban Method, Scrum, Scrumban, XP
Marc Danziger
Business and Strategy Development, Change Management, Team Agility, Online Communities, Promotional Initiatives, Sales and Marketing Collateral
Max Guernsey
Analysis and Design Methods, Planning/Estimation, Database Agility, Design Patterns, TDD, TDD Databases, ATDD, Lean-Agile, Scrum
Scott Bain
Analysis and Design Methods, Agile Design and Patterns, Software Design, Design Patterns, Technical Writing, TDD, Coaching, Mentoring, Online Training, Professional Development, Agile
Steve Thomas
Business and Strategy Development, Change Management, Lean Implementation, Team Agility, Transitioning to Agile
Tom Grant
Business and Strategy Development, Executive Management, Management, DevOps, Analyst, Analysis and Design Methods, Planning/Estimation, Innovation Games, Lean Implementation, Agile, Lean-Agile, Lean, Kanban