Refactoring
Contents
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
- settings
- Ask the user some settings for this run and store them as normal preferences
- checks if refactoring is possible
- which classes are affected
- refactoring
- get content
- 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:
- http://en.wikipedia.org/wiki/Refactoring
- http://www.refactoring.com/catalog/index.html
- http://industriallogic.com/xp/refactoring/catalog.html
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