Where leading programmers explain how they find
unusual and carefully designed solutions

Alberto Savoia

Recent Posts

Alberto Savoia

This blog is a follow-up to a previous entry in which I wrote about how thinking about beautiful code also made me think about the opposite end of the spectrum - the kind of code that most developers somewhat rudely refer to as "crap".

If I had to write a tool that would attempt to decide if a particular piece of code could be considered beautiful, I would not know where to start. Detecting crappy code, however, seemed more within reach; so we threw caution to the wind and we gave it a shot. Read on and you can decide if that shot would have been better used on something else (like our foot).

[Cue in sound of a giant can of worms being opened]

Disclaimer

The CRAP metric and the crap4j plug-in are, at this point, highly experimental in nature. The CRAP formula is based on what we believe are sound principles and ideas; but at this time the actual numerical values used in its calculation and interpretation should only be considered a starting point. We plan to refine the metric as we gain experience. Of course, it's also possible that we'll "scrap the CRAP" if we determine that it's not useful.


If you are adventurous and care enough about the topic, read on, download the plug-in, run it on some code, and work with us to improve it (or at least give us feedback, good or bad). Otherwise, I suggest you check back in a few months - after we've gained some experience with this early prototype and did the first round of tuning and cleaning up.

Introduction

There is no fool-proof, 100% objective and accurate way to determine if a particular piece of code is crappy or not. However, our intuition – backed by research and some empirical evidence – is that unnecessarily complex and convoluted code, written by someone else, is the code most likely to elicit a “This is crap!” response. If the person looking at the code is also responsible for maintaining it going forward, the response typically changes into “Oh crap!”

Since writing automated tests (e.g., using JUnit) for complex code is particularly difficult, crappy code usually comes with few, if any, automated tests. The presence of automated tests indicates not only some degree of testability (which in turn seems to be associated with better, or more thoughtful, design), but also that the developers cared enough and had enough time to write tests – which is a good sign for the people inheriting the code.

Because the combination of high complexity and lack of tests appears to be a good indicator of crappy code, my Agitar Labs colleague Bob Evans and I have been experimenting with a metric based on those two measurements. The Change Risk Analysis and Prediction (CRAP) score uses cyclomatic complexity and code coverage from automated tests to help estimate the effort and risk associated with maintaining legacy code. We started working on an open-source experimental tool called “crap4j” that calculates the CRAP score for Java code. We need more experience and time to fine tune it, but the initial results are encouraging and we have started to experiment with it in-house.

Crap4J is currently a prototype and it’s implemented as an Eclipse (3.2.1 or later) plug-in which finds and runs any JUnit tests in the project to calculate the coverage component. If you are interested in contributing to crap4j’s open-source effort to support other environments and test frameworks (e.g. TestNG) and/or coverage tools (e.g. Emma) please let us know. Instructions for installing the crap4j plug-in are below, but first let’s re-introduce our first pass for the CRAP formula.

> continue reading
Alberto Savoia

Note for the easily offended: I know that these blogs are supposed to be about beautiful code, but I believe that by exploring its opposite – nasty, ugly, horrific code – we will enrich our discussions of, and appreciation for, code beauty. I am also aware that the opposite of beautiful is ugly, not crap; and I realize that the term crap is mildly vulgar. I decided to use the word anyway because that’s the term most programmers use when referring to offensively ugly code. In other words, I heard the expression “This code is crap!” much more often than “This code is ugly!” Besides, Wikipedia says that “… [crap] is considered mild enough that even a child may use it informally.” So there :-).

Hell is other people. - J. P. Sartre

Hell is other people’s code. - T-Shirt seen recently in Mountain View, CA

While writing my chapter for Beautiful Code, I was forced to think beyond code functionality and efficiency. I had to think about beauty in code. And thinking about what makes a particular piece of code beautiful also made me think about the complementary question: What makes a particular piece of code crappy?

In the last few months, this question has led to heated conversations with colleagues, friends in the business, and random software engineers sitting next to me at the local coffee house. It would be naïve to expect programmers to unanimously agree on anything, but on the subject of crappy code most people I talked with agreed on a few of things:

> continue reading
Alberto Savoia

