Developer: J2EE

Managing Software Entropy with RefactorIT and Oracle JDeveloper 10g
by Dr. Robert J. Pefferly, Jr., Yuri Schimke, and Tanel Unt

Learn how to manipulate obtuse code into elegant source code that is both efficient and manageable using RefactorIT and Oracle JDeveloper 10g

Downloads for this article:
· Sample Code
· Oracle JDeveloper 10g
· RefactorIT for Oracle JDeveloper 10g


The Second Law of Thermodynamics, also known as "entropy," dictates that the chaos of a system increases with time and decreases if and only if outside energy (work) is applied to order the system. In the world of programming, this law often expresses itself as "software rot," in which software reliability degrades with time.

The Extreme Programming practice of refactoring is a powerful technique for minimizing software entropy via a disciplined approach to restructuring source code. Refactoring ensures that a system's functionality remains unaltered by making source code easier to understand and maintain, and to keep it operationally streamlined. By utilizing automated refactoring tools, programmers can keep tedious bookkeeping efforts to a minimum and focus their attention on "real" programming, thus increasing productivity and code reliability.

Developing intricate software applications is a logistical operation whereby limited resources must be allocated to cover resource-demanding activities subject to a tight time schedule. Refactoring and development are both methods for manipulating code in this manner, but they have a fundamental difference: code design adds functionality while refactoring streamlines pre-existing code by redesigning its internal structure. The laws of thermodynamics guarantee that the entropy of a software system or project will increase with time, thus software will degrade unless it is revised to maintain efficiency. Hence, design occurs when new functionality is being added, while refactoring fights software entropy via architectural manipulation that maintains existing functionality. Refactoring is used to overcome unnecessary complexity, changing requirements, architectural limitations, poor/degraded code, and incomplete understanding of complex systems.

Automated refactoring is a powerful tool that empowers developers with the ability to restructure/streamline source code in real time, allowing programmers to safely re-engineer code while leaving the functionality unaltered. Thus, refactoring improves the design of code after it has been written using a disciplined error resistant methodology. This approach is quite profound for software design, development, and maintenance because source code:

  • could have been written anywhere from minutes to years beforehand. Development and maintenance are a matter of perspective and the effort of previous legacy code can be recycled into current projects.
  • can be optimized and safely altered at any time. Design and maintenance are interchangeable and "hacked code" is a viable base to produce efficient industrial code.

Benefits of Refactoring

With the support of refactoring tools integrated into a strong development environment (for example, a refactoring plugin is available for Oracle JDeveloper 10g, and that product will soon support refactoring natively), code transformations and development can be contemplated and actually undertaken that would otherwise be considered too laborious or resource consuming. Even a large code base can be consistently modified in an instant by applying refactoring operations which ensure that the system's behavior will remain consistent and that the design will consolidate.

The benefits of combining refactoring and development tools into one platform aid developers throughout the development life cycle by encouraging refactoring during development. Although this may seem trivial, just as a small stream can erode a mountain, consistently performing small refactorings can drastically morph your environment by simplify code and improving design while ensuring that functionality remains consistent. When refactoring is combined with development, projects gradually evolve because functionality and structural design can be modified in real time to implement enhancements.

Refactoring also brings the benefits of Extreme Programming by:

  • Making the system more maintainable using well-structured code, leading to reduced costs and allowing limited development resources to be efficiently utilized
  • Increasing programmer understanding by allowing code "play" that does not introduce bugs, thereby increasing confidence to assess foreign code and conduct changes
  • Streamlining code on the fly in order to optimize performance and redesigning architectures as requirements change
  • Recycling quality code that has been tested, allowing developers to focus on new programming instead of reinventing the wheel
  • Allowing developers to act as teams and share responsibility over portions of code combining diverse learning, testing, development, and quality assurance platforms.

Thus, when developing software projects, refactoring helps answer these fundamental questions:

  • Why does this project exist and who would care (or prefer) if it did not?
  • What are the business results that this project is expected to produce, and how specifically do you envision getting there?
  • What are the keys to achieving these results, and how much of your energy are you putting into making sure that these things happen as planned?

