Refactoring

Revision as of 13:25, 8 August 2007 by Bertrand Meyer (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Warning: To adhere to the standards for the Projects category, this project page should include a "Project members" section listing contributors and means to contact them. Please add this information, then remove the present notice.


General considerations

To avoid problems with changes from the user it may make sense for each changed text to save/discard it before doing the refactoring. After this the code should be checked and only if it is valid continued. After the refactoring, the code could be checked again and all views where something has changed should be updated to show the changes. This could be implemented, by compiling before doing the refactoring and compiling after the refactoring.

It could be a good idea to work "atomic" on a class/file basis, that means only if everything went ok, the changes will be written to the file. It would also be useful if all the changes to the different files were logged in an undo log, so that they could be rolled back (either if something bad happens or if the user wants to undo the refactoring).

At the moment there are already some tools for refactoring or things that have a lot in common with refactoring.

  • tools under Edit, Advanced
  • various things in the diagram view
  • some of the auto insertions
  • search and replace

Maybe the difference between things like under Edit, Advanced and "normal" refactoring is, that refactoring can affect the whole universe. But both things could still share a lot of common functionality.

Another thing that could be very helpful is the possibility to optionally show each change to the user and let him decide if this realy should be done (preview).

Possible design

Low level text editing

For refactoring it is useful to have some text editing functionality. A preview functionality could alse be implemented on this level. This could also log every change and make the undo log. At the moment, the class CLASS_TEXT_MODIFIER has most of this things already implemented.

  • insert_code
  • remove_code
  • replace_code
  • get_code
  • index_of
  • some kind of undo log, where a whole bunch of changes can be put together in "transactions"


Syntactic editing

On a higher level, there should be tools that allow to make more complex things. At the moment, some of this things are implemented in CLASS_TEXT_MODIFIER and EB_FEATURE_EDITOR.

common

  • create/change/remove comment

cluster

  • create cluster
  • change cluster
  • remove cluster

class

  • create class
  • change class
    • rename
    • add/remove inheritance
  • remove class

feature

  • create feature
  • change feature
  • remove feature

Refactoring

Preferences

  • global settings
  • refactoring specific settings
    • normal preferences
    • set before run (but also implemented as normal preferences but hidden)

Run

  1. settings
    1. Ask the user some settings for this run and store them as normal preferences
  2. checks if refactoring is possible
  3. which classes are affected
  4. refactoring
    1. get content
    2. make refactoring using Syntactic editing
deferred class
    ERF_REFACTORING
 
feature
    name: STRING
            -- Name of the refactoring.
 
    description: STRING
            -- A description for this refactoring.
 
 
    preferences: EB_PREFERENCES
            -- The preferences for this refactoring.
 
 
    ask_run_settings is
            -- Ask for the settings, that are run specific (optional).
        do
        end
 
 
    checks: LIST [ERF_CHECK] is
            -- The checks that need to be run before this refactoring can be run.
        do
            create list.make
        end
 
 
    affected_classes: LIST [CLASS_I] is
            -- Get the affected classes.
        do
            create liste.make
        end
 
 
    apply_to_project is
            -- Make project global changes (eg. *.ace, create/remove/rename cluster, ...) (optional).
        do
        end
 
 
    apply_to_class (a_class: CLASS_I) is
            -- Make the changes in `a_class'. (optional? would allow to make "refactorings" that are only checks).
        do
        end
deferred class
    ERF_CHECK
 
feature
    do_check is
            -- Execute a check.
        deferred
        end
 
    success: BOOLEAN
            -- Did the check succeed?
class
    ERF_REFACTORING_MANAGER
 
feature
    register (a_refactoring: ERF_REFACTORING) is
            -- Register a new refactoring. Does everything that is needed (eg. add preferences, create menu item, ...)
    do
       -- ...
    end

Refactoring possibilities

A list of common known refactoring possibilities can be found here:

Rename class

Prerequisite

  • full code of a class (or filename)
  • possibility to change a filename (=> at least get filename)
  • list of all classes
  • list of all clients of a class
  • position where a certain class is defined/used
  • position of comments
  • position of strings
  • (root_class settings in ace file)
  • (other settings in project/ace file that specify a class)

Options

  • also rename file
  • update comments
  • update strings

Checks

  • does another class have the same name

Things to do

  • [rename file]
  • rename class itself
  • rename class usage
    • var: CLASSNAME
    • precursor
    • agent
    • inherit
    • ...
  • update ace file
    • because it is root class
    • cecil
  • [update comments]
  • [update strings]

Rename feature

Prerequisite

  • full code of a class (or filename)
  • list of classes that inherit (directly or indirectly) from a certain class
  • list of classes that are parent (directly or indirectly) of a certain class
  • list of all features in one class
  • list of all assigners/callers of a feature
  • position of feature definition/usage
  • position of comments
  • position of strings
  • (access to root feature settings in ace file)

Options

  • update comments
  • update strings

Checks

  • does another feature in the class have the new name?
  • problems further down
    • feature gets renamed to this name
    • another feature gets renamed to this name
    • merging of this feature
    • ...

Things to do

  • rename feature
  • rename feature usage
    • calls
    • inheritance
      • merge
      • rename
      • ...
  • rename feature in project file if it is root feature
  • [update comments]
  • [update strings]

Move feature to parent

Prerequisite

  • full code of a class (or filename)
  • direct parents of a certain class
  • list of features of a class
  • position of a feature
  • position where a feature can be added to a class

Options

  • which parent? (only possible if at least one parent)

Checks

  • already feature with same name in parent
  • is feature inherited

Things to do

  • create feature in parent
  • remove feature in class

Add inheritance

Prerequisite

  • full code of a class (or filename)
  • list of classes that inherit (directly or indirectly) from a certain class
  • list of classes that are parent (directly or indirectly) of a certain class
  • position where an inherit clause can be added to a certain class

Options

  • handling of features defined in class and parent

Checks

  • no cyclic inheritance

Things to do

  • add inheritance clause
  • handle features defined in class and parent