I’ve been programming for at least twenty years now, and I’ve seen a lot. It’s an unusual industry with a lot of nooks, and a lot of newcomers. It also has its fair share of veterans, some of whom are more jaded than they deserve. Let me write, as a programmer to a programmer, about the major lessons in living that I’ve learned while producing quality software. Let me tell you, regardless of what phase of your career you may be in, how to build yourself toward true peace of mind.
I’ve cut it down into ten points. For each point, I’ll let you know what you should probably do, why you should do it, and lastly, I’ll give you an example from back in the day when I failed to do it. This is almost entirely dedicated to ways of living, not programming advice and paradigms; I’ll explain those elsewhere in other posts. These are all about maintaining yourself, producing good work, and enjoying your life in the running.
1. If you hate it, you should know it.
This is a big one. I frequently hear one language fanboy or another shaming all of the others with notions that don’t really make any sense. A language is more than a set of keywords, a platform is more than a kickstand, and an operating system is more than an interface.
I humbly admit to having done this to a lot of tech. The reasons weren’t bad in themselves, most of them I still stand by; but the counterbalance is often of extraordinary importance. Ruby was my personal favourite for the longest time. It was released at the same time as Java, and took forever to take off; many people still hold that it never should have. The reasons are clear enough; it’s too loose in its rules, it has far too many control statements, it is in my opinion, on a syntactical level, just a poorly-put-together language. I was, and still am, a Java person. But I was ultimately wrong about Ruby, as the reasoning behind these features is the beautiful, and redeeming, feature of the Principle of Least Astonishment (POLA). That changed everything.
I didn’t actually realize this until early in an MIT course on algorithms. It was at that point that I realized that the language was designed to operate in a manner similar to the way that a natural language does; keywords exist to limit the number of operations that might be being described, until only one is left, after which the statement is executable. That blew my mind at the time, it was brilliant. Ruby still missed many of the features of Java that I care about, but this made it ideal for rapid creation and execution of any number of projects. As a man coming from the days of C, it was quite a revelation, and certainly nothing that even applied to the Java world.
My misguided rage was not exclusive to Ruby, either. I was disappointed in Python, as well. Its lack of true private fields and methods was on the border of the absurd for me. How am I supposed to protect future coders from unstable functions? Wait, there’s no compile-time type checking? Well what in hell is the compiler doing? This could run a hundred times faster if I wrote it in C or Java? (Partially absolved… maybe.) WTF?
Then I found out about the Python smart-compiling mechanism and the ease of extending a program with it, and was totally cool with all of that. Not to mention lambda expressions at the time, though those have gotten significantly more prolific in recent years.
Don’t get me wrong, for my purposes, JDK 8 is a godsend; but never brow beat your neighbour for using something else. Everything has its purpose.
2. If you love it, you should know what’s wrong with it.
And back to Java. The lack of lambda expressions was generally resolved in JDK 8, and I love it. They also introduced a spectacular streaming API and a few other goodies that resolve some of the old problems, perhaps forever. But it is, much to my chagrin, still not perfect. A few of the additions just give it more bugs.
My biggest concern is with its interfaces; they now have default methods that bring them much closer to abstract classes, but no way of creating default protected methods or default fields. Given the lack of multiple inheritance in Java, this is distressing. It’s like building a house and being given a nice, shiny hammer to bash in a bunch of the nails; except for one kind of nail, in which case you still have to pound it in with your trusty brick.
That’s the catch; the only reason these languages are capable of moving forward, adapting, and fitting themselves to new hardware is that they are not perfect. They are always being improved. This goes beyond languages, too; Linux has a yearly “Why Linux Sucks” festival, at which Linux junkies (such as myself) get together and talk about all of the holes they’ve backed the OS into and how to fix it. (Presumably there are also rides and cotton candy.) Because of that, the OS is always improving; declarations of perfection are a flaw in their own right. At this point, if you had a “Why Windows Sucks” festival, you wouldn’t be able to find a venue big enough.
3. You will always be learning, so never be afraid to try something new.
The simple reality is that the languages, tools, platforms, and hardware that we know and love will someday get old; long before we do. I couldn’t imagine using the earliest editions of Java or Python to write a program today. C has been through three separate standards (though I personally maintain that it’s time to let the language go, not out of hatred). Java recently moved to work its way out of the Swing standard, an otherwise beautiful thing, and establish a new standard for graphical interfaces with JavaFX.
The results of all of these things, for what we leave behind, are promising. However, they also mean that we need to learn to use the new tools. We need to learn what they do, why they do them, and again, what’s wrong with them. There is, thus, a certain critical point of experience that all programmers find themselves at; it is here that our old tricks expire at the same rate that we acquire new tricks. We reach our terminal velocity, and there are good parts of this. I’ve been programming for a couple of decades, but I can still carry on a mutually productive conversation with someone who has been programming for one decade or three, as we have all reached the saturation point. After a time, you become one with your industry.
4. There are many components of software development, know which ones you’re burdened with.
A lot of people use the words “coding” and “programming” like they’re synonyms; they’re not. Programming, that is, the creation of a program, is much larger. Coding is simply the construction of the source code. You also need analysis to determine the nature of the problem you’re solving; architecture to create a complete picture of all of the modular components of the software and their respective contracts; documentation so that the API is fully understood by both yourself and any other programmer that you are working with; and realistically quite a few other guys.
I’m sticking to programming here, I’m not worrying about marketing or any other faction of the business. Programming is a huge task. Sometimes, you even have borderline people, like systems engineers to keep your group in sync with other professionals in the company (value them). Many times, you will be doing most or all of these tasks yourself. If you’re negotiating a contract with a company, then find out who they have lined up for you to work with. Find out what their experience is, if you can. The more you are doing, the bigger the project will be; if you’re working for yourself, you can count on doing every part of this.
Personally, I save coding for implementation. For each of my major projects, I keep a notebook with crude UML drawings and notes on what needs to be done, where I am (point A), and where I’m trying to get to (point B). Often, I’ll sit down at a chai house or a coffee house and sip a latte while I go to town on that notebook. I encourage you to do the same.
You might be thinking about bringing a laptop or a tablet along. You can try it, but I discourage this. Coffee time is time to look at the project from 10,000 feet. That isn’t easy to do when it’s right in front of you, especially when your task centres on design and automation.
5. Document your code (seriously).
Writing undocumented source code is not too different from writing a book that no one will ever read. At least, it’s about as constructive. If you’re using Java, use javadoc. If you’re using some other language, see if it has a tool, otherwise, at least write it down.
If you can jot it in a comment, particularly a multiline comment. Many tools, such as javadoc, actually have a specific rule that you can follow with your multiline comments to declare one as documentation. If you are producing an API, and you don’t have a javadoc-like tool available, be sure to also enclose that commentary with the source once you have compiled it.
The central point of documentation is to communicate with the end user of the method, which may be yourself. It’s also useful to determine where a piece might go in the grand design of the project; it is not uncommon to rewrite a method a half dozen times before you have a utility that is efficient enough, comprehensible enough, and close enough to perfection for your project.
So how does this help you as a human being? Six months from now, you will not be drilled by your software sergeant on how to use some inscrutable bundle of letters and numbers that you duct-taped together half a year ago. You will be a happier person, because you wrote it down.
6. There’s a difference between functional code and good code. Lean toward good code.
(Though to be fair, good code is always functional.)
People have a strange idea about software engineering. I’ll give them this, it is a technical skill, but so is acting and writing. The reality is that there are a million different ways to write source code that accomplishes a specific task, but in the end it is more alchemical than that. Every line has not one effect but a cascade of effects on a variety of system resources. If you’re new enough to the industry to not have seen it yet, don’t worry, you will, and you’ll know it.
Sudden slow downs, memory jumps, and in the worst case crashes are all a part of this; at the same time, fluid animation, responsive key commands, and synchronization are also the result of this. Every line has a large number of effects. Even though they might be similar in function, printf, System.out.print, and sys.stdout.print all ultimately do slightly different things under the hood. Programming, and even isolated coding, is ultimately more of an art.
Accordingly, you will often need to understand more of what it is that your language is doing. (Particularly if you don’t want to look like a dunce when talking about it with other programmers.) If you’re a Java programmer, learn what Just-In-Time compiling is; it will come in handy. If you’re a Python programmer, learn the conditions under which .pyc files are recompiled. If you’re a graphics programmer, learn when your graphics calculations are offloaded to the graphics processor, or even if they are. Everything you know how to do is another tool.
7. Stay in shape—mentally.
As programming is an art, most programmers have an inclination toward an art. I know many who are musicians or cooks. I personally am a writer. This serves an additional purpose, as remaining creatively flexible will aid you in producing novel and effective code. It will also shine a light on the more frequently ignored aspect of the source code, in that it needs to be read by humans as well.
I strongly recommend reading material on items that you are least familiar with, even if they have nothing at all to do with software construction. Philosophy is a personal favourite. My rationale is that you can get programmer’s block just as easily as you can writer’s block, and exercising your logic and rationality with new ideas and modes of thought will always benefit you in the field.
Cognitive fatigue is a very real, and very fightable, thing. Forget these Hollywood images of programmers speeding through perfectly formatted code on the first try, and remember that a large part of the work is deep cognitive. I will often spend an hour just digging through my code, notes, and docs from the previous day before I even touch my code; simply because it is just as important for the algorithm to be present in my mind as in the computer itself.
8. Stay in shape—physically.
We have a saying in cognitive neuroscience. The boundary between the body and mind is illusory. If your body is not fit, your mind is not fit; and to a limited extent you can restore and reinforce the health of one by acting on the other.
As an example, three square meals per day, of good food (not junk). Get plenty of protein, vitamin B, and amino acids. If you’re the type to purchase them raw (as I am), I suggest throwing B-50 twice a day or B-100 once, and zinc or copper (depending on which one works for you, not both), into your regimen. Amino acids are a little trickier, as they have very specific effects; acetyl-l-carnitine has worked for me when I’m acquiring a lot of new job functions at once, but it’s not for everyone. There’s actually a whole medical field called orthomolecular psychiatry, which orbits around treating the mentally ill with dietary changes and changes in fitness lifestyle.
I personally don’t generally bother with such “supplements” as St. John’s Wort, or Kava Kava, or Lilly of the Valley, or anything other non-food item that was simply plucked out of the ground. This is not because I don’t think that there are compounds of value in them, or that I believe that they don’t ultimately work. My concern is that they rarely provide anything that a strong dosage of a more specific vitamin, mineral, or amino acid can’t bring about; and that they tend to interact with prescription or even over-the-counter drugs more frequently than I’m comfortable with. This is not a condemning of their usage, but I do advise you to be a little more careful.
Along with the diet, ensure that it gets into your system to begin with. Join a gym, lift some weights, spend some time on a treadmill whether you think you need it or not. The thing is, the body is a machine; and like a car, if it isn’t put to good use once in a while, it will break down. Go for a hike, walk your dog (or in my case, my cat), go to a public pool and get some laps in, go ice skating. Get your pulse up for a while. Stretch, for the love of all available gods, stretch your limbs. Stand up, flex, do some jumping jacks.
It’s things like this that keep me from programming in an armchair. Can’t do it. Insane. Unpalatable. Okay, next topic, I can’t think about this for much longer, the thought of spending an entire day sitting down is getting painful.
9. Keep your meetings short.
This is especially important for startups.
Toyota is my favourite reference for this one. They have the philosophy of the three “M”s, or “muri mura muda”. Remembering that Toyota’s a Japanese company, that is:
- muri: overload
- mura: inconsistency
- muda: waste
Obviously they don’t consider these to be good things. They are the symptoms of a bad meeting. Did the presenter ramble for thirty minutes without presenting any new information? Did the meeting focus on any real issues, or did it simply bounce over a little of everything? If it bounced on everything, you have a problem. Did someone actually waste time putting something frivolous on their presentation? You know, the whales-in-space crap that has become all too prevalent in PowerPoint documents? Because if that’s their young and attractive partner at the centre of the stage, she’s not distracting anyone. She’s pissing them off. You, sir, are the victim of a 3M-defiant meeting, you are now officially exhausted, and I’m betting that nobody got anything done.
Here’s what I suggest. Follow the journalistic principles in your presentation. That means keep paragraphs and slides short, sentences short, and words short. Know your target audience; if everyone present at the meeting is familiar with a particular short hand, then use it; if they aren’t, then absolutely do not. Have your point presented first, followed by supporting details, not the other way around (never the other way around). And if there are no points to be made, and everybody’s running on time, then you should not be having a meeting. Try and keep it to ten minutes or less, and be certain that everyone leaves the meeting knowing more about the project and their situation in it than they knew going in (otherwise, they should not have been at the meeting).
Meetings are meant for coworker communication; they are not an otherwise essential part of the job, and they are in many ways detrimental to it. They are dangerous. Many people get the idea in their minds that by having more meetings, they can have a tighter-knit team; but the truth is that they fatigue and limit that team. If someone starts um-ing and uh-ing, you get them the hell off the stage. An ideal meeting lasts five minutes.
After that, you need to be back in your studio or office, working on your art. If there is some policy of spending half an hour or an hour on meetings, bring it up at that meeting, because your competition is going to kill you like that.
10. Don’t beat yourself up over mistakes.
You’ll make them, and lots of them, and you always will make them. But you know what? I would rather look at a trashy piece of code that I produced, compiled, and published from a few years ago than realize that I was a smarter man then than I am today.
The trick is not to not make mistakes. Entire paradigms change on the basis of that. The trick is to learn from your mistakes, and if you’re doing your research, to learn from other people’s mistakes too. Never assume that a piece of code, no matter how well it works, no matter how easy to read it is, no matter how modular and dynamic it is, is perfect. There is always a flaw, and if you are analyzing that code, then it is your job to find those flaws and the conditions under which they would arise.
As I said before, there is no such thing as a perfect platform or operating system or language or program. This is a part of that, as you contribute to its better side you will also be contributing toward its limitations. In this sense, programming is a bit like sculpting; you define what your program is through what it is not. Often, you will leave a chip or a dent in it that you may not have intended to have put there; that’s alright, you can always refactor it. Most of the tools in IDEs like Eclipse exist entirely to reduce the impact of mistakes.
The best way to deal with potential mistakes is to keep your material as modular as possible. Remember (or learn) the old sayings, adages, and rules. One class means one responsibility. Program to an interface. Loosely couple. Write readable code. Comment the hell out of it. Know what you’re writing before you write it. (Coding may be an art, but it isn’t avant garde!)