Let's assume that there is sufficient economic justification for writing a portable application. The following sections describe some techniques I've found helpful in making this happen.
Use an Interpreted Language
From Lisp to Smalltalk, Java, and Perl, interpreted languages have an immediate portability advantage over compiled languages because the interpreter provides a much-needed layer of insulation from the underlying operating system. Of course, this doesn't mean that interpreters are foolproof, because differences in operating systems often find their ways into them. In fact, resource handling, threading, file system manipulations, network libraries, and user interfaces all present challenges to the portability of interpreted languages. Still, as a general rule such languages make sense if you're planning on building a portable system (provided, of course, that you have made certain that your language has an interpreter on every platform you intend to support).
If you're using a compiled language, you have to be sure that a compiler exists on every target platform. In addition, you need to educate the development team on the specific idioms that enhance portability within that language. If you're using C or C++, these techniques include using carefully designed source code management and build systems that select the proper file for a given target platform as well as conditionally include specific source code based on the language. Conditionally compiled code is more challenging than normal code because it is harder to write and maintain than its platform-specific counterparts, but the overall process is quite manageable. I know, because I've done it. You can too.
Use Standards-Based Persistent Storage
By persistent storage, I mean the ability to store and retrieve data on persistent media, such as a hard drive. For simple data use XML stored within whatever file abstraction is provided by the target platform. For complex, structured data use a relational database accessed through an intermediary layer like OBDC, Java's JDBC, or Perl's ODB. Although ANSI SQL is far less portable than it should be, try to use it. Limit the use of vendor-specific embedded procedures, such as Transact SQL.
Make Business Logic Portable
The area of your system that should be the most portable is your business logic. As detailed in Chapter 8, a well-architected system isolates business logic. This code should be easliy portable to other environments. If it isn't, further investigation is warranted to ensure that the development staff is not making poor implementation choices.
Closer to the User Means Less Portability
The backend infrastructure holds the areas of greatest portability. Moving from the server or backend toward the user, portability tends to decrease. Indeed, despite a variety of vendor claims to the contrary, the user interface is the area of lowest portability, because of substantial device differences in color schemes, fonts, display resolutions , and so forth. These realities, which don't appear likely to change, suggest a very practical approach in which the greatest investments in portability are in backend or infrastructure (e.g., invest in server-side portability before client-side portability).
Use XML for Standardized, Interoperable Communications between Subsystems
In complex distributed systems that run on different platforms, you will eventually have to resolve the issue of subsystem interoperation . Fortunately, you won't have work too hard, for the bright and talented people who invented the core technologies powering Web services, including XML, SOAP, WSDL, and XSLT, have already done all the heavy lifting . Use XML to support interoperable communications between subsystemsyou'll be happy you did!
When an application is centralized on a single platform, or when you require extremely high performance, you might want to consider a non-XML solution. Converting in-memory data into XML and back consumes a fair amount of resources and is not the best choice for every situation. Do this very carefully, as my own experience shows that XML is, in general, the most flexible solution, even though it is slower.
Avoid Hiding The Power of a Specific Platform in the Name of Portability
Consider database portability. While the major vendors claim to support ANSI SQL, they all provide vendor-specific variants tailored to different operations. Oracle's commands for manipulating hierarchies are too powerful to ignore for many applications. SQLServer 2000 commands for manipulating XML are just too fast to ignore. Challenge the notion that portability must mean taking the "lowest common denominator." Structure your tarchitecture to take advantage of the power of specific platforms.