Maverick Porting Code Model

version 1.1 March 24, 2006

by Geoffrey Slinker

Accesses: 
Maverick Development

Abstract

Porting code will ocurr as long as there are changes in software systems and the need to move code onto these new systems. Porting code "line by line" is an approach that is so close to the implementation that the design is not seen. Understanding the purpose of the code and the reasons why the code includes the statements it does is essential. Porting code requires a broad and thorough knowledge of the current implementation, the current system, the current implementation language, the functional requirements of the current product, the new implementation, the new system, and the new implementation language (sometimes in a port all of the things mentioned do not change). Since there is such a broad and thorough understanding needed its amazing that the task is given to "junior" developers. Ultimately code porting should be requirements porting.

Introduction

Porting code is an ongoing issue. As long as there are changes in software systems and the need to move code onto these new systems. Porting code is a difficult task that is often assigned to "junior" developers or developers that are not viewed as "current" or are not working on the core products or leading edge. The sheer amount of understanding needed to port a system is well beyound the typical understanding of those that usually get "stuck" with porting code. If you have ever experienced a failure in porting a system I would ask you, "Did you put your best people on the job or did you use someone else?".

Reasons for Porting

Following is a brief list of possible reasons to port a system. This list is not supposed to be a complete listing but just a subset of the possible reasons.

  1. Multiple platform release (consumer products, office suite products...)
  2. Host platform change (switching product line to a different and unrelated platform)
  3. Host platform update (host platform has new Operating System (OS) that is different and may be significantly different)

 

Porting Code has many Problems

  1. Propagates optimizations made for a specific configuration.
  2. Propagates bugs hidden in the code.
  3. Propagates work-arounds that were introduced into the code because of inadequacies of the host platform.
  4. Causes the creation of abstraction layers for OS specific things such as file systems, shared memory, threading, socket implementations, and synchronization.
  5. Propagates incorrect assumptions of the system, code takes the path of least resistance and programmers unknowingly code around problems. They choose some system call that doesn't work and so without investigating why their first choice was wrong they find another routine to call or they change some parameter that makes everything "suddenly" work.

From my experience I say, "Don't port code. It's not worth it." But we have to migrate systems to future needs. What should we do? We should port functional requirements, domain models, and domain language.

How to Port Software

There is no generic answer to how to port software. It is a situational problem just like most problems in software development. Following are some steps that can be applied if your situation calls for them.

  1. The team to port the software is the same team that developed the system to be ported. These people have the domain knowledge and the understanding of such things as "why the code uses linked list instead of a hash". But there are more things this team knows. They know the customer. They know why the config files were tweaked the way they are. They know why they used a flat file instead of a database. They know many other answers to the situational questions that were answered that caused the software to emerge the way it did. They also know that the new situation is different. In the previous examples they might say, "We used a flat file back then because the DB licenses were too expensive and the user base was only around 50 people. Now we need to use an SQL database that is transacted and fault tolerant." Just porting the flat file would be a mistake that a noninformed junior programmer would make.
  2. Port at a higher level than "line by line". If the code is developed with an object oriented language and you are porting it to an object oriented language then examine the public methods and consider them as candidates for public methods in the new implementation. If the code is non-object oriented then examine which functions are "exported" and consider them. The goal of these activities is to identify the interfaces.
  3. Provide a validation technique. Provide a way to capture the operating results of the current system in a way that can be used to compare to the operating results of the new system. If the comparison can be automated all the better! This will require an input set of data to drive the system in a predictable manner. This input data should cover normal operating conditions as well as exceptional conditions.
  4. If performance is a significant issue then least common denominator abstaction layers will be a problem. Mapping the Windows thread messaging and synchronization model onto Solaris will result in inefficiencies in Solaris. I worked on a code port from Windows to Solaris where the approach was to port the Windows API's that were used in the product to Solaris. By doing this there would be one code base for each product. After porting such things as WaitForSingleObject, WaitForMultipleObjects, CreateEvent, PulseEvent, and Interlocked Compares to Posix Thread equivelants we had achieved a single source for the "core" product. Since the Solaris version had to jump with "Window's hoops" it was inefficient. Also whenever a new Windows function was used in the product someone had to make a Solaris equivelant and so the porting team was always "down stream" of the "core" team.
  5. If "look and feel" is a significant issue for the platforms supported then a least common denominator solution for GUI components will not suffice. When porting from Windows to Macintosh if you truly expect Macintosh adoption then you must give them a Macintosh solution. If anyone remembers the first version of WordPerfect for the Macintosh you will know what I mean!
  6. Resist adding any new functionality until you have all of the required old functionality in place and working correctly. Do not ignore any system wide considerations for the new functionality but at the same time do not let the new functionality couple unnecessarily with the old domain.

Port the model and the functionality to the new system. Do not try to "just" port the code.

If you are fortunate enough to be in a modern development shop that has customer tests and programmer tests available you can use Test Driven Development to drive the port.

  1. Port the customer tests to the new system to drive the validation process.
  2. Divide the existing programmer tests in a fashion so that you can deliver functioning subsystems and efficiently use all of the team members by working in parallel.

Conclusion

Porting code will ocurr as long as there are changes in software systems. Porting code "line by line" erroneously propagates situational choices that are most likely not applicable to the new system. Understanding the reasons of the current code state is essential. Porting code requires a broad and thorough knowledge that is had by the team that developed the original system. Porting can not be done by junior programmers with minimal guidance. Ultimately you should not port code but you should port requirements, interfaces, and domain models.

Revision History:

Draft April 2004

v1.0 May 2005

v1.1 March 2006