The Three Ways to Work with Code

Obviously you read code more often than you write it. Nothing new here. This fact is brought up often when the need for clean code is discussed. Or when the merits of different programming languages are weighed.

I think this two fold distinction is not sufficient. You write code. Thats fine. But when reading code, there are actually two different kinds of reading. Lets start with an example:

  1. val string = "Hello World"
  2. string should startWith ("Hello")

Even if you didn’t follow my articles about ScalaTest you can understand what this line of code is doing. In this sense reading this line of code is extremely easy. I call this ‘skimming’

But what if this line of code is not doing what you expected? Then you need to really understand the code. Then you want to understand what is going on. In the Scala example above you might consider the following options: Is startWith("Hello") a parameter to should? Or is "Hello" an argument passed to the result you get after passing startWith to should? What is should anyway? A method? An object? A function? An instance with apply method?

As you can see what was realy easy to skim now gets quite challenging to ‘understand’.

The same can be the case for libraries. Consider Hibernate. If you have setup Hibernate, CRUD operations on an entity are really easy to write and understand. But once you get one of the dreaded Hibernate exceptions (LazyInitializationException, NonUniqueObjectException, …) you want to really understand what is going on. And at that point many people realize they have no idea what is actually happening when they call session.update or just the getter of an Hibernate Proxy.

Obviously you want all three kinds of handling code to be as easy as possible, and writing might be the least important, because we read more code then we write. But how important is the ability to skim versus understanding?

With anything you use in an application you will do a lot of skimming. Thats why DSLs like the ScalaTest example above are such a great tool.

I suspect if you do complex things with a library or a language, understanding will always be hard. But in some cases it gets extra hard because non standard tricks are used. In Java a typical case of trick is Reflection and Byte Code Manipulation. Many of the more powerfull libraries use it to work around the limitations of ‘normal’ Java. The result is code that is easy to skimm but for many people next to impossible to understand. Examples are Mockito or Hibernate.

So when evaluating a library or writing one you might consider how much magic it is using.

The other way to limit the problem with ‘understanding’ code is to make it unessecary. I think Hibernate is an example where this failed. You have tons of places where you have to understand pretty exactly what Hibernate is doing in order to use it correctly.

Java itself is an example where this works pretty good. In many, many projects nobody has to actually understand how the JVM works. It just works. Only in rare cases you have to dive into the details of the garbage collector or the memory model.

The key here is a clean non leaky abstraction. If you have that it doesn’t matter what kind of magic you use to make it happen. But if your abstraction is leaky, parts of the magic you use inside will leak out with the risc of turning your project into something that acts like it is bewitched.

The Boiling Frog

I hope everybody among my readers is familiar with the concept of technical debt: If you do a quick hack to implement a feature it might be faster to implement in the short run, but you have to pay interest for the technical debt in the form of higher development and maintenance effort. If you don’t pay back you technical debt by refactoring your code, sooner or later your quick hack will have turned in a quick and highly expensive hack.

This metaphor works well to communicate the need for refactorings if at least one person realized the need for it.

But in various cases nobody in the project realizes that there is a problem until the team face a huge debt which seems impossible to pay back.

I see two possible reasons:

Being blind: There is a different level of cleanliness people consider clean enough. In interviews I have repeatedly talked to people considering a 20 line method a good thing and don’t have problem with nested control structures 5 levels deep. Those developers wouldn’t notice anything smelly when looking at code which I would consider CMD (Code of Mass Destruction). This problem is most of the time fairly easy to fix by teaching and coaching. But there is a more insidious possible reason:

Being a frog in boiling water: There is a theory that a frog which sits in cold water doesn’t jump out of the water if you heat it realy slow until it dies. Wikipedia isn’t decisive if this is actually true, but I definetly see this effect in software development. It looks like this: At some point you find something in your code that looks like it has an easy abstraction. So you build a little class encapsulating that behaviour and use that class instead. It works great, so that little class gets used a lot. Sometime later the class gets a new feature to handle a variation of the original case. And it goes on like this, until one day what was a simple abstraction has turned in a complex library, possibly even a framework. And now that framework is a problem on its own. Its getting hard to understand how to use it.

And you realize you are a poor little frog sitting in boiling water with no idea how he got there. Hint: It’s a good idea to jump even when it is a little late.

Why does this happen? Just as the frog has a problem sensing the small change in temperatur and realizing he is getting into trouble the developer doesn’t see he is hurting the quality of the code base until it is to late.

