This blog is an extension to my earlier blog on Removing Dead Code.  One of the benefits of removing dead code is to make future code maintenance easier, and therefore cheaper.  Recently I read a blog which reminded me of the proper definition of refactoring, and I realized that refactoring is a logical next step after removing dead code.  One problem is knowing what it costs to do it. Let’s start with the original definition of refactoring, as defined by Martin Fowler and Kent Beck: A change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior… It is a disciplined way to clean up code that minimizes the chances of introducing bugs. So the users will visually see no benefit from this kind of work.  Without a specific project mandate to improve the code, what developer will risk breaking a working module just to make it easier to understand? I think that refactoring will mostly get used when it’s piggybacked on to other tasks, which could be from one of these categories:

  • Performance improvements, e.g. that batch job that’s taking too long to run.
  • Business rule changes that require modifications to a module that is known to be complex or difficult to understand.  Your resource estimates need to include both refactoring effort and business changes.
  • An existing module needs to be cloned for business reasons and some abstraction of that module will make future development, as well as maintenance, easier.
  • Learning new Uniface features.  You may be interested in some new functionality in a release of Uniface that you have recently upgraded to.  A genuine refactoring exercise is both a great learning tool, as well as a prototype for the new feature.
  • For new projects, the architecture design phase is a good time to try and improve your Application Model as well as your templates.  This is where you will probably get the highest payback from refactoring.

Choosing the scope of code for refactoring shouldn’t be too difficult.  Operations, included proc modules, validation triggers, or whole components are all candidates, based on their modularity.  This just means that they have a well-defined interface, use case, or unit test script.  Just be sure to complete the refactoring completely, before starting on any business rule related changes.  You should view refactoring and other changes as separate but serially executed tasks.  This will make the refactoring effort less error prone, and more measurable. So do look out for opportunities to refactor modules of code.  You know that it will be faster than refactoring is in other languages.  Uniface’s high productivity will help during refactoring as much as much as it did during the original development.

3 Comments

  1. Hi Eddy, I do not know what you want to mean with "faster than refactoring is in other languages": refactoring is not an issue of the language, but the IDE which manipulates the code. If you see eclipse, you will find a rename method which renames the definition as well as the references in one go. And this replacement is syntax based, so a variable with the same name will not be affected. What has the current IDF (i've heard some rumors about major improvements with uniface10) to offer in this area? One of the "refactoring jobs" i came across very often is just transfering modified code from components to the data-model to make it available in all components. Just a snap if you have an IDE with all the code of the component and all the code of the modeled entity side by side. Doing this in the IDF is a very complicate job because the socpe is only the code of a single trigger: open the trigger in the component editor copy the code open the model editor and navigate to the similar trigger replace the code there with the copied one close the windows until you are back to the component editor start a "refresh structure" from the menu delete the "local code" to get the one from the model back advance to the next trigger .... perhaps some days after you have centralised these entries, you compile another component, and if you pay attention to the warning count, you may learn that there is a name conflict now. So you have to rename entries in the model and their calls in your "old" component (and in the data model) as well. Even if you use a "find in all triggers", you have to open these triggers, find the position, change it, ... And another cleanup similar to move methods to the "real" classes tehy belong to: move entries which are entity specific from local proc modules of component (LPMX) to the entity (LPME): select the component from the tree select the LPMX trigger move the entries belonging to a specific entity to a central position. copy these entries select the entity from the tree select the LPME trigger paste your code here select the component from the tree select the LPMX trigger delete the entries you have just copied .. and do the same for the next entity .. Not very comfortable at all and one of the reasons why uniface coders have to stand the risks to do these cleanups on the XML-export of the component with just a simple text editor. AFTER THEY MADE A BACKUP OF THE PREVIOUS EXPORT
  2. please have in mind: I am not an enemy of uniface and the IDF as you can see from all my over 1000 posts in this forum, the uniface listserver, T.U.R.F. trying to help other uniface customers working with this tool. I held presentations for the german usergroup in 2006 and 2008 how to improve working with the IDF (the slides can be downloaded from http://www.c-b-g.org/tagungen/). But there are issues which are very hard to do with the functionality provided by the current IDF. Current "Global Updates" allows only a complete replace of the opration trigger, which does not help at all. See Lalit Singh's issue to just add an INIT operation to all his components which is another type of refactoring and the quote from Theo Neeskens at http://unifaceinfo.com/forum/uniface9/logging-a-form-whenever-it-is-activated-or-acessed/ MAKE VERY SURE THAT YOU HAVE A BACKUP !!! You are not an experience Uniface developer and making changes directly of the DICT tabls is DANGEROUS !!! Wouldn't it be better to have an improved "global update" functionality from the experts from "the Lab" so unexperienced uniface developers do not have to code it for themself ?
  3. Hi Uli, No one doubts your enthusiasm for Uniface, and your positive contributions. Thus there is no problem in pointing out limitations in the current UDE in supporting refactoring. I am aware that the Compuware Professional Services team have written some useful tools to examine and manipulate the repository, and maybe there is scope for improving refactoring tasks through some home-grown tools, but obviously we'd all prefer them to be built into the product. My comment on faster refactoring with Uniface was for the scenario where a module needs to be rewritten to improve some business rule logic, or some algorithm. This might mean using a selectcase block instead of a nest of if then else statements, or using pre-compiler directives like #for to generate repetitive code. There are plenty of older Uniface applications around that pre-date some of these newer language constructs. Thus I conclude that rewriting code in Uniface is faster than rewriting in other languages. So I acknowledge that there are refactoring tasks that don't involve rewriting code, which can be influenced by the features of the IDE. Thanks for pointing that out.