he media, particularly over the past decade, has made a huge point of discussing how fast computer technology changes. Terms such as “Internet years” and “Moore’s law” have been used so often that they are part of the public vernacular. However, the practitioners of computer technologydeveloperswhen confronted with the reality of technological shifts, will have a wide range of reactions running the gamut from eager acceptance to resigned acquiescence to angry denial to complete loss of trust and abandonment of the altered technology.
Recent shifts in focus?from text files, COM, classic VB, and C/C++ to XML and Web services, .NET, and Java?have helped illuminate some of the problems involved in rapid change. Although some programmers embrace these changes, either individually or en masse, others question whether XML provides any real gain over text files, or decry the loss of COM and deterministic finalization, detest the march toward Web services, protest the language changes to VB, or deny the increasing influence of Java. Although software vendors try to ease the pain of such transitions by offering “backward compatibility,” “interoperability,” and “support,” the reality is that these services, like the replaced technology itself, are finite.
As just one example, a loooong time ago (in Internet years), the Basic language introduced a command called “GOTO,” which let programmers write commands such as GOTO 200. The command caused the interpreter to stop executing code at one point in a program and to begin executing code at another point, line 200 in the example.
The ability to jump around within program code quickly led to the concept of structured programming, in which the GOTO was augmented with an “execution stack” (a way of automatically keeping track of certain points in a program) and two new paired commands called GOSUB/RETURN. This new command let programmers write GOSUB 200which would, like the GOTO command, jump to line 200 and begin executing code therehowever, the language also pushed the address of the code line after the GOSUB onto a stack. When the machine found the command RETURN, it would pop the top address off the stack, and begin executing code at that point. In other words, the GOSUB command automatically executed an implicit GOTO command that returned to the command following the GOSUB.
10 PRINT "START"20 GOTO 20030 PRINT "END"40 END200 PRINT "Hello" ' print something210 GOTO 30
That’s a useful concept. By adding the ability to use named code blocks rather than line numbers (yet another layer of indirection), you get code that begins to look relatively modern:
10 PRINT "START"20 GOSUB 200 ' push line 30 onto the stack30 PRINT "END"40 END200 PRINT "Hello" ' print something210 RETURN ' pop the top value off the stack executing an _implicit GOTO back to line 30
Sub Main Print "Start" Call printHello() Print "End" EndEnd SubSub printHello() Print "Hello"End Sub
Because people (even programmers) understand words better than abstract line numbers, such additions made programming easier and paved the way to a period of prolific coding. However, code isn’t as adaptable as people. The relatively simple concepts that make the last example easier to understand than the first example also introduce a potential problem. The language vendor must decide whether to continue to support the first version.
That’s easy once, but often becomes more and more difficult as the older version becomes less and less popular. The problem occurs when the vendor decides to stop supporting the older features. Now you have a problem. How do you migrate code from earlier versions to later versions when the supported feature set changes between versions?For programmers who don’t need to move code between versionsor who don’t have much code to migratesuch breaking changes matter little. But for commercial operations and people with large code bases, the migration issue is ubiquitous and expensive. Another problem is that while software vendors usually support older features for some period of time, the implementation may be modified or poorly tested.
Case in point: By Visual Basic version 4 (1995), which brought the glimmerings of true object-oriented programming concepts into the Basic language, Microsoft was attempting to get rid of the old-style GOSUB/RETURN commands. While VB4 still supported the feature, it was documented as being inefficient (read badly implemented). Microsoft recommended writing separate procedures and calling them instead. Yet, they continued to support GOSUB/RETURN all the way through the next two versions of the languagefor six yearsbefore finally doing away with it altogether in VB.NET, the latest version.
Dropping or altering features when automatic code migration tools exist that can seamlessly and accurately alter older code to comply with newer language versions is acceptable, but dropping featureseven after repeated warningswithout providing an automatic upgrade path is a questionable act. The loss of support for GOSUB is just one example; there are innumerable instances of languages and programs changing or dropping features from earlier versions.
Such changes are, at their core, an unexpected cost of doing business with a language vendor. When a language vendor drops support for code that was supported in earlier versions, programmers using that language have only one choice if they want to continue using their existing code base with the newer versionrewrite it. But rewriting code costs money. The direct costs to change the code may be small, but the indirect costs for notifying customers, manufacturing and distributing new versions, and perhaps worst of allretestingmay be quite expensive.
Still, it seems unreasonable to expect any company to continue to support every feature ever introduced into a language forever; after all, there’s a huge cost to maintaining such features indefinitely at the language vendor’s end as well, money that might be more productively spent finding and removing bugs in the currently supported feature set or developing requested features.
For coding constructs that are generally out-of-favor, such as GOSUB/RETURN, there’s an even greater cost, because the money the vendor spends supporting them is not only mostly wasted, but worse, implicitly encourages people to continue or start using those features. That exacerbates the problem and postpones the day when the vendor can finally drop support altogether. Further, it seems unfair that everyone continue to pay for the support of features that only a small percentage of the customer base uses regularly.
But of course, that’s part of the democratization of programming in general. We all pay for features that we rarely or never use in programming languages so that they will be available to those who do use them. Seen from that standpoint, it seems unfair to pick any particular feature as being “obsolete,” and it might be better to stick with a warning that the feature is obsolete and unsupported rather than drop the feature altogether and break existing code. Unfortunately, such warnings don’t appear to work welland not just with GOSUB. For example, INI files were labeled “obsolete” by Microsoft beginning with Windows 95; the API documentation advocated using the registry instead. Yet the original (and extended) Windows API functions to read and write INI files are still available in current Windows versions. In other words, Microsoft has supported INI file access functions despite the obsolete label for longer than six years.
Interestingly, despite the warning and the touted “advantages” of using the registry, even Microsoft still uses INI files for some purposes, and has reintroduced application meta-information files as XML-formatted “configuration” files in .NET, making the registry obsolete. Fortunately, it’s very easy to move from INI files to XML. It’s not any more difficult to switch application initialization values from the registry to XML, because the concepts are almost exactly alike. Those who learn from history would be wise to note this sea-change and begin eliminating their programs’ dependencies on the registry now rather than face sudden changes when it disappears in some future version of Windows. I know that’s hard to fathom right now, because COM is still ubiquitousbut at one point, so was GOSUB.
We’re currently in the midst of a real-life experiment concerning code longevity and control. Microsoft has apparently decided that the lure of better languages and faster development is sufficient to attract and keep a profitable customer base even though the languages themselves may not be particularly stable. On the other hand, the open source community has decided that breaking changes may be made only by consensus of the programming community. If the changes in Visual Basic from VB6 to VB.NETand the accompanying complaints of VB developerscan be held up as an example, that consensus will never happen. If that’s true, then open source languages are doomed to carry the baggage of current programming techniques until they are overwhelmed by the sheer weight of their own history. However, if it’s not true, and consensus can be relied upon, then companies will gradually (some say not so gradually) gravitate toward the more stable languages. We’ll see.
At any rate, how long is long enough? Is six years of support enough? Should Microsoft, or any company, commit to supporting older language features for longer than six years? How much longer? Is there a reasonable basis for deciding when to make a breaking change?
What type of warning should companies provide when breaking changes are planned? Does the cost of forcing the few to rewrite their code outweigh the benefit of eliminating obsolete coding techniques for the many? And who should decide, anyway, the language vendor or the programming community?