In essence, combining Oracle JDeveloper 10g with a refactoring tool (see Figure 1) allows one to recycle tested code into a project with minimal maintenance and transform proof-of-concept (hacked) code into a justifiably industrial level release.

figure 1
Figure 1: RefactorIT and Oracle JDeveloper 10g
Refactoring Cycle

The crux of refactoring source code is to approach design as a fluid operation vice a rigid adherence to possibly erroneous and incomplete architecture. Hence, refactoring maintains system functionality and empowers the evolution of code in real time, thus freeing developers from blindly following a priori designs, maintaining inadequate code, and having to reject enhancements outside of the original architecture. Refactoring effects software projects in various stages:

Building Stage:

  • Weak code can be objectively identified via statistical measuring and audit tools and the value added with each feedback iteration can be estimated.
  • Differences in architecture and logical relationships can be evaluated where points of diminishing returns can be identified and resources allocated appropriately.
  • One can finalize an iterative building process once the recommended changes add less than X value to an application-method-class-package.
  • Better comprehension is empowered by encouraging code play.
Manipulating Stage:

  • The question " Is one application more efficient than another?" can be objectively evaluated.
  • The value added when refactoring code can be measured.
  • One can demonstrate that a change is either beneficial, detrimental, or an exercise in futility.
Maintaining Stage:

  • The question "Is one application easier to maintain-test-manipulate than another?" can be addressed
  • Reusability, testability, and maintenance of an architecture can be objectively evaluated
  • Prohibitive complexity and substandard quality can be investigated
  • Overall performance, maintainability, and understandability are improved
  • Providing objective sufficient information on macro code bases too big to comprehend.
Recycling Stage:

  • Objectively measure code to provide management with useful metrics
  • Tested software, source code, and algorithms represent intellectual capital that can be recycled into other projects to decrease development expenditures/times.
Table 1: Refactoring Effects

Programmers use refactoring as a full life-cycle platform tool to learn, evaluate, measure, recommend, test, identify, describe, and communicate metainfo concerning source code. Thus, programmers continually repeat the following tasks:

Detect a Problem

Is there a problem? What is the problem?

If one can measure it, then one can manage it; but identifying "smelly" code to refactor during software development and maintenance is often more art than science. Unlike constructing a bridge, the lack of physical infrastructure when building a software application impedes definition and detection. For example, one can address objective and subjective quality measures such as:

  • Age, height, floor space, architecture, location, and amenities to assess a building
  • Speed, power, chassis, color, torque, gas mileage, and style to assess a car
  • Functionality, reception, layout, color, voice clarity, and style to assess a mobile phone.

Software audits and metrics exist for one singular goal: to encapsulate sufficient information used to predict an external quality that identifies high-risk code; metrics simply describe a system in a quantifiable manner. Yet when evaluating software, measures such as lines of code, function points, number of methods, and cyclomatic complexity seem inadequate when assessing the quality or complexity of a running software application. There is no consensus as to what should be measured when assessing code because quality, as described by Walker and Kitchenham in a 1989 Software Engineering Journal article, is "hard to define, impossible to measure, and easy to recognize." Thus, in order to identify code that should be refactored, a system of metrics, audits, and gut level engineering experience is required combined with techniques such as the University of Maryland's Goal/Question/Metric (GQM) Paradigm developed by V. Basili and H.D. Rombach.

