Practice 12. Isolate Platform Dependencies
If your code must support multiple platforms, a clean separation between platform-specific code and all the other code is essential to have software that can be easily kept in a working state. Some examples of a platform are operating systems, graphics subsystems, runtime environments, libraries, and user interface toolkits. The best way to isolate platform dependencies is usually through an abstract interface (such as a Façade design pattern) so that the majority of the software is isolated from the platform-dependent code. Otherwise, software can become littered with conditional code that makes the code hard to maintain, debug, and port to other platforms in the future. If platform dependencies are important to your project, take the time to do them right. The effort will pay off.
Beware of Copy and Paste Porting
I have seen a number of very poor ports of code, especially to a new operating system. The problem is that the quickest way to do a port is to simply copy and paste the code, then make the changes required for the new platform.
The most extreme example I've seen of copy and paste porting was a project where the programmers duplicated the contents of entire source files, even if all that was different for the new platform was a few lines of code! The result was extra effort, since bug fixes were often made in only one copy of the code, or features were only added for one platform. It was also hard to know what was actually platform-specific. The result was more time spent coding and testing. In the end, we had to completely redo the port, and the second porting effort was harder than the first!
Admittedly, the previous example is an extreme one. But even on a smaller scale, copy and paste can still be a major impediment to keeping a product in a working state. For example, I remember one project where a product was first written for UNIX, then ported to Windows, and then to the Mac. Because the ports were not done at the same time, there were far too many cases where three copies of the same few lines of code were duplicated one after the other. The code was hard to read, maintain, and keep working. We had to do a major cleanup, which probably cost as much as the total of the original ports. All this effort could have been saved if the ports had been done properly, by isolating the platform dependencies behind suitable abstract interfaces.