Recycling RPG

Article ID: 63105
Strategies to create new applications from legacy code

The buzz about "green computing" often focuses on reduced paper and energy consumption and employee telecommuting but, for IBM i development groups, "recycling" RPG application code can be another important way to "go green." Recycling old code includes code reuse, but goes further, creating new application functions or interfaces by employing code restructuring as well. This article explores strategies you can incorporate in your own development.


"Reduce, reuse, recycle" is good environmental strategy, but what are the benefits for IT? Reducing the amount of unnecessary code that's written, especially through well-established code reuse techniques, can lower the cost of application maintenance. But when code can't be reused in a conventional way, recycling is the next alternative. For example, you may not be able to "include" RPG code in a Java application, but that doesn't mean the only alternative to creating new or modernized applications is to throw your RPG code in the waste bin and reimplement all the original code's functionality in a new language.


Starting from scratch and replacing large amounts of working code is an expensive alternative and can introduce significant instability in business operations as replacement code is deployed. Yet, sitting pat on old applications, especially monolithic, 5250-interface programs, can cost an enterprise significant operational inefficiencies and lost opportunities with customers and business partners.


Recycling RPG lets you avoid both the extremes of doing nothing or rewriting from scratch. In many cases, you can reuse much of your existing code and implement new application functions and interfaces incrementally. Even when a new version of an application is created entirely in a new language, there are ways to reduce the cost and risk through "recycling."


Code Conversion and Refacing

