Loading ...
Sorry, an error occurred while loading the content.
 

[extremeprogramming] Re: When does refactoring become framework building

Expand Messages
  • Michael C. Feathers
    ... From: Jonas Karlsson To: Sent: Monday, January 03, 2000 4:56 PM Subject: [extremeprogramming]
    Message 1 of 10 , Jan 3, 2000
      ----- Original Message -----
      From: Jonas Karlsson <karlsson@...>
      To: <extremeprogramming@egroups.com>
      Sent: Monday, January 03, 2000 4:56 PM
      Subject: [extremeprogramming] When does refactoring become framework
      building
      > Fowler states that refactoring should be done where "code smells" can
      > be found. At first I thought he said that refactoring is done when
      > needed to make implementation of a new task easier. Then he seemed to
      > add that refactoring should be done all the time, whenever bad smells
      > were encountered. I love designing general purpose, reusable
      > frameworks, but my co-developers have forced me to compromise on many
      > occasions, saying that it adds complexity that is not needed at this
      > point in time. Can I now go and sneak in my general purpose
      > framework under the guise of refactoring ("Oh, I'll just split an
      > interface here, create an abstraction layer there, push some methods
      > down, and others up.. Then in February, I'll start on my assigned
      > tasks!")?

      To me, the most important way of avoiding this is to make
      sure that all of your code is being used. If you are not using
      a particular hook function, for instance, it is not necessary.
      If you have an abstract class with only one subclass and
      it isn't there to break a dependency, ditto.

      There are a couple of things that will keep you away
      from framework building. First of all, if you write your
      test cases first, you'll probably find creating things you
      don't immediately need tedious. Secondly, if you
      are making estimates and sticking to them as part of
      a team, and the rest of them are churning out correct
      tested code like mad, I doubt they'll give you until
      February to join in. :-)

      There is a really bright side, however. If you get a
      kick out of building generality into code, you'll
      probably be amazed at how your code evolves
      into both specific and general things over time,
      without a lot of up front planning.

      > I get the impression that despite "You aren't going to need it", in
      > order to refactor effectively, some judgements about what is likely to
      > change in the future must be made.

      Following Kent's lead, I've tried some experiments, delaying
      those judgements and it has worked out well. Just paying
      attention to the clarity of your code and duplication works.
      When your code can't be made any more understandable
      and you do not have duplication, you are at a stable point.
      The potential for movement in any direction is maximized.

      Michael

      ---------------------------------------------------
      Michael Feathers mfeathers@...
      Object Mentor Inc. www.objectmentor.com
      Training/Mentoring/Development
      -----------------------------------------------------
      "You think you know when you can learn, are more sure when
      you can write, even more when you can teach, but certain when
      you can program. " - Alan Perlis
    • jbrains762@hotmail.com
      Hello, everyone... I am new to this group, and as a result, may respond to some *very old* articles, only because I am still learning the essentials of XP. I
      Message 2 of 10 , Nov 28, 2000
        Hello, everyone...

        I am new to this group, and as a result, may respond to some *very
        old* articles, only because I am still learning the essentials of XP.
        I have a question regarding the issues of "interface/implementation"
        v. "code for now only".

        In my relatively short experience as a developer -- only about three
        years -- I have learned that one effective way to insulate yourself
        from change is first to build a component entirely comprised of
        abstract classes and interfaces (I use Java terminology here) *then*
        implement the concrete classes that provide the behavior. In essence,
        I am building a "framework" even though the goal is not to reuse the
        framework, but rather to delay specifying the concrete classes to a
        configuration file. The result is that if implementation X
        (implementing Z) needs to be replaced with implementation Y, then all
        I need to do is write Y, have Y implement Z, then change a
        configuration file setting so that the ZFactory creates Ys instead of
        Xs.

        Clearly, this is not the simplest thing that could possibly work;
        however, it means that as long as I'm just replacing an
        implementation and not changing the overall behavior of the system, I
        do not have to recompile any existing code. I find this theoretically
        pleasing, even if I don't have hard evidence that it saves me any
        time.

        The simplest thing that could possibly work results in my having to
        change client code everywhere, from using Xs to using Ys, because the
        client code never used the Z interface, but the X class directly. I
        have to change all my test cases, too, because my integration-level
        tests all think I'm using Xs when now I'm using Ys.

        So am I missing something? or is this one area where the XP tenets
        don't quite hold well? I would argue that having a component built
        entirely of abstract classes and interfaces is less simple, but more
        valuable. I think XP is a hell of an idea, so I must be missing
        something.

        What don't I get, then?

        J. B. Rainsberger.
      • Laurent Bossavit
        ... Could you look for evidence that it *costs* you time ? Do you think you might find any ? If it doesn t take any longer to implement things that way, then
        Message 3 of 10 , Nov 28, 2000
          > Clearly, this is not the simplest thing that could possibly work;
          > however, it means that as long as I'm just replacing an
          > implementation and not changing the overall behavior of the
          > system, I do not have to recompile any existing code. I find this
          > theoretically pleasing, even if I don't have hard evidence that it
          > saves me any time.

          Could you look for evidence that it *costs* you time ? Do you think
          you might find any ?

          If it doesn't take any longer to implement things that way, then you
          are fine anyway. If it takes about the same time, you might
          experiment with extracting the interfaces after coding the
          implementation and observe whether the change seems to benefit
          your projects in any other measurable manner.

          I'm just making this up, but there is a way doing things the way
          you describe could cost you more time than it saves. If you need to
          alter the interfaces as a result of changes in the implementation,
          you would have been better off not writing the interface. If you avoid
          altering the interface, however much you are tempted to, and
          instead make the implementation more complex, that might cost
          you time in debugging the implementation.

          One way I like to think of the YAGNI principle is with reference to
          the old saying that "No battle plan survives contact with the
          enemy". I suspect, based on my scant experience, that no
          interface survives contact with its implementation.


          ========================================
          Bless n'a pas de modele : son ambition
          est d'en devenir un.
          ========================================
          Laurent Bossavit - Software Architect
          >>> laurent.bossavit@... <<<
          >>> 06 68 15 11 44 <<<
          >> ICQ#39281367 <<
          Agence Bless http://www.agencebless.com/
          ========================================
        • Phil Lewis
          ... ... Could it not be said that by writing tests before writing code, we are actually specifying the interface at that time? I kind of think that
          Message 4 of 10 , Nov 28, 2000
            > From: Laurent Bossavit [mailto:laurent.bossavit@...]
            >
            > > Clearly, this is not the simplest thing that could possibly work;
            > > however, it means that as long as I'm just replacing an
            > > implementation and not changing the overall behavior of the
            > > system, I do not have to recompile any existing code. I find this
            > > theoretically pleasing, even if I don't have hard evidence that it
            > > saves me any time.

            <SNIP>
            > I suspect, based on my scant experience, that no
            > interface survives contact with its implementation.

            Could it not be said that by writing tests before writing code, we are
            actually specifying the interface at that time?

            I kind of think that something ever so slightly 'smells' (no offense JB)
            about the idea of defining interfaces seperate from implementation. Not as a
            principle in itself. I think as a general principle it is probably fairly
            sound - a great deal of the Java base classes are done this way - but
            within the context of XP.

            I would be tempted to get it working without automatically doing this, and
            assume YAGNI. Then if at some later stage it looks like its about to be
            useful (coz I'm about to do the example JB gave), I might be tempted to
            refactor this idea into the code - but only where and when it proves useful.

            Hey, I've never done any XP, so don't listen to me!

            Phil
          • John Brewer
            ... essence, ... all ... of ... Design by interface is good stuff. This finally dawned on me after I read Coad and Mayfield s book Java Design . One thing
            Message 5 of 10 , Nov 28, 2000
              --- In extremeprogramming@egroups.com, jbrains762@h... wrote:
              > In my relatively short experience as a developer -- only about three
              > years -- I have learned that one effective way to insulate yourself
              > from change is first to build a component entirely comprised of
              > abstract classes and interfaces (I use Java terminology here) *then*
              > implement the concrete classes that provide the behavior. In
              essence,
              > I am building a "framework" even though the goal is not to reuse the
              > framework, but rather to delay specifying the concrete classes to a
              > configuration file. The result is that if implementation X
              > (implementing Z) needs to be replaced with implementation Y, then
              all
              > I need to do is write Y, have Y implement Z, then change a
              > configuration file setting so that the ZFactory creates Ys instead
              of
              > Xs.

              Design by interface is good stuff. This finally dawned on me after I
              read Coad and Mayfield's book "Java Design". One thing Coad is quick
              to point out is that you don't want to have interfaces everywhere,
              just in a few key places. The question is, how do you find these key
              points?

              Since I've gotten into XP, I let the code tell me. I code a straight
              class first, and if I find duplication, I apply Fowler's "Extract
              Superclass" and "Extract Interface" refactorings. It helps a lot that
              Java has the notion of "compatible change" to a class. That is, you
              can do lots of things to a class, like adding methods and fields,
              without recompiling dependent classes.

              The cool thing about refactoring is that I trust myself to be able to
              handle these situations as the come up, so I don't need to design
              ahead the way I used to.

              John Brewer
              Jera Design
            • Glen Alleman
              ... are ... This is a very common practice in the hardware development world. Build the test fixture before the final board level product is finished, because
              Message 6 of 10 , Nov 28, 2000
                --- In extremeprogramming@egroups.com, "Phil Lewis" <phil.lewis@k...>
                wrote:

                > Could it not be said that by writing tests before writing code, we
                are
                > actually specifying the interface at that time?

                This is a very common practice in the hardware development world.
                Build the test fixture before the final board level product is
                finished, because how are you going to know if it works unless you
                can plug it into something and not have it catch on fire?

                > I kind of think that something ever so slightly 'smells' (no
                offense JB)
                > about the idea of defining interfaces separate from implementation.
                Not as a
                > principle in itself. I think as a general principle it is probably
                fairly
                > sound - a great deal of the Java base classes are done this way -
                but
                > within the context of XP.

                Better than that it is a Best Practice in most CORBA shops to isolate
                the underlying components from the IDL (if you use IDL that is). Look
                at Peter Coad's Java Design Second Edition for some nice "programming
                with interfaces" guidelines as well as Peter Haggar's Practical Java.
                This is the point where I part company with YAGNI in the practical
                sense. In a large scale system, NOT looking ahead and doing things
                like isolating with interfaces and planning the IIOP XML stream
                connections will only cause the whole team to jump up and down on
                your body, when you announce that a refactoring is needed and all
                their method signatures are also going to have to change.

                > I would be tempted to get it working without automatically doing
                this, and
                > assume YAGNI. Then if at some later stage it looks like its about
                to be
                > useful (coz I'm about to do the example JB gave), I might be
                tempted to
                > refactor this idea into the code - but only where and when it
                proves useful.

                This of course depends on the development environment and the "teams"
                rules for building Java objects. In the CORBA world "managing the
                interfaces" is everything. Since the scalability of the distributed
                object systems usually depend on how many remote object invocations
                are performed for each Function Point, defining these interfaces LONG
                in advance allows the system architects (people like me) to look at
                the system from a macro view and start making models of performance,
                reliability, fault tolerance, and all those annoying non-functional
                attributes of commercially robust products

                > Hey, I've never done any XP, so don't listen to me!

                Neither do a fairly large number of the other members of this group
                (at least according to the poll results (but there may be lots of
                hanging chad there, so don't certify the results just yet).
              • Kevin Smith
                ... Others have hinted at what I will try to state more explicitly. Initially, when you have just one class, the simplest thing is to write the class without
                Message 7 of 10 , Nov 28, 2000
                  > In my relatively short experience as a developer -- only about three
                  > years -- I have learned that one effective way to insulate yourself
                  > from change is first to build a component entirely comprised of
                  > abstract classes and interfaces (I use Java terminology here) *then*
                  > implement the concrete classes that provide the behavior. In essence,
                  > I am building a "framework" even though the goal is not to reuse the
                  > framework, but rather to delay specifying the concrete classes to a
                  > configuration file. The result is that if implementation X
                  > (implementing Z) needs to be replaced with implementation Y, then all
                  > I need to do is write Y, have Y implement Z, then change a
                  > configuration file setting so that the ZFactory creates Ys instead of
                  > Xs.
                  >
                  > Clearly, this is not the simplest thing that could possibly work;
                  > however, it means that as long as I'm just replacing an
                  > implementation and not changing the overall behavior of the system, I
                  > do not have to recompile any existing code. I find this theoretically
                  > pleasing, even if I don't have hard evidence that it saves me any
                  > time.
                  >
                  > The simplest thing that could possibly work results in my having to
                  > change client code everywhere, from using Xs to using Ys, because the
                  > client code never used the Z interface, but the X class directly. I
                  > have to change all my test cases, too, because my integration-level
                  > tests all think I'm using Xs when now I'm using Ys.

                  Others have hinted at what I will try to state more explicitly.

                  Initially, when you have just one class, the simplest thing
                  is to write the class without an interface.

                  As soon as you have a second class doing the same thing,
                  it's time to refactor because you're violating the OAOO
                  (once and only once) rule. That might mean creating an
                  interface, or it might mean taking some other solution to
                  the problem.

                  Having the same (or very similar) code in multiple places in
                  your project is a smell, and should be refactored.

                  If you grow your interfaces this way, you will only have the
                  ones that you need. And, by golly, each one will do exactly
                  what it must, and nothing more. You won't have wasted time
                  up front guessing about which interfaces will contain which
                  functionality.

                  Hope it helps...

                  Kevin
                • jbrains762@hotmail.com
                  ... work; ... this ... it ... are ... As soon as I read this, I saw that it must be so. In a way, my practice was equivalent to writing the test first,
                  Message 8 of 10 , Nov 29, 2000
                    --- In extremeprogramming@egroups.com, "Phil Lewis" <phil.lewis@k...>
                    wrote:
                    >
                    > > From: Laurent Bossavit [mailto:laurent.bossavit@a...]
                    > >
                    > > > Clearly, this is not the simplest thing that could possibly
                    work;
                    > > > however, it means that as long as I'm just replacing an
                    > > > implementation and not changing the overall behavior of the
                    > > > system, I do not have to recompile any existing code. I find
                    this
                    > > > theoretically pleasing, even if I don't have hard evidence that
                    it
                    > > > saves me any time.
                    >
                    > <SNIP>
                    > > I suspect, based on my scant experience, that no
                    > > interface survives contact with its implementation.
                    >
                    > Could it not be said that by writing tests before writing code, we
                    are
                    > actually specifying the interface at that time?

                    As soon as I read this, I saw that it must be so. In a way, my
                    practice was equivalent to writing the test first, although I was
                    writing the test on paper instead of as code.

                    > I kind of think that something ever so slightly 'smells' (no
                    offense JB)
                    > about the idea of defining interfaces seperate from implementation.
                    Not as a
                    > principle in itself. I think as a general principle it is probably
                    fairly
                    > sound - a great deal of the Java base classes are done this way -
                    but
                    > within the context of XP.

                    No offence taken.

                    Certainly, after mapping out all the interfaces and ensuring that
                    they integrate properly, one can refactor: look for interfaces that
                    only have one foreseeable implementation and change the interface
                    into a concrete class. This is equivalent to XP practices, I think.

                    > I would be tempted to get it working without automatically doing
                    this, and
                    > assume YAGNI. Then if at some later stage it looks like its about
                    to be
                    > useful (coz I'm about to do the example JB gave), I might be
                    tempted to
                    > refactor this idea into the code - but only where and when it
                    proves useful.

                    On the other hand, if you know that you need two different
                    implementations and that you need to swap 'em, build the interface
                    first. To me, it's a question of looking interface-down instead of
                    implementation-up. Coding the test cases first looks like
                    an "interface-down" approach to me.

                    JBR.
                  Your message has been successfully submitted and would be delivered to recipients shortly.