Recently in Code craft Category
Here's a little article about the "file header tax", lines of boilerplate at the top of files that serve no purpose. Copyright notices, disclaimers, maybe even some revision history, it's all just clutter, and clutter is technical debt.
Take a look at the next file you edit. Is there anything at the top of it that is not functional code? Ask yourself if it really needs to be there. If in doubt, throw it out.
Jared Parsons writes about how Part of being a good programmer is learning not to trust yourself. It's filled with basic but all-too-often-forgotten wisdom about defensive programming. Key bits: "Turn assumptions into compiler errors," "The best way to avoid making bad assumptions is to actively question them at all times," and "1 test is worth 1000 expert opinions."
I also chuckled to see a sidebar disclaimer that said "All code posted to this site is covered under the Microsoft Permissive Lice." I'd heard of parasitic licensing before, but never like this!
Dropping vowels to shorten names is a terrible practice. Quick, someone give me an idea what $hdnchgdsp means, an Actual Variable from some Bad Code I'm working on today.
It's not just variables names, either. Filenames often need to be shortened, but dropping vowels is not the way to do it. You're left with unpronounceable names that are annoying to type.
The key to effective abbreviation is not removal of letters from the middle of the words, but from the end. Sometimes, it doesn't make sense to shorten a word at all, like "post". If you have a file that is supposed to "post audit transactions", call it "post-aud-trans" or "post-aud-trx", not "pst_adt_trns".
Here's how to not do a Changes file:
http://search.cpan.org/src/FELICITY/Mail-SpamAssassin-3.1.5/Changes
That tells me nothing about whether I want to upgrade my SpamAssassin install. :-(
Oh, look, I wrote about this before, and how great Tim Bunce's Changes files are.
From David Fetter's page at http://fetter.org/optimization.html:
- The first rule of Optimization is, you do not talk about Optimization.
- The second rule of Optimization is, you DO NOT talk about Optimization.
- If your app is running faster than the underlying transport protocol, the optimization is over.
- One factor at a time.
- No marketroids, no marketroid schedules.
- Testing will go on as long as it has to.
- If this is your first night at Optimization Club, you have to write a test case.
Of course it's company policy never to imply ownership of a performance problem. Always use the indefinite article: "a performance problem", never "your performance problem."
Inspired by a post in the Beautiful Code blog, Simon Wistow created Acme::Numbers, which lets you do cleverness like this:
use Acme::Numbers; print two.hundred."\n"; # prints 200 print forty.two."\n"; # prints 42 print zero.point.zero.five."\n"; # prints 0.05 print four.pounds.fifty.five."\n"; # prints "4.55" print four.pounds.fifty.pence."\n"; # prints "4.50" print four.dollars.fifty.cents."\n"; # prints "4.55"
You probably wouldn't want to do this in production code, but like the best of Damian Conway's not-useful-but-thought-provoking modules, it may spark some ideas that you can apply to more useful situations. If nothing else, the source is a fine lesson in overloading and method importing.
For the past few months, I've been slogging through some PHP code written by a solo programmer with no real oversight from other programmers. His code is a monoculture.
I found this bit of code today that just sums up his unwillingness, or perhaps inability, to refactor.
if (substr($libtest,0,12) == "FOO COUNTY")
$foocounty=$getmultiples=1;
if ((substr($libtest,0,12) == "FOO COUNTY") && ($state=="TX")) {
$foocounty=$getmultiples=0;
$foocountytx=$getmultiples=1;
}
Just read those lines of code and you can recreate the crime in your head. First there was a customer in Foo County. Then, we had to handle a different Foo County, but this Foo County was in Texas. He couldn't even be bothered to change the initial test to be more specific, or to modify the existing code. His solution was the simplest thing that could possibly work, and was also the worst: Reversing the effect of the first check for Foo County. There's also no checking for non-Texas, non-original Foo County, but when I checked I found that we have customers that are in Foo County in THREE different states.
The programmer no longer works for us, so I'm unable to ask him about his motivations. I'm fascinated by the mindset that is unable to do the barest rework necessary.
Max Kanat-Alexander has a new blog up called Code Simplicity, and I'd love it for the name alone. His latest post, "Designing Too Far Into The Future", talks about the perils of trying to predict the future and guess what your code will have to do down the road. In the XP world, the term that gets thrown around is YAGNI, for "Ya Ain't Gonna Need It." When you have to write a report and you start by writing a report generator, that's a big violation of the principle of YAGNI.
Working on my Big Dirty PHP Project at work, I've found this bit of code in many places.
$categories = ""; $categories = Array();
Why is $categories set to an empty string, and then an array? It's not necessary to pre-initialize a variable before setting it to another value. So why is the code there? It's not just one case. It's throughout the codebase, where I delete the first line whenever I find it.
The original programmer is (thankfully) no longer around to ask, but I'm guessing it's superstition. Perhaps he had some problem that went away for an unrelated reason when he added the first line of the code. The problem is that he never considered why.
Here's another coding horror to avoid in Perl. Ever seen a regular expression by someone who wasn't entirely familiar with regexes and quoted everything whether it needed it or not?
if ( $name =~ /Marcus Holland\-Moritz/ )
The hyphen in Marcus's name isn't a metacharacter, but the unsure, superstitious programmer will quote it anyway. "Eh, it doesn't hurt anything," he may reply, but it also demonstrates his non-mastery of regexes.
If you ever find a piece of your code where you can't understand exactly why it works, why every single statement exists, stop and rework it until you do.