Again: Why? Let’s make the example a little more specific. You have blocks of 10 lines of simple repetitive code in N places in your code base. You replace it with a call to a simple class of 40 lines of code. So you save (9*N – 40) lines. On the call site your code gets significantly simpler, of course the class is a little more complex but thats ok. Now while implementing a new feature you are about to create another of those 10 line blocks. Obviously you want to use the helper class. But it’s not fit for the job. You need to add a feature to it. That’s ok. You also have to add something to the public API to turn that feature on or of. Maybe it’s a new constructor, a new method or an additional parameter. That’s not ok. Until you changed the API of your class the changes where local to the helper class and its usage at the new site. But when you changed the API, you added complexity to all the call sites of your class. Whenever you now call that helper you have to think a little more about the correct API to use. This unfortunatly isn’t easy to see. So it can easily happen that your API turns slowly so complex that using it is more painfull then just writing the 10 lines it replaces down.

Essential Stories for any Enterprise Application Product Backlog

Most of the customers I work with are huge companies. When trying to get an application accepted in such an environment some are a real no brainer. Like Websphere Application Server. While others like Jira are really hard to get some resources for. I couldn’t help wondering, what the reasons are for this. Let’s face it, from the simple examples above it is obviously not related to anything known as quality.

Through careful reengineering I discovered a list of essential features an application must have and compiled it as backlog items ready to use for your product backlog.

As a procurement manager I want the application to be expensive, in order to live of the bonus I guess when I negotiate a 1% reduction in price.

Acceptance criteria:

  • The price of a minimal installation is at least 5 figures
  • The price for a full installation is at least 500.000 Euro
  • Bonus points when there is a mandatory support option

As a procurement manager I want the application to scale only by upgraded to an enterprise super deluxe edition, so my daughter can have a horse for Christmas.

Acceptance criteria:

  • A demo setup needs at least 8GB RAM and 4 cores
  • A system for 100 users needs at least 5 such machines, plus the same number of machines as a hot backup which you need at least once a month.
  • You need 20 machines when 10 of the 100 users want to use it concurrently.

As an administrator I want the application to have only minimal documentation if at all, so I can claim to be an expert after reading all of it in an hour and charge a higher salary.

Acceptance criteria:

  • The documentation is preferable non existent.
  • Lengthy documentation is acceptable as long as it written so bad that nobody gains any knowledge from reading it.

As an administrator I want the application to be void of any user community, so nobody can provide easy free solutions to problems I claimed to be really hard.

Acceptance criteria:

  •  the apropriate tag at stackoverflow has a maximum of 200 followers and less then 1000 questions.
  • If you are looking for a real expert (one that actualy understands the product) you have to pay other my monthly salary as an hourly wage or look in a mental asylum.

As an administrator I want the application to rely heavily on as many other products as possible, so the beneficial effects of the application on my workday are multiplied.

Acceptance criteria:

  • The application needs a database management system installation from a specific vendor. The database itself needs to qualify as an enterprise application according to this criteria
  • The application needs at a queuing system, even when it doesn’t have any interface to any other system but itself.

As a person responsible for deploying clients I want the application only to run on IE6 or earlier so the people stop asking me for upgrades to Windows 7 or god behold these Apple thingies.

Acceptance criteria:

  • When the application is run in an IE 7 or above a message appears: “You are not running a compatible browser, please upgrade to IE6″
  • When any other browser is used the application should react with a http 500 or it should crash the browser.

As the manager responsible for deployment of the system I want the system to be still in development, so I never have to install anything.

Acceptance criteria:

  • The application is labeled early beta or preferable with
  • “latest build from Toms machine”

As a consultant recommending the application I want the application to be really hard to install and equally hard to keep alive, so my contract stays safe for the next years to come.

Acceptance criteria:

  • The short installation overview has at least 50 steps
  • a skilled person can’t install the system in less then 3 days.

As a network administrator I want the application to really hog the network, so I can get a larger budget for new shiny hardware.

Acceptance criteria:

  • the application uses protocols like http in a way that makes caching completely impossible.
  • the application downloads itself completely on every restart.

As a user I want the application to be really slow so I can’t blame the application for not getting anything done

Acceptance criteria:

  • every interaction with the application (like moving the mouse) causes the application to freeze for at least one second.
  • every use case requires at least 10 such interactions.

As a user I want the application to start up really slow so I can get some coffee and drink it too in the meantime.

Acceptance criteria:

  • Startup needs at least 10 minutes
  • The application needs to restart at least twice a day.

As a CIO I want the application to use single sign on so I can claim we are doing it without bothering with what it actually means.

Acceptance criteria:

  • The application contains its own single sign on system
  • The applications SSO solution is completely incompatible to anything else (other wise we would get asked to integrate them)

As a person responsible for the security of the system I want the application to have cryptography because it is soooo coool.

Acceptance criteria:

  • The application contains some cryptography code, preferable with nice acronym like ROT13
  • The cryptography is really hard to configure, so something easy like SSL isn’t acceptable
  • All private keys involved need to get emailed to the support distribution list, along with the password (thats what our processes require)
Posted in: Management by Jens Schauder 1 Comment ,