5.2 Design

 

As already introduced in chapter one, the goal of this research is to create a prototype for a tool, that lets developers refactor their software without „Copy-and-paste“. This fact has great influence on design decisions for DPT-tool. It is important to define a potential users of a refactoring-tool and then look at their expectations. The user can be separated into two groups:

 

1) A software developer, who would use refactorings in his daily work for:

-  „cleaning up“ the code, making code more flexible, easily extendible.

-  to increase the speed of implementation by use of „wizard“-futures of the tool ( e.g. „Implement“-transformation will create implementer-class for an interface)

2) An experts, who, for example, maintains a framework and could use refactoring for:

            - restructuring of the software for upgrade, adding new features to the program.

            - to create his own „monster“-refactorings, which can be reused in the future.

Usually programmers are very lazy and impatient users, they expect:

 

- Quick start-up procedure

If „start-up“ procedure takes too long (e.g. if programmer has to include all of the source-files into new project) developer will prefer to change code by hand rather then setup a project.

 

- Standard and intuitive user interface

The main goal for GUI is to keep the interaction with the user as short as possible. The user-interface should have the same layout for every transformation(e.g. Parameter-dialog), so that the developer won't lose time learning a new GUI. It is also important to show the developer no more information as needed to complete his task, otherwise he will get lost in all -options, -conditions, -possibilities of the tool. 

 

5.2.1 Environment

 

The DPT-tool is programmed in Java(JDK-2.0) on a WinNT4.0 platform with JBuilder3.0 development environment. DPT uses Swing-classes for the GUI and ANTLR2.7 compiler-compiler for the creation of the syntax-parser and the symbol table parser. DPT - runs on Win95/98/NT or Linux/Unix.

The implementation of DPT-software was completed in 3 months.

The initial design of  DPT allows transformations of  C/C++ and Java programs. Additionally it can support high level transformations like C to C++ or C++ to Java. The current version (DPT 1.1) supports only Java to Java transformations. To support the transformations for different programming languages the parser and the generators should be switched to the language of the source code.

 

5.2.1.1 Generators

 

The DPT-tool does not generate any changes to the program. Transformation is the job of additional modules(generator-beans) which will be dynamically loaded(and executed) on user-request. If the user chooses a transformation, DPT will load a generator for this transformation, pass the symbol-table and file-table to the generator, and wait while the generator does its job. Following each implementation of a transformation is a java-bean that:

- displays for the user the symbol-table(navigation for the parameters-setting)

- gets transformation-parameters from user

- checks the parameters of the transformation

- creates code-changes

- notifies the object-manager about code changes.

Although generators could be used for different languages (e.g. copy/move an entity) they depend on (written for) concrete programming-language.

 

Example:          Multiple inheritance is not allowed in Java.

C++ does not have class-interfaces.

Contrary to parsers, generators are not generated by compiler-compiler.

For more information about the implementation of generators(see section 5.2.2 Design)

 

5.2.1.2 Parsers

 

DPT parses the source code by use of an abstract parser which could be a Java or C/C++

parser. The current version uses a Java-parser. This parser generates a symbol-table that should offer the Symbol-table interface.The implementation of that interface is used by DPT and passed on the chosen generator to complete the transformation.

The source-code parser is a very important part for the refactoring-tool. It should resolve all references and create a symbol table of the project. Experience shows that in some cases a parser is not thorough enough to resolve all of the references correctly and

a language-interpreter is needed. The development of a language-interpreter is not a part of this research, so we decided to create a parser, which does its best, but without guarantee to resolve all symbols of the program. For the creation of the source code parser we used a compiler-compiler. There were  three compiler-compilers freely available for the language Java: JavaCC, ANTLR, SabelCC.

 

We decided to use ANTLR because:

- it is free

- a debugger is freely available for ANTLR

- it has a good error report.

- the syntax of the grammar for ANTLR is easy to learn

- parsers created by ANTLR are understandable

- ANTLR can generate parsers for Java/C++

-         ANTLR has many well described examples

 

Like generators, parsers are implemented as java-beans and can be used without DPT for other programs or as „stand alone“ java source parsers.  

 

There are three parsers available in the DPT-software package:

