I recently removed a lot of dead code from our code base at work. There were several similar directories, dead files, and unused code within live files.
All this unused code was a major nuisance for over a year. It would cause grep to show too much information -- most of it meaningless -- and it would even cause your IDE to jump to the old unused class file, rather than the one you actually wanted.
People were afraid to remove this code for fear of breaking things. After all, it was tied to our main shared library that could cripple over 200 of our websites at once. But enough was enough. I decided to embark on removing it. I have a lot of experience with removing dead code but rarely this high of a risk and with so much of it. I had only one day to figure it out, delete it, and test it. Otherwise, it would have to have be rolled back, for who knows how long, until anyone would attempt to remove it again.
Before removing code like this, I ask myself if it's good code that we might want to start using soon - or even right now under a configuration option. If it's useful code I wouldn't just delete it. Rather, I'd extract it out into classes that could become part of our library.
In my case it really was all just useless code. Some programmer from long ago had been a little too happy to copy and paste code to new files, leaving the old dead files lying around.
Some other code was living in live files but was effectively in a "dead block" because it would only happen under a condition that would never happen. I decided to remove this as well because such code will only confuse programmers every time they see it. In fact, I was about to spend time converting it to work with our new platform. What a waste of time that would have been! Fortunately, dead code like this is often easy to determine as dead, because you go to refactor it and can't figure out how to get it to run under that condition from the user interface. This is why it's we shouldn't rely solely on unit tests.
A coworker suggested that I keep the condition in the code at first, replacing the body of useless code with code to log a message such as "This condition should never happen." This way we could monitor the logs once it was deployed for a while, and really make sure the code wasn't being used by anything.
The easiest dead code to spot is commented-out code. Go ahead and remove this any time you see this. It will only sit there forever, no one will ever uncomment it, and if they really do need it that's what source control is for.
For those times that it's hard to tell if code is dead or not, the main tool I used to figure it out is grep. More specifically I use ack-grep. The key is to trust your grepping abilities and be extremely thorough. If you can prove that certain code isn't being referenced via other files, that's a huge step toward having the confidence to remove it.
Of course, it's not always that easy. Sometimes the code is referenced but that's okay; replacing it to use the proper files instead is certainly worth the effort.
Once you have removed the code, and all is working in your development sandbox, it's time to deploy it. It really isn't much different than writing new code or refactoring existing live code. Any time you commit code it could cause other things to break. This is why we do regression testing.
I highly recommend that you wait to push this kind of change out when there's no other important code that needs to be deployed too. If the "new" code is found to not be in a working state, then your code removal attempt will be the first source of blame and you will likely have to rollback and risk never getting to try again -- even if it wasn't the problem.
So go ahead and remove that dead code the next time you see it. You'll thank yourself later and so will your coworkers.
Showing posts with label clean code. Show all posts
Showing posts with label clean code. Show all posts
Tuesday, December 6, 2011
Friday, September 9, 2011
Readability Counts
In 2006, psychologist Daniel Oppenheimer won an Ig Nobel Prize for his research paper "Consequences of Erudite Vernacular Utilized Irrespective of Necessity." He researched vocabulary used in everything from resumes to academic essays, and found that the easier the texts were to read, the higher the readers judged the author's intelligence. This included anything that made the text hard to read, including "big" words and even the font type used.
It helps me to remember that coding is explaining. And not just to the computer, but to yourself and to others.
The nice thing is that you don't have to write perfect code (which is impossible anyway). It just needs to be understandable to you and others. If you can write code simply so that everyone can understand it, then you will come across as a much better programmer than you otherwise would.
The cleaner your code becomes the more side-benefits you will also notice such as having less fatigue when working with it and having less bugs!
If you run the python prompt and enter:
>>> import this
It will output "The Zen of Python" message by Tim Peters:
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
It's pretty sad that we still need to remind each other that readability counts (which was pointed out in the May of 2010 "Zen of Python" episode of the "From Podcast Import Python" podcast).
Sometimes the problem is that the code author has yet to read a book on how to write readable code. But they are definitely out there.
A book written in the 1970's by Brian Kernighan, a little before I was even born, entitled "The Elements of Programming Style" spoke of how the best documentation for a computer program is a clean structure. It also helps if the code is well formatted--with good mnemonic identifiers and labels. And a smattering of enlightening comments.
And again in 1999, Brian Kernighan coauthored another great book with Rob Pike called "The Practice of Programming" and outlined that the main principles are: "Simplicity," which keeps programs short and manageable; "Clarity," which makes sure they are easy to understand, for people as well as machines; "generality," which means they work well in a broad range of situations and adapt well as new situations arise; and "automation," which lets the machine do the work for us.
A few other seminal works, such as "The Pragmatic Programmer: From journeyman to master", Code Complete: A practical handbook of software construction", and of course Bob Martin's "Clean Code: A handbook of agile software craftsmanship", all go into great detail on how to write readable and maintainable code.
From my experience, a general rule is if you're looking at a piece of code and all you can say about it is "Boy, this sure is convoluted", then it's probably not clean code. If you can understand the code right away, it may or may not be well-written; perhaps you're just used to reading poorly written code. However, if it seems like the code is so nice that it actually gives you a good feeling -- or at least doesn't give you a headache from squinting -- then it's clearly readable code.
A few of the main guidelines for writing readable code are:
- Your functions / classes should be doing only one thing each.
- Your variable names should not require comments
- Use adequate whitespace and consistent indentation.
There are many more things you can do, and that differ between a normal code base and when designing APIs, and I refer you to the aforementioned books.
References:
59 Seconds: Change your life in under a minute
Science Daily
From Python Import Podcast
It helps me to remember that coding is explaining. And not just to the computer, but to yourself and to others.
The nice thing is that you don't have to write perfect code (which is impossible anyway). It just needs to be understandable to you and others. If you can write code simply so that everyone can understand it, then you will come across as a much better programmer than you otherwise would.
The cleaner your code becomes the more side-benefits you will also notice such as having less fatigue when working with it and having less bugs!
If you run the python prompt and enter:
>>> import this
It will output "The Zen of Python" message by Tim Peters:
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
It's pretty sad that we still need to remind each other that readability counts (which was pointed out in the May of 2010 "Zen of Python" episode of the "From Podcast Import Python" podcast).
Sometimes the problem is that the code author has yet to read a book on how to write readable code. But they are definitely out there.
A book written in the 1970's by Brian Kernighan, a little before I was even born, entitled "The Elements of Programming Style" spoke of how the best documentation for a computer program is a clean structure. It also helps if the code is well formatted--with good mnemonic identifiers and labels. And a smattering of enlightening comments.
And again in 1999, Brian Kernighan coauthored another great book with Rob Pike called "The Practice of Programming" and outlined that the main principles are: "Simplicity," which keeps programs short and manageable; "Clarity," which makes sure they are easy to understand, for people as well as machines; "generality," which means they work well in a broad range of situations and adapt well as new situations arise; and "automation," which lets the machine do the work for us.
A few other seminal works, such as "The Pragmatic Programmer: From journeyman to master", Code Complete: A practical handbook of software construction", and of course Bob Martin's "Clean Code: A handbook of agile software craftsmanship", all go into great detail on how to write readable and maintainable code.
From my experience, a general rule is if you're looking at a piece of code and all you can say about it is "Boy, this sure is convoluted", then it's probably not clean code. If you can understand the code right away, it may or may not be well-written; perhaps you're just used to reading poorly written code. However, if it seems like the code is so nice that it actually gives you a good feeling -- or at least doesn't give you a headache from squinting -- then it's clearly readable code.
A few of the main guidelines for writing readable code are:
- Your functions / classes should be doing only one thing each.
- Your variable names should not require comments
- Use adequate whitespace and consistent indentation.
There are many more things you can do, and that differ between a normal code base and when designing APIs, and I refer you to the aforementioned books.
References:
59 Seconds: Change your life in under a minute
Science Daily
From Python Import Podcast
Subscribe to:
Posts (Atom)