|By Yakov Werde||
|January 29, 2010 10:48 AM EST||
The migration march to PB 12.NET will have many shops revisiting legacy applications. The first article in this series will explain why refactoring code before migration can help ensure a smoother migration process and a post-migration enterprise integration effort. It will introduce the Test Driven Development methodology and explain how it can be used to ensure successful refactoring. It will also introduce pbUnit, an open source tool and framework for refactoring PB Classic applications. The next article will show you, by example, how to use the tool and methodology to refactor PB legacy code.
What Is Refactoring?
Martin Fowler, in his now classic work, Refactoring: Improving the Design of Existing Code, defines refactoring as "changing the structure of code WITHOUT changing its functionality." Refactoring is all about establishing or reestablishing order and structure in code; moving chunks of code about for optimum readability, maintainability, portability and reuse. If your intent is to add or change functionality, that's not refactoring, that's maintenance.
All code usually starts with a good design. But, as the scope of a system changes, unintended and unforeseen modifications must be added; usually under time stress. These changes eventually cause the design to fade and the structure to be lost. Consequently, as time passes, the coding style subtly changes from engineering to hacking. Over time the resultant code layout is lost. When refactoring you take a bad design and/or chaotic code and rework it into well-structured code.
Why Should Anyone Refactor?
There are three distinct benefits that any IT shop gets from refactoring:
The first benefit is clearer code whose design remains visible. Over time it can become harder to see the design by reading the code. The original developers probably had a mind set or methodology as to where they put things. Refactoring keeps things in order. You move things to where they should be to keep them in their right place. Hey if it's just your little private room, who cares if there's a mess! But if it's a big public place, carrying a lot of weight, structure and order must be maintained at all costs. Like anything, the longer you let it go the worse it gets and the longer it takes to clean it up
The second benefit is code that is easier to understand. If code is duplicated all over the place or methods are long or overly terse, it's going to be tough to get a thorough understanding of what the code is doing. Plus, it's likely that after a change is coded, extra debugging and testing will be needed to figure out if it was correct and effective. The goal of refactoring is to keep code clear and straightforward to understand (see Figure 1).
The ultimate benefit of refactoring is that it saves an organization time and money. Lost time can never be retrieved. Lost money might be retrievable; but not without additional effort. Change and its resulting maintenance activities are a fact of life. Who in management will care if the computer takes a few more cycles to compile or run something? But I can bet that they will care and not be pleased if it takes a programmer a week to make a change that would have taken only an hour if the code had been easier to understand or work with.
Let's face it; it's highly likely and most probable that someone other than the original author will maintain a piece of code. Now, that other person might in fact be the original author, but so much water has gone under the bridge since the code was written that the original author is really a different person than he or she was when the code was written. They're a virtual other with a slight advantage. Writing correct code is all about establishing and maintaining mental context, the context of the problem the code addresses, the context of the solution and its subparts, etc. Once you step out of a detailed situation, you have to re-establish clear mental context before you can jump back in to effectively address a need. Refactoring is all about making it straightforward to get that context.
Why Should PowerBuilder Shops Think About Refactoring Their Code Now?
Refactoring is the key to reestablishing code ownership. With .NET it's a new world. There's a new GUI paradigm, WPF; a new runtime platform, .NET; and a new IDE, Visual Studio. Yes, the PowerBuilder engineers have done a fine job of making PowerScript compatible with .NET, but there are some old language techniques the just can't be converted. A .NET migration will require lots of due diligence. The more you know and own your code and the clearer it is, the smoother the migration will go. Refactoring is a way to get that code ownership.
Refactoring is the key to thinning the GUI to making it portable. Moving from WinForms to WPF is a major change. To accomplish this you'll need to thin out your GUI. You'll need to move all nonpresentation-centric logic into Custom Class User Objects and rewire the GUI to access it in its new home. Refactoring is the way to accomplish this re-architecting.
How about setting up your logic so it can be shared across and beyond the enterprise? To accomplish this you'll need to move your logic into .NET assemblies or web services that can be deployed as standalone components, then rewire your app to access the logic in its new home. Refactoring is the technique you use to accomplish this move.
What Is Test-Driven Development?
In order to proceed confidently in any refactoring you must have unit tests in place that demonstrate the functionality of code under change. You can quickly run these tests before and after the change to prove that refactoring did not have nasty side effects like introducing bugs or changing functionality. In the words of Martin Fowler, "If you want to refactor, the essential precondition is having solid tests."
A unit test is a test that you do to prove that your code works and to improve your productivity as a programmer. You write the test before you write the code. The test characterizes everything that you expect the code to do. This is very different than the idea of testing that we are used to. The regular pattern is to code a bunch, then test the code using a debugger to see if it really worked, and then spend a bunch more time locating flaws in the code. Some refer to unit testing as object testing because it tests a single object's behavior in isolation from other objects. In the words of J.B.Rainsberger in his great book jUnit Recipies, "The idea of Object Testing is to take a single object and test it by itself, without worrying about the role it plays in the surrounding system. If you build each object to behave correctly according to a defined specification (or contract), then when you piece those objects together into a larger system, there is a much greater chance that the system will behave the way you want." Writing Object Tests involves writing code to exercise individual objects by invoking their methods directly, rather than testing the entire application "from the outside."
Automated unit testing was "discovered," formalized, specified, documented and automated in a framework API by Kent Beck (xUnit) first in Small Talk (sUnit) , then in Java (in cooperation with Erich Gamma) as jUnit and then in .NET as nUnit. The beauty of xUnit is that you write tests in your native coding language, run each test in isolation from all others and can group tests into suites that you can quickly run on demand. A powerful software development methodology called Test Driven Development (TDD) was formulated around unit testing. TDD has revolutionized software creation and maintenance as a part of an Agile development methodology.
In PowerBuilder we are fortunate that back in 2003 John Urberg and Jaimme York ported jUnit 2.1 to PowerBuilder as pbUnit in 2003. They made it freely available to the PB developer community. A 10.2 version is available for download on the Sybase CodeXchange (http://www.sybase.com/developer/codexchange). I migrated pbUnit to version 12 Classic. Send me an email and I'll send it to you.
In addition to providing essential test support when refactoring code, Test Driven Development provides these benefits:
- Cleaner code: The likelihood of the whole thing working when you put it together is greater when each individual piece works correctly.
- Confident coding: You proceed in a confident manner when you run a quick test every few minutes that affirms that you are on track. It is a lot different when you know that the changes you are making won't break the system.
- Future proofing your system: You wind up with a catalog of tests that are ready to be run anytime you need to change the system.
- Better programmer documentation: Just read the test to understand what an object or a method is supposed to do.
- More thoughtful programming: You will write better code because you need to think about it when you write the tests before you write the code.
In my next article, I'll get into the technical details. I'll show you how to install and use pbUnit, and how to write unit tests that support refactoring. After that, I'll show you how to do a couple of refactorings to thin out a GUI and partition business and data logic
- Beck, Kent. (2003). Test-Driven Development by Example. Boston MA, Pearson Education
- Fowler, Martin. (1999). Refactoring: Improving the Design of Existing Code. Addison Wessley
- Rainsberger, J.B. (2005.) jUnit Recipes. Greenwich CT, Manning Publications Company
- Where Are RIA Technologies Headed in 2008?
- PowerBuilder History - How Did It Evolve?
- Creation and Consumption of Web Services with PowerBuilder
- Cloud People: A Who's Who of Cloud Computing
- DDDW Tips and Tricks
- Cloud Expo 2011 East To Attract 10,000 Delegates and 200 Exhibitors
- Working with SOA & Web Services in PowerBuilder
- Dynamically Creating DataWindow Objects
- OLE - Extending the Capabilities of PowerBuilder
- Cloud Expo and The End of Tech Recession