Type hierarchy operations

First of all, I'd like to thank Resharper team for new refactorings that
I was missing from the time I used C# Refactory. Besides the fact that they
are still in EAP and are a lot buggy, it's nice they came to existance. At
this point I'd like to share some of my thoughts regarding these refactorings.
I'm not very much to refactoring ideology, but I code a lot and have some
practical observations that may be aligned or misaligned with the theory.

From my point of view, the concept behind "Extract interface/superclass"
refactorings is hierarchy manipulation. Major hierarchy changes should be
well planned by architect and probably reflected in appropriate diagram,
but there are much more small refactorings of this kind which serve momentary
needs and can be done with the help of tool such as Resharper. So, we need
to identify major requirements for manipulating type structure, split them
into elementary operations (if possible) and plan refactoring operations
with these requirements in mind. There are three most obvious operations
from the OOP/OOD point of view:

1. "Create abstraction". When you create interface or superclass you essentialy
create new abstraction (more abstract, so to say). It is pretty rare condition
to have only one class you need to abstract. Almost always you have several
classes that became too common and you want them share implementation or
semantics or both. That is first point:

-- Extract superclass/interface should manipulate multiply types --

Developer should be able to select several classes he wants to "merge" and
Resharper should provide pretty advanced interface to merge them in hierarchy
through creation of base class/interface. This can involve renaming methods,
changing signatures and otherwise preparing the merge. It's pretty complex
feature and you may consider it for IDE.

2. "Remove abstraction". Sometime types, that were initially considered similar
and has common base type become too different and base class become almost
empty and/or just useless. In this case developer wants to eliminate base
class altogether (or remove it from part of hierarchy). Existing members
should be copied into derived class and then inheritance can be removed.
This involves some smartness too, because there could be change in "virtuality"
of members, change from protected to private/internal, etc. This leads to
second point:

-- Extract superclass/interface should be reversible --

Developer should be able to point to class and issue "remove base class"
command and be able to propagate base's members to class itself. Removing
interfaces is not always just removing them from implementation list - there
could be explicit implementations that should be converted to private members.
If they are unused, they will be marked as such for the following removal.
Obviously, there can be casts to interface/base somewhere in the code. If
it is detectable, Resharper should warn.

3. "Move members". Obviously, developer may want to adjust base/derived class
members later, after "Extract superclass/interface" refactoring is completed.
There should be option to promote method to base class or interface with
appropriate change in visibility and body. As well, there should be command
to demote member from base to derived class(-es).

4. There are other things that I'd like to have in my toolbox, but they are
not so important as three above. For example, I wish to have "Copy type interface"
command, that will not copy implementation details, but instead copy public/protected/internal
interface of the type with method/property bodies filled with NotImplementedException
throws. This could work from class browser as well. Another thing is command
"Create derived type", so I can point to some class I designated as base
and then have all required abstract overrides, constructor calls (for selected
prototypes) and so on. These are just bells and whistles but they can improve
everyday coding and this is the goal of tool such as Resharper, isn't it?

Please, share your thoughts, I'd like to discuss it with Resharper team and
users.

Sincerely,
Ilya Ryzhenkov


4 comments
Comment actions Permalink

1. We recognize that one sometimes needs to extract common base class from
multiple types but have not implemented that (neither in ReSharper nor in
IDEA) because of complexity of the user interface required for managing such
refactoring. Do you imagine how could the user interface for this refactoring
look like?

2. I think refactoring you mentioned is named "Collapse Hierarchy" according
to Martin Fowler's classification. It's possible to implement it but we did
not include it because it did not seem to be that frequently needed.

3. Push Down Member and Pull Up Member refactorings will probably be scheduled
for the version for VS 2005.

4. "Copy type interface" - when do you need such operation?
"Create derived type" - we'll think about automation of this operation.

Valentin Kipiatkov
Chief Scientist, Vice President of Product Development
JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"