To start, I'll briefly cover two situations that may arise. For various reasons, including mergers and acquisitions, your enterprise may need to execute an entire RPG application on a platform that doesn't compile or run RPG directly. This situation requires a new implementation of the application to be created in a supported language (e.g., C# or C++), and one way to get there is through a tool that converts RPG statements to a supported language.


You can find RPG code converters by searching the web for strings, such as convert RPG "C#". Keep in mind that making significant modifications to the code generated by such tools may be difficult, because RPG programmers inexperienced with the target language may struggle with the new syntax, and programmers familiar with the target language may have difficulty following RPG "opcode" semantics in the generated code.


Automatically converting entire RPG programs to another language is most appropriate when the program(s) can be efficiently regenerated each time the original RPG code is modified. (There are also IBM and third-party tools to convert programs written in non-ILE versions of RPG to ILE RPG, but these are usually one-time conversions that produce a program similar to the original and still familiar and maintainable by RPG programmers.)


A more common situation that enterprises encounter is the need for a browser user interface as an alternative to a green screen. For many years now, a plethora of refacing tools have been available that use a variety of techniques, including intercepting the 5250 data stream and mapping the data, screen attributes, and keyboard and mouse actions between the browser and the RPG program's 5250 I/O. I won't discuss refacing in great depth because many other articles have covered the topic thoroughly.


Simple refacing (i.e., screen scraping) can provide a quick and, in many cases, relatively effortless way to give web access to an existing application. Many refacing products also allow for customization of the web page layout and input operations, for example, by using drop-down lists for selection. Refacing can broaden the range of access to an application and provide more attractive, easier-to-use screens. However, refacing doesn't address several broader and longer-term goals.


The Full Benefit of Recycling

The ideal goal of recycling RPG is to find a less wasteful way to produce improved or new applications by realizing the full value inherent in legacy applications. There are several kinds of value that we might exploit from existing applications:


  • a complete, executable application
  • executable application functions and processes that are already available from the application's external interfaces
  • executable code snippets that perform some subordinate function or a particular step in a process
  • the implicit design of the application, including its model of the problem domain, structure, main functions, and subordinate functions or steps

Automated code conversion and refacing address the first category in the above list, and refacing can provide improved access to the second category. Generally, however, we need additional tactics and tools to fully extract the value in the second through fourth categories. Let's look at each of these in turn.


Recycling Application Functions and Processes

Consider a traditional order entry application implemented in ILE RPG and supporting a 5250 user interface. This application would typically provide an item lookup function and a process using multiple screens to allow entering a new customer along with the customer's first order.


If you want to use this application's existing, executable function and process in a new application, you might first browse the source code. If you find that, despite being a "legacy" application, the code is well structured into a collection of procedures, including GetItemProperties, InsertOrder, and InsertCustomer procedures, your task may be relatively easy. You might, for example, use an RDi tool to generate wrapper code so these procedures can be used as web services, which are invoked by a new application developed with any language or tool.


More likely, you'll find the existing application was implemented as a few large programs with lots of unparameterized RPG subroutines, and the business logic, workstation I/O, and database I/O are all intertwined. A couple of alternatives are available to recycle this code, and both options hinge on 5250 I/O operations as the pivotal point in the existing programs.


First, you can manually revise the code to replace display file "read" statements with a procedure entry point and "write" statements with a procedure exit point. (An EXFMT statement can be treated as a write followed by a read.) The parameters to the new procedure are record structures to hold what are input and output fields read or written by the workstation I/O statements. (You may not need to include all of these for the new procedures.)


Of course, you generally need to create a service program, and you might also wrapper the procedures as web services. This branching of the original program could lead to duplicated source code and subsequent parallel maintenance, which is generally a bad idea. ILE RPG provides both a source code "include" feature and conditional compilation to address this issue. (If you're not using these two features, even for legacy applications, you're missing out on two simple yet powerful features of ILE RPG.)


Some IBM i development tool vendors make this strategy even easier by offering tools that intercept a program's 5250 data stream and generate a web service that interacts with your existing program via this stream. This exposes the functionality of a 5250 screen as a parameterized web service.


Recycling an available application process is just an expansion of the above technique, in which a higher level procedure or web service (or development tool runtime facility) composes the process by making a sequence of calls (which may be conditional) to the exposed functions in a sequence of 5250 screens. With some vendor tools, you can combine this technique with the tools' refacing capabilities to map a sequence of 5250 interactions to a reorganized browser interface of one or more pages. This level of composition and interface reorganization can take advantage of browser interface features to simplify processes supported by existing 5250 applications.


Mining for Smaller Gems

Not all the useful functions within a legacy application will necessarily be manifested through 5250 interactions that can be encapsulated as describe in the previous section. There are often smaller snippets of code that validate a business rule, perform some intermediate calculation, or perform some other non-5250-related task (e.g., sending an email).


Again, if you're working with code that's already a well-structured set of procedures, many such routines may already be accessible by wrappering with a web service or other interface. When existing code isn't so well-structured, the first step is to turn the code snippet into a procedure. Adding the necessary procedure interface code to a chunk of RPG code can be a bit tedious, but the more significant hurdle for recycling code snippets is dealing with code that intertwines both code that's relevant to the function you want to exploit and code that deals with other parts of the specific application (e.g., printing). Though you can copy sections of code and delete unnecessary statements, you raise the "branching" problem mentioned earlier.


Here again, facile use of ILE RPG's include facility and conditional compilation are powerful allies. It's practical to cut out a large chunk of a program's code and replace it with an /Include directive to reincorporate the extracted code when you compile the program. To produce an independent procedure using only some of the code in the extracted chunk, simply bracket parts you want to exclude with /If Defined(_Exclude) directives and define the _Exclude condition on the command used to compile the program. In many cases, a limited amount of rearranging the physical sequence of the extracted code can reduce the number of /If directives required, as well as make the code more comprehensible. A benefit of conditional compilation, however, is that you don't necessarily have to completely reorganize the execution structure of the extracted code. And, by using an /Include, you don't have to immediately revise existing application code that uses the original code.


You'll want to use a modern editor, rather than SEU, when you follow the technique just described, because the technique produces a number of source files (or members) as the source-level building blocks, and managing them with SEU is unproductive. It's also much easier with a decent editor to explore code to find snippets that are candidates for extraction.


The extract/include technique works well for creating functions, such as validity checks and financial computations, that aren't affected by the state of a multistep process. In other words, repeated invocations with the same input values always produce the same return values. A great deal of business application code, however, depends on a series of conditional steps to complete a transaction. For instance, entering a new order may require entering a new customer in some cases.


Extracting a step in a process can be more difficult than extracting a simple function when the implementing code uses many global variables across multiple steps or has poorly structured flow of control (e.g., use of GOTOs). One ad hoc technique that can help is to define a record structure that contains state variables and extract the process step as a procedure that uses this structure as an in/out parameter. Admittedly though, in some cases the best thing for truly pathologic code is to stick to the previous two categories of recycling until you can grow another application and throw the old one on the compost heap.


The Holy Grail--Design Extraction

A business application (including both the code and database) isn't just any organization of the underlying data, business rules, and operations; it's a particular organization that explicitly or implicitly embodies a model of the real-world domain. Ideally, the original application developers worked with people familiar with the domain (e.g., an enterprise's sales operations) and had a sound model in mind as they designed, implemented, and modified the application. An application's underlying model includes entities of interest (e.g., customers, items for sale, employees) and their interrelationships and interactions, how business operations are organized (e.g., sales channels, supply chain), and much more.


In my experience, many development groups have taken a fairly informal approach to application modeling, and the results may not be well documented. But this deficit is one of the main reasons there's significant potential benefit from extracting design elements from existing code. If useful parts of the business model can be extracted from legacy application code, we can potentially "recycle" that code's design by creating a new version in a different form or language.


The only problem is, extracting design from code can be very hard.


Program (or application) comprehension underlies both design extraction and plain old maintenance. And tools and techniques to help understand programs have been around for decades. Some of the earlier tools include a variety of cross-reference analyzers to show relationships such as the database files and fields a program uses and which programs use a particular file or field. Similar tools exist for listing static and dynamic relationships among programs, subroutines, procedures, and other code units. These tools have evolved to interactive search and exploration (e.g., drill-down) features in modern code editors and IDEs, such as WDSC and RDi.


In addition to becoming more convenient to use, code exploration and comprehension tools have incorporated more sophisticated analytic techniques. For example, some tools can trace program variable dependencies and life cycles, which not only improves impact analysis, but it also helps tie more of a program's elements together to produce a more complete picture of the application's underlying model.


As a program experiences years of code additions and modifications, the program typically becomes more opaque and the model fuzzier to discern. Thus, a developer's facility with a good set of tools becomes essential to productive design extraction. Developers who seek the Holy Grail should also have a basic understanding of how modeling and design underlie application development, so they know what to look for and how to use what they find. (To learn about comprehending a program's model by using display file record formats, see "A Hidden 'Window' into a Program's Design" at the end of this article.)


Large-scale design extraction isn't necessarily for the timid. But if your organization is looking at a major reimplementation project as part of your strategy for recycling current RPG applications, you should be sure to thoroughly assess available tools and bolster staff skills in design extraction. (Some of the best candidates to consider as developers to work on design extraction are your most productive maintenance programmers. Not only are their skills similar to what's required, but maintenance programmers may already have gained a good understanding of some applications' models as well.)


Design extraction (at least from applications written in older languages) is, and will probably remain, a task in which tools can greatly assist, but not replace, a human analyst. On the other hand, once a partial or complete design is extracted from a running program, there's promising potential to automatically generate another incarnation of the application (or parts of it). Unlike starting with a non-executable modeling language, such as basic UML, a design extracted from a running program's source code has adequately precise information from which to generate a different form of executable code.


Working with extracted design elements and generating code from them is different from the mechanical translation discussed earlier, which is essentially a one-for-one translation without restructuring. Design extraction and code generation based on extracted designs are promising areas that vendors of both program comprehension tools and application generators are actively pursuing.


Preparing for the Next "Cycle"

In the natural world, sustainable processes always involve recycling, whether it's carbon in the atmosphere and oceans or vegetables coming from garden and trimmings going into the compost bin. Sustainable software development also requires efficient recycling so the energy that was put into one generation of applications isn't all lost when the next generation replaces the old one.


This article has looked at how to capture more of the "energy" embodied in current RPG code. Just as important for the long range is to follow development practices that make recycling more efficient. These include good design practices and using development tools and languages that allow more of the model to be explicitly included in the definition of an application. Good--meaning comprehensible and updated--documentation is also important, and modern development tools and languages help in this area as well. Other practices and tools that are part of the entire application development life cycle, such as in the areas of requirements gathering and management and automated testing, and can also improve software recycling efficiency.


As you look at your next application project, keep in mind that recycling code is a good start toward being an "organic" programmer.


Paul Conte, a System iNEWS senior technical editor, is also president of PCES of Eugene, Oregon, which provides educational and consulting services in SQL and Java application development. Paul has been a software developer and consultant for more than 20 years and is a widely published expert on database systems, database design, programming languages, and application development. He's considered a leading authority on DB2 UDB for System i, and his articles have appeared in System iNEWS, DB2 Magazine, Database Programming & Design, and numerous other publications.


A Hidden "Window" into a Program's Design

The most obvious way to start understanding a program's model of the real world (after verifying that, as usual, there's no current external documentation) is to look at the program's procedure and subroutine names and hierarchical structure. This often reveals a lot, but with a non-object-oriented language, like RPG, and especially with typical legacy programming styles, the routines reflect the way the programmer decided to chop up the code into chunks for different branches of the program flow. This approach is often different from the way actors (e.g., employees) in the problem domain view the world.


Most programmers who've spent much time maintaining programs written by other programmers have learned to look to the database schema, especially record layouts and foreign key constraints, to get a better picture of the way entities and relationships have been modeled. Again, the physical database implementation doesn't always reflect the logical data model (nor should it necessarily). Nevertheless, the correspondence is often closer than between a program's routine organization and the business processes or use cases.


For years, I've used various tools and a variety of ad hoc tricks to tease out how a program models the activities of the real world of interest. Recently, a colleague with a great deal of experience in program comprehension techniques pointed out a "window" into IBM i programs that had been hidden right under my nose all along--the display file record formats used by the program.


The formats are where the data and allowable actions for a set of closely related use cases are nicely collected in one spot. If you start with an inventory and descriptions of the display formats and--following the dependencies to and from each field--work out from the field to the database, you generally traverse the code that implements one or more use cases. This can be a great boon to comprehending the model that underlies the program.

ProVIP Sponsors

ProVIP Sponsors