In Part I, I mentioned one of the dilemmas voiced by developers who want to inject some beautiful code in their day-to-day activities:

“I am maintaining a steaming pile of legacy code that I have inherited. I can barely keep the code base working – sort of. I would love to write some beautiful code, but have no time to think about beauty as long as I am saddled with this ugly code base.”

This is a very common situation. Most developers spend most of their time maintaining/enhancing code that they did not write and, more often than not, that code base is not just ugly, but coyote ugly*.

So, what’s a developer to do when stuck with code so bad that it should come with an “abandon all hope ye who enter here” warning? There are three basic options (besides the extreme the coyote option – which I don’t want to offer for legal liability reasons):

Option 1: Run for the hills (i.e., ask, beg, bribe for another assignment – or quit).

Option 2: Accept the job with resignation. Abandon hope and prepare yourself for a coding life of quiet desperation highlighted by moments of sheer panic. Help to prove that Thomas Jefferson was spot-on when he said: "Mankind are more disposed to suffer, while evils are sufferable, than to right themselves by abolishing the forms to which they are accustomed.”

Option 3: Accept the job as a challenge. Accept that the code base is ugly; it’s OK – therapeutic even – to make fun of it and of the careless, incompetent, so-called-programmers who developed it. Accept the fact that you cannot single-handedly turn a huge steaming pile of legacy code into a thing of beauty. But be determined and committed to reject and eliminate ugliness in the bits of code that you do touch. In other words: scorn globally, act locally.

The first option is probably the smartest one but, with so much crappy legacy code out there, you might have a hard time finding a suitable job. The second one is the easiest, but is not something that I would ever consider or recommend. The third option is the hardest to embrace, at least at the beginning, but the noblest and the one I want to talk about.

Since it’s unlikely that you will have the option to make sweeping design or architectural changes, the key to success in working with a pile of ugly code is to focus on small improvements. When you run into an ugly bit of code that you can or must change, make a conscious decision to make it more beautiful.

This, of course, raises the issue of what “more beautiful” means. If you have read Beautiful Code, you have probably realized that each author had a personal definition, or bias, for what constitutes beauty. The good news is that since you are the one working on the code, you can apply your own criteria for beauty.

Here are just a few of the many localized actions that you can practice – assuming you agree with my criteria for beauty:

- Write tests for a particular piece of code before you change it. A test suite is a beautiful thing to have and it will give you a safety net as you make those changes. If you are working with legacy code, you should become an expert at writing characterization tests**.

- Refactor to reduce complexity and improve testability. Method extraction is my favorite refactoring; it’s fast, safe (especially if you have tests), and easy to revert if needed. In my book, any method with a cyclomatic complexity of 8 or more is a candidate for refactoring.

- Rename cryptic or ambiguous identifiers. This is a pet peeve of mine. In this age of cheap computing resources there’s no excuse for using a variable name like “ac” instead of “areaCode”.

- Delete. If you can identify dead, useless, or obsolete code, get rid of it.

Sounds like easy and obvious advice, doesn’t it? Well, it might be easy and obvious but, unfortunately, it’s rarely practiced. Otherwise I would not have bothered to write this. The reality is that, in most cases, ugly code becomes uglier as it’s maintained or enhanced. As a matter of fact, a lot of code starts out pretty nice and clean (both in design and implementation) and degrades as time goes on. It happens gradually. It’s done innocently. In the short term, adding yet another if statement inside a nested for loop is faster and easier than taking some time to think of a way to refactor the code to reduce complexity; it does not look like a really bad thing. But over time, these actions add up.

Taking time to write a little test, perform a simple refactoring, or rename one variable, does not sound like much; but it represents a huge – HUGE – change in attitude and a rare and courageous stance toward legacy code. It means that you don’t accept the inevitable slide from ugly code to uglier code.

Reducing ugliness in legacy code one method at a time, may not be as glamorous as creating a few lines of beautiful code suitable for framing, but I would argue that it might be just as important and a far nobler thing to do – and you’ll never run short of opportunities to practice it.

Alberto

* Coyote ugly: code so ugly that some developers might prefer to chew their fingers off rather than work on it – much in the same way that a coyote captured in a jaw trap will chew off its own leg to escape certain death. Sorry if this is a bit too graphic.

