Nick Hodges recently posted a link to a guy named Mike Hadlow's blog post about working hard versus working smart. I think it's brilliant. I have often said that it's better to be lazy (while getting more done) than hard working (if by being hard working you are simply banging heads repeatedly into walls rather than walking around them), as a developer. I believe you measure results, not hours that bums are in seats.
Anyways, rather than sticking on that point and belabouring it, I want to talk about the practices that have made a real difference in my effectiveness, in the order of their importance. I promise to be biased, opinionated, and honest. I do not promise to have scientific proof for any of this, only anecdotes and war stories. I use Science when appropriate, but I approach the whole business as a craft.
1. Bisect and Isolate Problems to Determine Root Causes
Do not guess why something is not working, learn why it is not working. When you know, you know, when you do not know, you can not be an effective developer. If you do not understand and locate the exact source of a problem, you do not know if you fixed it. This is the single most important skill a developer who gets things done must have.
2. Learn New things, and learn Old things too
If you love what you do, you want to know the things that will make you more effective. I do not know any highly effective developers who know only one programming language, one approach to problem solving, or who hate reading books about their craft. Zero. Do you realize how much amazing stuff is out there that you could download and play with? You haven't downloaded and tried Pharo? Go? Python? Clojure? None of those? Sad, really sad. You mean to tell me it's 2013 and you haven't read the Mythical Man Month? Not just the one essay, the whole book. Oh, I weep for you.
3. Clean code
This has always been a personal point for me. I hate leaving my code in a place where it emits warnings or hints. I do not like code that has no test coverage. When code is not exactly right, sometimes I say it has a "code smell". I mean the same thing by Clean Code that Robert Martin means by it, but I like to stress that it's an ideal that you move towards, rather than a thing you achieve. The perfectionist streak in me detests the idea that any code ever is clean. It never is. It could always be cleaner. The standard is "what is clean enough that my co-workers, my employer's customers, and my own ability to work are not impeded". That's clean.
4. Do Science
Admit it you thought I was going to harp on unit tests as a separate point, didn't you? No. I'm leaving it as a sub-point or reasonable practice within the general norms of Clean Code. But clean code is not enough or even my main goal. I am a person who, like a mathematician in search of an amazing new result, is pleased by beautiful mathematical perfection in my work. I find that the most effective way to find where those beautiful bits of software are inside your current working product is to be a scientist. You want to know what a variable does? Take it out and find out. You want to know why this application was designed with a global variable that makes no sense? Rename it and find all the places where it's used instantly. You have version control. Poke your code, prod it. Abuse it. Run it on really slow computers so you can see the screen draw and figure out why it's so flickery and crappy, and make it better. Be a scientist. Do science. Ask question. Form hypothesis. Test hypothesis. Revise hypothesis. Remember that working copies should be cheap (you do use distributed version control right?) and easy and fast to revert any experimental changes you make.
5. Use structure effectively
In the beginning was the machine. Darkness moved on the face of the deep, it was formless and void. The programmer had a manual of opcodes. The programmer built programs out of opcodes, which were data values stored in words (registers) in the machine. The programmer somehow flipped switches, or clipped bits of paper out of cards, and somehow got those 1s and 0s into the machine, and pressed a button or flipped a switch and the code ran. Or didn't. Mostly it didn't run. The programmer went back and tried more stuff until some lights turned on, and the early computer printed a character on the teletype. Only by sheer brute will power was anything ever accomplished by this early programmer, with no Language tools. The evolution and development of compilers and computer programming Languages was a response to the futility and low productivity of these early tools. Practices, and ideas about how to use these languages grew and evolved along with them. Today you have Object Oriented, Aspect Oriented, Post-OOP, Dynamic and Statically Typed, Functional, and all other manner of attempts to provide Just the Right Structure for your program.
The two cardinal sins against the effective use of structure are to put too much structure in, so that the structure has no purpose or reason behind it, and not putting enough structure in. It is my considered opinion that the Design Pattern movement began to love using Patterns so much that it overdid it. I have seen a Factory for constructing Singletons that have a single method, that could have been implemented as a non-OOP procedure, and would have been better off for it. Mostly Delphi code bases are too far the other way. They tend to have 50K line methods, 100K line units, and all the code is in the .pas file that Delphi created for you when you created your main form. Because making new units with reasonable cohesion, and minimal coupling, was too hard.
When a codebase has not got an effective structure, the productivity of everyone working on it is sapped to nearly zero.
6. Use tools effectively
If you do not learn how to use the Delphi IDE, command line compiler, build systems, continuous integration tools, profilers, static analysis, and any other tool that exists to help you, you are less effective than you could be. If you never learned how a distributed version control system works, even if you don't actually use one for your company's central repository, you're missing out on one of the single most powerful software tools ever invented. Mercurial. There's git, too, if you like accidental complexity and technical hurt. (I never promised objectivity here, this post is 100% opinionated.)
7. Build new tools or frameworks but ONLY when it is effective to do so.
Sometimes a new tool is a script written in 100 lines of Python (for fans of code that is zen like in its beauty) or Perl (if you like accidental complexity and revel in it). Sometimes that 100 lines takes 10 hours to write, and saves you 100 hours, and then saves you another 100 hours a year later when you need it again, or something almost like it. This is something that people used to think was only possible if you were a LISP hacker. Nope. You can build tools to accomplish anything you can imagine and then precisely formally define in code. This meta-coding mentality can go TOO far. See the famous "I hate frameworks / hammer factory factory" forum post for more on that. You have to build tools when, and only when, they are justifiable.
What are your top effectiveness tips? Please share.
Anyways, rather than sticking on that point and belabouring it, I want to talk about the practices that have made a real difference in my effectiveness, in the order of their importance. I promise to be biased, opinionated, and honest. I do not promise to have scientific proof for any of this, only anecdotes and war stories. I use Science when appropriate, but I approach the whole business as a craft.
1. Bisect and Isolate Problems to Determine Root Causes
Do not guess why something is not working, learn why it is not working. When you know, you know, when you do not know, you can not be an effective developer. If you do not understand and locate the exact source of a problem, you do not know if you fixed it. This is the single most important skill a developer who gets things done must have.
2. Learn New things, and learn Old things too
If you love what you do, you want to know the things that will make you more effective. I do not know any highly effective developers who know only one programming language, one approach to problem solving, or who hate reading books about their craft. Zero. Do you realize how much amazing stuff is out there that you could download and play with? You haven't downloaded and tried Pharo? Go? Python? Clojure? None of those? Sad, really sad. You mean to tell me it's 2013 and you haven't read the Mythical Man Month? Not just the one essay, the whole book. Oh, I weep for you.
3. Clean code
This has always been a personal point for me. I hate leaving my code in a place where it emits warnings or hints. I do not like code that has no test coverage. When code is not exactly right, sometimes I say it has a "code smell". I mean the same thing by Clean Code that Robert Martin means by it, but I like to stress that it's an ideal that you move towards, rather than a thing you achieve. The perfectionist streak in me detests the idea that any code ever is clean. It never is. It could always be cleaner. The standard is "what is clean enough that my co-workers, my employer's customers, and my own ability to work are not impeded". That's clean.
4. Do Science
Admit it you thought I was going to harp on unit tests as a separate point, didn't you? No. I'm leaving it as a sub-point or reasonable practice within the general norms of Clean Code. But clean code is not enough or even my main goal. I am a person who, like a mathematician in search of an amazing new result, is pleased by beautiful mathematical perfection in my work. I find that the most effective way to find where those beautiful bits of software are inside your current working product is to be a scientist. You want to know what a variable does? Take it out and find out. You want to know why this application was designed with a global variable that makes no sense? Rename it and find all the places where it's used instantly. You have version control. Poke your code, prod it. Abuse it. Run it on really slow computers so you can see the screen draw and figure out why it's so flickery and crappy, and make it better. Be a scientist. Do science. Ask question. Form hypothesis. Test hypothesis. Revise hypothesis. Remember that working copies should be cheap (you do use distributed version control right?) and easy and fast to revert any experimental changes you make.
5. Use structure effectively
In the beginning was the machine. Darkness moved on the face of the deep, it was formless and void. The programmer had a manual of opcodes. The programmer built programs out of opcodes, which were data values stored in words (registers) in the machine. The programmer somehow flipped switches, or clipped bits of paper out of cards, and somehow got those 1s and 0s into the machine, and pressed a button or flipped a switch and the code ran. Or didn't. Mostly it didn't run. The programmer went back and tried more stuff until some lights turned on, and the early computer printed a character on the teletype. Only by sheer brute will power was anything ever accomplished by this early programmer, with no Language tools. The evolution and development of compilers and computer programming Languages was a response to the futility and low productivity of these early tools. Practices, and ideas about how to use these languages grew and evolved along with them. Today you have Object Oriented, Aspect Oriented, Post-OOP, Dynamic and Statically Typed, Functional, and all other manner of attempts to provide Just the Right Structure for your program.
The two cardinal sins against the effective use of structure are to put too much structure in, so that the structure has no purpose or reason behind it, and not putting enough structure in. It is my considered opinion that the Design Pattern movement began to love using Patterns so much that it overdid it. I have seen a Factory for constructing Singletons that have a single method, that could have been implemented as a non-OOP procedure, and would have been better off for it. Mostly Delphi code bases are too far the other way. They tend to have 50K line methods, 100K line units, and all the code is in the .pas file that Delphi created for you when you created your main form. Because making new units with reasonable cohesion, and minimal coupling, was too hard.
When a codebase has not got an effective structure, the productivity of everyone working on it is sapped to nearly zero.
6. Use tools effectively
If you do not learn how to use the Delphi IDE, command line compiler, build systems, continuous integration tools, profilers, static analysis, and any other tool that exists to help you, you are less effective than you could be. If you never learned how a distributed version control system works, even if you don't actually use one for your company's central repository, you're missing out on one of the single most powerful software tools ever invented. Mercurial. There's git, too, if you like accidental complexity and technical hurt. (I never promised objectivity here, this post is 100% opinionated.)
7. Build new tools or frameworks but ONLY when it is effective to do so.
Sometimes a new tool is a script written in 100 lines of Python (for fans of code that is zen like in its beauty) or Perl (if you like accidental complexity and revel in it). Sometimes that 100 lines takes 10 hours to write, and saves you 100 hours, and then saves you another 100 hours a year later when you need it again, or something almost like it. This is something that people used to think was only possible if you were a LISP hacker. Nope. You can build tools to accomplish anything you can imagine and then precisely formally define in code. This meta-coding mentality can go TOO far. See the famous "I hate frameworks / hammer factory factory" forum post for more on that. You have to build tools when, and only when, they are justifiable.
What are your top effectiveness tips? Please share.
"If you do not learn [stuff], you are less effective than you could be."
ReplyDeleteI think this is a technically accurate statement, but it probably resonates more with company owners than developers. I would tell developers that learning new skills give them more tools to solve a given problem. And if the employer isn't listening, I might add that it makes them more marketable.
"What are your top effectiveness tips?"
For me:
1) Repeating an earlier theme, automate non-trivial tasks (and maybe some trivial bit frequent ones) that are performed more than once. You point out that this can save lots of time compared to performing the same tasks manually. I would add that it provides an opportunity to understand the process better (opportunities to improve it), avoids inevitible mistakes and missed steps, and takes boring things off your plate, freeing up time for more important and interesting things.
2) Avoid writer's block. Whether you're facing a big block of work and don't know where to start, or get caught up in the minutia. The best thing I have found is to take one small, well understood piece and just implement it. A lot of times, this helps break up the log jam for me. For something a little more stubborn, I might have to walk away from the problem for a little while and come back to it with fresh eyes. This might mean switching to an unrelated work task for a little while, physically taking a walk around the block, or playing a video game.
3) Stop. A productivity specialist once told me that at peak times (in out field), a week should be no longer than 45 hours. After that, you aren't really gaining much. If you think that an 80 hour work week is twice as effective as a 40 hour one, you're kidding yourself. It's also bad for your health and home life.
I have to admit that I have a hard time with this one. A part of me stubbornly believes in a bit of that cowboy mentality, and even at my advanced age, I can still pull off an all-nighter a week when necessary, especially if I'm working for myself as opposed to someone else. But I'm working on it.
3a) If someone is in a job where the culture dictates that extra unpaid time is the norm, then they might be in the wrong job. Even more so if the boss thinks "work life ballance" is for pussies and socialists.
Definitely agree, Bruce. Places that do not respect "work life balance" will usually not change to suit one person who feels differently. It's best in such cases to come to a mutual agreement that it's just not working, and then move on. I find that the best and brightest burn out just like everybody else, so you can't "hire rockstars" and then just "milk them", that's not going to fly in the long term anywhere.
ReplyDeleteMy "learning" pitch to individual developers is that you can not only be more effective, but also enjoy your work more, if you know what you're doing. Think of the difference between a skilled Nascar driver going around a track at 180 miles an hour, and a non-skilled driver doing the same thing. Who is having more fun? The guy who knows how to do it, or the guy who is white-knuckling it through? You can do a good job, know more, do it better, and enjoy doing it, all the while, if you build up your technical chops.
Guitar players who are truly great don't practice because they hate it, they practice because they love their instrument. I find the computer fascinating. I find software fascinating. Maybe a little too fascinating. I could probably benefit from spending more time with my Aquarium and less on a computer. But then, that's me.
"you're missing out on one of the single most powerful software tools ever invented. Mercurial"
ReplyDeletePlease expand on this in a future blog post if you can. I'm finding a centralised vcs (Vault) still works well for us, though I have dabbled with Mercurial. Very keen to be convinced though, particularly how you use it day to day with Delphi.