First of all, I'd like to thank Resharper team for new refactorings
that I was missing from the time I used C# Refactory. Besides the fact
that they are still in EAP and are a lot buggy, it's nice they came to
existance. At this point I'd like to share some of my thoughts
regarding these refactorings. I'm not very much to refactoring
ideology, but I code a lot and have some practical observations that
may be aligned or misaligned with the theory.

From my point of view, the concept behind "Extract
interface/superclass" refactorings is hierarchy manipulation. Major
hierarchy changes should be well planned by architect and probably
reflected in appropriate diagram, but there are much more small
refactorings of this kind which serve momentary needs and can be done
with the help of tool such as Resharper. So, we need to identify major
requirements for manipulating type structure, split them into
elementary operations (if possible) and plan refactoring operations
with these requirements in mind. There are three most obvious
operations from the OOP/OOD point of view:

1. "Create abstraction". When you create interface or superclass you
essentialy create new abstraction (more abstract, so to say). It is
pretty rare condition to have only one class you need to abstract.
Almost always you have several classes that became too common and you
want them share implementation or semantics or both. That is first
point:

2. "Remove abstraction". Sometime types, that were initially
considered similar and has common base type become too different and
base class become almost empty and/or just useless. In this case
developer wants to eliminate base class altogether (or remove it from
part of hierarchy). Existing members should be copied into derived
class and then inheritance can be removed. This involves some
smartness too, because there could be change in "virtuality" of
members, change from protected to private/internal, etc. This leads to
second point:

3. "Move members". Obviously, developer may want to adjust
base/derived class members later, after "Extract superclass/interface"
refactoring is completed. There should be option to promote method to
base class or interface with appropriate change in visibility and
body. As well, there should be command to demote member from base to
derived class(-es).

4. There are other things that I'd like to have in my toolbox, but
they are not so important as three above. For example, I wish to have
"Copy type interface" command, that will not copy implementation
details, but instead copy public/protected/internal interface of the
type with method/property bodies filled with NotImplementedException
throws. This could work from class browser as well. Another thing is
command "Create derived type", so I can point to some class I
designated as base and then have all required abstract overrides,
constructor calls (for selected prototypes) and so on. These are just
bells and whistles but they can improve everyday coding and this is
the goal of tool such as Resharper, isn't it?

Please, share your thoughts, I'd like to discuss it with Resharper
team and users.

Sincerely,
Ilya Ryzhenkov



0
Comment actions Permalink

Hello Valentin,

VK> 1. We recognize that one sometimes needs to extract common base
VK> class from multiple types but have not implemented that (neither in
VK> ReSharper nor in IDEA) because of complexity of the user interface
VK> required for managing such refactoring. Do you imagine how could the
VK> user interface for this refactoring look like?

Mapping.

Imagine list of selected types (with add/remove ability) on the left side
of the form with members as subnodes. On the right side, you "compose" new
type (base class or interface). You go through the classes on the left and
establish mapping between this class members and members on the right (new
type members). Operations would be:
1. Copy to the right. Just creates similar method in the new type. For interface
it would just create signature and mark method in the existing type to be
made public or explicit interface implementation. For base class it could
include options to "make base implementation" (so implementation is moved
to base), override, make abstract, etc.
2. Link to right. Depending of what method is selected on the right, this
could map (a) directly (if signature matches) (b) with change signature on
the left (c) with create proxy on the left (d) create not-implemented-exception
override etc

Those are up from my head, there may be other or these could be tweaked.
The goal of this procedure is to create set of changes needed to be made
to existing classes as well as form the new type. Some of changes could require
moving fields, or adjusting inheritance as well. This should be expressed
with mapping of fields and mapping of bases.

When user clicks OK button, all those recorded operations would be performed
and new type created.

VK> 2. I think refactoring you mentioned is named "Collapse Hierarchy"
VK> according to Martin Fowler's classification. It's possible to
VK> implement it but we did not include it because it did not seem to be
VK> that frequently needed.

This is not frequently needed until you have powerful tool to "Expand Hierarchy".
Once you have it in place, it will be naturall "Think Back" after I created
base classes, tweaked it for some time (days, weeks, months) and then simple
undo will not work if I realise that initial intention was wrong.

