So this is my legacy application program MITMCLAS (Maintain Item Class) I searched for the oldest program I could find and it was originally coded in RPGIII - the first thing I did was Visualize the program using the Visualize Application feature of RDi
I ran this on two working versions of the same program. Which one would you pick to work on given the choice, none is not an option in this example.
The first diagram was generated from the original RPGIII program and the second from a refactored version of the original code which ended up as Free-Format RPG, well almost, the D-Specs are still there, but these can easily be changed using some of the open source tools available. I'll cover that later.
Straight away you'd have an idea of which program you'd pick, wouldn't you?
Refactoring is it necessary ?
There are many organizations still using these legacy applications for all sorts of reasons, mostly these reasons are associated with the prohibitive costs involved in re-writing something that works, which of course provides no additional business benefit whatsoever.
However adding enhancements or fixes is still an on-going requirement and code that has been enhanced or fixed over time will eventually decay. So what you end up with is code that has been patched and patched, which is hard to read and hard to modify.
This is where Code Refactoring adds value to an existing legacy application by making it easier to read and easier/quicker to modify, and puts you in a position where you are able to start looking at projects like enhancing the database without destabilizing the application. Check out the previous blog posts about database modernization if you haven't already. Surrogate DDS to DDL modernization and DDS to DDL modernization - adding constraints
Code refactoring The Benefits
Refactoring makes programs easier to read
Refactoring helps you program faster
Refactoring helps you find bugs
Refactoring helps you reduce the number of lines of code in your application, this leads to less code to maintain.
Bad Smells in RPG Code
The term bad smells comes from Refactoring - Improve the design of existing code and is a reference to one of the author's grandma's baby rearing skills - If it stinks, change it. So when you turn your nose up after reviewing code, you know what to do - Refactor.
The above mentioned book is a reference to Refactoring Java and I've used it as a template to refactoring some very old AS/SET generated RPGIII I have on my development box. Which is an on-going process and one I'm using to freshen up my RPG. Below is a list of code smells which indicate that you should refactor.
If your code contains lots of comments because it is hard to understand then refactor the code so it is self documenting.
If you have duplicated code within a program move this to a subroutine, /COPY member or subprocedure. If you can create your own BIF then do so by defining an external subprocedure and binding it to the program. This is useful if the code is duplicated throughout your application.
Modernize old RPG code
If your RPG code is RPGIII or RPGIV then convert it to RPG Free-format. I've done this using a couple of utilities that I've downloaded and updated - you can get them here www.jcrcmds.com thanks to Craig, if you want the optimized for AS/SET versions, contact me via the tab on this page and I will make them available to you. Also on Craig's site is a utility to convert D-specs to Free-Format.
Remove/rename all indicator references
Indicators pre-date RPG so please, if you still have them in your code remove/rename them. Here is a reference back in 2012 The New Basics: Indicators
Use Meaningful Names
All fields, files, subroutines, subprocedures and anything defined in the code should have meaningful names. With RPG Free format there are few limitations. Remember try to make the code as self documenting as you can. If you can't understand the code that you are reading or it takes a long time to understand, it needs to be refactored.
Long Parameter Lists
Try to keep parameter list to ten or less, long parameter lists are hard to understand. Pass in enough so that you can get the information you need elsewhere.
Use as many BIF's as you can
As RPG has evolved, so has the number of built in functions, for example remove all the date calculation code that used to fill legacy applications, use BIF's instead or write your own, here is a good reference for doing this. You used to be able to MOVEL and MOVE fields between character and numeric fields, now use %CHAR or %DEC
Replace Temporary Work Fields with Subprocedures
Instead of using lines of code to create (temp) work fields, move those into a subprocedure that returns the required value, for example instead of calculating a invoice line total in the main line code, create a subprocedure that does this and passes the value back.
Initialize Fields in your Data Definition Specs (D specs) if you can
Remove any code that initializes fields at the beginning of a program, a lot of RPG III programs had banks of Z-add *Zeros of Move *BLANKS at the beginning of each program, use the D specs or the free format data definition specs to initialize fields and remove the redundant code - that is just clutter and there is a more efficient way to do that.
Make Small Incremental Changes - Then Test
Make small changes to your program and then test, if you are replacing duplicate code make sure you don't break anything, testing is essential.
Use a change control system to automate deployment of code.
Make sure you are using change control to automate the deployment of small changes which can be backed out quickly and efficiently. If you have a big project try and break it down so that you can deploy incremental changes without de-stabilizing your production application.
Use Code Coverage
Use code coverage to ensure you actually use or can get to every line of code in the program. If you can't get to that code think about refactoring the structure of the program, it's pointless having code that you never can get to or execute. Check out what I've written on code coverage here.
Use Modern Tools To Work on your Source Code.
RDi has all sorts of features to refactor your code, do not use SEU or PDM to do this. For example when renaming a field or subroutine you can use the Find/Replace feature.
RDi can outline your code so that you can easily switch between subroutines with a mouse click. You certainly wouldn't want to use the old green screen development tools to do this.
If you have any questions or need help just refactoring please use our Contact Page to ask questions.