Code doesn’t change. It mutates.
A healthy codebase is one that is thriving with life and activity. Much like the genetics of any living thing, it requires constant mutation to evolve and harness new capabilities. The cost of all of this mutation can be messy, and if not carefully checked, inaction can lead to death.
Dead code — unused, old, brittle, or broken — must be expunged early and often for the continued health of a system. Commenting out and committing doesn’t count. Refactoring and not updating documentation or tests is a cardinal sin.
If you’ve ever played with a big box of lego bricks, you’d probably find that unless you were following specific directions, there’s a decent chance that your awesome spaceship ended up with a few weird appendages or blocks that were out of alignment. Over time, unless corrected, those blocks end up as a permanent blemish on the overall structure.
Our codebases are no different. Perfection isn’t the goal, it’s the baseline.
What defines perfect, though? Perfect is the enemy of good, isn’t it?
I think simplicity is perfect. Simple is elegant. Simple works.
Complex solutions to problems show defects in our comprehension of a feature, or of how that feature works within the larger system. When you feel like you have to retrace your steps when working with a file, that’s a sign that your code is getting too complex, and you should think about refactoring, time permitting.
The more complex your solution gets, the more mutations that it will have over time, and the more likely it’ll become the root cause of a problem rather than the fix to another.
Define a functional vocabulary.
You write software for two specific groups. The compiler, and the consumer. The consumer for what you write is other developers. Thus, agreeing to idioms in communication are key in order to participate in the discussion.
Don’t really worry about the compiler. It’s basically a blithering idiot. Assuming that a compiler were clever would remove the need for our job. Developers, though— that’s another story.
Imagine for a moment that you’re sitting in a meeting at work. People are talking about a new feature that needs to be implemented, and you are tapped to make the feature and push it live, all within a week.
People are throwing around acronyms and words that you don’t know. You’re handed a diagram of what you can only assume are a tube sock and a bottle of nail polish, and that’s it, you’ve got a week. Good luck.
So now you get to run head first into a project that you’ve never worked in before and figure out how to tell it what a tube sock is an how to make it this shade of nail polish in a week.
Senior programmers that I’ve worked with who were worthy of the title are able to find similarities into objects and move those from ‘gym sock’ into ‘tube sock’ and go from that point. Less senior developers tend to try to tell a dumb compiler exactly what a ‘tubè söck’ looks like. junior programmers attempt to find a tube sock online and copy and paste that into our project, only to spend the other 4.99 days figuring out why the tube sock looks more like a thimble and is blue.
People have argued with me at length that their code is readable, thus is discounted from having the same rules as all other code in a project. Readable code therefore is elegant enough for any common developer to read and understand how it is used, and in which context.
Reality is different. Your readable code is just hubris. You wrote a feature that may not be documented, and may not have gone through a refactoring phase and got cleaned up to standard because it’s ‘readable’.
So really, your readable code flies in the face of standards. All it does is throw the reality of the situation into the other programmers who have to maintain that feature in the future — perhaps when you’ve long since left — and they have to decode not only the instructions for the computer but the instructions for humans.
Be simple. Focus in the small. Ruthlessly analytize what you’re creating or modifying, and make a note of it in docstrings or full documentation blocks. Tell yourself what you’re going to do, and then implement that sentence. When you’re finished, take that sentence and write a test, then you can move on.
Review code as though you’ve never seen the system it exists in. Does it make sense? Overly esoteric classes only work for the extreme cases, and only with the proper ridiculous and long comment explaining the straying from the norm.
// Dear maintainer:
// Once you are done trying to 'optimize' this routine,
// and have realized what a terrible mistake that was,
// please increment the following counter as a warning
// to the next guy:
// total_hours_wasted_here = 42
//When I wrote this, only God and I understood what I was doing
//Now, God only knows
/// Class used to work around Richard being a fucking idiot
/// The point of this is to work around his poor design so that paging will
/// work on a mobile control. The main problem is the BindCompany() method,
/// which he hoped would be able to do everything. I hope he dies.
* You may think you know what the following code does.
* But you dont. Trust me.
* Fiddle with it, and youll spend many a sleepless
* night cursing the moment you thought youd be clever
* enough to "optimize" the code below.
* Now close this file and go play with something else.
At this point, I'd like to take a moment to speak to you about the Adobe PSD format. PSD is not a good format. PSD is not even a bad format. Calling it such would be an insult to other bad formats, such as PCX or JPEG. No, PSD is an abysmal format. Having worked on this code for several weeks now, my hate for PSD has grown to a raging fire that burns with the fierce passion of a million suns.
If there are two different ways of doing something, PSD will do both, in different places. It will then make up three more ways no sane human would think of, and do those too. PSD makes inconsistency an art form. Why, for instance, did it suddenly decide that *these* particular chunks should be aligned to four bytes, and that this alignement should *not* be included in the size? Other chunks in other places are either unaligned, or aligned with the alignment included in the size. Here, though, it is not included. Either one of these three behaviours would be fine. A sane format would pick one. PSD, of course, uses all three, and more. Trying to get data out of a PSD file is like trying to find something in the attic of your eccentric old uncle who died in a freak freshwater shark attack on his 58th birthday. That last detail may not be important for the purposes of the simile, but at this point I am spending a lot of time imagining amusing fates for the people responsible for this Rube Goldberg of a file format.
Earlier, I tried to get a hold of the latest specs for the PSD file format. To do this, I had to apply to them for permission to apply to them to have them consider sending me this sacred tome. This would have involved faxing them a copy of some document or other, probably signed in blood. I can only imagine that they make this process so difficult because they are intensely ashamed of having created this abomination. I was naturally not gullible enough to go through with this procedure, but if I had done so, I would have printed out every single page of the spec, and set them all on fire. Were it within my power, I would gather every single copy of those specs, and launch them on a spaceship directly into the sun. PSD is not my favourite file format.
Assume that every developer who has to open this file has a picture of you and your family, your address, and a vendetta.
Documentation is the encyclopedia of your mutations.
I absolutely do not believe a single person who says that their code is self explanatory. I firmly believe and will happily defend this position. Anything less than function/method/class/module level comments and you’re just lazy.
I’m still shocked that this is considered a hyperbolic position to take. People give you money for your creative writing output, and yet, you refuse to do any of it outside of the absolute baseline. Basic. For the sake of those who are your brothers and sisters on the front lines, make their lives easier.
A few lines of comments describing the contents of a file are far more likely to impress anybody than any clever optimization you may attempt to do beyond them. How often have you looked at a library that was well commented and remarked, “Oh hey, this even has comments!”.
Documentation is critical to prevent the signs of mud growing on the walls of your project. The encyclopedia of mutation gives everyone access, and equality of knowledge on how to use and mutate it further. It’s the importance of sequencing the human genome. Why would you not want this?
Having a dictionary that’s well organized is as essential as the dictionary itself. What language do you write in? It doesn’t matter — it’s got an automatic tool that turns docstrings into a webpage.
Automation is essential.
Every single time you stop writing is time that you’ve wasted doing something that you shouldn’t have to do.
Make is one of the oldest programs on the planet, yet only recently in the UI world, we’ve begun to automate the most tedious of tasks.
Automation is how you can grade everyone’s knowledge of the vocabulary and the rules of the grammar of the system. Linters, tests, continuous integration and automatic documentation generation are things that take effectively fractional margins of time compared to the lifecycle of the project and give them back to you.
Why is it that automation isn’t something everyone would want? We’re lazy, as I mentioned earlier, and if we can avoid it, we shouldn’t need to do it.
Regardless of what you’re building, tools exist that can automate vast portions of overhead from your project. Spend the time to invest in the scaffolding of what you’re building, and you’ll be safer in the long run.
Prototyping! —I get it. Who wants to do anything automated as a prototype? Well- the best of the best tend to automate their automations. Boilerplates, empty repositories— Blanks — are everywhere, especially in the web. Artists would get nothing done if they had to hand stretch every canvas and make their own oil and acrylics every time they needed to paint, so why do we do this to ourselves as developers?
My basic rule is this: If something is performed more than three times in a 4 hour span, automate it. No exceptions. Assuming this task is 10 minutes of effort each hour, that’s an aggregate of 3 hours saved every week. 14 hours a month, and so forth.
Gravity is my secret weapon.
This is something that speaks to my lifetime battle with debt. Dave Ramsay, a guy who’s ideas (on personal finances) I enjoy, has a theory about paying off debt as fast as possible.
The theory is, paraphrased, that if you focus on the smallest debt with all of your energy first, and get it completely paid off as fast as you can, while paying the minimums on every other debt you have, you can focus all of the effort from that onto the next one.
As you continue up the chain to the largest debt, typically mortgages, cars, and so forth, you’ll be better able to make a dent in the principal of the debt with larger than expected payments.
For the astute reader that has ever dealt with crushing amounts of technical debt, this theory might give you pause for a moment.
A good credit rating for a US citizen means that they have more affordable means of borrowing, and they can get more out of their money than folks with a bad credit rating, if at all.
Why should your codebase be any different? If new features and refactoring effort were credit, you’d want to be able to maximize how much your effort will get you before having to pay off the debt.
This is the snowball effect. Use gravity to help your snowball grow from a few minor annoyances to shipping an entire new suite of functionality quickly and deliberately.
Your peers are your students. Your code is your syllabus.
Take every opportunity you can to educate your peers about what your code does. Are there certain ways to interact with your interface? Do I need to have an instance of this or is it new-able? is there a pattern to how this file is constructed? Is there a private or public interface?
Code reviews are such an excellent opportunity to flip the switch for your co-workers.
All too often, I’ve seen code reviews go from the ‘The English Patient’ to ‘The Spanish Inquisition’, and frankly the environment is one of the most important — if not dangerous — interactions you have with your team.
Critically, code reviews give you an opportunity to show competence to your peers. It’s a five minute show and tell about what you’ve been doing. It shows that you’ve been catching on to the language of the project and can be fluent in it. It helps you build trust and show off your understanding of the relationships of the vocabulary.
I know you have no time. There’s no budget, there’s no flexibility in the features for launch and you certainly wouldn’t want to spend a day sitting in a conference room when there’s code to be written.
Do it anyway. Do it with ferocity and attention. Make time. Be measured, back up your arguments with fact, and whatever you do, do not utter the words “Well, actually…”. If you do, you’re out of the meeting.
Egotism and Defects are interdependent.
My final rule is one burned into my mind from a path of scorched earth I’ve left behind me.
Experience is the tincture we apply to failure caused by egotism. The most incredible developers I have met in my career have been the some of the warmest, decent, humble, approachable individuals I’ve had the pleasure of working with, without exception.
You’ve probably met some of these people, or at least I’d hope you’d have the good sense to seek them out and emulate them in their behavior. These are the people who aren’t politically afraid to ask if you actually understand something, and then spend the afternoon over beers and wings explaining just how they interact with one another, and why the decisions were made to build them this way.
They are the absolute backbone of any engineering culture. They are the vault of institutional knowledge of any company. Befriend them. Learn everything you can from them.
Egotism is selfishness in the guise of cleverness. Brevity is the soul of wit, in english, perhaps, but in code it can be a dangerous cloak to complexity or a lack of comprehension. Brash, dismissive developers are almost to the person hiding a lack of self confidence or are so absorbed in Egotism that they simply cannot believe they are wrong. They are. Go look at their defect counts over the last year. Bring an umbrella when you open the door, it’ll be messy.
Try real hard not to be an asshole. Nobody wants to work with someone who thinks everything they’ve written has been brilliant. We’re generally a self deprecating people. When you tell us that your shit doesn’t stink, we automatically assume it does and will start smelling it by default.
Being humble doesn’t mean that you can’t revel in your successes. It just means that once it breaks — and it will — you just get right to work on what went wrong, chuckling at the defect title being an obtuse little sentence, and discuss lunch options.
Never assume your code is finished. Remember; code mutates. Mutation happens with or without direct influence. Document it, and make the mutations as simple as you can, but no simpler. Don’t be a dick. Try to teach others about your decisions for each mutation.
Your peers require your respect, your attention, and your effort. You are the best person to set the example.