Over the past 6 months or so, I've spent a lot of time in code reviews and discussions with various teams writing "enterprise" code (i.e. the boring plumbing stuff).
This post is basically for me to record the stuff I find myself repeating in these discussions, along with some notes to explain myself.
The team members I'm working with have varying experience levels and varying knowledge of the frameworks we're using, but despite these differences, I find myself regularly thinking and saying very similar things. These are the things I find myself repeating as what seems to be good advice, in the hope that they'll become embedded as shortcuts we can use while wrestling with code together.
All these quotes I've either picked up from the elder demi-gods of software, or made up myself to get across ideas which others have probably said much better.
If I know a good single source of a quote, I'll try to reference it, but I think a lot of them are kind of mangled versions of things other people have said. I dunno where the line between badly remembered plagiarism and new thought should be drawn, but I'll do what I can.
The best line of code is one you didn't have to write.
Use libraries, write shorter code, look for chances to delete code.
Every line of code you write is one you have to understand, test, debug, deliver, and support. If you can make use of code that means someone else has to do all that stuff, your life gets easier.
This should also help you win friends when others have to alter, debug, support your code in future. Code they don't have to read, or that they know because it uses the same libs they used, saves them time and mental load.
If it doesn't compile, it isn't code & can't be code reviewed.
Keep the code compiling, don't break the build with dodgy commits, and make sure you have at least got it running before declaring it finished.
Luckily I've found myself mainly using this as a mantra when explaining to various managers why pseudo-code and half-baked code is not good enough to mark a Jira task complete. Developers themselves largely understand the purpose of typing weird stuff into text files, running commands to turn that into weird stuff in binary files that can be used as part of commands themselves.
For interpreted languages, the wording should technically be different, but the intent is the same - if the computer doesn't know what to do with it, it isn't "code" - it's just weird text.
Ugly, working code beats broken, pretty code.
Ideally code should be easy to read and work well, if you can only chose one, choose to make it work, and add a comment about the lack of prettiness - we can fix that later.
I'll sometimes use this approach as a pragmatic way to get through a knotty discussion or thought process and how a certain section of code should look. If it passes its tests, does what the customer needs and we can understand it, then it is at least a candidate for "good enough".
This also kind of chimes with Sandi Metz's idea of "Omega Debt" - well contained technical debt at the end of a message chain. If there's a nasty tangled pile of existing code which is fairly well encapsulated and does what we need, rewriting it to something easier to read which doesn't work (or pass its test) isn't an improvement.
Draw diagrams first, write words later
When working out a design, start from rough sketches, then expand and refine those until you get to a point where words say it better. You'll probably need far fewer words in the end.
Coding to a spec is like walking on water - easier when its frozen.
— seems I'm paraphrasing Edward V. Berard
If you are doing ye olde school waterfally spec-driven-development, that spec has to be pretty solid.
Even when you're acting more agile, a stable spec is a pretty powerful helper. It means the team can be far more confident about what they're doing and less likely to be demoralised by expectations of each day meaning a new chunk of rewrite.
If you can't do it in the command line, you can't automate it
Make everything scriptable, don't rely on IDEs and webapps, use scripts for anything you do frequently.
Also when you do automate it, you can put that script into source control - which you really want to do.
Get the most out of your editor/IDE
It's your toolbox, learn the tools in it. Keyboard shortcuts, quick refactoring & formatting, regexp search & replace, themes and plugins galore ...
This might be seen as a counter to the previous quote, but most IDEs also work with command line automation and plugin tools. Really these two go together - make sure you can do everything important from the command line, then use your IDE to make all those things happen neatly within your chose dev environment - the IDE can use the command line behind the scenes.
Never trust the client. NEVER trust the client
i.e. anything coming from the outside. You will be given bad data, the connection will go slow and die, validate everything you didn't create yourself.
It's a common security mantra, but it bears repeating especially when you're doing anything that involves network connections of any kind.
YAGNI is your friend.
You Aint Gonna Need It. Don't spend time designing and implementing things that haven't been asked for, unless you know it is needed.
It'll save you time, mental effort and disappointment when that neat thing you coded is either not appreciated, or gets in the way of whatever they do ask for.
If you can't debug it, you can't fix it.
This has a few meanings - the first of which is to reach for your debugger early and often. rather than println statements, write code you can understand when stepping through it, concentrate on what the debugger is telling you.
Another meaning is related to cognitive limitations - if you can't understand the code well enough to debug it, you can't fix any bugs in it. There's a related quote about debugging being twice as hard as coding, so if you've coded something you only just understand, you can't debug it.
Debuggers don't care about "should" or "shouldn't", only "did" and "didn't".
There's no arguing with the debugger when it tells you the code has acted a certain way (unless your source and JVM are out of sync).
A common cry when we're looking at the value of a variable, or the route through some logic, is "but that shouldn't happen!" or "but it should be set to X now!". Debugger don't care, debugger just shows what is, learn to deal with it.
The exception to this is when you find yourself stepping to empty lines, or comments, or outside any code at all. That's a sure sign the code that is running is not the code you're looking at. When you see that, just stop, tear down, and "redo from start".
Rule 1 of performance optimisation: don't do it
Rule 2 of performance optimisation: do it later
Rule 3 of performance optimisation: measure carefully, before and after
Premature optimisation causes painful problems and often doesn't actually work. Concentrate on get the system working, correct and maintainable first. Then measure the problem, then fix it.
I know this is paraphrasing a famous quote, I'll find the source and ref it.