** Characterization tests: a term coined by Michael Feathers in his excellent book Working Effectively With Legacy Code to describe tests that capture not the specified, but the actual, behavior of a piece of code. See: Characterization Test and Working Effectively With Characterization Tests

Alberto Savoia

You are a bright-eyed and bushy-tailed developer. You have just finished reading Beautiful Code and you are ready to create some beautiful code of your own. You can’t wait to put what you’ve learned into action. You fire up your IDE. As the blob of code that you’ve inherited and have to work with slowly loads, the brightness in your eyes is replaced by a glazed look. A minute later your bushy tail hangs limply in defeat. Reality sets in. Beautiful Code goes back on the shelf, next to Programming Pearls and Six-Pac Abs in Seven Days. You drink a sip of tepid coffee, sigh, and start hacking at the blob of code with the same level of energy and enthusiasm commonly displayed by those people in orange vests picking up litter on the side of the highway.

The two most common comments I’ve heard on the topic of beautiful code, following the release of the book, go something like this:

Comment 1:

“I have read a few chapters of Beautiful Code. It’s a great book, but in my job I have to maintain a ‘steaming pile of legacy code’. I don’t have many opportunities to think about beauty because I barely have time to keep the existing code functional. The best I can do it to keep crappy code from getting worse.”

Comment 2:

“Very interesting book. I wish I had an opportunity to think about cool algorithms for tough problems, but I am working on a boring enterprise application. I read stuff from a database, do something trivial to it and then I generate some reports. There aren’t that many opportunity for clever algorithms and beautiful solutions in business logic.”

It’s easy to sympathize with, and understand, both comments. The odds of finding truly beautiful code in most production systems seem to be on par with the odds of finding a well-read copy of IEEE Transactions on Software Engineering in Paris Hilton’s apartment. Furthermore, enterprise software, which represents the bulk of code in existence, deals mostly with forms, reports, etc., which – one might argue – seldom require much thinking or cleverness.

Let’s face it, the majority of code that has to be written does not offer chances for the kind of beauty and cleverness that would earn it an entry in Beautiful Code – Part II. For every opportunity to implement something cool and clever, like MapReduce (see Chapter 23), there are hundreds of blue-collar pieces of code that have to be written or maintained.

Does that mean that you should stop thinking about beautiful code in your day-to-day programming? Should you save those lofty ambitions for your after-hour pet projects – or abandon them altogether? Of course not!

The opportunities for creating a true masterpiece of coding worthy of sharing and bragging about may be rare, but you have dozens of chances everyday to make the code base you work with more beautiful – even if you are stuck working on a mortifying morass of legacy code. That’s what my series of blogs “Beautiful Code in the Real-World” will be all about.

In the next few days and weeks, I will use these blogs to share with you thoughts, strategies, and ideas for creating beauty in everyday production code – even if that code looks as if it fell off the ugly tree and hit every branch on the way down.

Make sure you come back for Part II – Scorn globally, act locally.

Alberto Savoia

My chapter in Beautiful Code is called "Beautiful Tests". In the chapter, I focus on a specific example of how a developer can use tests to make the code not only more robust, but also more beautiful.

I really enjoyed sharing my thoughts, and thought-processes, on developer testing using lots of actual code on a very specific example. But, as I was writing this chapter, I kept feeling a strong urge to also write something at a higher-level; something a bit more general and philosophical, to complement it.

The result is The Way of Testivus - Less Unit Testing Dogma, More Unit Testing Karma, a small booklet with twelve epigrams that summarize my philosophy on developer/unit testing.

Below are two of the epigrams; if you want to read more you can download the entire "The Way of Testivus" booklet.

If you write code, write tests

The pupil asked the master programmer:

“When can I stop writing tests?”

The master answered:

“When you stop writing code.”

The pupil asked:

“When do I stop writing code?”

The master answered:

“When you become a manager.”

The pupil trembled and asked:

“When do I become a manager?”

The master answered:

“When you stop writing tests.”

The pupil rushed to write some tests. He left skid marks.


Think of code and test as one

When writing the code, think of the test.

When writing the test, think of the code.

When you think of code and test as one,

testing is easy and code is beautiful.