VK> 3. Push Down Member and Pull Up Member refactorings will probably be
VK> scheduled for the version for VS 2005.

Abscence of these is stopship for use of extract superclass/interface. Well,
it technicaly doesn't, because it helps to do a one time refactoring of
this kind. But since I don't have a tool to push/pull and revert extraction
- all the following changes will be manual.

VK> 4. "Copy type interface" - when do you need such operation?

When creating similar entities which differs in semantics and cannot be expressed
in derived/implemented relationships. Consider CancelEventArgs. There is
single property Cancel in addition to EventArgs interface. And compare it
to KeyPressEventArgs, where I have Handled property. This is very similar,
but still different. In case of one property it's obviously simpler to create
one, but when there are many of them - that's become tedious. Another example
- primitive value types. To maintain usability, I would like to create my
primitive value types by copying int32 interface, so I don't forget various
Parse, ToString overloads, etc. So I would issue "Copy type interface" on
System.Int32 and then tweak as needed.

Sincerely,
Ilya Ryzhenkov


0
Comment actions Permalink

Mapping.


How should the links between members be shown?

Valentin Kipiatkov
Chief Scientist, Vice President of Product Development
JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"

Hello Valentin,

VK>> 1. We recognize that one sometimes needs to extract common base
VK>> class from multiple types but have not implemented that (neither in
VK>> ReSharper nor in IDEA) because of complexity of the user interface
VK>> required for managing such refactoring. Do you imagine how could
VK>> the user interface for this refactoring look like?
VK>>

Mapping.

Imagine list of selected types (with add/remove ability) on the left
side
of the form with members as subnodes. On the right side, you "compose"
new
type (base class or interface). You go through the classes on the left
and
establish mapping between this class members and members on the right
(new
type members). Operations would be:
1. Copy to the right. Just creates similar method in the new type. For
interface
it would just create signature and mark method in the existing type to
be
made public or explicit interface implementation. For base class it
could
include options to "make base implementation" (so implementation is
moved
to base), override, make abstract, etc.
2. Link to right. Depending of what method is selected on the right,
this
could map (a) directly (if signature matches) (b) with change
signature on
the left (c) with create proxy on the left (d) create
not-implemented-exception
override etc
Those are up from my head, there may be other or these could be
tweaked. The goal of this procedure is to create set of changes needed
to be made to existing classes as well as form the new type. Some of
changes could require moving fields, or adjusting inheritance as well.
This should be expressed with mapping of fields and mapping of bases.

When user clicks OK button, all those recorded operations would be
performed and new type created.

VK>> 2. I think refactoring you mentioned is named "Collapse Hierarchy"
VK>> according to Martin Fowler's classification. It's possible to
VK>> implement it but we did not include it because it did not seem to
VK>> be that frequently needed.
VK>>

This is not frequently needed until you have powerful tool to "Expand
Hierarchy". Once you have it in place, it will be naturall "Think
Back" after I created base classes, tweaked it for some time (days,
weeks, months) and then simple undo will not work if I realise that
initial intention was wrong.

VK>> 3. Push Down Member and Pull Up Member refactorings will probably
VK>> be scheduled for the version for VS 2005.
VK>>

Abscence of these is stopship for use of extract superclass/interface.
Well, it technicaly doesn't, because it helps to do a one time
refactoring of this kind. But since I don't have a tool to push/pull
and revert extraction - all the following changes will be manual.

VK>> 4. "Copy type interface" - when do you need such operation?
VK>>

When creating similar entities which differs in semantics and cannot
be expressed in derived/implemented relationships. Consider
CancelEventArgs. There is single property Cancel in addition to
EventArgs interface. And compare it to KeyPressEventArgs, where I have
Handled property. This is very similar, but still different. In case
of one property it's obviously simpler to create one, but when there
are many of them - that's become tedious. Another example - primitive
value types. To maintain usability, I would like to create my
primitive value types by copying int32 interface, so I don't forget
various Parse, ToString overloads, etc. So I would issue "Copy type
interface" on System.Int32 and then tweak as needed.

