Although I love writing code, I hate porting code. To me, the least enjoyable task in software development is crawling through an application, usually one that I didn’t write, trying to figure out what compile-time errors really mean, and tracing back the origins of puzzling run-time results. What has always fueled my dislike for porting code is that, having cut my teeth on systems and software built for portability and interoperability, I know that for the great majority of project types, porting is a necessity created by operating systems and development tool vendors. Yet the technology exists to take porting, and meticulous platform validation, out of the software development cycle.
Porting from hardware to hardware, from Xeon to Opteron, or from Opteron to IBM Power is no longer such a thorn in the side. It was never a hassle under Unix, where programmers weren’t allowed to assume anything about the hardware on which their code would eventually run. That message is spreading quickly among Windows and Mac developers, so the need to port and validate code across target processor architectures will likely decrease. It is another matter, and one that galls me, that commercial ISVs are so lazy about re-targeting their code. (Solaris 10 on Opteron could face a slow climb simply because ISVs won’t take their Sparc apps and recompile them for AMD64.)
The porting issue I’m focusing on here, though, is among operating systems. I grant that desktop applications don’t port easily, if at all, from one OS to another. Graphical user interfaces differ in appearance and behavior, and therefore require different coding, design, and testing practices. That’s as it should be. I’d argue, however, that there are far too many fat client applications. Many are little more than GUI front ends for software that runs in the background or on back-end servers. Non-user-facing code makes up the vast majority of commercial and in-house projects, and that’s where porting should be wiped out.
Unlike graphical user interfaces, most code that does not interact with users (in other words, most of it), relies on a surprisingly small set of external libraries and functions that have very few reasons to differ from one OS to another. For example, if you want to open a TCP/IP connection to a remote server, there are two ways to do it: the standardized way, using the Berkeley Sockets Library, or the squirrelly, OS-specific way that’s written up in the vendor’s documentation and code samples. Likewise, there are numerous approaches to publishing and consuming Web services. They all have the advantage of being transparently compatible from the outside, but developers struggle with, or become addicted to, methods that exist only with the OS and tools they used to write their code.
Doing away with porting clearly requires diligence on the part of developers and their project leads, but when it comes down to it, OS vendors must make application portability a best practice. Until developers wean themselves from APIs constructed to lock them into a given software platform, vendors must supply the tools and guidance to take developers from the old days (today), where there are Windows 2000, Windows XP, Windows 2003 Server, AIX, HP-UX, OS X, Solaris and Linux applications, to modern reality: If a vendor makes application porting and validation painful, it won’t lock developers in. It’ll get the vendor locked out.