- Syntax parser(Java grammar recognizer)

- Symbol-table parser(Symbol table generator)

- DPT-parser(Parser for reading configuration and initialization-files)

 

Different than  Syntax/ Symbol-table parsers, the DPT-parser is not generated by compiler-compiler. For more information see section 5.2.3.

 

5.2.2 Design of the transformation

 

The design of the transformation and the generator beans is the most interesting part of the DPT-tool. The design is based on the following considerations:

 

- The DPT-tool does not generate any changes; All of the code changes should be created by the current(chosen) transformation(=generator bean).

 

- Consequently, the setting of the transformation-parameters and precondition-check are also  parts of the current generator-bean. This implies that the parameter-assistant must be a part of the bean, too.

 

- Every transformation should have the same(similar) GUI-Dialog for their parameter-assistant, although the parameters and  preconditions of the transformations are different. This implies that GUI-dialog should be parametrized and this requires the implementation of the paramatrized GUI-component.

 

- DPT allows the creation of the composed transformations. A bunch of generator-beans which act like one transformation. 

 

5.2.2.1 Design of the  transformation-bean(generator):

 

1)   Each implementation of a transformation is derived from abstract class 

    GenAbstract, which implements generator-bean interface GenBean.

    The transformation-bean has to implement exactly three methods:

- Constructor, with the transformation-name and GUI-rule for the assistant.

- CheckParameter-Method, which checks the preconditions of the transformation

-         Create-Method, which generates the changes to the source code.

-          

2)  Abstract class GenAbstract,  implements generator-bean interface GenBean

   and has all GUI-components, action-handlers and execution logic.

 

3)  Interface GenBean is offered to the „outside“-world. (e.g. for DPT-tool).

 

(Figure 5.3 UML: Generator-beans)

 

Example: Transformation „New class“(from generator point of view):

DPT loads the java-class NewClass which implements the interface GenBean and calls the method „Execute“, and passes the symbol-table and file-table to this class.The „Execute“ method implemented in the class GenAbstract gets the GUI-rule of the NewClass and executes dialog „DlgBrowse“. Each time the user sets a parameter, the dialog notifies object GenAbstract, which  checks the parameter with the method implemented  in NewClass. If the check succeed,  GenAbstract stores this parameter, gets the next GUI-rule from NewClass and re-init dialog „DlgBrowse“ with a new rule. If  all of the parameters are set, „DlgBrowse“ displays „OK“-button. If the user clicks on the „OK“-button, dialog „DlgBrowse“ notifies the GenAbstract, which calls the „Create“-function implemented in NewClass .The NewClass creates changes, notifies the DPT-tool and exits. DPT-tool re-parses the project files. Then the task is completed.

 

5.2.2.2 Design of the  transformation-catalog:

 

1)   An instance of the class Catalog is a part of the DPT-object manager. Class Catalog is a class-loader, which loads and executes transformations(generator-beans). The class Catalog is also a factory of the object Transformation. This catalog is initialized with a init-file that contains the names of all generator-beans, which are belong to this particular catalog.

 

2)   DPT deals with composed transformations. For this purpose DPT has an object Transformation, which is an implementation of the interface GenBean like other generator-beans described above. The object Transformation is designed as a vector-container for  generator-beans. By calling an interface-method of the Transformation will call sequential this method in all generator-beans that are available in the vector. It takes the output-parameters from the current bean and passes these parameters on the next bean.

 

As result, the basic transformation is a vector with only one generator and the composed transformation is a vector of generators.

 

Example: Transformation „New class“(from DPT point of view):

DPT-Frame notifies DPT-ObjectManager, that the user wants to execute this transformation. ObjectManager calls up the method „Execute“ for the instance variable Catalog and passes on the transformation-name(“NewClass“). The object Catalog checks if the generator-bean is available(e.g. if  „NewClass.class“ can be loaded). If not it looks up a composition-file(“NewClass.trf“).The „.trf“- file contains the description (names) of all generator-beans that are available in this transformation. If generator („NewClass.class“) or „.trf“-file is available the catalog creates the object Transformation and loads all of the generator-beans to this object.

(Figure 5.4 UML: Transformation catalog)

 