Sincerely,
Ilya Ryzhenkov



0
Comment actions Permalink

Hello Valentin,

>> Mapping.
VK> How should the links between members be shown?
With pleasure! ;)

Actually I don't know. I'll think about it in the nearest future. However,
I don't yet feel if you like the idea or sceptic about it.. I'm not going
to do all this by myself - I simply doesn't have time. If you have any ideas
or feedback, please share.

Sincerely,
Ilya Ryzhenkov

>> Hello Valentin,
>>
VK>>> 1. We recognize that one sometimes needs to extract common base
VK>>> class from multiple types but have not implemented that (neither
VK>>> in ReSharper nor in IDEA) because of complexity of the user
VK>>> interface required for managing such refactoring. Do you imagine
VK>>> how could the user interface for this refactoring look like?
VK>>>
>> Mapping.
>>
>> Imagine list of selected types (with add/remove ability) on the left
>> side
>> of the form with members as subnodes. On the right side, you
>> "compose"
>> new
>> type (base class or interface). You go through the classes on the
>> left
>> and
>> establish mapping between this class members and members on the right
>> (new
>> type members). Operations would be:
>> 1. Copy to the right. Just creates similar method in the new type.
>> For
>> interface
>> it would just create signature and mark method in the existing type
>> to
>> be
>> made public or explicit interface implementation. For base class it
>> could
>> include options to "make base implementation" (so implementation is
>> moved
>> to base), override, make abstract, etc.
>> 2. Link to right. Depending of what method is selected on the right,
>> this
>> could map (a) directly (if signature matches) (b) with change
>> signature on
>> the left (c) with create proxy on the left (d) create
>> not-implemented-exception
>> override etc
>> Those are up from my head, there may be other or these could be
>> tweaked. The goal of this procedure is to create set of changes
>> needed
>> to be made to existing classes as well as form the new type. Some of
>> changes could require moving fields, or adjusting inheritance as
>> well.
>> This should be expressed with mapping of fields and mapping of bases.
>> When user clicks OK button, all those recorded operations would be
>> performed and new type created.
>>
VK>>> 2. I think refactoring you mentioned is named "Collapse Hierarchy"
VK>>> according to Martin Fowler's classification. It's possible to
VK>>> implement it but we did not include it because it did not seem to
VK>>> be that frequently needed.
VK>>>
>> This is not frequently needed until you have powerful tool to "Expand
>> Hierarchy". Once you have it in place, it will be naturall "Think
>> Back" after I created base classes, tweaked it for some time (days,
>> weeks, months) and then simple undo will not work if I realise that
>> initial intention was wrong.
>>
VK>>> 3. Push Down Member and Pull Up Member refactorings will probably
VK>>> be scheduled for the version for VS 2005.
VK>>>
>> Abscence of these is stopship for use of extract
>> superclass/interface. Well, it technicaly doesn't, because it helps
>> to do a one time refactoring of this kind. But since I don't have a
>> tool to push/pull and revert extraction - all the following changes
>> will be manual.
>>
VK>>> 4. "Copy type interface" - when do you need such operation?
VK>>>
>> When creating similar entities which differs in semantics and cannot
>> be expressed in derived/implemented relationships. Consider
>> CancelEventArgs. There is single property Cancel in addition to
>> EventArgs interface. And compare it to KeyPressEventArgs, where I
>> have Handled property. This is very similar, but still different. In
>> case of one property it's obviously simpler to create one, but when
>> there are many of them - that's become tedious. Another example -
>> primitive value types. To maintain usability, I would like to create
>> my primitive value types by copying int32 interface, so I don't
>> forget various Parse, ToString overloads, etc. So I would issue "Copy
>> type interface" on System.Int32 and then tweak as needed.
>>
>> Sincerely,
>> Ilya Ryzhenkov


0

Please sign in to leave a comment.