A little concept puzzle (involving refactoring)

Discussion in 'Java' started by Stefan Ram, Dec 17, 2013.

  1. Stefan Ram

    Stefan Ram Guest

    Here is a little puzzle about the definition of concepts:

    /The behavior/ of a program I call what can be observed
    from the outside by running the program.

    /A refactor/ I call a modification of the source code of
    a program that does not change the behavior of the program.

    Now, let's test these concepts!

    public class Main
    { public static void main( final java.lang.String[] args )
    { final double value = java.lang.Math.random();
    java.lang.System.out.println( value ); }}

    0.8262472065326088

    Now apply the modification
    »renameLocalVariable("value","number")«:

    public class Main
    { public static void main( final java.lang.String[] args )
    { final double number = java.lang.Math.random();
    java.lang.System.out.println( number ); }}

    0.4774192830734339

    The behavior has changed - so that was not a refactor!

    Should we see it this way or modify our definitions?

    PS: Here's a quotation from the book »Refactoring« by Martin
    Fowler at al.:

    »Refactoring is the process of changing a software
    system in such a way that it does not alter the external
    behavior of the code yet improves its internal structure.«
     
    Stefan Ram, Dec 17, 2013
    #1
    1. Advertising

  2. Stefan Ram

    Joerg Meier Guest

    On 17 Dec 2013 16:16:35 GMT, Stefan Ram wrote:

    > The behavior has changed - so that was not a refactor!


    The behaviour has not changed: the behaviour is that it prints out a random
    number. This behaviour is consistent over many calls and does not change
    with the refactoring. By your definition, my Firefoxes behaviour is changed
    all the time without even recompiling it! And following that logic, it is
    impossible to ever refactor an NTP client!

    Clearly, that definition makes no sense. The real issue here is that your
    program is not written in a way that allows for proper unit testing, and as
    a result, you can not confirm changes in behaviour because of your
    inability to mock proper input.

    The real solution is to use a supplied Random that can be initialized with
    a fixed seed for mocking/testing, and then refactoring can be defined as
    getting the exact same output (if you so wished).

    Liebe Gruesse,
    Joerg

    --
    Ich lese meine Emails nicht, replies to Email bleiben also leider
    ungelesen.
     
    Joerg Meier, Dec 17, 2013
    #2
    1. Advertising

  3. Stefan Ram

    Eric Sosman Guest

    On 12/17/2013 11:16 AM, Stefan Ram wrote:
    > Here is a little puzzle about the definition of concepts:
    >
    > /The behavior/ of a program I call what can be observed
    > from the outside by running the program.


    Here's where you need to be more specific, I think. For
    example: A printed stack trace can be "observed from the outside,"
    and the number of stack frames and the line numbers they show are
    part of the "behavior."

    --
    Eric Sosman
    d
     
    Eric Sosman, Dec 17, 2013
    #3
  4. Stefan Ram

    Arne Vajhøj Guest

    On 12/17/2013 11:16 AM, Stefan Ram wrote:
    > Here is a little puzzle about the definition of concepts:
    >
    > /The behavior/ of a program I call what can be observed
    > from the outside by running the program.
    >
    > /A refactor/ I call a modification of the source code of
    > a program that does not change the behavior of the program.
    >
    > Now, let's test these concepts!
    >
    > public class Main
    > { public static void main( final java.lang.String[] args )
    > { final double value = java.lang.Math.random();
    > java.lang.System.out.println( value ); }}
    >
    > 0.8262472065326088
    >
    > Now apply the modification
    > »renameLocalVariable("value","number")«:
    >
    > public class Main
    > { public static void main( final java.lang.String[] args )
    > { final double number = java.lang.Math.random();
    > java.lang.System.out.println( number ); }}
    >
    > 0.4774192830734339
    >
    > The behavior has changed - so that was not a refactor!
    >
    > Should we see it this way or modify our definitions?
    >
    > PS: Here's a quotation from the book »Refactoring« by Martin
    > Fowler at al.:
    >
    > »Refactoring is the process of changing a software
    > system in such a way that it does not alter the external
    > behavior of the code yet improves its internal structure.«


    You did not change the behavior of the program.

    Behavior is really:
    output = behavior(input)

    You changed the input (the default seed of Random) and got
    a different output.

    The behavior is the same as you would get the same output
    with the same input.

    Arne
     
    Arne Vajhøj, Dec 17, 2013
    #4
  5. Stefan Ram

    Arne Vajhøj Guest

    On 12/17/2013 12:34 PM, Arne Vajhøj wrote:
    > On 12/17/2013 11:16 AM, Stefan Ram wrote:
    >> Here is a little puzzle about the definition of concepts:
    >>
    >> /The behavior/ of a program I call what can be observed
    >> from the outside by running the program.
    >>
    >> /A refactor/ I call a modification of the source code of
    >> a program that does not change the behavior of the program.
    >>
    >> Now, let's test these concepts!
    >>
    >> public class Main
    >> { public static void main( final java.lang.String[] args )
    >> { final double value = java.lang.Math.random();
    >> java.lang.System.out.println( value ); }}
    >>
    >> 0.8262472065326088
    >>
    >> Now apply the modification
    >> »renameLocalVariable("value","number")«:
    >>
    >> public class Main
    >> { public static void main( final java.lang.String[] args )
    >> { final double number = java.lang.Math.random();
    >> java.lang.System.out.println( number ); }}
    >>
    >> 0.4774192830734339
    >>
    >> The behavior has changed - so that was not a refactor!
    >>
    >> Should we see it this way or modify our definitions?
    >>
    >> PS: Here's a quotation from the book »Refactoring« by Martin
    >> Fowler at al.:
    >>
    >> »Refactoring is the process of changing a software
    >> system in such a way that it does not alter the external
    >> behavior of the code yet improves its internal structure.«

    >
    > You did not change the behavior of the program.
    >
    > Behavior is really:
    > output = behavior(input)
    >
    > You changed the input (the default seed of Random) and got
    > a different output.
    >
    > The behavior is the same as you would get the same output
    > with the same input.


    This leads to the point that if you want to write unit testable
    code, then you should use the constructors that takes the seed
    as argument to enable you to unit test that your refactoring
    did not change behavior.

    Arne
     
    Arne Vajhøj, Dec 17, 2013
    #5
  6. On 12/17/2013 12:16 PM, Stefan Ram wrote:
    > Here is a little puzzle about the definition of concepts:
    >
    > /The behavior/ of a program I call what can be observed
    > from the outside by running the program.
    >
    > /A refactor/ I call a modification of the source code of
    > a program that does not change the behavior of the program.
    >
    > Now, let's test these concepts!
    >
    > public class Main
    > { public static void main( final java.lang.String[] args )
    > { final double value = java.lang.Math.random();
    > java.lang.System.out.println( value ); }}
    >
    > 0.8262472065326088
    >
    > Now apply the modification
    > »renameLocalVariable("value","number")«:
    >
    > public class Main
    > { public static void main( final java.lang.String[] args )
    > { final double number = java.lang.Math.random();
    > java.lang.System.out.println( number ); }}
    >
    > 0.4774192830734339
    >
    > The behavior has changed - so that was not a refactor!
    >
    > Should we see it this way or modify our definitions?
    >
    > PS: Here's a quotation from the book »Refactoring« by Martin
    > Fowler at al.:
    >
    > »Refactoring is the process of changing a software
    > system in such a way that it does not alter the external
    > behavior of the code yet improves its internal structure.«
    >

    I'm a little cog in a big machine, so my opinion carries little weight.
    But that Fowlerian usurpation of the definition of a useful word to suit
    his own opinions is not something I am all that happy about. It's an
    overly constraining term, it's impractical, and it doesn't conform to
    real life. What's a system? What's external behaviour? The entire list
    of refactoring techniques is heavy on changing interfaces, at every
    level of an application.

    Don't get me wrong, I recognize the value of the espoused techniques.
    But the definition is impractical. The extent to which it is ignored, in
    the real world, is not an example of "an exception that proves the
    rule", it's more like the rule is badly flawed.

    I don't think Martin Fowler is an idiot, nor that we as software
    developers shouldn't at least pay some attention to his musings. I don't
    ignore what the GOF guys say either, or what Josh Bloch had to say, or
    what Scott Meyers or Herb Sutter or Andrei Alexandrescu have to say, or
    what Brian Goetz says, or Thomas Erl, etc etc etc.

    But let's keep some perspective here. My apologies to Martin Fowler for
    using him as an example. The man is a few years younger than I am, and
    he started programming - according to his bio - well after me (or a
    bunch of guys I went to school with, for that matter). Barely a decade
    after he started FT work he wrote his first book. I'll give him credit,
    he's articulate and he's obviously not stupid. Is he infallible like the
    Pope? I daresay no more so than a dozen IT guys I can think of off the
    top of my head who have more real world experience than he does...just
    saying. But nobody's heard of these other guys because they ain't
    writing books or going to conferences.

    How many people here were experienced programmers when the original GoF
    book came out? If you were like me, you may have read that book and
    exclaimed to yourself, Boy, I've been doing half that shit all along but
    it sure is nice to see my thinking validated. Now, it was fantastic that
    those guys wrote that book, but it's seriously irksome to listen to all
    the younger programmers who think that Gamma, Helm, Johnson and
    Vlissides actually *invented* the patterns.

    I have rather more basic terminology to describe what Fowler labelled as
    "refactoring". Back in the day - believe it or not software
    practitioners were this enlightened in the '60's and '70's even - we
    called it maintenance. That term covers everything he is talking about.

    AHS

    When a true genius appears, you can know him by this sign:
    that all the dunces are in a confederacy against him.
    -- Jonathan Swift
     
    Arved Sandstrom, Dec 17, 2013
    #6
  7. Stefan Ram <-berlin.de> wrote:
    > public class Main
    > { public static void main( final java.lang.String[] args )
    > { final double value = java.lang.Math.random();
    > java.lang.System.out.println( value ); }}
    > 0.8262472065326088


    There's already something wrong before the refactoring...
    I cannot reproduce this result ;-)


    PS: ok, I admit: I didn't even try...
     
    Andreas Leitgeb, Dec 19, 2013
    #7
  8. Stefan Ram

    Daniel Pitts Guest

    On 12/17/13 8:16 AM, Stefan Ram wrote:
    > Here is a little puzzle about the definition of concepts:
    >
    > /The behavior/ of a program I call what can be observed
    > from the outside by running the program.
    >
    > /A refactor/ I call a modification of the source code of
    > a program that does not change the behavior of the program.
    >
    > Now, let's test these concepts!
    >
    > public class Main
    > { public static void main( final java.lang.String[] args )
    > { final double value = java.lang.Math.random();
    > java.lang.System.out.println( value ); }}
    >
    > 0.8262472065326088
    >
    > Now apply the modification
    > »renameLocalVariable("value","number")«:
    >
    > public class Main
    > { public static void main( final java.lang.String[] args )
    > { final double number = java.lang.Math.random();
    > java.lang.System.out.println( number ); }}
    >
    > 0.4774192830734339
    >
    > The behavior has changed - so that was not a refactor!
    >
    > Should we see it this way or modify our definitions?
    >
    > PS: Here's a quotation from the book »Refactoring« by Martin
    > Fowler at al.:
    >
    > »Refactoring is the process of changing a software
    > system in such a way that it does not alter the external
    > behavior of the code yet improves its internal structure.«
    >

    Behavior and outcome are not the same thing. You're preconditions are
    different, and therefor your test is invalid.

    Math.random() explicitly uses
    http://docs.oracle.com/javase/7/docs/api/java/util/Random.html#Random(),
    which implicitly takes "time" as a precondition.
     
    Daniel Pitts, Dec 19, 2013
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Xah Lee

    Re: Lisp refactoring puzzle

    Xah Lee, Jul 12, 2011, in forum: Python
    Replies:
    17
    Views:
    427
    Gregory Ewing
    Jul 14, 2011
  2. ex
    Replies:
    41
    Views:
    380
    Peña, Botp
    Jun 23, 2008
  3. Neal Becker

    A little morning puzzle

    Neal Becker, Sep 19, 2012, in forum: Python
    Replies:
    2
    Views:
    186
    Paul Rubin
    Sep 19, 2012
  4. Peter Otten

    Re: A little morning puzzle

    Peter Otten, Sep 19, 2012, in forum: Python
    Replies:
    0
    Views:
    186
    Peter Otten
    Sep 19, 2012
  5. Dwight Hutto

    Re: A little morning puzzle

    Dwight Hutto, Sep 19, 2012, in forum: Python
    Replies:
    0
    Views:
    160
    Dwight Hutto
    Sep 19, 2012
Loading...

Share This Page