There’s an old computer joke. “There are 10 kinds of people. Those who count in binary and those who don’t.”
I think there are two kinds of software developers, those who constantly reexamine their skill set and those who like working on antique cars. Mind you, I have nothing against antique cars. A good chunk of my personal library is dedicated to computer history. I love reading about how we got to where we are. I’ve been privileged to have been an observer to some of that history. That being said, ours is a discipline where answers are only as good as the half-life of their questions.
What’s the lifetime of a question you ask. It depends. If the question is “What is the length of the diagonal of a right triangle given the lengths of the other two sides?”, pretty damn long. On the other hand, if it’s “What is the best way to teach people how to write a program?”, well, tick-tock.
So, what does this have to do with shelfware? As it happens, a fair number of the projects I’ve worked on have become shelfware. Sometimes it was tech that the world just wasn’t ready for. Other times, it was a case of the tank shell and mosquito. Way too big of a hammer for the problem. (The bigger the hammer, the greater the resources needed to create and eventually wield it.) There are those time when you’ve created a solution either without a problem or by the time you’ve got your solution, the problem has either been solved another way thank you very much, or simply no longer exists. (Remember how everyone got all wound up about Y2K?) Finally, some projects simply run out of time.
The interesting thing is that no one has as their goal the creation of shelfware. But, you know what? Shelfware happens. So, what is one to do? My favorite exercise in such is the post mortem. As with all things, I ask my two questions. “What do I have?” and “What do I need?” What I have is easy to answer. It’s one of the above cases. What I need is to determine is how it got there and what can I do to prevent the same sequence of events from occurring again.
Part of what comes from this analysis help me improve my situational awareness. Contrary to popular belief, it is not enough to be good at what you do and expect that your insight, code or experience will suffice. Software is like an elaborate dining experience. If you can’t get the right dishes out to the right people in the right order at the right time, there will be hell to pay. By the same token, if your team isn’t able to fire on all cylinders, you’re bound to either lose the race or crash and burn. Eventually. Nothing is more pathetic than a software team who’s sole purpose is to sustain a dead product. But I’ll leave zombieware for another day.
Situational awareness is all well and good, but it’s a external. The more important thing for me is to see what I can do to up my personal game. This is not to say that I wait for a train wreck to do this, only that unlike my usual mental fitness endeavors (consuming all the Apple WWDC and other conference sessions, Coursera classes, etc.) and scanning the horizon for interesting directions that the industry is moving toward, I like to take stock of my core skill set.
It takes skill to drive a nail with one or two hammer strikes, but it’s far more efficient to use a pneumatic nail gun. More fun too. And you don’t need the same level of skill. The same is true of software development. In the early days of both C and C++, there were no libraries. Everything was handcrafted in every single program. The number of times any given problem was solved, to varying degrees of success and quality, is staggering. People created problem-specific solutions which were then expanded upon for other projects. As usually occurs, they accreted unrelated and inseparable bits. By the time an opportunity to refactor the code base into some semblance of modernity, it is usually deemed too great a risk. So, while you’re becoming the expert in dinosaur care and feeding, the next generation of developers has been tinkering away with the latest and greatest.
I know, I know, the fundamentals you say. Okay. So, how about you show my your linear and logarithmic interpolation skills? No? You used Matlib perhaps? Hmm. Well then, how about explaining why 8.3 file names are storage efficient? Surely balancing binary trees. But wait, don’t you get that from maps in C++ and just about every other modern language? The finer details of memory allocation and pointers? Have you ever talked to a Java or Python developer? Binary tree common ancestors? Understanding how to implement that must be important. Seriously? In thirty-two years of developing software full time, I have never needed to re-balance a binary tree or find a common ancestor, except for interview questions. Which probably makes me unqualified to create the next great search algorithm. And that’s okay. All these answers reached their half-life long ago. Well, maybe not Tango trees. But they’re still a solution looking for a practical problem.
Over time, all these problems have had their solutions codified into either the language or the language’s standard library. This is a good thing. Map / reduce was once new and shiny. Now it’s built into Apple’s Swift language. I would much rather people who live to create the best sorting algorithm do so. That way everyone benefits. I don’t want to have to care if my data is partially sorted, whether I have fifty or fifty million items, if I have strings or structures. I want to sort my data in order to do something else with it, not because sorting it amuses me. By the same token, no one in their right mind would even consider creating a GUI from the ground up today. I’ve personally had to do this more than once. It’s a boat load of work and not portable. Why should data structures and their manipulation be any different? After all, we create abstractions so that we can handle problems of greater complexity.
So, if I’m not looking at these, then what?
Currently, three things have my attention. The first is Apple’s Swift. I’ve been watching this language develop over the past two years into a nearly complete solution for application creation. The second is C++11/4/7. I started working with C++ in the mid ’90s and it has managed to keep pace with developments in the processor and compiler spaces. Anyone who is still writing code as if nothing has changed since C++03 really needs to look at C++14. Between auto, atomics and memory handling changes, C++ continues to bring its A game. Finally, and most importantly, I’ve been looking at secure coding. Having recently taken the US CERT secure coding course, I was surprised at the level of code exploitation possible because of patterns of coding that go back decades. If OpenSSL has issues being exposed on a near weekly basis, would we expect that other major pieces of our infrastructure are not equally at risk?
To remain relevant in the world of software development, one must not only be competent in the current use of technology, but also be actively learning and incorporating the advances in the materials (languages / frameworks), methodologies (paradigms) and tools (editors, compilers, IDEs, etc.). Not to mention other peoples’ code.
Everything can and should be learned from, even shelfware. It’s merely experience without exposure.