I had an interesting conversation today about how one must constantly negotiate transitions in one’s career in order to succeed and stay relevant.
I have had some variant of this same conversation since I started my professional career back in the mid 1980s.
A common mistake made in the field of professional software development – from the most junior of coders to grizzled veterans of the trenches – is that if, by some magic, we could only master tool / language / strategy / product X we would be on easy street and the jobs would be plentiful.
Wrong. Wrong. Wrong. Wrong. Wrong.
It is not the tools we master that makes us proficient – it is our ability to transition between the useful life-cycle of one set of tools when they become obsolete and the arrival of the “next thing.”
My programming experience spans writing IBM 360 assembler using card keypunch machines and Hollerith code (I still have my IBM “Yellow Cards” with opcodes) to writing 8086 assembler for the first IBM PCs to writing SCSI device drivers to writing Terminate and Stay Resident (TSR) C Language Apps to writing Multitasking Kernels that ran on MS-DOS (think something like Quarterdeck and you’re not too far off) to writing Point of Sale Software to Writing Enterprise Data and VoIP Engineering Tools to writing Social Networking Apps to writing iPhone Apps.
In short, I’ve had dozens of different software “careers” if all one did was focused on the tools I used to build my projects.
I am not the best software developer in the world by a damned sight. Nor am I the most economical or the fastest or the cheapest or the most expensive.
But what I am is a software developer who knows that if I simply concentrate on the now, and not continously learn and re-learn about what is happening in my profession every single day that I will be roadkill tomorrow.
So, in my life and in my approach to software development, I begin each day with the premise that during the administrative lifetime of any project, there will ultimately be more that I don’t know about the problem set at hand than what I do know presently, and when possible, make allowances for that ignorance.
A beautiful example of this design principle is the concept of interrupt vectors in the original IBM PC. An interrupt vector is a place in pre-set areas of protected memory on a computer that initially holds the address of a hardware routine to do some task (operate the hardware clock, check incoming serial ports, check the keyboard, etc.).
The beauty of interrupt vectors is that they can be re-written with the address of another rotuine in memory that can then take control to insert additional tasks to be performed and then either chain back to the original hardware routine or declare the interrupt to be processed or handled.
In short, the designers of the IBM PC knew that they could not possibly conceive of everything that needed to occur on a clock tick, or upon every keystroke, or upon every incoming bit on a serial line. They planned on being extensible in order to stave off obsolescence.
As professional developers, we need to be extensible as well, so that we don’t become obsolete. We do that by concentrating on the process of creating product and not just on the tools that help us create the product.
Don’t get me wrong – I love working with people who have mastered their tools of the trade. And some folks are natural born tool making and using sons of beeches.
But tools are merely the means to the end.
Five years ago, I spent the majority of my time writing ASP and VB6.
Twelve years ago I spent the majority of my time writing C, C++, and 808x assembler.
Twenty years ago I spent the majority of my time writing Fortran, Cobol, and IBM 360 assembler.
It’s not the tool that defines what kind of developer that I am.
It is my ability to take whatever tools are made available to me and to craft something useful that people are willing to pay me money for.
And at the end of the day, to me, that is what defines a software professional “lifer.” Someone in it for the long haul.