Re: decustmomising



Roedy Green wrote:
The last few days I have been decustomising three of my projects.

Html static macros, a Xenu back end broken link checker, and a tool
for manipulating HTML tables.

Each started out an in-house one-day project and grew and grew, then
I realised the code would have general application. But the code
contains all manner of magic strings and constants. It is quite a bit
of mindless work to remove the mindprod-specific code, and make
everything configurable.

Apps have to be split into core and customised sections.

This a special kind of refactoring. I wonder if there are any special
tools to help, e.g. to move magic configuration constants to a class,
convert them to variables, compose code to set them with a Properties
file or a generate a little GUI to set and validate them.

Some of the refactoring tools in IntelliJ have been invaluable, but
there is still a lot of mindless bull work that might be automated.

So the questions:

1. What is the official name of this process?
I would call it generalizing.
2. What tools do you use to expedite it?
IntelliJ IDEA has good ways to convert magic values to constants, methods, variables, parameters, or fields (Introduce *). Deciding on which one of those introductions to use is an engineering decision, and I don't see how a tool can help you with that. Then I use extract super-class and/or extract interface. Pull-up and push-down too.


3. If there were special tool created to help, what might it do? how
might it work? What features would you like?
Hmm, Actually, a tool I *would* like, is one that would take two classes, figure out what is semantically similar between them, and factor that out into a common base class.

Another tool/feature would be the ability to "find common method signatures", and suggest interfaces and hierarchies for those interfaces.

Something else that I've found is that sometimes a "method" that is designed to be overridden should actually not be overridden, but the behavior in it should be externalized (strategy pattern). For example,
before:
class A{public void myMethod(int x, double y) { /* base definition */ }}
class B extends A {public void myMethod(int x, double y) { /*...*/ }}
after:
interface MyMethodStrategy { void doMethod(int x, double y); }
class A {
MyMethodStrategy strategy = new NullStrategy();
public void myMethod(int x, double y) { strategy.doStrategy(x, y); }
}

I would call this feature "Introduce Strategy". It would give the option of remove overridden methods, but create the appropriate implementation and instantiation of a new strategy class (combining duplicates as necessary).

Basically, what you should ask yourself is,
"Am I applying a process in a mechanical way?"
"Are all of my decisions non subjective, or are those decisions simple enough to present a dialog to the tool user?"
"Is this process a structural change only (no semantics are changing)."

If you answer no to any of those, then you probably can't create a useful tool to do what you want to do.

Hope this helps,
Daniel.

--
Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
.