[Cuis-dev] ExtractMethod improvements

Joel Camera joel.camera at 10pines.com
Mon Jul 27 05:32:22 PDT 2026


Hi everyone,

I wanted to share some improvements I made to the Extract Method
refactoring in Cuis. There are three main additions:

*1. Support for assignments to temporary variables*

Previously, if you tried to extract a fragment that assigned a temp var,
the refactoring would fail with an error. Now it handles several cases
automatically:

- If the variable isn't used after the fragment, it just moves inside the
new method.
- If it's used after, the new method returns it and the call site assigns
it back.
- If multiple variables are assigned and all used afterwards, it uses an
"assignment block" pattern:

*"Before:"*
process
    | subtotal tax |
    subtotal := self price.
    tax := subtotal * self taxRate.
    ^ subtotal + tax

*"After extracting 'subtotal := self price. tax := subtotal * self
taxRate.':"*
process
    | subtotal tax |
    self computeAssigningWith: [ :newSubtotal :newTax |
        subtotal := newSubtotal. tax := newTax. ].
    ^ subtotal + tax

computeAssigningWith: anAssignmentBlock
    | subtotal tax |
    subtotal := self price.
    tax := subtotal * self taxRate.
    ^ anAssignmentBlock value: subtotal value: tax

*2. Support for non-local returns*

Extracting fragments with a `^` also used to fail. Now:

- A plain `^` in the fragment becomes the return of the new method.
- A `^` inside a block uses a "returning block" pattern so the non-local
return still works correctly:

*"Before:"*
findFirst
    self do: [:each | each isValid ifTrue: [^each]].
    ^ nil

*"After extracting 'self do: [...]':"*
findFirst
    self findValidElementReturningWith: [:res | ^ res].
    ^ nil

findValidElementReturningWith: aReturningBlock
    self do: [:each | each isValid ifTrue: [^ aReturningBlock value: each]].


*3. Parameterizable code detection*

Extract Method now detects occurrences that are structurally similar to the
selected fragment but differ in some arguments — just like it already does
for equivalent code, it searches across the whole class hierarchy. When
found, a new window appears letting you decide whether to parametrize them:

*"Before:"*
process
    self foo: 10 bar: 'hello'.
    self foo: 20 bar: 'hello'.
    self foo: 10 bar: 'world'.

*"After selecting 'self foo: 10 bar: ''hello''' and accepting
parametrization:"*
process
    self m: 10 with: 'hello'.
    self m: 20 with: 'hello'.
    self m: 10 with: 'world'.

m: aFoo with: aBar
    self foo: aFoo bar: aBar

All three improvements are already integrated into Cuis. Thanks Juan for
merging them!

Happy to answer any questions!

<https://10pines.com/>Joel CámeraAgile Software Development

Alem 896, Floor 6, Buenos Aires, Argentina

+54 9 011 6091 3125
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.cuis.st/mailman/archives/cuis-dev/attachments/20260727/71b91ea4/attachment.htm>


More information about the Cuis-dev mailing list