reprinted with permission from Programmer's Paradise, Inc.
|
|
|
After a program has achieved success in the marketplace on a particular computer or operating system, the vendor will often attempt to make it available on a second platform. This is a move that is potentially fraught with danger as well as advantage. Any vendor giving serious consideration to such a move implicitly asks itself (or should ask) three questions:
- What is the probability of success?- How much will it cost?
- Will the resulting effort make good business sense, in terms of what it offers users, compared to the projected price to them?
Fortunately, there are some specific elements of a program which can provide a more accurate idea of how difficult, and how successful, a conversion will be. This article will discuss the specific elements to look for in order to evaluate the feasibility of porting between dissimilar platforms. (Examples of porting between dissimilar platforms include the Macintosh to or from MS DOS or Windows, minicomputer operating systems such as Unix and VMS to a microcomputer operating system, a non-GUI to a GUI and visa-versa.)
Unfortunately, there are virtually no rules of thumb that predict the outcome of a port. Porting software from one platform to another is always a complex task. A candidate for porting must be examined carefully to get even a rough idea of how much work will be needed, and how successful the effort can be expected to be. Moreover, the understandable desire to extend a demonstrated success to new platforms can easily cloud judgement, creating overoptimistic estimates of the amount of work required - and therefore of the cost.
Sometimes program maintenance can be more difficult if done by someone other than the original programmers. This is even more true in the case of porting, since porting can be thought of as a type of maintenance. This article assumes that the work will be done by someone other than the programmers who designed and implemented the original program. Even if those programmers are available the issues discussed here are still relevant - the questions will just be easier to answer.
The uncertainty surrounding the future of OS/2 makes programs developed for it prime candidates for porting to Microsoft Windows. The two environments are sufficiently similar that many applications can have large portions of code ported with only minor modifications. The similarities in system software capabilities as well as hardware requirements are numerous. The learning curve is also small enough that the same programmers who developed the OS/2 program could implement the Windows version. OS/2 and Windows can be considered "similar platforms", and therefore outside the scope of this article.
The key question about porting is, how much of the original code can be ported? Porting may not be the wisest decision if too much code has to be rewritten. Some indications of the difficulty can be gathered very quickly, from a few critical items.
A program that intersperses the user-machine dialog in its main processing routines, instead of bunching those routines together and gathering user-specified options at program start-up, promises to be a more difficult one to convert. Heavy use of machine-specific features may also raise a warning flag. For example, a Macintosh program which requires transferring text and color graphics between different applications may not port gracefully to MS DOS. However, such a program may move easily to Windows.
A large amount of machine-specific code in a program may make the port difficult. Many calls or references to specific machine locations may mean that the original programmer used machine-specific methods in writing the original program. This may have been a requirement of the original specifications - for example, to produce displays with exceptional speed. This does not automatically rule out porting, since machine-specific code may not need to be transferred at all. For example, if the proposed port is to a faster machine, specialized calls for the purpose of creating faster screen displays may not be required. Thus, it is important to consider the reason any machine-specific coding techniques may have been used.
Similarly, assembly-language routines interspersed in a program written mostly in a high-level language such as C probably signals that the programmer was unable to write everything in the higher-level language. Again, this probably signals something that is machine-specific, and thus, not as readily ported to a new architecture.
Two important considerations are the relative speed of the current and new platforms, and the memory space. A program's new platform may well be faster than the previous one, or have more memory space. In that case, it will not be necessary to spend so much time optimizing the speed of the program, or shoehorning everything into limited memory. Routines created to make a program memory-efficient may also make its code more difficult to maintain. This is a trade-off that may have been acceptable on the old platform, but may not be acceptable on the new one.
Some software written for machines with limited memory space used very clever techniques (such as self-modifying code) to fit everything in. Those techniques have become less and less common as standard memory sizes become larger and standard methods of dealing with overlays come into more general use.
With the introduction of relatively low&endash;end palmtop computers, such issues may once again become important. Developers of MS DOS programs porting to XT compatible palmtops may need to reduce RAM and disk requirements as well as reliance on fast processors. In their favor, palmtops often use RAM cards rather than magnetic disks. Disk access speed that may have been an issue even on a 386 based platform may not be an issue on a 8088 or 8086 based palmtop.
The areas noted above can be examined without detailed knowledge of any specific programming language, but they form only part of any decision on porting. It is also necessary to have detailed information about a program's coding techniques.
One key indicator is the modularity of the code. The more modular the program &endash; that is, the more that specific functions are accomplished in well-defined blocks of separable code or subroutines &endash; the better. Similarly, if the user and machine interfaces are interspersed with the program's "core" or central functions (see sidebar), that may signal a programming style that lacks modularity.
This is a separate issue from the difficulty of separating user-supplied input from program functions. In separating functions, core functions may remain strong, or may need considerable reworking. Thus, a key question is, after those routines have been separated, how much work will need to be done to repair the damage caused by the separation, and how much work will be necessary to attach the new user interface and machine interface?
In addition, successful programs almost always have undergone revision, such as to eliminate bugs or to add new features. If maintenance work has already been done on the code, this will have to be taken into account when judging the code's modularity and robustness. Too often, it seems that maintenance decreases a program's ability to support further maintenance.
Programs written using an object oriented language such as C++ may port easily since machine specific functions are often isolated from the program's core engines. A pitfall in porting an object oriented program may lie in the differences between the class libraries available on the different platforms.
One reason a software product becomes a commercial hit is that it meets the needs of the marketplace. But the computer marketplace is one of the fastest-moving markets in the world, and it is likely that the market for the ported version of the program will differ at least somewhat from the market for which it was originally designed. For example, word processors for MS DOS and the Macintosh target different markets in terms of user expectations. Thus, a candidate for porting must also be examined as a reflection of the original target market. It may be advantageous to do some research to determine the justifications for certain design decisions.
It should be noted that word processors for Windows are more similar to word processors for the Macintosh than they are to those for MS DOS. The hardware aspects of the platform may be less of an issue than the system software aspects.
Some old issues in both development and design will need to be reconsidered, and new issues will need to be addressed. For example, suppose a piece of software is ported to a less&endash;expensive machine. The price of the software may well have to be reduced, to be in line with the cost of the new machine. That may mean limiting the cost of the port &endash; which will be accomplished by dropping certain "bells and whistles". In addition, some functionality may have to be cut. This will be an extremely difficult decision to make, and must be considered by both engineering and marketing staff.
The code to be retained must be robust enough to survive the port. Porting may inadvertently expose some latent bugs or weakness in the structure of the program. If the code can not be transferred whole, as entire routines or groups of routines, then it may be desirable to step back and assess how difficult it will be to rebuild the code to its previous architecture.
Additional areas that should be examined are the processors, the RAM, the operating system, the output devices, and inter&endash;application communication.
Processor
Can the program afford to "waste" time, or is it highly optimized to squeeze out every cycle? Are certain instructions not used in the old program, but useable in the new one? Is the old platform's processor a RISC? Does the program use delay loops for some reason, and can they be removed for the new program? Many programs use internal tables in some way to control processing; for those files, is byte order important? For example, Intel and Motorola microprocessors use opposite byte orders for integers.
Random Access Memory
Some programs are optimized to use every available byte. Although this is required on some computers, the trade-off is maintainability. Are contiguous blocks important? (Apple II+, MS DOS extended, expanded). Relocatable memory (Macintosh "handles")? Virtual memory?
Operating System
How much did the operating system influence the programmers? Is the code which performed printing inefficient since the developers knew that the native operating system provides print spooling? Does the program implement its own print spooling because the native operating system provides none? Different operating systems not only provide different services, but implement them in different ways, with different implications.
Screen & Printer
Few computers use the same language for both the display and printer. Graphics capabilities, color output, proportional vs. fixed-width fonts, output speed, screen size (resolution in pixels per inch, or number of lines and columns), can the graphics primitives be ported &endash; all are significant questions. A program written for a NeXT machine, for example, can assume that there are many similarities between the screen and printer because the output language is Postscript; but this is by no means universal.
In the (hopefully not too distant) future porting between Windows 3 applications and Macintosh System 7 applications will be made easier by the acceptance of True Type by both Apple and Microsoft. True Type will allow those programs to assume that operations on screen and hardcopy layout of text can be implemented in a platform independent manner.
Inter-Application Communication
How do programs communicate with each other on the native platform? Clipboard? Messages? Windows 3 applications that rely on DDE (dynamic data exchange) may not port well to System 6 on the Macintosh. In this case developers may choose to wait for the release of System 7.
Are files ASCII-only, or do they use some structured format (e.g., Macintosh and Windows resource files)?
Sophisticated Operating System Features
What are the multitasking and multiuser capabilities of both platforms, and how has this influenced program design? What is expected of the program on the new platform in terms of this functionality?
Other areas that might have influenced the original design are the development budget and schedule limitations. If a relatively long amount of time was available for the original design and implementation, this may have allowed for added complexity to the program's design, and many small features ("bells and whistles") may have been implemented. Strong user response to a particular feature probably indicates that it should be retained. However, if a feature is not vital, and if time is critical, then it should probably not be ported &endash; though the engineers doing the port may provide hooks which allow for future growth and the readdition of those features.
On the other hand, the original program might have been designed on a tight budget, which can lead to hurried work and possible weaknesses in some areas of program functionality. If sufficient resources are available for the port, then a number of features could be added to the design.
Programmer's Style
All programmers have their own style, which is reflected in the program. User interface implementations are only one of the ways in which a programmer's style is visible. Some programmers who write in high level languages nevertheless still think of themselves as assembly language programmers (you know who you are!), and may not be able to resist the temptation to optimize code "because it is possible". Just because some part of the original program is unbelievably fast, for example, does not mean that the ported program must excel in the same way.
For the same reason, an application that is slow need not be slow after porting. If some liberty can be taken with the design, or if the programmers who will do the port are capable enough, a "clunky" implementation can be made sleek.
The ported program must be positioned against its new competitors, not its competitors on the old platform. Before starting a port, it's important to ask, what does the original program do? Will the ported version need to do the same, or should some major parts of the functionality be changed to meet the demands of the new target market? This question can make the difference between a good application and a great application. The goal should be to build a great application for the new platform not just a new version of a great application from another platform.
Did the old program meet the expectations of users on the old platform? Will users on the new platform have the same expectations? If new functionality must be added to meet user expectations, what will that cost? For example, DOS users expect batch files and command line arguments. Macintosh users expect to be able to copy and paste text and graphics from one part of the program to another as well as from this program to a different program. In both of these examples, the functionality would be difficult to implement for a program going from either platform to the other.
Is any of the existing functionality inappropriate to the new platform? For example, I worked on the development of a MS DOS based workstation product that included utilities such as a calculator, note pad, appointment calender, and a rolodex. Because these are readily available on the Macintosh or MS Windows, it would be inappropriate to port these features.
Utilities in an original program should not automatically be ported to the new platform. There are many alternatives, including buying or bundling a suite of utilities from a third party. This might well turn out to be less expensive than porting the utilities. Moreover, if the original utilities are better in some way than the standard utilities on the target machine, then they could be ported and implemented as a desk accessory on the Macintosh or as a separate application for MS Windows. Perhaps they could even be spun off as a separate product.
Even when porting to a platform with a similar user interface such as Windows and the Macintosh, small differences should be noted. Windows supports two types of windows - parent (or top level) and child. The latter can not be dragged beyond the bounds of its parent. Another difference is that resizing a window in the Windows environment automatically resizes and redraws its scroll bars. The Macintosh programmer porting a Windows application will need to write code to implement resizing of scroll bars. The Windows programmer porting a Macintosh program will likely need to implement all windows as top level windows.
How is the amount of information presented in the user interface and output (such as printed reports) defined by the hardware capabilities and limitations of the screen and printer on the native platform? Are any features gratuitous, such as color, graphics, or sound?
Example: there is a word processor for the Macintosh based closely on its MS DOS version which allows the user to select a different display color for many parts of its user interface. This is common for an application running in an EGA or VGA environment. Even now, four years since color was introduced to the Macintosh, few applications allow users to customize the user interface colors. In hindsight, the effort put into a color user interface could probably have been put elsewhere and resulted in a better market share.
The last category which could determine functional design decisions is whether there are similarities between the original version and programs from its competitors. Desktop publishing programs for the Macintosh are an example where updates to applications often contain features that were added to match or beat a recent update made to a competitor's program. The target platform may be part of a market in which the competition has a different set of capabilities than the previous market.
The design of the ported program might well be different from the design of the original program. However, while the functionality will differ in some ways, it should not be changed without reason. The design team must resist the temptation to change features for personal or whimsical reasons. Similarities may even be beneficial. Similarities aid in documentation, technical support, testing by the client, and perhaps even in marketing. The priority here must be to provide the ported application with a logical and comfortable interface for the new users. An interface that is consistent with the original program may be implemented for purely marketing reasons. Existing users may decide to switch platforms yet still use the same product.
By definition, porting means cutting and revising code. This process requires courage. The programming team must be brave enough to cut away what is not needed, but also brave enough to save and work with everything that is salvageable, regardless of how tempting it is to rewrite less-than-perfect code.
The amount of code to be cut will depend in part on how deeply the user interface and machine interface are embedded. For example, some parts of the program may be table-driven, so the instructions to process the table will probably be taken along with the table as a whole, or both rewritten completely.
Other code might have a special meaning and may be required for non-technical reasons. For example, perhaps the president of the company which wants the program ported was the one who originally wrote certain features, and wishes to see them live on, and so has made that a requirement.
An example of linking old code to a new machine interface occurred in a port that we recently completed. We ported a rule-based application from MS DOS to the Macintosh. The rules engine read rules in compressed form as integers from a rules file that we also ported. The problem was that Intel and Motorola byte orders for integers are opposite. Since the rules engine was ported virtually intact, we wanted to avoid making any changes to it unless absolutely necessary. Our solution was to write a small utility program to swap every other byte in the rules file. The benefit of this decision was that the environment for the rules engine was similar enough to its original MS DOS environment that the engine operated exactly as it did in its original form. Rather than recode or extensively modify the engine, which was the core of this program, we were able to concentrate on Macintosh specific issues.
This same program had its menuing system implemented in C source code files separated from the engine. Other files contained routines to parse user input before passing it to the engine, and still other files to format output from the engine. By completely replacing the files containing the routines that handled the input and output, and modifying both the interpreter and formatting routines we were able to isolate the core from the new environment.
Knowledge of Platforms
Are the programmers familiar with both platforms? Are they comfortable on the old platform as users, or, better yet, can they use development tools on the old platform? A port can not be done successfully if the developers cannot understand the code or techniques used in the old platform. The programmers must understand enough about the original platform to understand why certain design decisions were made.
Fanatics: Friend or Foe?
Does the client want the port done because it is excited about supporting another platform, or is it for another reason, such as competing with another product offering similar functionality? Do the programmers like the old platform? Do they look down at the existing program, and see their version as the better one? Or do they look up to the old platform, and are they therefore excited by the challenge of bringing a great product to another machine?
Obviously it is beneficial for the development team to be enthusiastic about their project, and it helps if their enthusiasm is shared throughout the management hierarchy. Too often vendors choose a platform because of its market value, even if they do not personally believe in those values themselves. It is important for the entire team to bridge any "religious" differences between platform philosophies. Such differences have too often driven a wedge between the developers of Macintosh, and MS DOS and Windows developers. Those differences can only hurt the effort to port from either platform to the other.
A clear difference between porting philosophies can be seen in the products of two competitors in the MS DOS grammar checker market &endash; we'll call them product A and product B. Both companies set out to port their MS DOS versions to the Macintosh. Product A's vendor sought to embrace the Macintosh interface to its fullest, yet did not redesign enough of its application to fit the interface. Effort expended on implementing a complex user interface that was poorly designed would have been better spent fixing the functional bugs that plagued the first release. At the other extreme, product B's vendor allowed extensive design changes in order to make its program fit the Macintosh. This was accomplished by using a relatively simple but consistent interface. The temptation to implement every new feature that the Macintosh offered was resisted. Product B's MS DOS core code is wrapped in less Macintosh than is product A's, but product B's core fits into its new user interface and machine interface more naturally.
From an engineering viewpoint, product B had the right philosophy. Although from a marketing viewpoint, customers don't always purchase the "better" product &endash; they buy the one that's marketed better. It remains to be seen which philosophy will be the most profitable. Perhaps neither philosophy will prove to be a clear winner.
While a bridge between philosophies is necessary, an appropriate level of compromise is crucial. Leaning too much to either side is as bad as not leaning at all. There are no sure&endash;fire ways to hit a moving target. Aiming for the middle is as much a compromise as aiming for either end.
If it is to be accepted as a new program in its own right, rather than a rearrangement of old code dressed up to look like something that it isn't, a ported program must be accepted as natural both by users and by the operating environment of the target platform
Porting can be an excellent way to extend the life of a program, widen its audience, and generate additional income. Correctly and intelligently done, porting can be eminently successful. However, the financial backers of the project must weigh a port's risks and alternatives against its benefits. The engineers must determine what is within their skill and budget to do given the current condition of the code. The goal of the project must be understood in terms of the target market, not merely the original market.