When Transformation-object is created, the catalog simply calls up the execute-method ( GenBean-interface) of the object  Transformation and passes symbol-table and file-table as parameters. The object Transformation takes the first generator-bean from the vector and forwards the execute-method call to it. 

 

5.2.3 Classes and Objects

 

The implementation of the DPT-tool can be described as the development of several nearly independent modules:

- Generators-beans that implement the transformations.

- Development of the symbol-table for a java-program.

- Parsers for language Java(1.1).

- Implementation of a file-table for a project.

- GUI-components for the tool

- Objects for management of the tool-components.

 

Some of these modules(implemented as java-beans) I have developed as „stand-alone“ programs (like parsers, file-table) and attached then to the project by using the interface-features of the language java. The defined interfaces between the modules allow the extension and the switching of the modules for the future releases of DPT-tool.

In this section I would like to introduce some implementation features of the DPT-tool.

 

5.2.3.1 DPT-Classes

 

Package „dpt“ contains the GUI-components  of the DPT-tool.

(Figure 5.5 UML: Package DPT)

 

- Class AppDPT contains the main-function of DPT. It creates the FrameDPT

- Class FrameDPT is the main frame of the DPT(see section 5.4.3)

- Dialog DlgGoTo is the implementation of „GoToLine“- action.

- Dialog DlgProject browses the attributes of the DPT-Project (see section 5.4.3)

- Dialog DlgAbout browses information about DPT-tool

- Dialog DlgCompose shows the composition of the transformation (see 5.4.3.1)

Note:  Dialogs DlgHelp and DlgBrowse are parts of the package „generators“

 

Package „dpt.object“ contains the managment-objects  of the DPT-Project.

- Interface OMIF offers the access-methods of the object-management.

It contains such methods as Save- ,Open-, Close-,  a DPT-project.  OMIF is the

interface to the GUI-Components of the tool. (Currently DPT uses concrete class OMAll instead OMIF) Any object-manager which offers this interface can be used by DPT-tool. Or any GUI can use OMAll object-manager by accessing its interface.

- Abstract Class OMAbstract implements interfaces: OInterface, OMIF

The interface-OInterface extends interfaces FileTab and SymbTab. The purpose of OMAbstract is the delegation of the Symbol-table and File-table to the Object-manager of the DPT-tool. OInterface is used by generator-beans for the execution of the transformation. The OMIF (described above) is used by GUI-components of the DPT-Tool for the initialization, action handling and browsing of the project data.

- Class OMAll extends the class OMAbstract. It contains the  implementation of the

            interface OMIF, during class OMAbstract implements OInterface.

- Class  Catalog manages all transactions with the generator-beans. It generates the

information about available transformations( catalog-tree), dynamically loads the

required beans to the Transformation. A  Catalog acts also as a factory for the class Transformation, which is a collection of the generator- beans. Catalog maintains the composition-files for catalogs and transformations.

 

(Figure 5.6 UML: DPT-objects)

 

5.2.3.2 File table implementation

 

Package „dpt.filetab“ contains the implementation of the file-table for DPT-Project.

- Interface FileTab offers the access-methods of the file-table.

Any file-table which offers this interface can be used by the DPT-tool. DPT can be attached to the development environment that already has a file-table.

- Abstract class FATAbstract implements FileTab-interface and contains some of

the default methods like copy-files, add/delete multiple files.

-  Class FAT is an implementation of the file-table. It extends the class FATAbstract

and implements  FileTab methods which are not already implemented in class FATAbstract. The files are stored as a vector of  FileDPT-objects. Class FAT maintains the path to the working directory and the initialization-file. It parses each file by syntax-parser before adding  this file to the file-table.

- Class FileDPT. Because the DPT-Project can be placed in any directory of the file-

system, a file in the file-table know only its name and its original location. The  location of the working-copy will be built dynamically by the file-table (filename + working directory)

- Class ExtendFileFilter implements file -info and -extensions for Open-dialogs

(Figure 5.7 UML: File table classes)

 

5.2.3.3 Symbol table implementation

 

Package „dpt.symbtab“ contains the implementation of the Symbol-Table.

- Interface SymbTab offers access methods for the symbol table.

            Benefits: Any symbol-table which offers this interface can be used by DPT-tool.

