Refactoring in Tunes

btanksley@hifn.com btanksley@hifn.com
Sun, 9 Jan 2000 15:26:39 -0800


> From: Laurent Martelli [mailto:martelli@iie.cnam.fr]
> Subject: Re: Refactoring in Tunes

> >>>>> "bill" == btanksley  <btanksley@hifn.com> writes:
>   >> From: Laurent Martelli [mailto:martelli@iie.cnam.fr] Subject: Re:
>   >> Refactoring in Tunes

>   bill> Refactoring in this sense cannot be helped by a runtime
>   bill> system, but it can be helped by a language designed for it.
>   bill> Forth is well-suited for refactoring because of its absence of
>   bill> explicit variables; Java works well because of it moderately
>   bill> strong compile-time typechecking (to help the programmer catch
>   bill> typos written during the refactoring); and Smalltalk works
>   bill> well because there are automated tools to performs some of the
>   bill> most common refactorings.

>   >> I can't what makes C more difficult to refactor than smalltalk. I

>   bill> I didn't mention C at all here.

> I I don't think that a language is more refactorable than an other, so
> I just took C as an example.

Ah, an excellent point.  I've listed above some of the ways a language can
help refactoring; surely you can see that Forth is easier to refactor than
C, becuase in well-written Forth you don't have to worry about renaming
variables when you move a chunk of code out of a function.

>   bill> However, let's take a look at it.  C has slightly stronger
>   bill> typechecking than Smalltalk, so the C compiler will warn you
>   bill> of a few errors; however, C's typechecking is weak enough that
>   bill> if you try to take advantage of it you'll wind up letting a
>   bill> lot of errors slip by you.  Advantage: neither one.

> What has refactoring to do with typechecking ?

Typechecking isn't essential to refactoring -- witness how Smalltalk is such
a commonly used language for refactorers.  However, it _does_ help, by
catching a certain class of common errors.  If the typechecking in the
language is reasonably complete, the programmer is free to spend less effort
writing test cases and mentally checking his work.  This reduced effort
results in a much higher willingness to perform refactorings, thus hopefully
resulting in a more flexible design.

>   bill> Smalltalk has more possible refactorings: it's easy to make a
>   bill> "parameter object" im Smalltalk, and it's hard in C.  It's
>   bill> even harder in C to do refactorings which "split" a function
>   bill> which has internal state, but Smalltalk (of course) has no
>   bill> trouble at all.  Strong advantage to Smalltalk.

> I don't see what you're talking about. Can you give an example ?

Okay.

I can't give a single concrete example, because this refactoring is
inherently complex, but I'll give a simple one and ask you to imagine that
there were a lot more calculations and variables.

Suppose we have this function:

int CalculateTaxAndSetFinalBill(int centsOwed, int taxRatePercent)
{
   int total;
   total = (centsOwed * (100+taxRatePercent))/100;
   global_finalBill = total;
   return (centsOwed * taxRatePercent)/100;
}

In C++, we might refactor this into the follwing functions:

class Bill // no relation to myself
{
  int taxRatePercent;
public:
  void setTaxRate(int);
  int getTaxRate(void);
  void setOwed(int);
  int getBill();
}

The important thing here isn't the specific functions I broke that
monstrosity down into; the important thing is that I extracted the
taxRatePercent out of the function and made it part of an object.  This
allowwed me to split the function up into smaller parts without creating
more global variables.

>   bill> Smalltalk wins versus C, all in all, because as an OO language
>   bill> it has many more possible refactorings.

> What makes you think so ?

Because procedural programming is a strict subset of object oriented
programming.

>   >> think that refactoring does not only apply to OO languages. I see
>   >> it as finding patterns which are used more than once.

>   bill> No, that's function factoring, not Refactoring.  My
>   bill> "Refactoring" book calls that "Extract Method".  Refactoring
>   bill> also includes the inverse of that -- "Inline Method".  A good
>   bill> coder should know how to do both refactorings; sometimes you
>   bill> need to inline a method in order to get special behavior

> Are you saying that there are things that you can only do by 
> inlining ? 

Yes -- for example, inlining can only be done by inlining.  Seriously,
though, I'm saying that inlining is exactly as important as factoring: it
provides the inverse operation, just in case you make a mistake when
factoring.

For example, suppose you took that math formula you showed me and factored
the two occurences out.  Suppose that later on the customer told you that
the formula was going to have to change in one of the places, but not in the
other. You *could* solve that by adding parameters to the function call, but
often that's a bad idea -- it could be that the correct solution is to undo
what you did, inline the function, and make the appropriate changes to each
seperate copy.

>   bill> The full art of refactoring is about being able to change the
>   bill> design of a program, not simply make it take up less space.
>   bill> You accomplish that change in two steps: first, you apply
>   bill> source changes which preserve the old behavior but provide a
>   bill> more suitable class or function layout (these are what Fowler
>   bill> calls "refactorings"); and second, you change the arrangement
>   bill> of these new classes to provide your new behavior.

> Thanks for the clarification on the meaning of refactoring. But I
> still don't see why refactoring could only be applied to OO. Excepted
> that you use `class' in your definition. If you only take the first
> part of the defitinition (``The full art of refactoring is about being
> able to change the design of a program''), it can be applied to any
> language. 

I don't recall ever saying that refactoring only applied to OO languages.
It applies to any source code of any kind, including English.  You can take
both parts of my definition to apply to any language -- although I do admit
that I was lazy when I said "classes" there; perhaps I should have said
"units of organization".  In a functional language, those would be
functions.

> Laurent Martelli

-Billy