The purpose of a metrics collection is not to prescribe a correct suite of metrics for a user or to pontificate a single methodology; metrics, audits, and patterns are provided as a means of evaluating software via a variety of standards or measures. Hence, organizations should pick methodologies and metrics appropriate to their system to fit their requirements and adhere to the following principles when utilizing evaluating code:

  1. No singular metric or audit provides a silver bullet when evaluating software and too many metrics may lead to information overload. A well-chosen subset of four to 10 measures is beneficial for evaluating an applications status.
  2. Measurements should be taken often and recorded such that a time series graph can be generated tracking the evolution of the system.
  3. Occasionally a complete snapshot of metrics (30-40 unique measures) should be recorded and analysed such that milestone deliverables can be compared and effective metrics identified. Save these snapshots using a time-date naming structure for reference and posterior analysis.
  4. Do not be afraid to change the measures you utilise to evaluate quality, complexity, or project status. Different phases require different measures, thus analysis of a complete metric set should indicate which metrics correlate with the reality of a particular project.
  5. Software is a physical system hence variability is omnipresent. All metrics should be viewed with a plus/minus tolerance for error.
  6. Use metrics as a guide, not as an omnipotent rule. If management is overly reliant on reporting numbers instead of producing code, the program style can (and will) change, thus encouraging encouraging Hawthorne and Heisenberg effects.

Characterize the Problem

Why is it necessary to change the code? What are the benefits? Are there any risks? Similar to detection, characterization involves identifying the culprit of the error and fitting the problem into a pattern that can be corrected such that the solution is not worse than the current state. When deciding if one should refactor a piece of code, one determines if the pain is worth the gain. With an integrated and automated refactoring tool, refactoring is a painless process that can always be undone.

Design a Solution

What is the "goal state" of the code? Which code transformation(s) will move the code towards the desired state? When analyzing source code, one should keep in mind a "big picture" state of the project such that if a piece of code smells, then the level of cleaning required is clear. For examples of solution designs refer to the work of Sven Gorts and Philipe T'Seyen at refactoring.be/thumbnails.html.

Modify the Code

Once a patch of smelly code is found and an alternative has been identified, then transformations that correct the code can be performed, tested, and analyzed to measure improvement.

Test the Code

To make sure it still works as intended, tests must be run after every major change. If unit tests are not yet used in your project, Oracle JDeveloper 10g can generate much of the unit test code automatically.

Practical Example

To illustrate these steps, let's walk through these steps using JDeveloper and RefactorIT to refactor a sample application.

We have an application with three classes, Customer, Order and Register. The source code for these classes can be downloaded here.

The problematic piece of code is in Register.java.

figure 2
figure 3
Table 2: Problemistic code - Register and Customer classes

Creation of the customer's full name definitely doesn't belong here, but unfortunately, many developers throw together quick hacks like this to get the job done quickly.

Now to make things right, we must put everything where it belongs. We start with moving the customer's full name creation into the Customer class.

We extract the method:

figure 4
Figure 2: Extracting the method

And then move the new method to Customer class:

figure 5
Figure 3: Moving the new method to Customer class

After only a few clicks we have a much more maintainable code. However, we cannot be 100% sure if the program still behaves as it did before.

This is where unit testing comes into play. Before refactoring, we used JDeveloper's JUnit support which is freely available as a JDeveloper Extension. The test case checks if the customer full name is created correctly. (see Figure 4).

We run the test suite.

figure 6
Figure 4: Using Oracle JDeveloper's Junit support to test refactoring operations

figure 7
Figure 5: Checking to make sure the external behavior of the code hasn't been altered

Using tool supported refactoring operations and automated unit testing, this change could be implemented and verified in less than one minute. On a real-life project consisting of tens, hundreds, or thousands of classes, the time savings and improvements in quality assurance are dramatic.

In the above example, we used two refactoring techniques, "Extract Method" and "Move Method/Field." Following are some more examples of refactoring operations.

Refactoring operations

Refer to refactoring.com/catalog/index.html for a listing of over 90 different refactoring operations as well as refactoring.be/thumbnails.html for UML diagrams and refactorit.com/index.php?id=1370 for a listing of descriptions.