- Class SymbolTable implements  interface SymbTab. This class will be passed on

the „symtab“-parser in order to fill the symbol table with data.

 

The following classes are used  internally by  the class SymbolTable:

- Interface Reportable is used as a handle to all symbols that can be reported.

  Implementation of this interface reports location, name, sub-symbols of the symbol.

- Class Definition. Every java construct is stored in symbol table as Definition

- Class BlockDef is a wrapper for unnamed „{}“-block statement.

- Class PrimitiveDef is a definition of primitive type such as „int“, „long“ 

- Class LabelDef is a definition of a label(e.g. „break“, „switch“)

 

(Figure 5.8 UML: Symbol table classes)

 

- Interface TypedDef represents definitions that have a "type" associated with them. 

- Class VariableDef defines a variable.

- Class ArrayDef is a definition of an array

- Class MethodDef is an implementation of a method-definition

- Class MiltiDef is used for such  multidefinitions as „overloaded methods“

- Abstract class ScopedDef extends Definition.

            It  represents a symbol that provides a scope that contains other symbols.

- Abstract class HasImports extends ScopedDef.

            It represents a symbol that can import packages.

- Class PackageDef is a definition of  a java-package

- Class ClassDef defines a Class or Interface

- Class DummyClass holds temporarily the name of a class until it can be resolved

Supporting classes:

- Class Occurance implements an occurrence of an indentifier in a file.(Location) 

- Class StringTable. Symbol-table stores each unique string in the StringTable.

- Class JavaVector extends Vector(provides lookup and type resolution methods)

- Class JavaStack extends Stack(provides lookup and type resolution methods)

- Class JavaHashtable extends the class Hashtable(provides lookup and type resolution methods)

 

5.2.3.4 Parser-beans

 

Package „parsers.symbtab“ contains the  symbol table parser

- Interface JavaTokenTypes contains the definition of java-tokens.

- Class JavaLexer  is a character-scanner(Lexer) for the language Java (1.1)

- Class JavaToken is used to relay information from the scanner to the parser.

- Class SymbTabParser is the implementation of the parser.

-         Class Main is the test program for the symbol-table parser.

-          

Package „parsers.syntax“ contains the  syntax-parser for Java(1.1).

- Interface JavaTokenTypes contains the definition of java-tokens.

-Class JavaLexer  is a character-scanner(Lexer) for the language Java (1.1)

-Class JavaParser is the implementation of the parser.

-Class Main is the test program for the syntax parser.

 

Package „parsers.tools“ contains the helper-parser for DPT-tool.

-Class DPT-Parser  is a parser for configuration-files with many additional features

-Class MsgBox is the implementation of the Pop-Up Box.

-Class ItemD is the implementation of the dictionary item(Name=Value)

-Class Converter has a couple of useful conversion-methods(static)

 

5.2.3.5 Generators-beans

 

As already described in section 5.2.2.1,  the transformation is implemented by generator -bean. Every implemented bean extends class GenAbstract, that implements the interface GenBean. Most of the implemented beans use the generator-class Gen to create the code-changes. The package „generators.beans“ contains all of the implemented transformation-generators described in chapter 4: „Design of refactoring-catalog.“ (see section 5.2.2.1)

The package „generators“ (see below) contains abstract generators and the implementation of the base functionality for a transformation-bean. 

 

„DPT-Assistant“-GUI components:

- Interface RuleIF describes the GUI-initialization parameters for the components of

   the dialog-DlgBrowse(= „DPT-Assistant“)

- Abstract class RuleAbstract default implementation of the  interface RuleIF

- Dialog DlgBrowse is the implementaion of the Transformation-Assistant

- Control CTabBrowse implements one tab-page of the dialog DlgBrowse

- Class RuleTAB implements the initialization rule for the CTabBrowse component

- Control CPanBrowse implements the symbol-panel of the CTabBrowse

- Class RuleGUI implements initialization rule for CPanBrowse

- Dialog DlgHelp displays the information about the transformation

- PopUp MsgBox displays the transformation messages

 

Transformation-bean components:

- Interface OInterface extends interfaces symbtab and filetab. Describes the interface which must be passed to the generator-bean in order to execute transformation.

