Express lane vs. journey
There's an excellent piece on the practice of programming called Teach Yourself Programming in Ten Years by Peter Norvig, a Computer Science PhD. and Director of Search Quality at Google. The big question asked by that article is Why are people in such a rush to learn programming? Is it because they want to learn in a hurry -- or is there a perception that computers are easier to learn than anything else? Regardless, becoming a good programmer is not the result of learning fast, but of learning well and of being smart about what you choose to learn. With that, here are six bits of advice for those embarking on (or are already on) what should be a lifetime quest to becoming a good programmer.
Learn by (good) example
Some programmers are lucky. They've had good teachers or mentors who guided them toward successful ways of approaching the problems of software design and coding. They learned how to distinguish good designs from bad ones, and robust implementations from shaky ones. Their guides also gave them good advice on how to advance a career in programming, and they learned which paths lead to success and recognition, which projects to tackle, and which projects to avoid.
Mentoring is powerful and imperative. If you take two equal programmers and give one a good mentor, the mentored programmer will grow while the untutored one can flounder.
Learn by (bad) example
If the untutored programmer has a good sense of survival, however, alternative ways of learning the practice of programming will become apparent. Learning by reading the code of others is one method that's available to all programmers throughout their careers -- and which is forced on virtually all new programmers in the form of code maintenance.
In one of my first programming jobs, I learned what not to do while maintaining code written by my new boss. This boss, the co-owner of a small and fast-growing company, was an anti-mentor. We primarily wrote in FORTRAN then and he was producing a lot of code when I arrived. He used variable names like a, b, c, aa, bb, cc, and so on; I was just learning FORTRAN, but it was obvious to me even then that this was bad. Then he made these variables global by putting them in FORTRAN common blocks; it was obvious that this was really, really bad. This made it impossible to grep a source tree for variables to rename them -- or to do anything at all with them. There were no good integrated development environments for FORTRAN that I knew of back then to help with this situation, so I cleaned up a lot of this old code by hand, and swore to write better new code -- starting with good variable names.
The lessons learned by (bad) example: Write code that is human-readable; make your package, class, method, and variable names reflect what they are all about; avoid trendy naming conventions, to name a few. In the early '90s I tried Hungarian notation while working in C++, and today I cringe when I see m_ in front of a Java™ identifier. Good names for these artifacts are the foundation of good code. Even more than an elegant and robust architecture, good names will make your code understandable to others. But coming up with good names isn't easy. Tim Ottinger offers some good tips.
Recognize the impact of the iron triangle
Certainly, there are things a programmer can do to positively impact a project. But there are also things that are often beyond our control that can make it challenging for a project to succeed. Remember the iron triangle, even if your management chain does not. The iron triangle depicts the three dimensions of a project, generally defined as time, resources, and functionality, which combine to affect quality. The programmer does not typically have any control over these three project dimensions, which are instead often determined by marketing departments, corporate stakeholders, important customers, and others. Though far removed from the processes that set a project's dimensions, the programmer needs to be aware of a project's iron triangle as the project progresses, particularly if problems habitually occur. This knowledge can help by:
- Enabing the programmer and the programming team to achieve success by exploiting inefficiencies in the software development process -- in spite of rigid requirements and insufficient resources.
- Signaling to the programmer that it might be time to move on, professionally.
- At the very least, explaining why successful project completion seems so elusive, even though everyone is working hard and doing the best they can.
While I was working for that small company, management landed a big deal with one of the world's most recognized names in healthcare. We were to deliver requested software functionality in a year; a few new programmers would be hired; it was an exciting time. But then the reality of the project began to sink in. Upon analyzing the requirements, it was clear that a year would not be enough. Then we learned that the requirements we had were incomplete -- they were to be "hammered out over time." The company did hire more new programmers, but additional project requirements were also brought in, and the staff simply couldn't handle all the work.
I decided to move on three years after that big deal was made; four years after that -- seven years altogether -- the last piece of the originally planned functionality was finally delivered. The small company was sold to a big one a year after the big deal had been announced; the healthcare project was a plum in the portfolio before the deal, but a rotten egg for years afterwards, thanks to the iron triangle.
Keep it simple
Make your software designs as simple as possible while meeting project requirements. This can mean throwing away initial work and starting over with what you learned in early iterations. It doesn't mean designing until time runs out. Write code as you work on the design. Get a feel for the implementation, even if you are not going to be responsible for it. Understanding - and coding to - an overly complex design takes extra time and effort. As programmers, we are stuck between a rock and a hard place, between resolute business needs and the desire to create elegant designs and to write excellent code. The company that pays you for your programming work needs to have your software in hand, right now, ASAP, in order to close deals and bring in revenue. The ability to effectively simplify software designs takes practice. But it's worth striving for because it saves time and effort in the long run.
Work well with others
Programmers are team members and a successful programmer works well with others; the inability to do so can hamper the career path of some very bright people, since it's likely they will be excluded from decision-making at higher levels. Of course, higher-level programmers and decision makers aren't always easy to get along with, but what they bring to the table needs to outweigh their organizational goofiness, painful shyness, or downright obnoxiousness. For most of us, our talents don't outweigh these kinds of shortcomings, so we have to develop teamwork skills:
- Start by compiling your code locally so you don't break production builds.
- Continue by asking for code reviews and taking criticism gracefully, and actually implementing the best ideas from those reviews.
- Take teamwork a step farther by offering criticism when it is asked for, not when you feel like giving it.
- Take teamwork to a new level by complimenting someone on a job well done (because others can do good work, too).
- Blossom into the ultimate team player by offering to do some unpleasant job for some period of time -- something you've noticed senior developers do -- especially if it means getting up early (and you're a late-night person) or staying up late (if you're an early morning person). Organizations like their people to feel pain sometimes.
Know what makes you happy -- really
These days, the role of software architect is coveted by many programmers. If you interview young programmers for entry level jobs and ask what they want to do, you'll find out that they want to be architectural leads, determining the direction of entire software organizations with a zillion combined years of software development experience. Why does a beginning programmer think they can be an architect, whether lead or junior? Because they don't know what it really means to be one.
The perception is that a software architect leads a team or a larger organization with sheer technological prowess, designs software the Right Way, chooses the right tech tools, and so on. But the architect is as much a political role as a technological one. Many technologists would not be happy as architects when they discover they have to negotiate, compromise, make deals, answer 200 daily e-mails, and entirely give up the pleasure of heads-down programming.
A similar fate awaits the programmer who is asked to become a people-manager. The true lover of programming must pause when this happens and seriously assess the situation. Are they being shunted to management because they're not a good programmer? Is the offer being made because they are good at programming and it is hoped they will command respect from a programming team? What will their daily job entail when they are a programming manager? Most importantly, will they be happy doing it?
Learn the skills, learn the roles, learn what you like and where you fit in. Then, blaze a trail.
- IBM WebSphere Developer Technical Journal by Peter Norvig
- Teach Yourself Programming in Ten Years by Peter Norvig
- Ottinger's Rules for Variable and Class Naming by Tim Ottinger
- Something's Gotta Give by Scott W. Ambler
- Process: the Fourth Dimension (Tricking the Iron Triangle) by Alistair Cockburn
- The Role of the Software Architect, Bredmeyer Consulting