Refactoring Description/Benefit
Rename The renaming function allows you to rename any package, class, method or variable, and automatically find/correct all references to it. For any item being renamed you can preview all references in a convenient tree-structure, select usages/references to be refactored, and search for all name occurrences in JavaDoc comments, xml, and other text files to keep them up-to-date. The Rename refactoring can be invoked from any view, i.e. Project, Source, Commander and Structure.
Move ClassThe move class functionality allows you to manage the structure of a project by moving a class or interface into another package. RefactorIT Updates all references automatically, saving you time and effort.
Move Method/Field The move functionality allows you to move a method or field declared in a class to another class or interface in order to manage a program. Once again, RefactorIT Updates all references automatically, minimizing tedious bookkeeping and minimizing errors.
Pull Up/Push Down in HierarchyTo rearrange a project's hierarchy, you can "pull up" (move) fields and methods into a superclass and "push down" code into a subclass. This functionality allows you to streamline a project for optimal performance.
Extract Method This extraction function analyses a selected piece of code and transfer it into a separate method. This aids program modularization and allows code to be broken into manageable and understandable pieces.
Extract Super- class/InterfaceYou can select existing methods and fields and extract them into a new super class or interface. Once again, this aids the programmer in maintaining OO code that is both programmer friendly and efficient.
Introduce Explaining VariableThis functionality allows you to place the result of an expression, or parts of an expression, into a temporary variable with a name that explains its purpose. This function is useful for breaking long expressions into manageable pieces.
Add Delegate MethodsUsing this functionality, it is possible to create delegating methods for a given field that enhance modularisation for creating programmer friendly applications.
Override/ Implement MethodsThis refactoring allows you to add implementation methods to a super class. This is useful when enhancing a method by overriding the implementation of an inherited method or subclass to add functionality.
Inline VariableThis feature replaces all references of a variable with a declaration expression, then deletes the older variable text. This saves you time and effort when rearranging code and minimizes referencing errors.
Change Method SignatureThis new refactoring functionality combines several different modifications that form a method signature. This functionality allows you to add, remove, reorder, and rename parameters for a given method.
Encapsulate FieldThis functionality, allows you to select a class and replace direct field usages with corresponding read/write accessor methods. Thus, you can easily change the visibility of the fields and how they are accessed.
Minimize Access RightsThis function determines the minimal access modifiers for different class fields and methods. RefactorIT will automatically change selected modifiers for the user.
Use Super type where possibleUsing this functionality, a user can replace subclass with super class usages. RefactorIT identifies where this replacement is possible and replaces occurrences of a type with one of its super types.
Table 3: Different kinds of refactoring operations

Summary

Next Steps

Getting Started with Unit Testing
Learn how to test an application running over the internet using HttpUnit and JDeveloper 10g

In-Container Testing with JUnit
Learn how in-container testing with JUnit is superior to mock objects for integration testing, how to apply that technique using Oracle JDeveloper.

By using refactoring tools every software engineer and manager can manipulate obtuse code into elegant source code that is both efficient and manageable. A project manager or SQA (Software Quality Assurance) staff can use RefactorIT to monitor compliance with the programming rules by tracing how code size/complexity increase over time and trigger corrective actions (i.e. refactorings) before it is too late. In integrating with Oracle JDeveloper 10g's strong base of development tools, developers can both develop and refactor with the same application, thus designing code while leaving mundane tasks to automated tools.

Oracle JDeveloper 10g is the canvas, RefactorIT is a brush, now you can create a masterpiece.

Robert Pefferly is currently CEO for Harpster Informatics and Sunitia operating out of Tallinn, Estonia. His previous positions include: Head of the Software Engineering Department at Luleå Tekniska Universitet, Quantitative Analyst, Applied Stochastician - Mathematician, Project Manager, and Technical Writer for a number of government-industrial organizations in the US and EU.

Yuri Schimke has a Bachelor of Computer Science from the University of Technology, Sydney. He worked in telecommunications and security for Forge Research in Sydney, Australia before moving abroad. He now works in Tallinn, Estonia for Aqris Software developing RefactorIT.

Tanel Unt is an experienced Java developer. He has worked for the National Tax Board of Estonia, the Estonian Energy Corporation, and several other enterprises, designing and developing a wide variety of information systems. He is currently working as senior software developer for Aqris Software.



Please rate this document:

Excellent Good Average Below Average Poor


Send us your comments

E-mail this page
Printer View Printer View
Oracle Is The Information Company About Oracle | Oracle RSS Feeds | Careers | Contact Us | Site Maps | Legal Notices | Terms of Use | Privacy