- Interface GenBean the generator-bean interface to DPT-tool and to the dialog    

DlgBrowse. The class GenBean is implemented by every transformation.

- Abstract class GenAbstract implements the interface GenBean and contains the           base functionality of the generator-bean.(see section 5.2.2.1)  

- Class OParameter implements a parameter for a transformation.

- Class Transformation implements GenBean and acts like an usual generator-

bean. This class contains a vector of  transformations.(see section 5.2.2.1)

- Bean Browser is the example implementation of default class-browser bean

- Class Gen is the real generator. Generates changes to the source-code.

 

5.2.4 Source code management

 

DPT-philosophy: The source code management is accomplished by application and not by generator-beans, because only the application has knowledge and information about original or working- source location, state, volume and dependencies. DPT operates only on copy of original source, because this is a "clean way" to differentiate between source to be built/run and source to be transformed. (Note the difference: the source of the transformation-program must be always correct!)

 

1)  Location of the source code

 

DPT has no requirements for the location of the program code. DPT-Tool can be installed in any directory and is independent from the location of the source code.

Problem:   How DPT will find the source code of program which has to be transformed?

Solution: Let the user specify his source files. Via Add/remove-file dialog, DPT copies all necessary files to the „/src“ directory of the project. Real(original) file-location and the date are stored in fat.ini -file of the project. DPT works on copy of the source code (working code) FAT-Object(file-table) takes care of all operations with source files.

It is stored in fat.ini.File allocation table for DPT-project contains:

a) Absolute path to root (change via add / remove files) like: „C:/Projects/root/proj1“

b) Absolute path to Myproj2( static) like: “C:/Projects/root/DPT“

c) List of relative path to root + filename + date(/beans/src/sql.java 30.01.1998)

 

2)  Working code always has to be correct(no syntax errors)

 

Problem: The working code and symbol table always have to be correct.

Solution: Only correct source will be added to the project.

 

- Action: Add/Remove file dialog:

Step 1: New source-file will be checked for the correct syntax by the syntax-parser

Step 2: If the new file is ok, the symbol-table will be updated by symbol-table parser

- Action: Open project / start transformation:

DPT-Tool verifies that the project-files are up to date, otherwise they will be updated

Step 1: All updated source-files will be checked for the correct syntax by syntax-parser

Step 2: If all updated files are ok, the symbol-table will updated by symbol-table parser

- Action: After Transformation

Step 1: Modified source-files will be checked for correct syntax with syntax-parser

Step 2: If they are fine, the symbol-table will updated by symbol-table parser

 

(Figure 5.9 Management of the project files)

 

3)Working code always has to be up to date(with source code)

 

Problem: After the user changes the source code, DPT has to update its working code

Solution: fat.ini will store the date of the last change in the source code

Update: After opening project, before transformation, upon user request(synchronize). During the update procedure DPT checks files for correct syntax.(see section 5.2.1.2) All updated source-files will be checked for the correct syntax by the syntax-parser. If an error occurs, this problem will be shown to the user and the old version of file will be used(and marked in fat.ini) After each transformation the source code has to be updated.

 

Problem: DPT gives the user a chance to built source code after each transformation

Solution: DPT has a list of affected files which need to be copied to their original               

locations. The user can always built his new code and test it’s functionality.

Update: After transformation, after "undo" / "redo" – Action

 

4)  User have to be able to "undo" and "redo" the transformation

 

Problem: The user may be unhappy with the behavior of his program after the

transformation. DPT needs to give the user a chance to undo/ redo the  transformation.

Solution: Temp-copy of files which was selected to be modified.

    Note: This affects the modification of existing source files!

Example: File sql.java was chosen to be modified -> copy this file to sql.j1

(if exists to sql.j2) Transformation start->end, DPT will write new sql.java to original source location. User built his application, tried it and decided to "undo" the transformation -> In this case DPT will copy sql.java to sql.j1%(e.g. sql.j2%) for "redo" and then it will copy sql.j1(e.g. sql.j2) to sql.java back to it’s original source location.

sql.java(work)---> sql.j1%

sql.j1 -->sql.java(work)---> sql.java(org)