New refactorings for Pharo 9
These months I was working fixing and introducing new refactorings.
Below is a list of the new refactorings introduced:
1. Extract setUp method
I’m a refactoring for creating a setUp method from a code fragment.
You can select an interval of some code in a test method and call this refactoring to create a setUp method implementing that code and replace the code with nothing.
The selected class needs to be a subclass of TestCase.
The preconditions are quite complex.
- The code needs to be parseable valid code.
- The class must not implement the setUp method.
- Class must inherit from TestCase class
Example
Before refactoring:
TestCase subclass: #RBDataTestinstanceVariableNames: ‘’classVariableNames: ‘’package: ‘Example’.RBDataTest >> someMethod#someMethod.RBDataTest >> testExampleself someMethod.self assert: true.
After refactoring:
RBDataTest >> setUpsuper setUp.self someMethod.RBDataTest >> testExampleself assert: true.
Video: https://youtu.be/feKsdci0dL4
2. Remove senders of method refactoring
I am a refactoring to remove all possible senders from a method (you cannot remove those calls where the result of the method call is used or when the method name symbol is referenced).
Example
Remove all senders of printString
Before refactoring:
RBRefactoryTestDataApp >> caller1| anObject |anObject := 5.self called: anObject + 1on1:[:each |each printString.^anObject]
After refactoring (notice that the call to printstring was removed):
RBRefactoryTestDataApp >> caller1 | anObject |anObject := 5.self called: anObject + 1 on1: [:each |^anObject]
Video: https://youtu.be/nMJiyy8US8U
3. Copy package as refactoring
I am a refactoring to copy a package.
My preconditions verify, that the copied package exists (in the current environment) and that the new copy package name is valid and not yet used as a global variable name
The refactoring transformation create a new package and copy defined classes of origin package (exclude all class’ extensions)
Example
The following package has these classes,
and these classes has these references between them:
MyClassA >> foo^ MyClassBMyClassB >> example4#MyClassA1
After copy #Example package we obtain this result:
and references were updated
MyClassACopy >> foo^ MyClassBCopyMyClassBCopy >> example4#MyClassA1Copy
It can also be noted that the hierarchy was correctly updated with the copied classes.
4. Rename package (rename manifest)
I’m a refactoring to rename a package.
My preconditions verify that the new name is different from the current package name and is a valid name.
I change all the references of the classes that are defined within the package, and if there is a manifest, it is updated with the new name of the package.
Video: https://youtu.be/94qlZmmIMwY
5. Merge instance var into another
I am a refactoring for merge an instance variable into another.
I replace an instance variable by another, in all methods referring to this variable and rename the old accessors, then if the instance variable renamed is directly defined in class it is removed.
My precondition verifies that the new variable is a defined instance variable in class.
Example
Before refactoring:
Class Foo -> inst vars: x, yFoo >> foobar^ xFoo >> foo^ x + y
After refactoring merging X into Y
Class Foo -> inst vars: yFoo >> foobar^ yFoo >> foo^ y + y
Video: https://youtu.be/sntrzsHCW9A
6. Move to class side method
I’m a refactoring to move a method to the class side.
My preconditions verify that the method exists and belongs to instance side.
I catch broken references (method senders and direct access to instVar) and fix them.
Example
Before refactoring (move #rewriteUsing: to class side):
RBTransformationRuleTestData >> rewriteUsing: searchReplacerrewriteRule := searchReplacer.self resetResult.
After refactoring:
RBTransformationRuleTestData >> rewriteUsing: searchReplacer^ self class rewriteUsing: searchReplace.RBTransformationRuleTestData class >> rewriteUsing: searchReplacer| aRBTransformationRuleTestData |aRBTransformationRuleTestData := self new.aRBTransformationRuleTestData rewriteRule: searchReplacer.aRBTransformationRuleTestData resetResult.
7. Create accessors with lazy initialization
I’m a refactoring for creating accessors with lazy initialization for variables.
I am used by a couple of other refactorings creating new variables and accessors.
My precondition is that the variable name is defined for this class.
Example
Before refactoring:
Object subclass: #RBLintRuleTestDatainstanceVariableNames: ‘name foo1’classVariableNames: ‘Foo1 Name1’poolDictionaries: ‘TextConstants’package: ‘Refactoring-Tests-Core-Data’
After refactoring we get:
RBLintRuleTestData >> foo1^ foo1 ifNil: [foo1 := 123]RBLintRuleTestData >> foo1: anObjectfoo1 := anObject
Video Example: https://youtu.be/SO0G6f1Y0fk
That’s all for this post, goodbye and happy coding :)