Responsibility Driven Design Kata

234 views
Skip to first unread message

Nieve

unread,
May 9, 2011, 4:21:45 PM5/9/11
to software_craftsmanship
Hello all,
I am wondering whether anyone can direct me to a kata that would work
on the way a developer can use TDD especially to extract certain roles
and responsibilities from one class to other collaborators...Does that
make any sense?

-nieve

Corey Haines

unread,
May 9, 2011, 4:40:12 PM5/9/11
to software_cr...@googlegroups.com

I like Conway's game of life for this.

On May 9, 2011 1:21 PM, "Nieve" <niev...@gmail.com> wrote:

Nieve

unread,
May 9, 2011, 5:03:32 PM5/9/11
to software_cr...@googlegroups.com
Brilliant!! Thanks a lot Corey :)

On 9 May 2011 21:40, Corey Haines <corey...@gmail.com> wrote:

I like Conway's game of life for this.

On May 9, 2011 1:21 PM, "Nieve" <niev...@gmail.com> wrote:
--
You received this message because you are subscribed to the Google Groups "software_craftsmanship" group.
To post to this group, send email to software_cr...@googlegroups.com.
To unsubscribe from this group, send email to software_craftsma...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/software_craftsmanship?hl=en.

Matteo Vaccari

unread,
May 10, 2011, 3:16:10 AM5/10/11
to software_cr...@googlegroups.com
It makes a lot of sense IMO.  In part, the fact that you use a kata to
extract responsibilities depends on how you perform the kata.  For instance,
the Bowling Score kata can be performed in a single object, like in the
famous presentation by Robert Martin, or you can choose to move some
responsibilities to other objects.

One way to do this is to apply additional restrictions to the TDD rules so
that the performer is forced to work on more than one object; one such set
of restrictions is the Object Calisthenics kata [0], another is my OCP Dojo
[1].

Another way is to add new requirements to the problem in a way that breaks
the "obvious" single object solution.  Sometimes I use the FizzBuzz
"problem".  Simple as it is, when you add new rules you can make the
"obvious" solution explode with the number of IFs!

Matteo

Nieve

unread,
May 10, 2011, 7:06:42 AM5/10/11
to software_cr...@googlegroups.com
Matteo,
Thanks a lot for you thoughts!
Funny that you say that this is something you can add as a restriction to your kata- that's something I've been thinking of lately.
The way I'm starting to see this lately is that in order to respect SRP you *would* want to extract certain responsibilities from your kata object into other object that will collaborate with the object in question, so that your object would have optimally only one reason to change; I do believe the kata, as well as my TDD usage will demand me to do these extractions in the 'refactor' of my red, green, refactor, since green would be just writing the code the way it will just work. Or am I missing something here?

Regards,
n

--

Matteo Vaccari

unread,
May 10, 2011, 8:58:26 AM5/10/11
to software_cr...@googlegroups.com
On Tue, May 10, 2011 at 1:06 PM, Nieve <niev...@gmail.com> wrote:
Matteo,
Thanks a lot for you thoughts!
Funny that you say that this is something you can add as a restriction to your kata- that's something I've been thinking of lately.
The way I'm starting to see this lately is that in order to respect SRP you *would* want to extract certain responsibilities from your kata object into other object that will collaborate with the object in question, so that your object would have optimally only one reason to change; I do believe the kata, as well as my TDD usage will demand me to do these extractions in the 'refactor' of my red, green, refactor, since green would be just writing the code the way it will just work. Or am I missing something here?

Regards,
n


I expect JB Reinsberger would point out that if you *really* do the
"refactor to remove duplication" step, you will end up separating
responsibilities.  So yes, in fact you are right; when I'm facilitating a
dojo I often have to point out that until you remove all duplication you
should not write the next test.

The fact is that most TDD beginners, including at times me, don't see how
important it is to remove every tiny bit of duplication, even when it seems
you're overdoing it!  So the reason for the additional rules is to push learners to strive harder.  For instance, after doing the OCP Dojo for a while it's become more natural for me to extract functionality to new methods and then to new classes.

Matteo

Ron Jeffries

unread,
May 10, 2011, 11:28:33 AM5/10/11
to software_cr...@googlegroups.com
Hello, Matteo. On Tuesday, May 10, 2011, at 8:58:26 AM, you wrote:

> I expect JB Reinsberger would point out that if you *really* do the
> "refactor to remove duplication" step, you will end up separating
> responsibilities. So yes, in fact you are right; when I'm facilitating a
> dojo I often have to point out that until you remove all duplication you
> should not write the next test.

> The fact is that most TDD beginners, including at times me, don't see how
> important it is to remove every tiny bit of duplication, even when it seems
> you're overdoing it! So the reason for the additional rules is to push
> learners to strive harder. For instance, after doing the OCP Dojo for a
> while it's become more natural for me to extract functionality to new
> methods and then to new classes.

+ SomeLargeConstant;

I am continually surprised at how much improvement in my code comes
from a constant focus on removing duplication. I'm sure there are
more sophisticated checks and refactorings to be aware of, but even
those, to me, are more and more driven by simply observing and
removing duplication.

Thanks!

Ron Jeffries
www.XProgramming.com
It is better to attempt something great and fail that attempt,
than to attempt to do nothing and succeed.
--Cookie, Garden Court Chinese Restaurant, Hamburg, MI

Steve Tooke

unread,
May 10, 2011, 2:46:11 PM5/10/11
to software_cr...@googlegroups.com, software_cr...@googlegroups.com
Maximise clarity and remove duplication! http://www.jbrains.ca/permalink/the-four-elements-of-simple-design

Steve

Ralf Westphal

unread,
May 11, 2011, 2:26:04 AM5/11/11
to software_craftsmanship
On 10 Mai, 14:58, Matteo Vaccari <matteo.vacc...@gmail.com> wrote:
> On Tue, May 10, 2011 at 1:06 PM, Nieve <nieveg...@gmail.com> wrote:
> > Matteo,
> > Thanks a lot for you thoughts!
> > Funny that you say that this is something you can add as a restriction to
> > your kata- that's something I've been thinking of lately.

Kata really come to shine if you don´t present them fully in the
beginning.
Instead do them in iterations, e.g. Kata Potter:

1. Calculate the total price for a shopping basket full of HP books,
each is $8.
2. Calculate the total price, but grant a rebate if it´s 2, 4, 7
books.
3. Grant the rebate only for rows of different HP books.

This more like real life, where you don´t know all requirements up
front :-)
And it puts the evolvability of code under stress.

The question always is: Why do you want to do a kata at all?
Since TD has two purposes, namely producing correct code and producing
evolvable code, you need to pose the kata in a way so that both sides
of TDD get exercised.

However, another, altogether different question is: Should you do
katas to learn TDD at all? ;-)
I find TDD highly overrated.


> > The way I'm starting to see this lately is that in order to respect SRP you
> > *would* want to extract certain responsibilities from your kata object into
> > other object that will collaborate with the object in question, so that your
> > object would have optimally only one reason to change; I do believe the
> > kata, as well as my TDD usage will demand me to do these extractions in the
> > 'refactor' of my red, green, refactor, since green would be just writing the
> > code the way it will just work. Or am I missing something here?

I find TDD overrated because it puts refactoring on a pedestal: red -
green - refactor.
It´s core to TDD. It´s TDD´s design technique.

But refactoring is not producing any value for the customer.
So I´d say: refactoring should be avoided altogether if possible.

Why write code thereby producing customer value - while at the same
time being fully conscious you need to refactor it in the end thereby
burning the customer´s money?

When I´m doing a kata, I´m not refactoring anymore. Still my code
follows all core principles of clean code: SRP, SoC, SLA, loose
coupling; it´s most easily testable (I don´t even need a mock
framework); it´s highly evolvable.

That´s because I replaced TDD´s "test hard" approach with a "test
smart" method.

I´m still doing test-first implementation. For every functional unit I
´m implementing I´m writing the tests first.

But which functional units I need does not come from refactoring, but
from thinking.
Careful requirements analysis and explicit design are core to me.
So when I start coding I know exactly which functional units I need.
They are all small. And they were easily found during design. No CRC
card shuffling needed.

One thing I have to admit, though: This is not possible when you
approach a kata with your grandpa´s OO thinking ;-) You need to forget
about nouns and data for a while.

-Ralf

Curtis Cooley

unread,
May 12, 2011, 2:23:58 PM5/12/11
to software_cr...@googlegroups.com

I TDD because I can not yet reliably predict the perfect design for
the problem I'm solving. Given this handicap, I've found TDD to be the
best coping mechanism. When I can reliably and perfectly predict the
optimal design, I'll probably abandon true TDD as well.

Also, given there is no shortcut for experience, I find TDD to be the
best way for novices and advanced beginners to learn about design and
what makes a design good. That moment when you get a new requirement
and you see the code in your brain and realize all you need to do is
change this one line and the new requirement will fit right in is the
epiphany you need to get from Advanced Beginner to Proficient, IMHO at
least :)

I also get the design wrong a lot because I don't really know what's
coming next, so honing my refactoring skills seems appropriate and
necessary.
--
Curtis Cooley
curtis...@gmail.com
blog:http://ponderingobjectorienteddesign.blogspot.com
===============
Leadership is a potent combination of strategy and character. But if
you must be without one, be without the strategy.
-- H. Norman Schwarzkopf

Peter Gfader

unread,
May 12, 2011, 10:06:50 PM5/12/11
to software_cr...@googlegroups.com, tch...@gmail.com
>>I find TDD overrated because it puts refactoring on a pedestal: red -green - refactor.

I wouldn't say that I find TDD overrated, but I agree, it is good to step back and think about the problem a bit more before starting to hack away...

< personal experience >
I did the "alpha-end converter" kata in TDD manner. Description of the coding problem here http://www.thycotic.com/codetest.txt

During doing this Kata I got into this "brute force coding" mode, where I didn't think too much, but I just wanted to get the test to green. It took me a while to get over this hurdle and I couldn't solve the kata in that 1 hour session...

This annoyed me a lot, so I stepped back, thought about the problem on paper for a couple of minutes and had the solution there... 
</ personal experience >

A friend of mine had the same experience and he suggested me the "Call the shots" technique for beating this. More on his blog http://www.davesquared.net/2010/08/calling-your-shots.html

Note: By working in pairs that problem wouldn't probably happen, because the observer is already focused about what should happen while the other one is typing.

What is your experience doing TDD? 

.peter.gfader.



--
You received this message because you are subscribed to the Google Groups "software_craftsmanship" group.
To post to this group, send email to software_cr...@googlegroups.com.
To unsubscribe from this group, send email to software_craftsma...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/software_craftsmanship?hl=en.

Matteo Vaccari

unread,
May 13, 2011, 2:07:08 AM5/13/11
to software_cr...@googlegroups.com
On Fri, May 13, 2011 at 4:06 AM, Peter Gfader <pe...@gfader.com> wrote:
>>I find TDD overrated because it puts refactoring on a pedestal: red -green - refactor.

I wouldn't say that I find TDD overrated, but I agree, it is good to step back and think about the problem a bit more before starting to hack away...

< personal experience >
I did the "alpha-end converter" kata in TDD manner. Description of the coding problem here http://www.thycotic.com/codetest.txt

During doing this Kata I got into this "brute force coding" mode, where I didn't think too much, but I just wanted to get the test to green. It took me a while to get over this hurdle and I couldn't solve the kata in that 1 hour session...

This annoyed me a lot, so I stepped back, thought about the problem on paper for a couple of minutes and had the solution there... 
</ personal experience >



I find that this is a problem with kata that drive towards an algorithm, wrt
katas that push me to write a maintainable solution.  I don't think that
getting folks to recognize that we're asked to convert from base-10 to
base-13 is particularly interesting.  It gets more interesting if you start
asking yourself: can I change base?  Can I change the symbols?  Can I also
support Roman numerals?  Hours and angles (base-60 but with more than one
symbol per "digit")?  Babylonian?  Can I support different  number systems
in the same program?  Without introducing IFs?

<http://www.antiifcampaign.com/>

Matteo

Peter Gfader

unread,
May 13, 2011, 5:28:24 AM5/13/11
to software_cr...@googlegroups.com
@Matteo

I agree.
I realized that not all coding problems are good candidates for kata's. 
I wanted just to highlight that sometimes it helps to step away from code and do some thinking on paper/whiteboard.

BTW: I actually did the additional tasks of changing base...

.peter.gfader.


--
You received this message because you are subscribed to the Google Groups "software_craftsmanship" group.
To post to this group, send email to software_cr...@googlegroups.com.
To unsubscribe from this group, send email to software_craftsma...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/software_craftsmanship?hl=en.

Ron Jeffries

unread,
May 13, 2011, 6:17:58 AM5/13/11
to software_cr...@googlegroups.com
Hello, Matteo. On Friday, May 13, 2011, at 2:07:08 AM, you wrote:

> I find that this is a problem with kata that drive towards an algorithm, wrt
> katas that push me to write a maintainable solution. I don't think that
> getting folks to recognize that we're asked to convert from base-10 to
> base-13 is particularly interesting. It gets more interesting if you start
> asking yourself: can I change base? Can I change the symbols? Can I also
> support Roman numerals? Hours and angles (base-60 but with more than one
> symbol per "digit")? Babylonian? Can I support different number systems
> in the same program? Without introducing IFs?

A kata is not a free-form fight. It is an exercise to practice one
small set of things. Some of Uncle Bob's adhere more closely to this
notion than others that are out there. I prefer to solve a small
problem in a new way, rather than repeat a solution the same way
again and again.

Strictly speaking, that sort of thing, and the ones Matteo mentions
above, are not katas, despite how enjoyable and helpful they can be.
They are more of a free-form dance with the devil in the pale
moonlight. Or something.

Ron Jeffries
www.XProgramming.com
Make it real or else forget about it -- Carlos Santana

Ralf Westphal

unread,
May 13, 2011, 7:17:48 AM5/13/11
to software_craftsmanship
> I TDD because I can not yet reliably predict the perfect design for
> the problem I'm solving.

This is an important statement, Curtis. For it points at the main
difficulty of software development.
OOAD is trying to solve this, as is CRC cards, as is TDD.

I call it "the fear of the empty flipchart" :-) Developers faced with
the task of implementing some requirements stand before an empty
flipchart (or whiteboard) and need to fill it somehow. But how to
start? Which class to draw on the flipchart first? Then how to assign
methods to those classes...

For a long time - essentially 25 years, I´d say ;-) - I struggled with
this problem, too.
But then... then I changed my approach completely.

Todays it is very easy for me to design software. It just depends on
my understanding of the problem.

Take the Alpha-end Kata as an example (http://www.thycotic.com/
codetest.txt).

Here´s my problem analysis: http://ge.tt/5a7Emfe/problem%20analysis.pdf?type=download
It took me about 10-15 minutes to come up with the algorithm. (Needed
to refresh my math knowledge about logarithms ;-)

Only after understanding the problem and knowing how to solve the
problem in general, I could have started to code.
TDD would not really have helped me beyond some trivial code.

Instead, though, I did not start coding, but modelled my solution
using Flow-Design (essentially data flow diagrams).
Here´s my design: http://ge.tt/5a7Emfe/solution%20design.pdf?type=download
After understanding the problem it was pretty simple to come up with a
model. The model here is a formalization of the algorithm´s steps.
Modelling took me about 5-10 minutes.

Then I translated the model into code. This was the most boring part,
since I already knew the solution ;-) It lay right before me.
Implementation including unit and integration tests took about 45min.

Here´s the code of the conversion class. It runs flawlessly againts
the predefined kata tests: http://codepaste.net/h5pfe6
Intentionally the methods in the code are left in the order I
implemented them. This is not optimal for understanding the code, but
I wanted to demonstrate how implementation can advance without TDD, if
you have a model you´re transforming into code.

Bottom line:
a. Thinking before coding is essential. TDD does not replace
understanding the problem.
b. Implementation is so much easier without the need for refactoring -
which TDD requires. I just coded away on the model. No refactoring
needed, no mock fx needed.
c. The model is devoid of any implementation detail like classes or
loops. This makes it easy to understand. Explaining the solution with
the model in hand is much easier than showing off code and tests.


>Given this handicap, I've found TDD to be the
> best coping mechanism. When I can reliably and perfectly predict the
> optimal design, I'll probably abandon true TDD as well.

I´d argue even if you do not know the solution right away you should
not start coding using TDD.
More to the contrary! Code is much harder to change. So stay away from
coding as long as possible.
Why refactor a single line if you can shuffle around functional units
of code on a higher level of abstraction (aka a model)?

Coding should be done if and only if you´re perfectly sure what to do.
(Which does not mean you know every line of code before you write it,
but you know exactly the purpose of the method/class you´re writing.)

>
> Also, given there is no shortcut for experience, I find TDD to be the
> best way for novices and advanced beginners to learn about design and
> what makes a design good.

Again I beg to disagree. TDD is about an implementation detail: code
and platform.
Design is about, well, design, that means a map, and abstraction, a
plan.
Maps are not the terrain. So you better plan a trip using a map.


>That moment when you get a new requirement
> and you see the code in your brain and realize all you need to do is
> change this one line and the new requirement will fit right in is the
> epiphany you need to get from Advanced Beginner to Proficient, IMHO at
> least :)

I´d say it´s very hard to spot the place to change in code.
Mostly it requires digging around a lot before you know what to do.

That´s different if you´ve a model like the one I drew. Spotting the
places to change in a model is much easier. And it´s much easier to
reason about that with a group in front of a whiteboard showing the
model than looking at code.


>
> I also get the design wrong a lot because I don't really know what's
> coming next, so honing my refactoring skills seems appropriate and
> necessary.

Hm... there´s two sides to your statement:
a. You seem to thing you need to get your design right the first time.
But why? Requirements are ever changing. So your design will need to
change with new requirements. Designing does not mean doing it once
and for all. It´s an ongoing task...

Take the Alpha-end Kata again as an example. For the additional
converters for the hex/octal/binary number systems I reasoned about
the necessary changes using my understanding of the problem and the
model. It was immediately clear that conversion for a number system
depends only on 2 data items: the base and the digits. This I
visualized in the model first: http://ge.tt/5a7Emfe/solution%20design%20iteration%202.pdf?type=download

Then I reasoned about how to translate this into code. And again the
solution was obvious: make the current converter a base class.
See here: http://codepaste.net/vf4gt2

And then add converter classes for all bases, e.g. http://codepaste.net/3a2rm7

If I only had the code... how much more difficult would have reasoning
been about the necessary changes.
But with the model in hand and a simple translation of the model into
code, it took me just 11 minutes.

-Ralf

Curtis Cooley

unread,
May 13, 2011, 6:24:05 PM5/13/11
to software_cr...@googlegroups.com
I just recently went through a real world example of why refactoring
works. I was tasked with implementing a feature set, that existed in
one application, in another application. Not wanting to repeat myself,
I decided to model a framework on the whiteboard that could then be
reused in other applications.

Since I only had one real implementation, I got it mostly wrong. Not
only do I now have to rebuild the framework, I wasted a week building
it in the first place. In short, I was lazy and jumped to the
framework without at least two example implementations.

Had I been on my game, I would have hacked the feature into the new
application then refactored out the commonalities into a framework
that can be reused in the next application that requires this feature.

I tried design up front and got it terribly wrong. I wasted my time
and the company's money. No model of the two implementations would
have helped me see the common pieces, because I would have gotten the
model wrong. Only the code would have shown me the common pieces and
what could be refactored out.

You say that you don't have to get the model right the first time, so
what do you call it when you get the model a little wrong and then
have to improve the design of the existing code?

Additionally, I do not wander blindly into TDD without doing some
analysis of the problem and design of the solution. Which is why
kata's are not a great barometer of TDD's effectiveness given how a
kata is usually algorithm discovery which usually can be done on a
whiteboard.

TDD is not a silver bullet to perfect systems, but it's the best way
I've found so far to build highly maintainable, loosely couple, highly
cohesive systems. I believe that it's much more difficult to build a
tightly coupled, low cohesion system while doing TDD. As you start to
depend on more and more objects, TDD gets harder. As your class starts
to do more and more things, TDD gets harder. It has built in viscosity
that works in your favor.

After 25 years of doing this sort of thing, you have an intuition into
design that others do not. When I stare at and empty flip chart and
start to feel anxious about what to write, I can often relieve my
anxiety by writing the simplest test that fails and going from there.

> --
> You received this message because you are subscribed to the Google Groups "software_craftsmanship" group.
> To post to this group, send email to software_cr...@googlegroups.com.
> To unsubscribe from this group, send email to software_craftsma...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/software_craftsmanship?hl=en.
>
>

--

Ralf Westphal

unread,
May 14, 2011, 3:11:40 AM5/14/11
to software_craftsmanship
Hi, Curtis!

On 14 Mai, 00:24, Curtis Cooley <curtis.coo...@gmail.com> wrote:
> I just recently went through a real world example of why refactoring
> works.

Please get me right: I´m not denying the value or the necessity of
refactoring if you´re already wading through a brownfield.


> I tried design up front and got it terribly wrong. I wasted my time
> and the company's money. No model of the two implementations would
> have helped me see the common pieces, because I would have gotten the
> model wrong. Only the code would have shown me the common pieces and
> what could be refactored out.

Hm... my guess is, you´re mixing up two things here.
You´re blaming your modelling for your failure. But it wasn´t
modelling that made things go wrong.
Rather it was your assumption you were already able to come up with a
framework.
That´s a whole different reason.

Modelling is not there to save you from false assumptions or not
understanding the problem.
I could not have designed the model for a framework if I had solved
the problem just once, either.


>
> You say that you don't have to get the model right the first time, so
> what do you call it when you get the model a little wrong and then
> have to improve the design of the existing code?

I call it "change" or "refactoring" if you will. But it´s refactoring
of a model first.
So, yes, refactoring is needed as you improve your understanding of a
problem or extend a solution.
But this mostly happens within the model, not within the code.

With the sample I´ve given (alpha-end kata) this might not be obvious.
I translated the model to methods.
But that was just for simplicity´s sake and because it was an
algorithmic problem.

Still, though, you sure will agree the methods are very small. So if
changes are needed, not much refactoring can even take place. What do
you want to extract from a 3 line method to go into another class?

Again: I´m not saying refactoring is not needed. I just claim (code)
refactoring is the wrong tool to arrive at a design. Don´t use code
refactoring to plan (!) software.

This is not BDUF I´m talking about. No, I´m thinking very short
iterations each starting with a "thinking phase" aka design.
Model a little, code a little...


>
> Additionally, I do not wander blindly into TDD without doing some
> analysis of the problem and design of the solution.

I´d love to hear from you how you do your design. Can you tell more
about it?


>Which is why
> kata's are not a great barometer of TDD's effectiveness given how a
> kata is usually algorithm discovery which usually can be done on a
> whiteboard.

So if katas are not the problem size where TDD shines - although only
algorithmic katas are used throughout the community to get people
started on TDD -, what size problems show TDD´s effectiveness and
efficiency to design (!) software.

Would you feel more comfortable to start an invoicing application
using TDD?
You´d open your IDE of choice and create a test first to get a handle
on the problem?


>
> TDD is not a silver bullet to perfect systems, but it's the best way
> I've found so far to build highly maintainable, loosely couple, highly
> cohesive systems.

I believe you, no doubt. You must be frustrated with the
ineffectiveness of OOAD or the lack of design guidance your software
development education gave you.
But I´m sure we as an industry can do better than TDD to come up with
designs for code.


>I believe that it's much more difficult to build a
> tightly coupled, low cohesion system while doing TDD.

I agree: it´s more difficult - but compared to what? Compared to OOAD,
CRC, or whatever you call your "homegrown OO design approach"?
Yes, TDD is more effective because while doing TDD you´re not even
thinking in terms of objects. Rather you´re thinking in terms of
functionality, you´re focussing on verbs, actions.

Take the alpa-end kata for example again. You start by focussing on
Converter.Convert(). A single function, an action. Then you might do
the simplest possible thing:

string Convert(int n10)
{
return "5";
}

And then... You need to step up from 1 digit numbers to multi digit
numbers. So you think hard what can be done (!) next.
Maybe you come up with this:

string Convert(int n10)
{
string nBase13;
if (n10 > 12) then nBase13 += "1";
nBase13 += MapDigit(n10-13);
return nBase13;
}

This would satisfy the test:

Assert.AreEqual("17", c.Convert(20));

And so on... You´re focussing on actions. That´s great!

But you see: now you are forced to refactor. You need to shuffle code
around.
That´s effort you don´t have to go thru, if you model your solution
first.
TDD essentially is wasting the customers money because, well, changing
code is always harder than changing lines on a whiteboard.

Yes, "bubbles don´t crash" - but that´s an advantage. You´re much more
free to design code with bubbles than without.

The question is, however, which bubbles to use for modelling :-)
My conclusion after many years of trying to do it like the OOAD (or
even DDD) guys are saying: the "look for classes approach" is plain
ineffective and inefficient.
It´s a waste of time, it´s frustrating, it´s only occaissonally
leading to systems living up to clean code principles.

So I can perfectly well understand you´re so inclined to get your
hands on a keyboard and work with code.
Mainstream design approaches simply don´t deliver on their promises.

But they are not the end of it. Neither is TDD. TDD - to me - just is
a reaction to the frustration OOAD brought about.
The pendulum is winging back from bubbles to code.
But in the end... we´ve to take code for what code is: just code. A
clumsy necessity to deliver value to our customers.
Code is the material from which we build software skyscrapers.

But how to arrange the material? That should not be determined by just
trial and error at code level. We´d be not better than medieval masons
- which undoubtedly did marvellous things, but would not have been
able to build the Empire State Building or the SF Bay Bridge or the
Sydney Opera.

Code is just an implementation detail ;-)
If we´re making more of it we´re violating the basic Separation of
Concerns principle.

So the question remains: How to design code? By coding? No, I don´t
think so. Thinking (and modelling) are much more powerful and
efficient.
Again: I did not need to refactor a single line during implementation
of the alpha-end kata.
Coding was straightforward and boring.

And my understanding of the problem would not have been better if I
had started right away with TDD.
Right to the contrary! Understanding is a different mental process
then coding. So I´d say understanding would have been hampered if I
had mixed it with coding.
TDD is multitasking. And multitasking - as we´ve come to know - is
bad.


>As you start to
> depend on more and more objects, TDD gets harder. As your class starts
> to do more and more things, TDD gets harder. It has built in viscosity
> that works in your favor.

That´s true. So you´re literally forced to refactor, which is a good
think if you did not know what to do in the first place.
But why not use our brains a little more?

My guess is: people jump to TDD because they are lacking mental tools
to tackle a problem otherwise.
If you don´t know anything about compilers you´d probably start by
TDDing like this for a math expression compiler:

Func<double, double> Compile(string expression)
{
return x => return 1;
}
...
Assert.AreEqual(1, c.Compile("1")(1));

And then?

But with some compiler theory, ie. a model of how compilers look, you
´d first come up with a grammar, which is a model. And you then would
mechanically translate this grammar into code, and the code would be
split at least into three disctinct and canonical functional units:
scanner, parser, code generator. All else would be stupid (except for
using ANTLR or Coco/R ;-)

So a little theory, a small basket of thinking/modelling tools goes a
long way.
Math is a thinking tool, state machines are a thinking tool - and flow-
design is a thinking tool.
No, object orientation - to me - is no thinking tool; we´ve tried that
for 20 years now and the results are desastrous.
(That´s a critique of OOAD, not OO languages like C# or Java.)


>
> After 25 years of doing this sort of thing, you have an intuition into
> design that others do not. When I stare at and empty flip chart and
> start to feel anxious about what to write, I can often relieve my
> anxiety by writing the simplest test that fails and going from there.

Sure I have more of an intuition than a freshman. But still every
problem is as new to me as to a freshman.
Solving alpha-end was not about intuition. Some math helped me, for
sure. But designing the solution, drawing the model, had not much to
do with intuition.

But I can understand that you find relieve in writing some code. I
understand that very well.
The purpose of coding, though, is not bringing relieve. I don´t want a
musician get on stage to relieve herself. I want her to perform at her
best for me and all the others in the audience. I don´t want her to
practice and try out new stuff on stage, either.

So to relieve your coding anxiety (which essentially stems from not
understanding the problem enough) write some code - but don´t call it
production code. Call it a spike. XP did much good by bringing spike
solutions to the industries consciousness.

And then, after you improved your understanding of the problem enough,
go back to modelling ;-) And after modelling your solution on the
basis of your spike-improved understanding go back to coding; but now
it´s production code whose structure you arrive at by translating the
model. You should feel relaxed or even bored when writing production
code.

Solving problems, tackling challenges, overcoming lack of
understanding all should not be done while writing production code.
This also is a fundamental separation of concerns.

Learning and relieving anxiety is different from delivering value to a
customer.

Explicit modelling and spike solutions are powerful means to separate
those concerns within your software production process.

-Ralf

Ron Jeffries

unread,
May 14, 2011, 4:52:18 AM5/14/11
to software_cr...@googlegroups.com
Hello, Ralf. On Saturday, May 14, 2011, at 3:11:40 AM, you wrote:

> I call it "change" or "refactoring" if you will. But it�s refactoring
> of a model first.
> So, yes, refactoring is needed as you improve your understanding of a
> problem or extend a solution.
> But this mostly happens within the model, not within the code.

I'm going to offer here a different way of looking at the model /
code question than seems to be in your text.

What seems to be missing in the above is that the code /is/ a model.
In fact it is the /only/ model that completely represents the code.

To be useful, a model, including the code, has to represent
something (I'll just say "something") that we want to think about.
Sometimes a drawing or some other form is easier, for some people,
to think about.

> With the sample I�ve given (alpha-end kata) this might not be obvious.
> I translated the model to methods.
> But that was just for simplicity�s sake and because it was an
> algorithmic problem.

I don't understand what you're saying here. It sounds to me as if
you are saying the model is real and the methods are not. The
opposite is the case. The program is what we want, the model is a
means to the program.

Can it be easier, for some people, at some times, to think in terms
of another model? Yes. Does that make it best for them or for
everyone? That's not so clear.

> Still, though, you sure will agree the methods are very small. So if
> changes are needed, not much refactoring can even take place. What do
> you want to extract from a 3 line method to go into another class?

If the program wants the other class,and we pay attention to it, it
will tell us so. If we have an idea in our head, we can put it into
the code, or extract it from the code, as seems best. If we do not
have an idea in our head, it doesn't matter what form of modeling we
use.

It is possible that thinking in some other "format" will help some
people, sometimes, get a new and better idea.

> Again: I�m not saying refactoring is not needed. I just claim (code)
> refactoring is the wrong tool to arrive at a design. Don�t use code
> refactoring to plan (!) software.

I think you're saying that for you, sometimes, you do not reach a
good design using code and refactoring. I can understand that. I can
identify with it. And yet your conclusions, "wrong" and "don't",
seem to me not to follow.

> This is not BDUF I�m talking about. No, I�m thinking very short
> iterations each starting with a "thinking phase" aka design.
> Model a little, code a little...

No one is opposed to thinking, as far as I know. Personally, I would
not think it ideal to think sometimes and then code sometimes, as
the words above suggest. It seems to me to be better to be thinking
about design all the time.

The code /is/ a model. The code is /the/ model. I find many ways of
thinking to be useful, cards, pictures, text. Of them all, I find
the code to be particularly useful, in the sense that it represents
what actually is.

I understand that it can be difficult to look at what is and think
about what ought to be. I would suggest that that's not some
inherent difference between "code" and "model", because there is no
inherent difference between "code" and "model".

What you have discovered, I suggest, is something about your own
mental skills, abilities, preferences, not something about the
universe. That's the good news. We can do something about ourselves,
adjusting and changing our skills. The universe seems not so ready
to accommodate.

For me, I find that more and more I can work in the code and get
from one design to another, often quite different (and often much
better). And I can think about the code / design / model in other
ways with my fingers still on the keyboard. That's useful, because
it tends to keep my program always working as its design improves.

And sometimes, I still like to take a few minutes and draw a
picture. I think that's about me, not about the reality of pictures
and code.

Ron Jeffries
www.XProgramming.com
Know what I pray for? The strength to change what I can, the inability to
accept what I can't and the incapacity to tell the difference. --Calvin and Hobbes

Ralf Westphal

unread,
May 14, 2011, 8:04:07 AM5/14/11
to software_craftsmanship
Hi, Ron,

thanks for bringing this up:

On 14 Mai, 10:52, Ron Jeffries <ronjeffr...@acm.org> wrote:

> What seems to be missing in the above is that the code /is/ a model.
> In fact it is the /only/ model that completely represents the code.

and again here

> The code /is/ a model. The code is /the/ model. I find many ways of
> thinking to be useful, cards, pictures, text. Of them all, I find
> the code to be particularly useful, in the sense that it represents
> what actually is.

It has been pointed out several times in the past 15 years or so that
"the code is the design".
This was helpful in distinguishing software development from
construction work etc. We now know why some analogies fail - at least
partly.

But why be content with this? Why think this is it, now? Nothing more
to say about code and design.

If you look at design in a general way, then you probably can agree
with the following:

"Stuff" consists of "material". How the "material" is arranged into
"stuff" depends on requirements.
Design is the description of how to arrange "material" on a higher
level of abstraction. You won´t find mentioning of pieces of
"material" in designs.

Example architectural blueprint: There are no bricks, no window panes,
not shingles in a blueprint. A blueprint is just a high level
framework according to which later on individual pieces of building
material are arranged.

If descriptions of arrangements become more precise/detailed they are
not called design anymore, but plan.

So what about design in software?

Sure, source code is a description of an arrangement for machine code,
and does not contain machine code itself.
Source code thus is some kind of design (not a plan).
And a compiler is the "mason of software development" ;-) who reads
the design to concretely arrange op code "material according to the
design to deliver functional software "stuff".

We are agreeing on that, I guess.

However, I beg to disagree if someone says, that´s it with design in
software. Because this leaves out the purpose of design in general.

If I know how to arrange material into a solution, I´ll do that right
away. No design needed. And if there´s much to do, I hire some help.
If the "stuff" I intend to produce is somewhat big or I need to work
with helpers, I step up a level and make a plan.
And if the "stuff" is even bigger and/or I don´t really know how the
arrangement of "material" should be in detail to fulfill the
requirements... I step up another level and start desiging.

Whether or not to design thus is a matter of complexity.
That means: if source code becomes complex... I better design it
explicitly.
And that means in turn, I use a representation on a higher level of
abstraction.

TDD thus almost is an oxymoron, I´d say, because if combines the
"material" whose arrangement is complicated (or even complex), and
designing.
"Material" and design exist on different levels of abstractions. That
´s the purpose of design.
So designing for "material" by using "material" should not really be
the way to go.

Bottom line: Since source code usually is complicated is deserves a
design. This does not contradict the notion of source code being
design itself.
The design I´m referring to is on a higher level: a design for a
design, if you like.

So what you call a personal discovery I´d call a position based on
principles and fundamental concepts and basic terminology.

Of course I´d be happy to hear your view on why further design that
writing source code is not necessary in software development.
Unfortunately Wikipedia say about design (http://en.wikipedia.org/wiki/
Design): "No generally-accepted definition of “design” exists"
So maybe you want to relate your arguments to my above ad hoc
definition.


>
> No one is opposed to thinking, as far as I know. Personally, I would
> not think it ideal to think sometimes and then code sometimes, as
> the words above suggest. It seems to me to be better to be thinking
> about design all the time.
>

Hm... "no one is opposed to thinking" is not the reality in the shops
I visit for consulting or when I participate in a coding dojo.
Maybe there is no opposition to thinking before coding - but this does
not show in the process of software development.
On a regular basis teams have a very hard time to not talk in terms of
implementation details about a solution.
They mostly lack shared concepts, methodology, and terminology to do
other than code (and maybe draw a class diagram).

-Ralf

philip schwarz

unread,
May 14, 2011, 8:55:54 AM5/14/11
to software_craftsmanship
@Peter Gfader

You said: "I wouldn't say that I find TDD overrated, but I agree, it
is good to step
back and think about the problem a bit more before starting to hack
away... "

This made me think of the following twitter exchange I saw back in
December 2010:

KentBeck: gave up developing a complicated fsm test-by-test. at some
point i just needed to see the whole picture at once.
RonJeffries: @KentBeck FSMs hard test by test. i always draw the
picture first. i figure no one will hurt me for a few minutes'
planning
KevlinHenney: @KentBeck Why are these two things (focusing on detail
and seeing the whole thing) considered contradictory?
jamesshore: @RonJeffries Infidel!
RonJeffries: @jamesshore i am not an infidel. i believe me. see XP
Installed, "Quick Design Session". LOL
RonJeffries: @jamesshore if i had it to do all over again, i'd start a
religion. worked for Hubbard :)
kaleidic: An edge of TDD is nicely indicated by Kent Beck's note, "at
some point I just needed to see the whole picture at once."
RonJeffries: @kaleidic yes. one does need to see the whole program at
times. TDD can be useful for that, with programming by intention ...
RonJeffries: @kaleidic but that does not cover all issues.
KentBeck: @coreyhaines yep. i tried to draw the fsm first, gave up &
started tdd, then gave up & drew the picture. more tdd is next.
KentBeck: @KevlinHenney for me in this case they are informing each
other as i go back and forth.
KevlinHenney: @KentBeck Yup, that's how I see it. Without cycle
between the two, the development/growth may be skewed, faltering or
otherwise unhealthy.

Philip

On May 13, 3:06 am, Peter Gfader <pe...@gfader.com> wrote:
> >>I find TDD overrated because it puts refactoring on a pedestal: red -green
>
> - refactor.
>
> I wouldn't say that I find TDD overrated, but I agree, it is good to step
> back and think about the problem a bit more before starting to hack away...
>
> < personal experience >
> I did the "alpha-end converter" kata in TDD manner. Description of the
> coding problem herehttp://www.thycotic.com/codetest.txt
>
> During doing this Kata I got into this "brute force coding" mode, where I
> didn't think too much, but I just wanted to get the test to green. It took
> me a while to get over this hurdle and I couldn't solve the kata in that 1
> hour session...
>
> This annoyed me a lot, so I stepped back, thought about the problem on paper
> for a couple of minutes and had the solution there...
> </ personal experience >
>
> A friend of mine had the same experience and he suggested me the "Call the
> shots" technique for beating this. More on his bloghttp://www.davesquared.net/2010/08/calling-your-shots.html
>
> *Note: By working in pairs that problem wouldn't probably happen, because
> the observer is already focused about what should happen while the other one
> is typing.*
>
> What is your experience doing TDD?
>
> .peter.gfader.http://blog.gfader.com
> > curtis.coo...@gmail.com

Ralf Westphal

unread,
May 14, 2011, 9:35:35 AM5/14/11
to software_craftsmanship
Thanks, Philip, for this:

On 14 Mai, 14:55, philip schwarz
<philip.johann.schw...@googlemail.com> wrote:

> KevlinHenney: @KentBeck Yup, that's how I see it. Without cycle
> between the two, the development/growth may be skewed, faltering or
> otherwise unhealthy.
>

I can only wholeheartedly agree.
You should consciously switch between the two modes designing and
implementing.
Design a little, code a little.

But that to me also means: coding is not (!) designing - with regard
to source code. Coding is translating a design for source code into
source code.

Likewise is compiling the translation of source code as design for
machine code into machine code.

Designing is working on the level of the big picture.
And I don´t get how TDD can be designing in that regard, since you´re
immersed in source code.

TDD is explicitly not about the big picture. It is doing small steps
without much looking ahead, like cautiously walking through thick fog.

-Ralf

philip schwarz

unread,
May 14, 2011, 9:49:38 AM5/14/11
to software_craftsmanship
@Ralf Westphal

You said: "refactoring should be avoided altogether if possible."

So you want be signing http://refactoringmanifesto.org any time
soon ;-)

Philip

philip schwarz

unread,
May 14, 2011, 3:32:00 PM5/14/11
to software_craftsmanship
@Ralf Westphal

You said: "TDD is multitasking. And multitasking - as we´ve come to
know - is
bad."

"From Wikipedia's definition of multitasking: An example of
multitasking is listening to a radio interview while typing an email.
Some believe that multitasking can result in time wasted due to human
context switching and apparently causing more errors due to
insufficient attention."

In his afterword to Kent Beck's 'Test Driven Development by Example',
Martin Fowler explores the idea that the switching done in TDD
increases focus, lowers stress, and reduces monotony. Here is the gist
of Fowler's idea (I have turned excerpts of his afterword into bullet
points):

1. Programming is hard.

2. It sometimes feels like trying to keep several balls in the air at
once: any lapse of concentration and everything comes tumbling down.

3. TDD helps reduce this feeling, and results in rapid unhurriedness
(really fast progress despite feeling unhurried). This is because
working in a TDD development style gives you the sense of keeping just
one ball in the air at once, so you can concentrate on that ball
properly and do a really good job with it.

4. When you are trying to add some new functionality, you are not
worried about what really makes a good design for this piece of
function, you are just trying to get a test to pass as easily as
possible.

5. When you switch to refactoring mode, you are not worried about
adding some new function, you are just worried about getting the right
design.

6. With both of these activities, you are just focused on one thing at
a time, and as a result you can concentrate better on that one thing.

7. Adding features test-first and refactoring, are two monological
flavours of programming.

8. A large part of making activities systematic is identifying core
tasks and allowing us to concentrate on only one at a time.

9. An assembly line is a mind-numbing example of this - mind numbing
because you always do the one thing.

10. Perhaps what test-driven development suggests is a way of breaking
apart the act of programming into elemental modes, but avoiding the
monotony by switching rapidly between those modes.

11. The combination of monological modes and switching gives you the
benefits of focus and lowers the stress on the brain without the
monotony of the assembly line.

Philip
> model. You should feel ...
>
> read more »

Ron Jeffries

unread,
May 14, 2011, 4:12:35 PM5/14/11
to software_cr...@googlegroups.com
Hello, Ralf. On Saturday, May 14, 2011, at 6:35:35 AM, you wrote:

> But that to me also means: coding is not (!) designing - with regard
> to source code. Coding is translating a design for source code into
> source code.

Honestly, even if all you can do when writing code is translate an
existing design, that does not imply that is all that anyone can do.

Naturally the design we move to has to be in our head ... at least
somewhat. But for god's sake sit down with any good refactoring
person and watch what they do. They can evolve the design all over
without turning to some other form of "design".

Ron Jeffries
www.XProgramming.com
Ron gave me a good suggestion once. -- Carlton (banshee858)

Ron Jeffries

unread,
May 14, 2011, 4:34:17 PM5/14/11
to software_cr...@googlegroups.com
Hello, Ralf. On Saturday, May 14, 2011, at 5:04:07 AM, you wrote:

> Hm... "no one is opposed to thinking" is not the reality in the shops
> I visit for consulting or when I participate in a coding dojo.
> Maybe there is no opposition to thinking before coding - but this does
> not show in the process of software development.

You are supposed to learn to think while you code. It seems that may
be the element that has eluded you so far.

> On a regular basis teams have a very hard time to not talk in terms of
> implementation details about a solution.

I don't have that difficulty. And I can talk about design by showing
code or by other means. So I know it is possible. You speak as if it
isn't. But it's not impossible if people can do it.

> They mostly lack shared concepts, methodology, and terminology to do
> other than code (and maybe draw a class diagram).

They, who? Some people you know? I'm not sure who "they" is in this
sentence.

Ron Jeffries
www.XProgramming.com
Knowledge must come through action;
you can have no test which is not fanciful,
save by trial. -- Sophocles

J. B. Rainsberger

unread,
May 14, 2011, 9:56:48 PM5/14/11
to software_cr...@googlegroups.com

I use one in my courses that I haven't written up yet. Maybe I should.
Removing duplication leads to a structure emerging, then improving
names leads to moving responsibilities to more sensible places.
--
J. B. (Joe) Rainsberger :: http://www.jbrains.ca ::
http://blog.thecodewhisperer.com
Diaspar Software Services :: http://www.diasparsoftware.com
Author, JUnit Recipes
2005 Gordon Pask Award for contribution to Agile practice :: Agile
2010: Learn. Practice. Explore.

J. B. Rainsberger

unread,
May 14, 2011, 10:03:28 PM5/14/11
to software_cr...@googlegroups.com
On Tue, May 10, 2011 at 12:58, Matteo Vaccari <matteo....@gmail.com> wrote:

> I expect JB Reinsberger would point out that if you *really* do the
> "refactor to remove duplication" step, you will end up separating
> responsibilities.  So yes, in fact you are right; when I'm facilitating a
> dojo I often have to point out that until you remove all duplication you
> should not write the next test.

In problems that want MVC-style solutions, I find that removing
duplication creates the classes to which reponsibilities will
eventually move, but improving names helps identify which
responsibilities should move where.

J. B. Rainsberger

unread,
May 14, 2011, 10:11:53 PM5/14/11
to software_cr...@googlegroups.com
On Sat, May 14, 2011 at 19:32, philip schwarz
<philip.joh...@googlemail.com> wrote:
> @Ralf Westphal
>
> You said: "TDD is multitasking. And multitasking - as we´ve come to
> know - is
> bad."

I don't find this pattern to match the definition of "multitasking".

0. Write out a list of things you might do.
1. Decide what to do next.
2. Do it. If, in the process, something jumps into your mind that
doesn't help with the current task, then write it down.
3. Go to 1.

I believe this is "Getting Things Done". It's also TDD.

J. B. Rainsberger

unread,
May 14, 2011, 10:16:14 PM5/14/11
to software_cr...@googlegroups.com
On Sat, May 14, 2011 at 12:04, Ralf Westphal <in...@ralfw.de> wrote:

> Hm... "no one is opposed to thinking" is not the reality in the shops
> I visit for consulting or when I participate in a coding dojo.
> Maybe there is no opposition to thinking before coding - but this does
> not show in the process of software development.
> On a regular basis teams have a very hard time to not talk in terms of
> implementation details about a solution.
> They mostly lack shared concepts, methodology, and terminology to do
> other than code (and maybe draw a class diagram).

This sounds really frustrating, Ralf, and I understand why it would
get you down. I recently spent time with a group of well-meaning
programmers whose code made it look like it was written in 2000, just
judging by their use of the language. In that situation, TDD seems
years away.

When I started practising test-first programming -- even before my
tests really drove my design -- I spent about 1 year before I felt
that I really began thinking of code in terms of input/output rather
than algorithms and implementation details. I spent that 1 year
practising an average of 4 hours/day. That means 1,000 hours of
practice. Do you think the teams with whom you consult consist of
people who have practised 1,000 hours yet?

It's not easy, it takes time, and we must have patience if we want to
see people improve.

Ralf Westphal

unread,
May 15, 2011, 1:41:26 AM5/15/11
to software_craftsmanship
On 14 Mai, 15:49, philip schwarz
<philip.johann.schw...@googlemail.com> wrote:
> @Ralf Westphal
>
> You said: "refactoring should be avoided altogether if possible."
>
> So you want be signinghttp://refactoringmanifesto.organy time
> soon ;-)
>
> Philip
>

Yes, refactoring is an activity which does not add customer value by
itself.
It's definition says, you must not change functionality while
refactoring.

Thus refactoring should be avoided - unless it is necessary to make
adding functionality aka customer value easier.

If I can come up with evolvable code without refactoring I think
that's better than being forced to go thru refactoring steps first. I
hope we can agree on that.

If so, then we can go on to discuss the more interesting question: how
to arrive at clean code right away? (Sure I'm talking greenfield code
here. But thats difficult enough for a start.)

People advocating TDD seem to be saying: that's (almost) impossible;
you can't sit down an write clean code just like that. For a given
requirement you need to approach an evolvable structure thru
refactoring. You cannot know it before you have started to code.

As much as I like writing code test first, I nevertheless contest the
notion of "you need to go thru refactorings to find an appropriate
structure."

-Ralf

Ralf Westphal

unread,
May 15, 2011, 2:17:05 AM5/15/11
to software_craftsmanship
On 14 Mai, 21:32, philip schwarz
<philip.johann.schw...@googlemail.com> wrote:
> 10. Perhaps what test-driven development suggests is a way of breaking
> apart the act of programming into elemental modes, but avoiding the
> monotony by switching rapidly between those modes.

I'm all in favor of focus. That's why I'm saying: focus on getting the
code right while coding.
Slinging code by itself is difficult enough. So you should start doing
it with the addition burden of finding evolvable structures on your
shoulders.

Sure, whatever structures are below the radar of prio modelling need
to be defined while coding.
But since code is comparatively hard to change you want the explicit
modelling radar to cover as much ground as possible.

I some guru programmer can do without, that's fine. But as you cited
even Kent Beck found it difficult to arrive at a solution just doing
TDD.

Structure code in an evolvable way as much as possible on a
whiteboard. Postpone coding. Make coding a no brainer.

Design work done on a whiteboard is not only easier (bubbles dont
crash, drawings are easier to change than code), it also allows more
team members to participate. That increases the likelihood of good
design. That increases the understanding of structures by more people.

Again: coding is no virtue, but a necessary evil in order to satisfy
customers with software. I guess we can agree on that, because we're
constantly seeking relieve from coding thru compilers, DSL, or some
other form of code generators.

So why make coding more difficult by mixing it with "structure
finding"?

To me there are two reasons:

1. addiction to code: writing code is so satisfying personally, that
developers seek out ways to keep doing it (on a level matching the
current culture; today that's 3GL, but formerly they were happy with
assembler and opposed higher level languages).

2. lack of an idea of how otherwise evolvable structures could be
found before coding. Take a pol at your average developer conference:
how many of the attendees are using UML? how many of those are using
more than class diagrams and sequenz diagrams?

I've done this poll several times in my talks at conferences in
Europe. The results are roughly: 15% doing UML, 5% using more than
those two diagrams.

Naturally TDD, an all code approach, must appeal to the 85% of
developers not using the #1 world wide standard for designing
software.

But does that really show the validity of TDD as a successor to
explicit design? Or is it a sign of failure of UML?

I indulge in thinking the latter - an am on a quest for easier
modelling tools, modelling tools for the masses, so to speak. Because,
as said above, code is hard to change, and refactoring does not add
value, and "structure finding" and "code instruction finding" are so
different, they should not be mixed.

-Ralf

Ralf Westphal

unread,
May 15, 2011, 2:28:36 AM5/15/11
to software_craftsmanship
> Naturally the design we move to has to be in our head ... at least
> somewhat. But for god's sake sit down with any good refactoring
> person and watch what they do. They can evolve the design all over
> without turning to some other form of "design".

Sure, very good developers might be able to do that.
But then, there exist people who can calculate the square root of
numbers with 10 digits in their head.
Or there are painters who can do whole wall paintings without
sketching first.

These are marvellous feats - but I doubt we should expect them from
average developers.
I at least know not a single developer who posesses the capability
you're describing. (hm, on second thought, maybe I know 2.)

You might attribute that to the culture and education of the .Net
community; poor slobs having to work with Microsoft trash. Or you
might say, that's the deplorable state of the are in far away Germany.
But to be honest, on my trips to England or the US doing conference
talks I haven't found that much of a difference between developer
communities/cultures.

But I'm happy for you that you're working in environments where such
capabilities are common.

-Ron


>
> Ron Jeffrieswww.XProgramming.com

J. B. Rainsberger

unread,
May 15, 2011, 5:04:02 AM5/15/11
to software_cr...@googlegroups.com
Ralf Westphal wrote:

> Yes, refactoring is an activity which does not add customer value by
> itself.
> It's definition says, you must not change functionality while
> refactoring.
>
> Thus refactoring should be avoided - unless it is necessary to make
> adding functionality aka customer value easier.

This sounds to me like saying "you should avoid exercise, unless it is
necessary for you to keep your metabolism efficient enough to burn
excess fat and avoid heart disease". While strictly true, the condition
is so close to universally true that stating it explicitly in most
contexts obscures the truth, rather than helps to reveal it.

I prefer to say "the point of exercise is to increase one's metabolic
efficiency in order to burn excess fat and avoid heart disease", which
is the same statement made in a way that doesn't risk misleading the reader.

Similarly, the point of refactoring is to simplify the design to reduce
the marginal cost of features and to stop the cost of delivering a given
feature from rising quickly over time.

Refactoring /done well and for a sensible purpose/ adds customer value
that most customers with whom I work have difficulty seeing and
therefore that I have learned to articulate clearly.

I don't know many things that, /not/ done well nor for a sensible
purpose, help a business realise more profit, so don't do any of those
things.
--
J. B. Rainsberger :: http://www.jbrains.ca ::
http://www.thecodewhisperer.com

Ron Jeffries

unread,
May 15, 2011, 6:06:49 AM5/15/11
to software_cr...@googlegroups.com
Hello, Ralf. On Saturday, May 14, 2011, at 11:28:36 PM, you wrote:

>> Naturally the design we move to has to be in our head ... at least
>> somewhat. But for god's sake sit down with any good refactoring
>> person and watch what they do. They can evolve the design all over
>> without turning to some other form of "design".
>
> Sure, very good developers might be able to do that.

Yes. I would argue that the ability to do that is one of the marks
of a good developer. Why you are arguing against being a good
developer concerns me.

You seem to have conveniently forgotten that in my notes on this
thread I have said repeatedly that other ways of thinking about the
design are just fine, and that the ability to think about the design
while coding has particular value.

You have then argued that thinking about the design while coding is
impossible -- but it is not.

You have then argued that all multi-tasking is bad -- but it is not
-- and that thinking about design while coding is bad -- but it is
not.

You are now arguing that the ability to think about the design while
coding is something that only a genius or an autistic can do -- but
it is not.

The ability to think about design while coding is a valuable skill
which is readily improved by practice doing it. If one were to
trouble oneself to watch people doing it, one would see that they
interweave design considerations and code in quite a fine-grained
fashion, so that the result is that the design they have does not
deviate from one they want by very far at any time, while
maintaining the enviable situation that they always have a program
that actually, testably works.

Your ideal seems to be a good design which is "evolvable". I take
that to mean, a good design that supports the next things one plans
to do: a design which is always ready to receive the changes we want
to make to the program (and therefore the design).

History has placed before you a new way to do that, called TDD,
embodying producing tests that keep the program working and growing
in functionality, with refactoring, techniques that evolve the
program's design smoothly whenever we discover, by any means, that
it needs improving.

TDD plus refactoring exists. Normal people can do it. It requires
deep skill, as does good programming and design no matter how we do
it. Unlike up-front work, which is always insufficient, TDD plus
refactoring allows us to apply what we learn, when we learn it.

The alternatives to TDD are dark and dire. We can

- try to think of everything important up front.
this is doomed to failure, and even if it were not, it delays
the delivery of any value until we have thought of everything.

- discover design ideas later and put them in the next program.
this is not helpful. we need for our design ideas to go into the
current program, not some future one.

- discover design ideas later and put them in without tests and
without refactoring.
this is very difficult and risky. we tend to break programs that
are not well supported by tests, and we tend to break designs
when we do not use function-preserving transformations.

TDD/Refactoring just happens to be better than all the known
alternatives. It allows us to produce value quickly and safely, and
to make sure that all our best design ideas are in the code.


Now then. When we set out to learn to do this valuable thing,
//one// good approach is to work almost entirely with the code in
front of us. (And, surely, to work together with someone else to
talk with.) Doing this is difficult. We feel the need to take a
break, to draw a picture, to do some CRC cards, for god's sake just
to get a chance to THINK!

Of course we feel those things. We are pushing ourselves to learn,
just as we might push ourselves to lift that weight one more time,
to ride that bike just a bit further.

We do that "in the lab", in trying to learn this powerful new
technique. Our pair helps us do this, because we learn to speak
about our design (yet another way of representing the idea), and we
learn to let them drive while we pay attention but think as well.

Even in a TDD/Refactoring exercise, of course, we might well draw a
picture or do some other form of design, or we might just rest.
That's fine. If you ever work in a code-fest where you build the
same program, again and again, with different pairs, you'll find
that ideas from the last time around will pervade the next time.
That's fine, too. Part of the learning is that an idea we had an
hour ago can go into the code now. Part of the learning should be
that the code we get is not all that different from the code we had
at the moment we had the idea ... and therefore we could have moved
the code to support that idea then ... without the rewrite.

All this is learning. It strengthens our ability to support code
with tests, and to evolve it smoothly without disruptive rewrites.
These are valuable things to be able to do.

> But then, there exist people who can calculate the square root of
> numbers with 10 digits in their head.

Yes. And there are perfectly normal people who can do arithmetic
more rapidly and accurately than we can, using techniques that are
easy to learn and apply with practice.

> Or there are painters who can do whole wall paintings without
> sketching first.

Yes. And there are perfectly normal people who can visualize enough
of a wall painting in their head to get started, and who can work on
details in such a way as to produce such a thing without either
being a genius or otherwise mentally bizarre. They have one thing
that we do not have ... hours and hours of practice.

> You might attribute that to the culture and education of the .Net
> community; poor slobs having to work with Microsoft trash. Or you
> might say, that's the deplorable state of the are in far away Germany.
> But to be honest, on my trips to England or the US doing conference
> talks I haven't found that much of a difference between developer
> communities/cultures.

I attribute it, primarily, to people not doing the work, instead
denying the value of that skill, or its ability to be grasped by
ordinary people. No doubt at some past time, the ability to add a
few numbers together seemed like magic. It wasn't. It was a matter
of attaining some elementary skills, and practice.

The thing we call "model" is not a UML diagram (a standard which, by
your accounting, most people do not use, suggesting, perhaps that it
isn't all that good but I digress ...

A model is not a diagram in some particular form. A model is an idea
in our head, which we get there, and manipulate there, using some
physical means such as UML, hand-waving, CRC, or any other means.

One way -- just one way -- of modeling our ideas is in code. This
particular way has the property that it is the only model that we
/must/ produce if we are going to get a program working on the
computer.

The better able we are to produce that particular unique model
incrementally, the faster we can deliver value. But if we do produce
it incrementally, we will surely make design discoveries //no matter
how much up front work we do//. Therefore there is value to
producing that code so that it is strongly supported by tests, and
there is value to knowing how to smoothly improve the design of code
so that we can put in our new design ideas safely at any time.

We can still get design ideas any way we want to, with diagrams, arm
flapping or through the creative use of song. We have to be able to
put them into our programs or those ideas will not be of value.

The best known way to produce code that supports our new design
ideas is TDD/Refactoring, and the best way to get code like that is
to practice TDD/Refactoring until we are good at it.

> But I'm happy for you that you're working in environments where such
> capabilities are common.

I do not work in "environments" where such capabilities are
"common". I work with people who value the ability to program
better, more effectively, more smoothly, and with increasing skill.

Anyone can do those things ... unless they do not try.

If we dismiss the observations of people who have been down the
journey before us, we're going to get lost in all the same dead
ends. That can be a lot of fun ... but we might be able to do
better.

Ron Jeffries
www.XProgramming.com
No one expects the Spanish Inquisition ...

Ron Jeffries

unread,
May 15, 2011, 6:34:41 AM5/15/11
to software_cr...@googlegroups.com
Hello, Ralf. On Saturday, May 14, 2011, at 11:17:05 PM, you wrote:

> I'm all in favor of focus. That's why I'm saying: focus on getting the
> code right while coding.
> Slinging code by itself is difficult enough. So you should start doing
> it with the addition burden of finding evolvable structures on your
> shoulders.

Should /not/ start, I imagine you meant to say.

Those of us who do TDD/Refactoring reasonably well, and we are many,
don't think of ourselves as "slinging" code. This may be important.
We write a test showing what we intend to accomplish, and a few
minutes later, we have accomplished it. If doing that has made the
design not quite as nice as it was before we started, we evolve the
design in place to keep it good.

The more we practice this, the easier it gets and the better we get
at it.

That said, there will always be times when our design ideas come too
late for immediate inclusion but they are still desirable to put
into the program. This is the original meaning of "technical debt",
the deviation of the code now from what we understand of the
desirable design now.

It turns out that our tests, and our refactoring skill, enable us to
bring the program and our understanding back in line more readily.
That's a good thing, and we get it by building our skill in TDD and
refactoring.

> Sure, whatever structures are below the radar of prio modelling need
> to be defined while coding.
> But since code is comparatively hard to change you want the explicit
> modelling radar to cover as much ground as possible.

That is one thing to want. Another thing to want is to write code
that is not so hard to change. Another thing to want is to build the
skill to notice design issues that are above the radar. And another
is to build the skill to do something about it in the moment.

> I some guru programmer can do without, that's fine. But as you cited
> even Kent Beck found it difficult to arrive at a solution just doing
> TDD.

Perhaps the most distressing thing about programming is that "guru
programmers" are not some kind of mutant that was born programming.
Guru programmers, as Joe pointed out earlier, have spend thousands
upon thousands of hours learning how to be good programmers.

Some of that learning was done with katas and other exercises. Much
of it was done "on the job", paying attention to what happens,
trying new things at small enough scale to learn without doing harm,
and so on.

There are thousands of programmers with good skill at evolving the
design. That facility is available to programmers who are beginning
at any level and the results seem primarily to be a function of how
much they practice.

> Structure code in an evolvable way as much as possible on a
> whiteboard. Postpone coding. Make coding a no brainer.

If coding were a no brainer, penguins could do it. It isn't a no
brainer and shouldn't be. Sure, draw on a whiteboard, it's fun and
useful. But bring your brain to the coding keyboard, please, and
learn all the good ways to use it.

Earlier you said that coding was hard enough. I think that's more
likely than that it will ever be a no brainer. So, again, learn to
apply your brain to more aspects of programming. It can only help.

> Design work done on a whiteboard is not only easier (bubbles dont
> crash, drawings are easier to change than code), it also allows more
> team members to participate. That increases the likelihood of good
> design. That increases the understanding of structures by more people.

Yes, it does all those things. And it is incomplete, imperfect, and
unlikely ever to be right "up front" ... because we never, ever,
know up front everything that is going to happen and to be asked
for.

We can //and should// turn back to the whiteboard when, later on, we
need to think about the design in ways we can't encompass in code.
We will always need to do that, I'd guess.

And having done so, we need to bring that new understanding back to
the code. We can't do that with no brain. We can't just "sling" code
to do that. We need discipline and skill to put our new
understanding into existing code.

The best known discipline and skill for doing that, so far, is
called TDD and refactoring. Programmers who know how to do that will
prosper.

> Again: coding is no virtue, but a necessary evil in order to satisfy
> customers with software. I guess we can agree on that, because we're
> constantly seeking relieve from coding thru compilers, DSL, or some
> other form of code generators.

> So why make coding more difficult by mixing it with "structure
> finding"?

> To me there are two reasons:

> 1. addiction to code: writing code is so satisfying personally, that
> developers seek out ways to keep doing it (on a level matching the
> current culture; today that's 3GL, but formerly they were happy with
> assembler and opposed higher level languages).

> 2. lack of an idea of how otherwise evolvable structures could be
> found before coding. Take a pol at your average developer conference:
> how many of the attendees are using UML? how many of those are using
> more than class diagrams and sequenz diagrams?

> I've done this poll several times in my talks at conferences in
> Europe. The results are roughly: 15% doing UML, 5% using more than
> those two diagrams.

> Naturally TDD, an all code approach, must appeal to the 85% of
> developers not using the #1 world wide standard for designing
> software.

So this #1 world wide standard that is used by only 15% of the
people who might use it. Is that telling us something about the
people, or about the standard? As you suggest below, it is likely
something about the standard.

The purpose of a model is to get ideas into our brain. It might just
barely be possible that there are ways other than UML to do that.

> But does that really show the validity of TDD as a successor to
> explicit design? Or is it a sign of failure of UML?

> I indulge in thinking the latter - an am on a quest for easier
> modelling tools, modelling tools for the masses, so to speak.

That's good. I'd suggest that you consider CRC as you think about
this, and, really, I think that a few non-formal UML-like diagrams
can be incredibly useful.

And don't forget human, shared, spoken language. Good naming
conventions and a few diagrams can go a long way toward getting
everyone an improved understanding of the design.

> Because,
> as said above, code is hard to change, and refactoring does not add
> value, and "structure finding" and "code instruction finding" are so
> different, they should not be mixed.

Some code is harder to change than other code. It seems prudent to
learn to write the easier to change kind. TDD and refactoring help
us to do that. (Refactoring does add value: I'll come back to that.)

It turns out that what makes code hard to change is that people do
not learn to do "structure finding" at the same time as typing in
the code (apparently even when it is a "no brainer"). This is not
some amazing new skill that only a genius can attain. It is a simple
matter of pausing every few minutes, looking at what we have built,
and taking a few minutes to improve it. It's not a big deal: it does
require practice.

Now then: As it happens, refactoring does add value. It does not add
features. It does, however, result in a program that is easier to
add features to.

Adding features without refactoring adds some number of features
over time. Adding features plus doing refactoring can add /more/
features over the same period of time. That is more value.

Now of course, we could refactor forever and never add another
feature. I've not seen many teams fall into that trap, because the
business people generally won't let them. Nonetheless it is
possible.

It seems to happen, most commonly, when the team's understanding of
a good design has gone forward and the real design has stayed bad,
so there is much work to do to get to the better place. Whether they
call it a rewrite or a 40day refactoring, the result is the same,
angry customers.

It's better to keep up on the design, and its better, when new ideas
and new needs come along, to know how to do refactoring. And when
refactoring, good tests are of immense value.

Hmm, tests and refactoring. Here we are again. These are skills that
normal people can build, and they are incredibly valuable.

You seem to care deeply about programming skill. I suggest that you
start thinking of TDD and refactoring in terms of a skill that is
potentially good to have, and that you learn them well enough to
understand even better than you do now, when to apply them and when
not.

Ron Jeffries
www.XProgramming.com
There is no award for "being XP". There is an award for doing the
right combination of practices: success.

Nieve

unread,
May 15, 2011, 7:09:11 AM5/15/11
to software_craftsmanship
Hello J. B. Rainsberger,

On May 15, 2:56 am, you wrote
> I use one in my courses that I haven't written up yet. Maybe I should.
> Removing duplication leads to a structure emerging, then improving
> names leads to moving responsibilities to more sensible places.

reading through the thread, it seems like for many people the process
of uncovering different responsibilities is coupled with removing
duplications, and I'm wondering why do we tend to focus on that
aspect.
If we follow TDD so that we write first the code so that it works in
the simplest way, we can continue then to read through the code and
find blocks that play a certain role and extract them; these roles
could end up defined as separate responsibilities, so that SRP is
applied. Finding areas of different responsibility in our code doesn't
have to be necessarily duplicate code, does it? Code that does
something, decides something or maintains some information can be
extracted into a different class to separate its responsibility from
the current class.

Does this make sense? Am I missing something here? Or am I not the
only one to think so?

philip schwarz

unread,
May 15, 2011, 8:56:14 AM5/15/11
to software_craftsmanship
@Ralf

TDD is the development technique used in XP.
XP is not viable/suitable for all projects:
1. XP is meant to be used when requirements are vague or changing
2. XP is most valuable when uncertainty is greatest
3. The key technical premise for XP is a flat 'cost of change' curve
4. One of the cases in which usage of XP is not recommended is when "a
customer or manager insists on a complete specification or analysis or
design before they begin the small matter of programming"

To help me better understand the points you are making in this thread,
can you tell me the following:

When you say that design and coding should be separate, that the goal
of design is to create a model, and that the goal of programming is to
code the model, are you saying that this approach is viable/
recommended for all projects, or only for a subset?

How do the following aspects of a project affect (if at all) the
viability/suitability of what you are advocating?:

1. degree of vagueness/changeability of requirements
2. degree of other uncertainty, e.g. from technical risk, changing
business environment
3. nature of the cost of change curve: XP-enabled flat cost of change
curve, or traditional exponential cost of change curve

Since TDD came about in the context of XP, in order to help me better
understand your points, can you confirm that you are familiar with the
following XP concepts which are found in "Extreme Programming
Explained - Embrace Change - 1st edition"):

Software development fails to deliver, and fails to deliver value.

The basic problem of software development is risk.

2 examples of risk:
Business misunderstood—the software is put into production, but it
doesn't solve the business problem that was originally posed.
Business changes—the software is put into production, but the business
problem it was designed to solve was replaced six months ago by
another, more pressing, business problem.

XP was invented to address risks.

We need to make our software development economically more valuable by
spending money more slowly, earning revenue more quickly, and
increasing the probable productive lifespan of our project. But most
of all we need to increase the options for business decisions.

Software project management can be looked at as having four kinds of
options:
1.Option to abandon
2.Option to switch
3.Option to defer
4.Option to grow

(see the actual book for more details on these options)

The worth of options is generally dominated by uncertainty in the
eventual value of the option: the difference between the cost of the
option and the value of exercising the option.

XP maximises the value of the project analyzed as options by
providing:
1. Accurate and frequent feedback about progress
2. Many opportunities to dramatically change the requirements
3. A smaller initial investment
4. The opportunity to go faster

The greater the uncertainty, the more valuable XP is.

One of the universal assumptions of software engineering is that the
cost of changing a program rises exponentially over time.
The problem is that this curve is no longer valid.
With simple design, tests, and an attitude of constant refinement of
the design it is possible to experience a flattened cost of change
curve

When the cost of change curve is flat:
1. You make big decisions as late in the process as possible, to defer
the cost of making the decisions and to have the greatest possible
chance that they would be right.
2. You only implement what you had to, in hopes that the needs you
anticipate for tomorrow wouldn't come true.
3. *** You introduce elements to the design only as they simplified
existing code or made writing the next bit of code simpler. ***

The main technical premise of XP is the flattened cost of change curve

"When should I use XP?" Use XP when requirements are vague or
changing.

*** Learning to Drive ***
We need to control the development of software by making many small
adjustments, not by making a few large adjustments, kind of like
driving a car.
This means that we will need the feedback to know when we are a little
off, we will need many opportunities to make corrections, and we will
have to be able to make those corrections at a reasonable cost.
Driving is not about getting the car going in the right direction.
Driving is about constantly paying attention, making a little
correction this way, a little correction that way.
This is the paradigm for XP. There is no such thing as straight and
level.
Even if things seem to be going perfectly, you don't take your eyes
off the road. Change is the only constant. Always be prepared to move
a little this way, a little that way. Sometimes maybe you have to move
in a completely different direction. That's life as a programmer.
Everything in software changes. The requirements change. The design
changes. The business changes.
The technology changes. The team changes. The team members change. The
problem isn't change, per se, because change is going to happen; the
problem, rather, is the inability to cope with change when it comes.

*** Two cases when you shouldn't try XP ***
1. The biggest barrier to the success of an XP project is business
culture. Any business that runs projects by trying to point the car in
the right direction is going to have a rough time with a team that
insists on steering.
2. A variant of "pointing the car" is the big specification. If a
customer or manager insists on a complete specification or analysis or
design before they begin the small matter of programming, then there
is bound to be friction between the team's culture and the customer or
manager's culture.
The project may still be able to be successful using XP, but it won't
be easy.

Philip

Ron Jeffries

unread,
May 15, 2011, 9:16:58 AM5/15/11
to software_cr...@googlegroups.com
Hello, philip. On Sunday, May 15, 2011, at 5:56:14 AM, you wrote:

> *** Two cases when you shouldn't try XP ***
> 1. The biggest barrier to the success of an XP project is business
> culture. Any business that runs projects by trying to point the car in
> the right direction is going to have a rough time with a team that
> insists on steering.
> 2. A variant of "pointing the car" is the big specification. If a
> customer or manager insists on a complete specification or analysis or
> design before they begin the small matter of programming, then there
> is bound to be friction between the team's culture and the customer or
> manager's culture.
> The project may still be able to be successful using XP, but it won't
> be easy.

I would still use TDD and refactoring in these cases, even if I
wouldn't use all of XP, which has much more to it than TD and
refactoring.

The reason I would use TDD and refactoring in these cases is that it
is the best way I have found in a half-century of doing this, to
create a program that I understand all the time, that does what I
intend it to all the time, and that responds to requirements changes
both from the business side and to design improvements from me and
the rest of the team.

I'm not equally good with TDD in all languages. In particular, I
find it very difficult to use in Linden Scripting Language for
Second Life, where so much of what one scripts is only measurable in
what one /sees/, that is, in what some object in the world does.

Even there I use TDD when I can and I use refactoring all the time.

Ron Jeffries
www.XProgramming.com
The lyf so short, the craft so long to lerne. -- Geoffrey Chaucer

Ron Jeffries

unread,
May 15, 2011, 9:29:16 AM5/15/11
to software_cr...@googlegroups.com
Hello, Nieve. On Sunday, May 15, 2011, at 4:09:11 AM, you wrote:

> reading through the thread, it seems like for many people the process
> of uncovering different responsibilities is coupled with removing
> duplications, and I'm wondering why do we tend to focus on that
> aspect.

I think there are at least two reasons, relating to what you say
next:

> If we follow TDD so that we write first the code so that it works in
> the simplest way, we can continue then to read through the code and
> find blocks that play a certain role and extract them; these roles
> could end up defined as separate responsibilities, so that SRP is
> applied. Finding areas of different responsibility in our code doesn't
> have to be necessarily duplicate code, does it? Code that does
> something, decides something or maintains some information can be
> extracted into a different class to separate its responsibility from
> the current class.

What you describe is a good practice. It turns out that when we do
as you describe, we do often manage to extract bits of code that
have some meaning. This relates very closely to the notion of
"Programming by Intention", where when we set out to do something,
we first posit a method of function that does what we want, then
call it, then write it. This, too, results in areas of
responsibility factored out.

As you suggest, we can certainly look at a block of code we have
just written and realize it has some meaning or "intention", and
extract it. This is a good thing to do.

It's not enough for the at least two reasons I refer to above:

First, sometimes we miss doing this. Instead we write two similar
patches of code without realizing we're doing it, or perhaps two
team members or pairs write them. Usually we really are doing just
the same thing again, though perhaps in our mind we don't remember
that we have had that intention before, or perhaps we are thinking
of it a bit differently now.

The result is that we wind up with sections of code that look
similar: duplication. So duplication shows us where we haven't
gotten things quite right.

Second, quite often we find that when we are about to fit in some
new feature and find the design to be not quite right, our guesses
about what the design should be are weak. If we make the design
changes first--which seems quite logical-- we often find that we
don't get it just right. It is too much or too little. So, instead,
we push the new feature into the existing code, which often results
in some duplication, which we then remove.

> Does this make sense? Am I missing something here? Or am I not the
> only one to think so?

You're right: there is more to it than duplicate code, and there are
other valuable practices that help keep the code clean and the
design good. What is quite interesting, however, is that duplication
removal takes us so far along the road to good code, all by itself.

Ron Jeffries
www.XProgramming.com
Perhaps this Silver Bullet will tell you who I am ...

Ralf Westphal

unread,
May 15, 2011, 10:25:42 AM5/15/11
to software_craftsmanship
On 15 Mai, 04:16, "J. B. Rainsberger" <m...@jbrains.ca> wrote:
> When I started practising test-first programming -- even before my
> tests really drove my design -- I spent about 1 year before I felt
> that I really began thinking of code in terms of input/output rather
> than algorithms and implementation details.

This is so great you´re bringing up "input/output thinking".
Exactly that´s what´s needed: input - processing - output.
(In German that even leads to an easy to remember acronym: EVA ;-)

But this now might surprise you: input/output thinking did not make
TDD more palatable for me.
I feel fine doing test-first development, I´ve also climbed the TDD
mountain, and am feeling comfortable up there.
But... - and this is a big "but" ;-) -, but... for input/output
thinking TDD is a clumsy tool.

Why should I chase developers up the TDD mountain, if there´s a
helicopter to take them to the input/output thinking top?

It´s so cool we seem to agree on the input/output view of software.
Because that means we agree that processing is core to code.
And I mean processing as in "doing" or "transforming" or "acting on"
etc. Verbs and actions are the notions to start with - not nouns or
actors.

I like TDD because of it´s focus on verbs/actions. That´s what you
start with when pondering your first test: What´s the API? How can I
start the whole thing? Take the alpha-end kata again: it starts with a
verb, "to convert". The same is true for about any other kata, I´d
say. And I´d even say, it´s true for any software.

What´s the input?
What´s the action to process the input?
What´s the expected output of the process?


>I spent that 1 year
> practising an average of 4 hours/day. That means 1,000 hours of
> practice. Do you think the teams with whom you consult consist of
> people who have practised 1,000 hours yet?

Sure not. Learning, practicing, i.e. consciously developing software
and assessing one´s actions is not the regular mode of most of the
developers I know.
They´re mostly under so much pressure, they don´t know when to
practice.
Or they have hardly learned how to learn and practice.
The just perform day in and out - on the level of programming they
learned many years.

And this is not gonna change any time soon, I´d say.
So what´s needed are easier methods to arrive at correct and evolvable
code than TDD.

-Ralf

philip schwarz

unread,
May 15, 2011, 10:34:13 AM5/15/11
to software_craftsmanship
@Ralph

You said: Designing is working on the level of the big picture. And I
don´t get how TDD can be designing in that regard, since you´re
immersed in source code.

From XPE (Extreme Programming Explained - embrace change - 2nd
edition):

"In the XP view, design is not drawing a bunch of pictures and then
implementing the system to conform to the pictures. That would be
pointing the car. Learning to Drive points the way to a different
style of design—get the car started, then point it a little this way,
then a little that way, then this way again."

For the meaning of "pointing the car", see
http://groups.google.com/group/software_craftsmanship/msg/a8fbe3341a449b0f
The rest of this post is all based on excerpts from XPE, only slightly
rephrased, and often in a different order from the one in which they
appear in the book. If there are any mistakes, they are my mistakes.

The paradigm for XP is steering a car based on feedback, not pointing
it at the destination. Creating a design before programming begins, is
a variant of pointing the car.

Because the cost of change curve is flat (thanks to simple design,
automated tests, and constant refinement of the design) you make big
decisions as late in the process as possible, to defer the cost of
making the decisions and to have the greatest possible chance that
they will be right. You only implement what you have to, in hopes that
the needs you anticipate for tomorrow won't come true. #### You
introduce elements to the design only when they simplify existing code
or make writing the next bit of code simpler. ###

The best design is the simplest design that runs all the test cases.
The simplest design is the one meeting the following constraints, in
priority order:

1. The system (code and tests together) must communicate everything
you want to communicate.
2. The system must contain no duplicate code.
3. The system should have the fewest possible classes.
4. The system should have the fewest possible methods.

If you ever find yourself with a class that does nothing and
communicates nothing or a method that does nothing and communicates
nothing, then you delete it.

The result of the first iteration is a functioning skeleton of the
system as a whole: you pick simple, basic stories that you expect will
force you to create the whole architecture.

...there is nothing wrong with designing software using explicit
pictures instead of a purely mental or textual model of the system,
and there is much to be said for a graphical approach. Trouble drawing
the pictures can give you subtle clues about the health of a
design. ...

Another strength of designing with pictures is speed. In the time it
would take you to code one design, you can compare and contrast three
designs using pictures.

The trouble with pictures, however, is that they can't give you
concrete feedback. They give you certain kinds of feedback about the
design, but they insulate you from others. Unfortunately, the feedback
they insulate you from is exactly the feedback that teaches you the
most—Will this run the test cases? Does this support simple code? This
is feedback you can get only from coding.

So, on the one hand, we can go fast when we design with pictures. On
the other hand, we are at risk when we design with pictures. We need a
strategy that let's us take advantage of the strength of designing
with pictures that also reduces its weaknesses.

The XP strategy is that anyone can design with pictures all they want,
but as soon as a question is raised that can be answered with code,
the designers must turn to code for the answer. The pictures aren't
saved. For example, the pictures could be drawn on a whiteboard.
Wishing you could save the whiteboard is a sure sign the design hasn't
been communicated, either to the team or to the system.

If there is a kind of source code that is best expressed as pictures,
then you should definitely express it, edit it, and maintain it as
picture. CASE tools that let you specify the entire behavior of a
system are fine. They may call what they do "code generation," but it
certainly looks like a programming language to me. My objection is not
to pictures, but to trying to keep multiple forms of the same
information synchronized.

If you were using a textual programming language, following this
advice, you would never spend more than 10 to 15 minutes drawing
pictures. Then you know what question you want to ask of the system.
After you get the answer, you can draw a few more pictures, until you
reach another question that needs a concrete answer.

The same advice applies to other noncode design notations, like CRC
cards. Do a few minutes of it, enough to illuminate a question, then
turn to the system to reduce the risk that you have been fooling
yourself.

How Does "Designing Through Refactoring" Work?

... We'll pick up the first test case. We'll say, "If all we had to do
was implement this test case, then we would only need one object with
two methods." We'll implement the object and the two methods. And
we'll be done. Our whole design is one object. For about a minute.

Then we'll pick up the next test case. Well, we could just hack in a
solution, or we could restructure the existing one object into two
objects. Then implementing the test case would involve replacing one
of the objects. So, we restructure first, run the first test case to
make sure it works, then implement the next test case.

After a day or two of this, the system is big enough that we can
imagine two teams working on it without worrying about stepping on
each other all the time. So we get two pairs implementing test cases
at the same time and periodically (a few hours at a time) integrating
their changes. Another day or two and the system can support the whole
team developing in this style.

From time to time, the team will get the feeling that the crud has
been creeping up behind them. Perhaps they have measured a consistent
deviation from their estimates. Or maybe their stomachs knot up when
they know they have to change a certain part of the system. In any
case, somebody calls, "Time out." The team gets together for a day and
restructures the system as a whole using a combination of CRC cards,
sketches, and refactoring.

Not all refactorings can be accomplished in a few minutes. If you
discover that you have built a big tangled inheritance hierarchy, it
might take a month of concentrated effort to untangle it. But you
don't have a month of concentrated effort to spend. You have to
deliver stories for this iteration.

When faced with a big refactoring, you have to take it in small steps
(incremental change again). You'll be in the middle of a test case,
and you'll see a chance to take one more step toward your big goal.
Take that one step. Move a method here, a variable there. Eventually
all that will remain of the big refactoring is a little job. Then you
can finish it in a few minutes.

Philip

On May 14, 2:35 pm, Ralf Westphal <i...@ralfw.de> wrote:

Ralf Westphal

unread,
May 15, 2011, 10:51:23 AM5/15/11
to software_craftsmanship
On 15 Mai, 11:04, "J. B. Rainsberger" <jbrainsber...@gmail.com> wrote:
> This sounds to me like saying "you should avoid exercise, unless it is
> necessary for you to keep your metabolism efficient enough to burn
> excess fat and avoid heart disease". While strictly true, the condition
> is so close to universally true that stating it explicitly in most
> contexts obscures the truth, rather than helps to reveal it.

I´m all with you with regard to physical exercise or healty eating
habits.
Don´t wait until some chronic disease has its grip on you.

But with refactoring it´s like with doing workout: it´s hard to know
when it´s enough.
I know quite a few shops who went overboard refactoring their code.

That´s why my first rule of refactoring is: Only do it when you need
it to fulfill a concrete requirement.

My second rule of refactoring is: Write clean code in the first place.

Maybe we should differentiate between two kinds of refactorings:

a. existential refactoring: That´s refactoring you need to survive
because otherwise you´re gonna drown in your brownfield mud. That´s
where most projects are which call me in for help. They´ve hit a wall
where they almost can´t apply any changes without major efforts.
Earning money from adding new features has become difficult.

b. functional refactoring: That´s refactoring not because you´re
wading through a brownfield, but because some new functionality
suggests a different structure. Or you could call it "refactoring to
deeper insight" (as they say in DDD).

What I´m trying to say is:
-You can´t avoid refactoring type B.
-But you can and should avoid reactoring type A by writing code that´s
clean in the first place.

Now take TDD: What type of refactoring does TDD in red-green-refactor?

It looks like type B, but in fact it´s type A refactoring.
Why? Because in most cases the refactoring could have been avoided by
a little more thinking prior to coding.
Again the alpha-end kata is an example for that. Look at my code
(http://codepaste.net/h5pfe6) and tell me, if this looks much
different from what you would have come up doing TDD? My guess, the
difference is small and maybe just a matter of style/taste.

So the structure of my solution is the same as with TDD - but without
a single refactoring.
Only one refactoring was necessary to accomodate the "new requirement"
of providing converters for different number systems.
That clearly was a refactoring of type B and thus unavoidable.

But all other refactorings TDD would have needed to go through where
not necessary to arrive at a pretty clean structure.
Thus TDD refactorings are of type A.


> Refactoring /done well and for a sensible purpose/ adds customer value
> that most customers with whom I work have difficulty seeing and
> therefore that I have learned to articulate clearly.

Any refactoring of type A cannot really be explained to customers.
They rightly would say: But why didn´t you program in a clean way in
the first place? That´s what we expect from surgeons, to operate with
sterile tools and only after washing their hands.

As a customer I´d certainly say, don´t make me pay for cleaning up
your mess.

A refactoring of type B, though, can be explained to customers. It´s
like reinforcing a wall because a new requirement came up for a
building.


But maybe this is all very hard to discuss here. It would be better to
experience how much easier it can be to come up with a structure for
code without the need for coding, that means thru trial and error. At
least that´s my experience here in Germany where I do a lot of
presentations on the subject "model before code".

-Ralf

Ralf Westphal

unread,
May 15, 2011, 11:13:40 AM5/15/11
to software_craftsmanship
On 15 Mai, 12:06, Ron Jeffries <ronjeffr...@acm.org> wrote:
> The best known way to produce code that supports our new design
> ideas is TDD/Refactoring, and the best way to get code like that is
> to practice TDD/Refactoring until we are good at it.

Ron, I appreciate the time you have invested to write up your reply.
At this point, though, it´s hard for me to continue.
You do not seem to be open to thinking beyond "the best know way to
produce code".

I´ve brought before you concerns why I think TDD is less than perfect.
And I´ve tried to shed some light on what I mean by doing it
differently thru providing a small, but concrete solution to a problem
which usually is tackled using TDD.

I can emphasize with you in that TDD delivers and is much better than
many other approaches.
OOAD has not delivered on desiging evolvable software.
So TDD has taken up the challenge - and does better.
Great!

But I find it very limiting to stop at that.
So I have ventured into "unknown territories" beyond TDD... (which in
the end where not uninhabitated; I met other travellers back from
another century over there).
And what I´ve found is much more efficient than TDD - but maybe
require a departure from some dearly held believes.

Never mind, though.
Good luck to you with TDD!

-Ralf

philip schwarz

unread,
May 15, 2011, 11:18:15 AM5/15/11
to software_craftsmanship
@Ralph

One point I am trying to remind you of with my previous post is that
on XP projects there is a lot of uncertainty, which poses risks, but
by using simple design, automated tests, and constant design
refinement through refactoring, XP enables a flat cost of change
curve, and so can maximise the value of the project as options (to
abandon/switch/defer/grow). The greater the uncertainty, the more
valuable XP is. When the cost of change curve is exponential, it is
crazy to use XP's approach.

Designing systems using XP/TDD is not easy, it requires a lot of
discipline, but the pay-off is effective risk management in the face
of great uncertainty. Simplicity is central. Earlier you and Curtis
talked about the best design. In XP, the best design is the simplest
design for today's needs. The constant refactoring with the protection
of automated unit tests is not waste/masochism: together with simple
design it is what allows XP to keep the cost of change curve flat, and
so to maximise the value of the project.

Philip

On May 15, 3:34 pm, philip schwarz
<philip.johann.schw...@googlemail.com> wrote:
> @Ralph
>
> You said: Designing is working on the level of the big picture. And I
> don´t get how TDD can be designing in that regard, since you´re
> immersed in source code.
>
> From XPE (Extreme Programming Explained - embrace change - 2nd
> edition):
>
> "In the XP view, design is not drawing a bunch of pictures and then
> implementing the system to conform to the pictures. That would be
> pointing the car. Learning to Drive points the way to a different
> style of design—get the car started, then point it a little this way,
> then a little that way, then this way again."
>
> For the meaning of "pointing the car", seehttp://groups.google.com/group/software_craftsmanship/msg/a8fbe3341a4...

Ralf Westphal

unread,
May 15, 2011, 11:24:17 AM5/15/11
to software_craftsmanship
On 15 Mai, 12:34, Ron Jeffries <ronjeffr...@acm.org> wrote:
> You seem to care deeply about programming skill.

Sure I do.

> I suggest that you
> start thinking of TDD and refactoring in terms of a skill that is
> potentially good to have, and that you learn them well enough

Sorry to say, but this seems to imply you know about my TDD skills
well enough to recommend I improve on them.
How come?

Do you think just because I´m not all for TDD I´m not good at doing
TDD?

I´d say there are other possible explanations:
a. I´m good at TDD and still am dissatisfied with it´s results.
b. I´m not good at TDD, but TDD nevertheless is not the pinnacle of
software design, and even someone outside the "TDD believe system" can
sense that.

Also your statement implies: Ron is good at TDD (because TDD is the
best way to design software); thus whoever is not doing TDD is wrong
(or at least in danger of malpractice because he´s not applying what´s
broadly recognized as the pinnacle of design).

Hm... this does not feel good, Ron.
This does not sound like the scientific method.

-Ralf

Ralf Westphal

unread,
May 15, 2011, 11:47:32 AM5/15/11
to software_craftsmanship
On 15 Mai, 14:56, philip schwarz
<philip.johann.schw...@googlemail.com> wrote:
> To help me better understand the points you are making in this thread,
> can you tell me the following:

Thx for asking, Philip!

>
> When you say that design and coding should be separate, that the goal
> of design is to create a model, and that the goal of programming is to
> code the model, are you saying that this approach is viable/
> recommended for all projects, or only for a subset?

This I can recommend for any project.

If requirements are vague, how can you produce code that fulfills
them? You can´t. You need to make a stab in the dark and see if you
hit a nerve with the customer ;-)

If requirements are vague, explicit design also cannot produce the
final correct design. So you need to make a stab in the dark, model a
bit, implement the model, show the software to the customer - and then
change the model, implement the changes etc.

Doing explicit design does not mean going back to the waterfall. Right
to the contrary.
I´m talking modelling explicitly on a daily basis, implementing on a
daily basis, delivering value to the customer on a daily basis.


>
> How do the following aspects of a project affect (if at all) the
> viability/suitability of what you are advocating?:
>
> 1. degree of vagueness/changeability of requirements

Not at all.
Or: The more volatile the requirements are, the better it is to model
explicitly thereby arriving more quickly at evolvable structures.
Modelling explicitly in a group brings all developers to the design
table, not just a pair in front of an IDE doing TDD.


> 2. degree of other uncertainty, e.g. from technical risk, changing
> business environment

Not at all. Why should have technical risk have an impact on
modelling, I mean whether you do it or not?


> 3. nature of the cost of change curve: XP-enabled flat cost of change
> curve, or traditional exponential cost of change curve

Explicit modelling leads to a flat cost curve like TDD does. But with
less effort in coding.
Coding skills are the constraint (in terms of the Theory of
Constraints, TOC) in most shops.
So we need to do everything in our power to relieve the constraint,
that means:

-code only what you know will have some value
-avoid refactoring during coding
-deliver a design of high quality to coding to make coding as fast as
possible
-deliver high quality code (through relentless automatic testing)

Coding is just one step in producing software. Other steps precede and
succeed it.
If coding is the constraint, then...

-the coding constraint needs to be exploited, i.e. coder´s capacity
needs to be focused on coding (that means on writing correct lines of
code delivering value); designing does not deliver value; so during
coding no designing should take place.
-other production steps need to be subordinated to coding, i.e.
preceding steps need to deliver high quality input to coding
-the coding constraint needs to be elevated, i.e. it´s capacity/
productivity needs to be increased

High quality output from the constraint is important; that´s why
testing and reviews are so important; rework by the coding constraint
needs to be avoided.
But also high quality needs to be input to the constraint; that´s why
explicit design is so important. Requirements are low quality input to
coding. They need to be digested first by preceding production steps:
analysis, architecture, modelling, planning of coding activities.


> Software development fails to deliver, and fails to deliver value.

Sure. That´s what I see every single day during consulting or doing
team assessments.


>
> The basic problem of software development is risk.
>
> 2 examples of risk:
> Business misunderstood—the software is put into production, but it
> doesn't solve the business problem that was originally posed.

Sure.


> Business changes—the software is put into production, but the business
> problem it was designed to solve was replaced six months ago by
> another, more pressing, business problem.

Sure.

And you can add: Business misrepresented. The customer himself did not
know what he wanted.



> XP maximises the value of the project analyzed as options by
> providing:
> 1. Accurate and frequent feedback about progress

I´m all for that!


> 2. Many opportunities to dramatically change the requirements

Sure! I invite the customer to come in any day and change anything he
likes.
No, I´m not joking.


> 3. A smaller initial investment

Sure.


> 4. The opportunity to go faster

Well, faster than delivering to the customer each and every single day
of the week to me seems unattainable for most shops ;-)


>
> The greater the uncertainty, the more valuable XP is.

Even though I do not subscribe to XP, I agree that iterations are at
the core of software development.


> With simple design, tests, and an attitude of constant refinement of
> the design it is possible to experience a flattened cost of change
> curve

I agree on this statement.
But I disagree on the method of how to attain such code structures.

Now what, Philip? Did I pass your little test? ;-)

-Ralf

Nieve

unread,
May 15, 2011, 5:13:36 PM5/15/11
to software_cr...@googlegroups.com
Ron, thanks a lot for your words, they are bang on the spot :)
Just one thing I'm questioning:

On 15 May 2011 14:29, you wrote:
What is quite interesting, however, is that duplication
removal takes us so far along the road to good code, all by itself.

Is it because upon actually removing duplication we see our code 'shrinking' and get to see an immediate improvement, whereas refactoring code into reusable smaller components of single responsibilities doesn't give us an immediate visible result in the sense that removing duplication does?
I really hope I don't come across as nit-picking or tedious, this is far from what I'm aiming at here; I honestly try to understand what you/other people think of these two practices and their importances without trying to say which one's 'better'. Just being truly curious from my not-so-experienced stand...

-n

Adam Sroka

unread,
May 15, 2011, 5:21:41 PM5/15/11
to software_cr...@googlegroups.com

There's more than one kind of duplication and more than one way to
remove it. If, for example, we need to do something similar in two or
more places then creating a smaller reusable component *is* removing
duplication. Pretty much all refactoring can be reduced to either
eliminating duplication or clarifying intent (or both.)

philip schwarz

unread,
May 15, 2011, 6:03:27 PM5/15/11
to software_craftsmanship
Hi Ron,

I was wondering if any aspect of TDD changes depending on whether or
not it is practised in the context of XP. Have you noticed any
difference?

In "TDD by Example", Kent Beck says:

TDD isn't an absolute the way that XP is. XP says. "Here are the
things you must be able to do to be prepared to evolve further". TDD
is a little fuzzier. TDD is an awareness of the gap between decision
and feedback during programming, and techniques to control that gap.
"What if I do paper design for a week, then test drive the code? Is
that TDD?" Sure, it's TDD. You were aware of the gap between decision
and feedback. and you controlled the gap deliberately.

Assuming that doing paper design for a week is not contemplated in XP
(is that right?), would this be an example of doing TDD differently
when not in an XP context?

Philip

Olivier Azeau

unread,
May 15, 2011, 6:15:05 PM5/15/11
to software_cr...@googlegroups.com
Le 15/05/2011 16:51, Ralf Westphal a �crit :

>
> Again the alpha-end kata is an example for that. Look at my code
> (http://codepaste.net/h5pfe6) and tell me, if this looks much
> different from what you would have come up doing TDD? My guess, the
> difference is small and maybe just a matter of style/taste.
>
> So the structure of my solution is the same as with TDD - but without
> a single refactoring.
> Only one refactoring was necessary to accomodate the "new requirement"
> of providing converters for different number systems.
> That clearly was a refactoring of type B and thus unavoidable.
You pointed out this "Alpha End converter" exercise. I just tried to do
it with TDD. Well, TDD as I do it - not sure it is a standard and
"certified" way of doing TDD.
My result, including refactoring history, is here :
https://github.com/Oaz/AlphaEndConverter
Basically, my tests and refactorings led me to a much shorter piece of
code with no need to introduce concepts such as 'base power' in the design.
And the whole thing took me no longer than a quarter of hour.

I do not say that TDD is always the best thing to do.
But TDD as I see it is more a way of thinking : at some point in time, I
have a design materialized by some code.
Then I just ask to myself : can I make it better? - whatever that means
: simpler, faster, more maintainable, etc.
Adding tests, one at a time, just help me to do this.

Regards,
Olivier

Ralf Westphal

unread,
May 15, 2011, 6:50:14 PM5/15/11
to software_craftsmanship
Thx Olivier for sharing your code.
Great TDD stuff.

So at least your code proved me wrong, eh ;)
It does not really look like my solution, of which I thought it would
resemble a TDD solution.
How come?

My guess is, that the main difference stems from your use of
recursion.
That's very elegant for an algorithmic problem.

To be honest I did not even think of it in this context.
I'm biased towards "sequential solution".
That I should try to overcome. Thx for reminding me of that.

But does your solution prove me completely wrong?
No, I don't think so.
Implementing algorithms is not really what baffles most developers.
Rather it's working on larger problems, how to structure software
systems.
And it's how to put several developers to work on the same feature at
the same time to jointly produce it as fast as possible (think WIP=1).

For that some kind of "design of coarse grained functional units" is
necessary, eg classes, components, packets, services. TDD is hardly of
help then.

Maybe we should continue to compare different approaches on a larger
scale.
How about a small but whole application? Like maybe a Tic Tac Toe
game?
Or maybe someone wants to suggest a different scenario?
That would be great.

-Ralf

philip schwarz

unread,
May 15, 2011, 7:18:08 PM5/15/11
to software_craftsmanship
Hi Ron,

In Extreme Programming Explained, we find the following two
paragraphs:

####################################
With these elements in place—simple design, tests, and an attitude of
constant refinement of the design—we experienced the flattened curve.
A change that would have taken a few minutes before much coding had
occurred took 30 minutes after we had been in production for two
years. And I see projects spending days or weeks making the same sort
of decision, rather than doing what they need to do today and trusting
themselves to fix it tomorrow if they need to.

With this shift in assumption about the cost of change comes the
opportunity to take an entirely different approach to software
development. It is every bit as disciplined as other approaches, but
it is disciplined along other dimensions. Instead of being careful to
make big decisions early and little decisions later, we can create an
approach to software development that makes each decision quickly, but
backs each decision with automated tests, and that prepares you to
improve the design of the software when you learn a better way to
design it.
####################################

How does TDD relate to the cost of change curve (CCC)?
What allows the flattening of CCC in XP is simple design, automated
tests, and constant refactoring,
TDD also involves simple design, automated tests, and constant
refactoring.
Is TDD necessary to flatten the CCC?
Is TDD sufficient to flatten the CCC?

Philip

On May 15, 2:16 pm, Ron Jeffries <ronjeffr...@acm.org> wrote:

philip schwarz

unread,
May 15, 2011, 7:19:03 PM5/15/11
to software_craftsmanship

Adam Sroka

unread,
May 15, 2011, 7:23:29 PM5/15/11
to software_cr...@googlegroups.com
On Sun, May 15, 2011 at 4:18 PM, philip schwarz
<philip.joh...@googlemail.com> wrote:

> What allows the flattening of CCC in XP is simple design, automated
> tests, and constant refactoring,
> TDD also involves simple design, automated tests, and constant
> refactoring.
> Is TDD necessary to flatten the CCC?
> Is TDD sufficient to flatten the CCC?
>

Interesting. How would you define TDD without simple design, automated
tests, or constant refactoring? If you had all three how would that be
distinct from TDD?

George Dinwiddie

unread,
May 15, 2011, 10:07:51 PM5/15/11
to software_cr...@googlegroups.com
Hi, Ralf,

On 5/15/11 1:41 AM, Ralf Westphal wrote:
> Yes, refactoring is an activity which does not add customer value by
> itself. It's definition says, you must not change functionality
> while refactoring.
>
> Thus refactoring should be avoided - unless it is necessary to make
> adding functionality aka customer value easier.

Looking at it that way, then typing is an activity that does not add
customer value by itself. It's just a means to express the desired
functionality.

The funny thing is, I've found that I can create that functionality
faster by using refactoring, plus the tools of the IDE. Some years
back, I started wondering why I was coding faster using TDD than I had
been before. I realized that the use of refactoring let me think about
the code in higher level constructs than characters or lines of code.
Like using higher level languages let me express things more quickly
than assembly language did, using known refactorings let me express
things more quickly than the lines of the higher level language.

> If I can come up with evolvable code without refactoring I think
> that's better than being forced to go thru refactoring steps first. I
> hope we can agree on that.

I wouldn't agree on that. I know that it takes me longer to create code
that evolves in the right way without refactoring than it does for me to
create dirt simple code and then evolve it with refactoring that
supports that evolution. It takes me less time because I don't have to
think so many moves ahead. And, if I change my mind about the direction
it should evolve, then refactoring makes the code easy to push into the
new shape I want, like manipulating a hunk of well-worked clay.

> If so, then we can go on to discuss the more interesting question: how
> to arrive at clean code right away? (Sure I'm talking greenfield code
> here. But thats difficult enough for a start.)
>
> People advocating TDD seem to be saying: that's (almost) impossible;
> you can't sit down an write clean code just like that. For a given
> requirement you need to approach an evolvable structure thru
> refactoring. You cannot know it before you have started to code.

That's not what I'm saying. I'm just saying it's faster and easier to
do so with TDD and refactoring. And that some of what makes code clean
depends on what the code needs to do. Doing that in little steps is
faster than thinking it all out and then correcting the little places
where I lacked sufficient foresight.

> As much as I like writing code test first, I nevertheless contest the
> notion of "you need to go thru refactorings to find an appropriate
> structure."

Need is a strong word. It's just easier, I find. And, even when I
think I know the appropriate structure ahead of time, I'm sometimes
surprised that I find a better one along the way. I write tests that I
intend to push for the need of the structure I thought was appropriate,
and find that a simpler structure suffices.

I don't care if you use TDD and refactoring, or not. But I don't think
your rationalization holds water. Refactoring isn't waste if it gets me
to a good solution faster, even if it looks like it's adding a step. (I
suspect that there are other steps that get shorter.) It's done that
for me. I don't know why it wouldn't do that for you.

- George

--
----------------------------------------------------------------------
* George Dinwiddie * http://blog.gdinwiddie.com
Software Development http://www.idiacomputing.com
Consultant and Coach http://www.agilemaryland.org
----------------------------------------------------------------------

Ron Jeffries

unread,
May 15, 2011, 10:27:13 PM5/15/11
to software_cr...@googlegroups.com
Hello, Nieve. On Sunday, May 15, 2011, at 2:13:36 PM, you wrote:

>> What is quite interesting, however, is that duplication
>> removal takes us so far along the road to good code, all by itself.

> Is it because upon actually removing duplication we see our code 'shrinking'
> and get to see an immediate improvement, whereas refactoring code into
> reusable smaller components of single responsibilities doesn't give us an
> immediate visible result in the sense that removing duplication does?
> I really hope I don't come across as nit-picking or tedious, this is far
> from what I'm aiming at here; I honestly try to understand what you/other
> people think of these two practices and their importances without trying to
> say which one's 'better'. Just being truly curious from my
> not-so-experienced stand...

I believe / theorize that there is a more concrete basis for
duplication removal being so powerful. I think it has something to
do with recognizing that two patches of code, while not identical,
share some commonality (duplication), which leads us to look at them
and build the abstraction that is trying to emerge in the code.

Turning this around, it suggests that missing abstractions may very
frequently show up in (partially) duplicated code, which means that
a sharp eye for duplication will identify ideas that have not yet
even become well formed in our mind.

Of course, it could just be that duplication is a very common
"mistake" and so removing it goes after a large percentage of
problems. I think it's more than that but I could be wrong.

Ron Jeffries
www.XProgramming.com
Accept your conditions, but not your fate. -- Rod Walsh & Dan Carrison

Ron Jeffries

unread,
May 15, 2011, 10:48:22 PM5/15/11
to software_cr...@googlegroups.com
Hello, philip. On Sunday, May 15, 2011, at 3:03:27 PM, you wrote:

> I was wondering if any aspect of TDD changes depending on whether or
> not it is practised in the context of XP. Have you noticed any
> difference?

I'm not sure I can answer this in a useful way, because the XP
"style" is now pretty much embedded in my nervous system. Let's see
what I say ...

> In "TDD by Example", Kent Beck says:

> TDD isn't an absolute the way that XP is. XP says. "Here are the
> things you must be able to do to be prepared to evolve further".

I believe that I do not agree with the premise that XP is an
absolute (and I suspect that Kent would no longer say that it is
either.) XP is not the only way to do software well, any more than
TDD is not the only way to do software well (Ralf, please note that
I've been saying this right along.)

XP, like TDD, is /one/ good way (or actually a whole related family
of good ways) to do software well, and the better I can do XP (or
TDD) the more qualified I am to decide when to do them, and when
not.

Neither of these things is "binary" to me, and each pays off more
the more skill I have with them. In both cases, despite my long
education and background in computing, they pay off more the better
I get at them.

I have been, years ago, really good at UML and other forms of
non-code design. Investing more in the details of those did not pay
off for me. Investing more in the details of XP, of Agile in
general, and in TDD continues to pay off to this very day.

> TDD
> is a little fuzzier. TDD is an awareness of the gap between decision
> and feedback during programming, and techniques to control that gap.
> "What if I do paper design for a week, then test drive the code? Is
> that TDD?" Sure, it's TDD. You were aware of the gap between decision
> and feedback. and you controlled the gap deliberately.

> Assuming that doing paper design for a week is not contemplated in XP
> (is that right?), would this be an example of doing TDD differently
> when not in an XP context?

One needs to do as much paper design as needed, whenever it is
needed, be that up front or right in the middle of an afternoon's
coding.

Because paper design advances understanding but not "features", it
can quickly lose value when compared to a technique that advances
understanding plus feature progress. Some people can advance
understanding plus feature progress very well using techniques like
TDD. No people ... literally NO people, can advance understanding
plus feature progress at the same time using paper design.

However, a little paper design can then make feature progress go
faster because understanding is necessary to good programming. Can
it make us go faster than TDD? It depends on several things:
- How good are we at paper design? It happens that I'm very
good at it, and still I reach diminishing returns quite quickly.
People who are less good at it will reach diminishing returns
even more quickly.
- How good are we at simultaneous coding and design (via TDD or
some similar approach? The better we are at these, the sooner we
reach the transition point where a simultaneous approach is
better than a design then code approach ... at least for a
while.
- How good are we at recognizing that it is time to switch?
Sticking with either one too long is wasteful ... but it is
differently wasteful. A little too much paper design doesn't do
much harm. We might have a few too many ideas but ideas don't
usually hurt us. A little too much simultaneous coding and
design can result in a bad physical design which, depending how
good we are at refactoring, can take a long time to get out of.

All these play together. If our TDD/Refactoring skill is very high,
we need not spend much time in the solo paper mode, which does not
advance features, yet we do not lose velocity by going off on random
"code slinging" adventures that mess up the design, because we have
the skill to observe the design and the code at the same time.

It is quite possible that some people really cannot simultaneously
do code and design. These people are doomed to do paper design and
then try to work toward it. I believe they are also doomed not to be
very good.

(I will address this last paragraph a bit further in my reply to
one of Ralf's comments to me because I think he has caught himself
in a contradiction.)

For me, I don't do TDD differently when I'm doing XP than when I'm
not, because I am always trying to work more like XP and to work
more like TDD and to do a better job of paper design when I do it,
and so on. To me these things are not exclusive and conditioned by
each other: they are all things to continue to learn to do well.

Hmm, I was right: I couldn't directly answer your question. I hope
this explanation of why is somehow enlightening anyway. :)

Ron Jeffries
www.XProgramming.com
Testing quality into a program is like spinning straw into gold.
-- George Cameron.

Ron Jeffries

unread,
May 15, 2011, 11:17:28 PM5/15/11
to software_cr...@googlegroups.com
Hello, Olivier. On Sunday, May 15, 2011, at 3:15:05 PM, you wrote:

>> Again the alpha-end kata is an example for that. Look at my code
>> (http://codepaste.net/h5pfe6) and tell me, if this looks much
>> different from what you would have come up doing TDD? My guess, the
>> difference is small and maybe just a matter of style/taste.
>>
>> So the structure of my solution is the same as with TDD - but without
>> a single refactoring.
>> Only one refactoring was necessary to accomodate the "new requirement"
>> of providing converters for different number systems.
>> That clearly was a refactoring of type B and thus unavoidable.
> You pointed out this "Alpha End converter" exercise. I just tried to do
> it with TDD. Well, TDD as I do it - not sure it is a standard and
> "certified" way of doing TDD.
> My result, including refactoring history, is here :
> https://github.com/Oaz/AlphaEndConverter
> Basically, my tests and refactorings led me to a much shorter piece of
> code with no need to introduce concepts such as 'base power' in the design.
> And the whole thing took me no longer than a quarter of hour.

Very interesting, Olivier, thanks for doing this.

And let me congratulate both of you for putting your code out to be
looked at. That takes great nerve to do. Well done both.

Olivier, your solution exemplifies a thing that happens often ... in
these smaller problems if not in larger.

Namely, the design we create on paper turns out to be more design
than we need to solve the problem in hand. TDD has a strength in not
causing us to do more design than we need, which is good because it
can lead to solutions that are no more complex than they need be.

This is also a weakness, of course, since sometimes not enough
design is done //anywhere// (whether on paper or in code) and the
design is not robust enough. I'd far rather do too much than too
little design.

To me, Olivier's design is arguably "more procedural", but it is
shorter and simpler and therefore has a lot going for it. This is a
common outcome with TDD ... we do not over-design ... by which I
mean that at any moment, we have no more design than we need.

It can be argued that Ralf's design will be easier to extend. This
may even be true. Nonetheless, that extra design is not carrying its
weight now, even if at some future time it may.

One last point, which I'll put here rather than in yet another reply
to Ralf.

This careful paper design may have some good properties. I do not
think "didn't need to refactor" is automatically a good property,
however, because it depends on how long it took to get there and how
long it takes to refactor.

But more interesting to me are these facts:

1. We don't know if Ralf's solution works or not: we do not see the
tests. He says there are tests but we didn't get to see them. It
sounds like the tests are created after the fact. There may be blind
spots when we do that. In any case, we just can't tell. Easily
enough corrected, and of course in a real situation we could browse
them if we wanted to. Nonetheless, right here right now, we can't
tell.

2. We don't know why the solution is what it is: we do not see the
progression (which we can see in a series of tests). This is
uncorrectable. We can show evolution with TDD much more readily than
we can see how the paper design evolved and why.

3. The design as it stands has some rather visible flaws. Perhaps
the most important of these is the preponderance of "internal"
methods, which often signal an abstraction trying to appear. The
most telling of these is the returning of a tuple, which is always a
red flag in the code saying "I have an object in mind here but I
didn't bother to make it an object". In this case, if I understand
the code correctly, we have a mantissa (cleverly named Item1) and an
exponent (named Item2). These names do not communicate our design
intention nor our implementation intention.

We then have a separate method that slams values into that tuple.
This is a violation of the Law of Demeter. A better design might
encapsulate all of that behind some new class with mantissa and
exponent, and methods internal to that class that set the
components.

The result of all this this is that while perhaps the paper design
saved a refactoring, it remains further than one might like to see
from a design that correctly presents the abstractions that it
contains.

Now back to Olivier's program. It is in fact simpler ... but is it
as easy to understand? I'm not sure. On the one hand it has
everything embedded in that single convert method but even for a
lover of the ternary operator, that method is tricky to understand.
It is recursive (very cool) and therefore harder to understand than
Ralf's loop.


We see here, I hope, that the question of "which is better" is quite
complex. We get to see a bit more of Olivier's thought process and
really none of Ralf's because he did it on paper that we cannot see.
Olivier's solution covers exactly what it needs to and no more:
there seems to be no excess in it.

Ralf's solution seems to me to have more design than was needed to
do what it does, but I can't be sure because I can't see the tests.
Furthermore, it contains more abstractions, which is not necessarily
good, and it contains some very incomplete abstractions around the
tuple and the demeter-violating method that hammers on it.


I'd have to say that I prefer Olivier's for being simpler, and agree
with Ralf that another reader might prefer the other. More of
Olivier's design process is visible and Ralf's design process is
hidden.


It's a hard question. Partly it is a matter of taste, but I think
the partially-implemented abstractions, the violation of Law of
Demeter, and the absence of the tests gives Olivier the win in this
case, by a small margin, in this referee's opinion.

Your mileage may vary.

Ron Jeffries
www.XProgramming.com
War remains the decisive human failure.
-- John Kenneth Galbraith

Ron Jeffries

unread,
May 15, 2011, 11:31:16 PM5/15/11
to software_cr...@googlegroups.com
Hello, Ralf. On Sunday, May 15, 2011, at 3:50:14 PM, you wrote:

> But does your solution prove me completely wrong?
> No, I don't think so.

You're right, it doesn't. And I actually believe that the recursive
solution, while it has a certain elegance, is less robust when we
realize that we'll have to face it in the future and figure out out
again. The looping solution is simpler in some important ways.

> Implementing algorithms is not really what baffles most developers.
> Rather it's working on larger problems, how to structure software
> systems.

Very true ...

> And it's how to put several developers to work on the same feature at
> the same time to jointly produce it as fast as possible (think WIP=1).

Yes ... which requires a common understanding among those
developers, as you rightly point out ...

> For that some kind of "design of coarse grained functional units" is
> necessary, eg classes, components, packets, services.

Yes. Readers of Extreme Programming Installed (Jeffries,
Hendrickson, Anderson) will recall the "Quick Design Session", which
is a short period of time when the people working on some feature or
features work through a design sketch prior to moving into code ...
or in the middle of coding when they feel the need to bring their
head up out of the muck.

This is very important ... which is why right along I've been saying
that drawing pictures or tossing CRC cards or other means are
important. However ...

> TDD is hardly of
> help then.

This may be true for you, but it is emphatically not true world
wide. Many individuals and teams understand how to show and
manipulate "course-grained functional units" in code. It's not
always the best way but sometimes it is.

You, Ralf, assert on the one hand that you are very skilled in
TDD, and yet on the other hand you state that you cannot work on
both design and code at the same time, and that you cannot see the
coarse grained design (very well) in the code.

I can think of a few explanations for this. One would be that your
brain is simply not capable of doing what many other brains can
do. I think this unlikely. My own model of what would cause you to
say those things is that your skill at TDD is not as high as that
of people who CAN work on design and code at the same time, and
who CAN envision coarse-grained design while working in code.

You seem to take that as a bit insulting. Hardly. I'm assuming
that you could learn how to do this as well as anyone ... and that
as yet, you have not.

> Maybe we should continue to compare different approaches on a larger
> scale.
> How about a small but whole application? Like maybe a Tic Tac Toe
> game?

There can be value to this, though it may be quite difficult to
bring it out in a written forum like this one. To compare the two
approaches, we need to control for quality at least in the sense of
running all the tests, and quite possibly for other matters of
quality such as having all the abstractions needed and no more, and
so on.

I'd like to see it done and I am not sure whether we have the time,
the will, or the medium to bring it off.

You guys have already gone further than most in displaying your
code, and again, I congratulate you. If you can do more that will be
great.

Ron Jeffries
www.XProgramming.com
Here is Edward Bear, coming downstairs now, bump, bump, bump, on the back
of his head. It is, as far as he knows, the only way of coming downstairs,
but sometimes he feels that there really is another way, if only he could
stop bumping for a moment and think of it. And then he feels that perhaps
there isn't. -- A. A. Milne

Ron Jeffries

unread,
May 15, 2011, 11:39:38 PM5/15/11
to software_cr...@googlegroups.com
Hello, philip. On Sunday, May 15, 2011, at 4:19:03 PM, you wrote:

> ####################################
> With these elements in place�simple design, tests, and an attitude of
> constant refinement of the design�we experienced the flattened curve.


> A change that would have taken a few minutes before much coding had
> occurred took 30 minutes after we had been in production for two
> years. And I see projects spending days or weeks making the same sort
> of decision, rather than doing what they need to do today and trusting
> themselves to fix it tomorrow if they need to.

> With this shift in assumption about the cost of change comes the
> opportunity to take an entirely different approach to software
> development. It is every bit as disciplined as other approaches, but
> it is disciplined along other dimensions. Instead of being careful to
> make big decisions early and little decisions later, we can create an
> approach to software development that makes each decision quickly, but
> backs each decision with automated tests, and that prepares you to
> improve the design of the software when you learn a better way to
> design it.
> ####################################

I'm really not here to explain or justify Kent's words from over a
decade ago. I'm not even always able to justify mine from the same
era.

What he says here is mostly true, I think, depending on what we mean
by flattening the curve.

> How does TDD relate to the cost of change curve (CCC)?

TDD provides a suite of very tight tests as a /side effect/ of a
very useful design technique. (Not the /sole/ design technique but a
very useful one.

The tests provide for increased certainty that changes have not
broken things and increase speed of detection when they do. This
reduces the cost of change and the cost of error, flattening the
curve.

> What allows the flattening of CCC in XP is simple design, automated
> tests, and constant refactoring,
> TDD also involves simple design, automated tests, and constant
> refactoring.

TDD is how an XP programmer DOES simple design, automated tests, and
refactoring. It is the name for the suite of behaviors that cover
those topics in XP.

> Is TDD necessary to flatten the CCC?

Depends how much you want to flatten it. Comprehensive unit tests
might do the same level of testing at higher cost. Changing the code
without understanding behavior-preserving transformations might
still allow us to make changes, but more slowly thus not flattening
the curve as much.

TDD / refactoring are the best way we know // at the coding level //
to keep the curve flat. Perfect up front design will not do this,
from the viewpoint of XP and Agile, because (a) perfect up front
design is not possible, (b) implementing a perfect design perfectly
is not possible, (c) up front design is done at the moment we know
less than we ever will again, and (d) things change anyway.

That doesn't mean we don't do paper design: we do and it is good. It
just doesn't give us the things that TDD does and we need those
things.

> Is TDD sufficient to flatten the CCC?

Nothing is sufficient in software and never will anything be
sufficient. We are always challenged by harder and harder problems
and we must always be advancing our skill. We need to know how to do
paper design early, and how to do it late. We need to know how to
test early and how to test late. We need to know how to write code
to a design and how to evolve the code to include our new learnings.

And a thousand other things.

Ron Jeffries
www.XProgramming.com
Curiosity is more powerful than skepticism.

Ron Jeffries

unread,
May 16, 2011, 12:33:40 AM5/16/11
to software_cr...@googlegroups.com
Hello, Ralf. On Sunday, May 15, 2011, at 8:13:40 AM, you wrote:

> But I find it very limiting to stop at that.
> So I have ventured into "unknown territories" beyond TDD... (which in
> the end where not uninhabitated; I met other travellers back from
> another century over there).
> And what I�ve found is much more efficient than TDD - but maybe
> require a departure from some dearly held believes.

I do not prefer TDD because of faith, nor because of a lack of
understanding how to do non-code design. On the contrary, over the
half century I've been developing software, I have studied and
developed as much skill as I could in every design technique that
has attained prominence over that period ... including TDD plus
refactoring.

I have found value in all of those. I prefer TDD because, like Adan,
having developed rather high skill in all the techniques out there,
I find that a very liberal dose of TDD lets me go faster, with less
stress and fewer mistakes than any approach heretofore.

I have every reason to believe that the equation would hold true for
anyone of (roughly) equal skill in all the various forms of design
and coding under consideration. (I could imagine that some special
mental or physical characteristics might play in there. For example,
I would expect that a blind person would find UML design to be much
less productive than a sighted person might. And I can at least
imagine that someone's unique mental characteristics might leave one
ill equipped to do TDD (which to be done well MUST include focus on
both detailed coding and what you have elsewhere called "coarse"
design).

My experience in teaching TDD to many many individuals and teams has
led me to believe that most anyone can learn it. Since many people
can do in TDD what you say you cannot -- namely deal with detailed
and coarse design issues in that "medium" -- my confident
expectation is that these people learned something, attained some
perhaps small skill, that you, as yet, have not.

If there was just one guy standing here saying TDD can do what you
say it cannot, it might be a tossup. However, I can do it, Adam can
do it, George can do it and the many people we have helped learn it
can also do it.

That makes me quite confident that you could do it too. I'm not sure
why that seems insulting to you, but it seems that it does, and I
regret that. I still think you could also do it if you cared to, and
that it would change your preferences between paper and in-code
design if you did.

I'm perfectly happy if you choose not to. What I'm less happy about
is that your description of the universe as being one in which no
one can do coarse and fine design in the code is not the universe
I'm living in.

Ron Jeffries
www.XProgramming.com
I must create a system, or be enslaved by another man's;
I will not reason and compare; my business is to create. --William Blake

Ron Jeffries

unread,
May 16, 2011, 1:02:50 AM5/16/11
to software_cr...@googlegroups.com
Hello, Ralf. On Sunday, May 15, 2011, at 8:24:17 AM, you wrote:

> Sorry to say, but this seems to imply you know about my TDD skills
> well enough to recommend I improve on them.
> How come?

> Do you think just because I�m not all for TDD I�m not good at doing
> TDD?

No ... but since you say things about TDD that in my experience, and
that of many others, are simply not true, namely that it is
"multitasking" and therefore bad, and that it is not possible to
deal with fine and coarse design in code, I have to conclude that
some of us must know something about it that, as yet, you may not.

> I�d say there are other possible explanations:
> a. I�m good at TDD and still am dissatisfied with it�s results.

If that were the case you'd be saying different things. You'd not be
talking about how impossible it is to design this way but how
inefficient it is. Yet your argument leans much more on possibility
than it does on efficiency.

Even then, it would be necessary to explain why, despite reports of
TDD experts all around you, saying that it's the best way they know
so far, they are all wrong.

> b. I�m not good at TDD, but TDD nevertheless is not the pinnacle of
> software design, and even someone outside the "TDD believe system" can
> sense that.

The assumption that people who like TDD do so because they are
"believers" is ... a bit off. I like it because I've been doing it
assiduously for 15 years. Prior to those 15 years I have worked just
as hard learning every design technique as it came along. The sum
total of my current half-century of software development leads me to
the //discovery// -- not the mere belief -- that it is a very
powerful addition to my way of working and that, in particular, it
allows me to think about design in the presence of code, which
provides faster feedback than thinking about it separately.

But no one is saying TDD is "the pinnacle of design". We are saying
that day in and day out, we find that doing TDD, full-on, with
refactoring, gets our software done faster and better than when we
do it with up front paper design and then "code slinging", and
better than interleaving "code slinging" and paper design.

It turns out, we don't do "code slinging" at all: we use a very
disciplined way of producing code that keeps it clean, keeps it very
well supported by tests, and builds great skill in evolving the
design on the off chance (only 100%) that it will need it.

We still draw pictures of the code, or go chat about it, or get a
really good design idea in the shower or on the drive home. And we
build that design in a disciplined way that lets us incorporate not
just those insights, but the ones that come to us as we produce the
code in our incremental disciplined fashion.

> Also your statement implies: Ron is good at TDD (because TDD is the
> best way to design software); thus whoever is not doing TDD is wrong
> (or at least in danger of malpractice because he�s not applying what�s
> broadly recognized as the pinnacle of design).

Doesn't imply that at all. It happens that I've tried lots of ways
and find this one to be substantially more valuable than you do ...
and it happens (but does not imply) that I've helped many others get
this same discovery.

I didn't come to TDD directly from gross hackery. I came to it with
35 years of experience doing all the disciplined design approaches
that came along, and now I come to you with a full half century of
that plus 15 years of developing my TDD skills in the same way.

> Hm... this does not feel good, Ron.

Yes, I see that, and it really confuses me. I'm assuming something
good about you, namely assuming that you have the innate ability to
do what I can do, what Adam can do, what George can do, what many
others can do, and use TDD more effectively than you've reported
here.

And yet ... you seem to feel badly because I'm supposing you can
readily learn to do these things that you're reporting trouble on
just now.

I have confidence in you ... and somehow that hurts your feelings.
I'm sorry about your feelings, but not willing to withdraw my
confidence in you.

> This does not sound like the scientific method.

It isn't the scientific method. It is more like a report from your
future from someone who has been there. I've done waterfall method,
ad-doc development, Spiral Method, Structured Design, the Booch
Method, UML, and many more, in real world software development. And
I've done TDD for a long time as well.

I'm reporting that I find that TDD gives me certain advantages. I
observe that you are not getting those same advantages in the same
proportion. My best guess is that I have stumbled on a way of doing
it which you have not. Another possibility, of course, is that you
know a way of doing paper design that I don't know, that somehow
multiplies its power. Since you have repeatedly said things about
TDD that are not true for me and lots of people I know, I lean
toward the theory that there's at least one more TDD learning
waiting for you.

I could be wrong, and even if there is, you can decide not to seek
it. That's OK. I don't get royalties from people using TDD. I do
care that whenever you, or anyone, says "TDD can't do this", and
there are people out there like me who know that it can, one or more
of us says so.

TDD can be used to evolve a design faster than at least some people,
highly skilled in paper design, can do paper design and then code to
it. TDD can be used in situations where the requirements change, and
therefore the paper design initially created needs changing, and it
can let us do those changes without a rewrite.

It doesn't make much sense to me for you, or anyone, to suggest that
it cannot do that, because people are in fact doing it. The fact
trumps the theory. So whenever such a suggestion is made you can be
sure that I, and the others who know how to do those things, are
going to say "Hey, wait, we can do those things. It's just not true
that the only way to go is that other way."

Ron Jeffries
www.XProgramming.com
In times of stress, I like to turn to the wisdom of my Portuguese waitress,
who said: "Ol�, meu nome � Marisol e eu serei sua gar�onete."
-- after Mark Vaughn, Autoweek.

Ralf Westphal

unread,
May 16, 2011, 9:18:54 AM5/16/11
to software_craftsmanship
Ron, thx again for your time and effort to convince me of TDD.

Howver to quite some extend I don´t need to be convinced, because even
I acknowledge the value TDD has or can have.
It surely was, is, and will be an important step for our industry. No
doubt about it.
And even I am telling developers, they should practice it.
Once they are coding, they should do it using TDD.

We disagree only on one small detail. Rather then { red green
refactor } I think it should be red green { refactor red green }.

Our main disagreement is about when to start coding.
Where you concede sometimes working on paper might help, I´m a firm
believer in more "paperwork".
Not in the sense of producing heaps of documentation up front, of
course.
No, I view "paperwork" as an important method for a separation of
concerns in the process of producing software.

But maybe this hard to talk about in a discussion forum like this.
It would be easier to just show what I mean.
So again I´d like to motivate setting up a larger kata, a whole
application.

And despite your concerns it would be hard to compare solutions I´d
say we at least would see what the other parties mean, when they
describe their method.

I´d put correctness and evolvability to the test. How different
solution are able to evolve could be demonstrated by going through
iterations,
Example: You as some kind of host could think up a problem with, say,
12 features to be implemented in 4 iterations.
For each iteration you´d only publish 3 features - and leave the rest
in the dark. Then participating parties get some time to implement
them.

In the end, everyone is a winner, because we all learn from each other
and/or by exercising our skills.

How´s that? Less talk, more code ;-)

-Ralf

Curtis Cooley

unread,
May 16, 2011, 2:31:07 PM5/16/11
to software_cr...@googlegroups.com
On Mon, May 16, 2011 at 6:18 AM, Ralf Westphal <in...@ralfw.de> wrote:
> Ron, thx again for your time and effort to convince me of TDD.
>
> We disagree only on one small detail. Rather then { red green
> refactor } I think it should be red green { refactor red green }.
>
> Our main disagreement is about when to start coding.
> Where you concede sometimes working on paper might help, I´m a firm
> believer in more "paperwork".
> Not in the sense of producing heaps of documentation up front, of
> course.
> No, I view "paperwork" as an important method for a separation of
> concerns in the process of producing software.
>

I'm not sure what red green { refactor red green } looks like. Is the
first red on paper? Hmm, I hope not.

I am very interested in hearing more about your technique, Ralf. Like
Ron, I do TDD because it's given me the best rate of return so far. It
seems that every time I've tried to model and write clean code up
front, I've stalled, stumbled, made mistakes, and bumbled around
getting little done. Almost every time I've done a short design
session, then TDD, I've finished my task, and been proud enough to
share. Like George said, I "feel" much more efficient and effective
when I build features TDD.

If you have a new way to model that I can practice and learn that will
make me more efficient at building maintainable code than TDD, I'm all
ears. Just saying "do more modeling up front" isn't it, though,
because I've done that and then went to TDD.

I always try to remember the goal when I write code. The goal is
maintainability. No other measure of good design matters, because the
goal is keeping it easy to add new features. TDD clicked right away
with me in terms of the goal because TDD makes you maintain the code.
Again, it's viscosity working in your favor. And I'll say it again: If
you have a new way to build maintainable code better then TDD, please
share.

This has been a fascinating conversion, a little tense at times
perhaps, but very interesting. Thanks all!
--
Curtis Cooley
curtis...@gmail.com
blog:http://ponderingobjectorienteddesign.blogspot.com
===============
Leadership is a potent combination of strategy and character. But if
you must be without one, be without the strategy.
-- H. Norman Schwarzkopf

philip schwarz

unread,
May 16, 2011, 4:04:56 PM5/16/11
to software_craftsmanship
@Ron

thank you very much for your thoughts on, amongst other things,
investing into different design types, the role of paper design, how
its productivity compares to that of pure TDD, the importance of
knowing when to switch between paper design and TDD, and the
possibility that not everyone can do code and design at the same time.

Kaleb Pederson

unread,
May 16, 2011, 5:13:32 PM5/16/11
to software_cr...@googlegroups.com
Hi Curtis,

On Mon, May 16, 2011 at 11:31 AM, Curtis Cooley <curtis...@gmail.com> wrote:
...


> I always try to remember the goal when I write code. The goal is
> maintainability. No other measure of good design matters, because the
> goal is keeping it easy to add new features. TDD clicked right away
> with me in terms of the goal because TDD makes you maintain the code.
> Again, it's viscosity working in your favor. And I'll say it again: If
> you have a new way to build maintainable code better then TDD, please
> share.

I suppose this is automatically implied for many people, but when
reading Bob and Micah Martin's /Agile Principles, Patterns, and
Practices in C#/ (APPP) it really struck me that it's not nearly as
simple as focusing on maintainability. Indeed, I had often focused too
much on maintainability; I had used too many design patterns for the
sake of maintainability when a few functions would have been simpler
and sufficient. It probably didn't take me much longer to use those
design patterns, but I wasted time. I was attempting to anticipate
changes that would never come.

APPP puts it this way, '"Fool me once, shame on you. Fool me twice,
shame on me." This is a powerful attitude in software design. To
keep from loading our software with needless complexity, we may permit
ourselves to be fooled once. This means that we initially write our
code expecting it not to change. When a change occurs, we implement
the abstractions that protect us from future changes of that kind. In
short, we take the first bullet and then make sure that we are
protected from any more bullets coming from that particular gun" (pg
129).

I think there are many barriers to doing TDD well, like the above.
Despite following the three laws of TDD, I wasn't doing TDD
particularly well. How much is too much refactoring, for example? I
overdid it, and I recognize that now. I had to learn to trust myself
enough to leave the code as-is until a sufficiently strong stimulus
came along at which point I could refactor it to a more reasonable
design against real "changes of that kind."

--
Kaleb Pederson
Blog - http://kalebpederson.com
Twitter - http://twitter.com/kalebpederson

>
> This has been a fascinating conversion, a little tense at times
> perhaps, but very interesting. Thanks all!
> --
> Curtis Cooley
> curtis...@gmail.com
> blog:http://ponderingobjectorienteddesign.blogspot.com
> ===============
> Leadership is a potent combination of strategy and character. But if
> you must be without one, be without the strategy.
> -- H. Norman Schwarzkopf
>

> --
> You received this message because you are subscribed to the Google Groups "software_craftsmanship" group.
> To post to this group, send email to software_cr...@googlegroups.com.
> To unsubscribe from this group, send email to software_craftsma...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/software_craftsmanship?hl=en.
>
>

Olivier Azeau

unread,
May 16, 2011, 5:55:39 PM5/16/11
to software_cr...@googlegroups.com
Le 16/05/2011 05:17, Ron Jeffries a �crit :

>
> Now back to Olivier's program. It is in fact simpler ... but is it
> as easy to understand? I'm not sure. On the one hand it has
> everything embedded in that single convert method but even for a
> lover of the ternary operator, that method is tricky to understand.
> It is recursive (very cool) and therefore harder to understand than
> Ralf's loop.

Ron,
Thanks for your comment.
I agree with your statement: the code is not easy to understand and
needs further refactoring to make it understandable.

In my opinion, this is the kind of refactoring the most difficult to
deal with: transform the code so that someone else will find it easy to
read.
One thing that usually helps me is to think about the model behind the
code that comes out of the TDD and check if this model is visble just by
reading the code.
I should have done that with this program but I did not and the model
("the digits in base N for a given number is the concatenation of the
digits representing the part of the number grouped in packs of N units
and the single digit for the remaining units") remained hidden.

Olivier

Olivier Azeau

unread,
May 16, 2011, 5:54:32 PM5/16/11
to software_cr...@googlegroups.com
Le 16/05/2011 00:50, Ralf Westphal a �crit :

> But does your solution prove me completely wrong?
> No, I don't think so.
> Implementing algorithms is not really what baffles most developers.
> Rather it's working on larger problems, how to structure software
> systems.
> And it's how to put several developers to work on the same feature at
> the same time to jointly produce it as fast as possible (think WIP=1).
>
> For that some kind of "design of coarse grained functional units" is
> necessary, eg classes, components, packets, services. TDD is hardly of
> help then.
Putting several developers to work on the same feature is, to me, an
issue with TDD because design emerges from coding and, at some point,
the multiple designs have to fit with each other.
I did not figure out any other way than starting with a bit of design
before coding ;-)
In my team, being given a feature to implement, we try to stick to WIP=1
and we proceed more or less like the following:
1) split the feature in tasks
2) define rough 1st version of contracts to articulate tasks: real code
-OOP "interfaces" in our case- but no tests + stick to minimal set of
contracts for the current feature (reuse existing contracts if any)
3) work in parallel with TDD on tasks.
For each task:
3a) red
3b) green
3c) merge code in trunk
3d) refactor - if refactor modify contracts, immediately sync design
ideas with colleagues
3e) merge code in trunk
3f) go to 3a until task is done

Does it make sense to you?


Olivier

Curtis Cooley

unread,
May 16, 2011, 5:52:55 PM5/16/11
to software_cr...@googlegroups.com

Hi Kaleb!

I couldn't agree more with what you just wrote, and it means I
misrepresented what I meant. TDD helps me write maintainable code
because it helps me keep the design simple. I can see how designing
for maintainability could lead to over-designed code, but I would
argue that over-designed code is less maintainable than simple TDD
code.

You've made me start to contemplate the meaning of maintainable, and
that's a good thing! Off the top of my head, I meant maintainable in
the sense that it's easy to understand, fix, and extend. I guess that
it conforms to the XP rules of simplicity?

The reason we care about design is so we don't make a mess. We don't
want to make a mess because someday we'll have to go back and fix or
extend the code. I guess that's the goal? Don't make a mess?

philip schwarz

unread,
May 16, 2011, 8:08:27 PM5/16/11
to software_craftsmanship
Hi Ron,

>> Is TDD necessary to flatten the CCC?

> Depends how much you want to flatten it. Comprehensive unit tests
> might do the same level of testing at higher cost. Changing the code
> without understanding behavior-preserving transformations might
> still allow us to make changes, but more slowly thus not flattening
> the curve as much.
> TDD / refactoring are the best way we know // at the coding level //
> to keep the curve flat. Perfect up front design will not do this,
> from the viewpoint of XP and Agile, because (a) perfect up front
> design is not possible, (b) implementing a perfect design perfectly
> is not possible, (c) up front design is done at the moment we know
> less than we ever will again, and (d) things change anyway.
> That doesn't mean we don't do paper design: we do and it is good. It
> just doesn't give us the things that TDD does and we need those
> things.

Although your answer does tell me an important part of what I wanted
to find out with my questions, it also makes me realise that to find
out the other parts I should have phrased the questions thus:

Is TDD a part of XP that is NECESSARY to flatten the curve
Is TDD a part of XP that is SUFFICIENT to flatten the curve

Asking both questions was just my roundabout way of asking whether TDD
is PRECISELY the part of XP that flattens the curve.

The reason I wanted to know this is because I remember that when I
first read about how XP worked, I found the idea of flattening the
curve remarkable. One minute, XP was putting me at ease by mentioning
the familiar universal software engineering assumption that the cost
of change curve is exponential, and the next minute it was turning
everything upside down by saying that it was able to flatten the
curve, which allowed it to justify contrarian strategies like TSSTCPW,
YAGNI, and Last Responsible Moment, which in turn reduced project risk
and thus increased project value. Also, you know how sometimes you
hear developers asking: "How can I sell the idea of refactoring the
codebase to my manager". And the answer is some compelling analogy,
e.g "Think of code that needs refactoring as a "growth". Removing it
requires invasive surgery. You can go in now, and take it out while it
is still small. Or you could wait while it grows and spreads - but
removing it then will be both more expensive and more dangerous. Wait
even longer, and you may loose the patient entirely". Well I thought
that the key technical premise of XP, a flat curve, was also
remarkable in that although at first it clearly seemed impossible, it
was so simple to grasp (due in part to people's familiarity with the
exponential curve) that once I suspended my disbelief, it was
compelling how the seemingly contrarian strategies were justified by
the premise. I thought that XP's premise would be very important and
effective in selling XP to managers.

Assuming the answer to my questions is that TDD is THE part of XP that
flattens the curve (or at least a significant part of it), then TDD
has the same key technical premise as XP. But unless I am mistaken,
when TDD is discussed/advocated as a stand-alone technique, outside
XP, I don't think I hear people mentioning the technical premise. I
don't think I hear people using the idea of the flat curve to justify/
explain TDD.

When Ralf said that doing design through refactoring is wasteful/
painful, that it is faster/cheaper to refactor the design model
instead, I decided to suggest to him that he should view the cost of
slowly refactoring from passing test to clean design as the reasonable
price to pay for the benefits that result from TDD's flattening of the
cost of change curve: much reduced risks and the attending increase in
project value.

Here is a passage from Extreme Programming Explained that acknowledges
the cost, but balances it with the payoff:

"When implementing a program feature, the programmers always ask if
there is a way of changing the existing program to make adding the
feature simple. After they have added a feature, the programmers ask
if they now can see how to make the program simpler, while still
running all of the tests. This is called refactoring. Note that this
means that sometimes you do more work than absolutely necessary to get
a feature running. But in working this way, you ensure that you can
add the next feature with a reasonable amount of effort, and the next,
and the next. You don't refactor on speculation, though; you refactor
when the system asks you to. When the system requires that you
duplicate code, it is asking for refactoring. If a programmer sees a
one-minute ugly way to get a test working and a ten-minute way to get
it working with a simpler design, the correct choice is to spend the
ten minutes. Fortunately, you can make even radical changes to the
design of a system in small, low-risk steps"

I have not replied to Ralf yet because I am still digesting his claims
that by doing the design before the coding, he also experiences a flat
cost of change curve, and that rather than designing through
refactoring, he says he can pay less by refactoring the design model,
and then modifying the code to reflect the new design. I find your
answers at the top of this post, and in other posts useful in
addressing these claims.

Philip

On May 16, 4:39 am, Ron Jeffries <ronjeffr...@acm.org> wrote:
> Hello, philip.  On Sunday, May 15, 2011, at 4:19:03 PM, you wrote:
>
>
>
>
>
>
>
>
>
> > ####################################
> > With these elements in place simple design, tests, and an attitude of
> > constant refinement of the design we experienced the flattened curve.

Adam Sroka

unread,
May 16, 2011, 8:29:15 PM5/16/11
to software_cr...@googlegroups.com
On Mon, May 16, 2011 at 5:08 PM, philip schwarz
<philip.joh...@googlemail.com> wrote:

> Is TDD a part of XP that is NECESSARY to flatten the curve

I believe it is. The reason I believe that is that I believe that
comprehensive automated testing is necessary to get the level of
feedback needed to flatten the curve, and these tests must be run very
often (At least on the order of a few times per hour. Much faster
should be possible.) I have heard many claims that such aggressive
testing is possible without TDD, but every time I have had an
opportunity to investigate such a claim I have found that the team
wasn't doing nearly enough "test-after" to get the benefits.

> Is TDD a part of XP that is SUFFICIENT to flatten the curve

I believe it is *not*. At the very least some sort of aggressive
automation is needed so that changes can be tested and shared
immediately with the whole team. Whether this looks like traditional
continuous integration, continuous delivery, or something else I am
not sure.

I also think that having a collaborative work environment where I can
simply shout when I need to have a discussion about something I am
about to do is a huge benefit to flattening the curve. I have heard of
teams managing this adequately when they were distributed, but, again,
I have never witnessed it (I have witnessed distributed environments
where design was shared within hours or days, but not immediately.)

Pair programming is also useful. In my experience good pair
programming is at least as important to simple design in XP as
test-first programming is. Having my pair chime in with a good idea at
just the right moment or catch a mistake right when I make it is a
huge factor in flattening the curve.

>
> Asking both questions was just my roundabout way of asking whether TDD
> is PRECISELY the part of XP that flattens the curve.
>

What would you do with that answer if you got it?

Part of the challenge of adopting XP piecemeal is that the practices
support each other very nicely. There is a synergistic effect that
happens when you are doing just enough of each of them that doesn't
seem to happen when you do one or two in isolation. That's not to say
that everyone does (or should do) XP the same way, but when it works
it works like a stew -- the right stuff in the right proportions, no
single ingredient dominates.

Ron Jeffries

unread,
May 16, 2011, 10:36:21 PM5/16/11
to software_cr...@googlegroups.com
Hello, philip. On Monday, May 16, 2011, at 5:08:27 PM, you wrote:

> Although your answer does tell me an important part of what I wanted
> to find out with my questions, it also makes me realise that to find
> out the other parts I should have phrased the questions thus:

> Is TDD a part of XP that is NECESSARY to flatten the curve

No ... there are many practices to keep the code alive and they all
flatten the curve somewhat. TDD is one of the more powerful
flatteners.

> Is TDD a part of XP that is SUFFICIENT to flatten the curve

It flattens it somewhat. There are ways to flatten it more.

> Asking both questions was just my roundabout way of asking whether TDD
> is PRECISELY the part of XP that flattens the curve.

No. ATDD does. Continuous integration does, pair programming does,
refactoring sans TDD does ...

> The reason I wanted to know this is because I remember that when I
> first read about how XP worked, I found the idea of flattening the
> curve remarkable. One minute, XP was putting me at ease by mentioning
> the familiar universal software engineering assumption that the cost
> of change curve is exponential, and the next minute it was turning
> everything upside down by saying that it was able to flatten the
> curve, which allowed it to justify contrarian strategies like TSSTCPW,
> YAGNI, and Last Responsible Moment, which in turn reduced project risk
> and thus increased project value.

The cost of change topic is, in my opinion, mostly a red herring. A
sufficient reason for doing the simplest thing is that doing a more
complex thing (obviously) takes longer. A sufficient reason behind
YAGNI is that investing prior to the moment one needs the investment
is wasteful. Similarly for LRM.

> Also, you know how sometimes you
> hear developers asking: "How can I sell the idea of refactoring the
> codebase to my manager". And the answer is some compelling analogy,
> e.g "Think of code that needs refactoring as a "growth". Removing it
> requires invasive surgery. You can go in now, and take it out while it
> is still small. Or you could wait while it grows and spreads - but
> removing it then will be both more expensive and more dangerous. Wait
> even longer, and you may loose the patient entirely". Well I thought
> that the key technical premise of XP, a flat curve, was also
> remarkable in that although at first it clearly seemed impossible, it
> was so simple to grasp (due in part to people's familiarity with the
> exponential curve) that once I suspended my disbelief, it was
> compelling how the seemingly contrarian strategies were justified by
> the premise. I thought that XP's premise would be very important and
> effective in selling XP to managers.

When a team tries to sell "refactoring the code base" they are in
very dangerous territory. First of all the request tells me that the
team have crapped up their code base, which is prima facie evidence
that the team isn't really very good.

Second, the only argument for refactoring after the code is crapped
up is that we will go "faster, later". So this team that wasn't
smart enough not to crap up their code base is now asking me to
throw good money after bad so that they -- demonstrably incompetent
though they are -- can work in some invisible way in hopes of doing
a good enough job to speed up later.

I don't think so. A manager would, nine times out of ten, be a fool
to agree to this.

The right strategy when the code is bad is to make it better
incrementally, by refactoring areas where new features are wanted,
making them a bit cleaner (and therefore making the next feature to
pass through a bit easier to do), while continuing to deliver
features, which is, after all, what the team is paid to do.

So if a team said to me "we need to refactor our code base", I would
be pretty sure that they don't know what a good code base looks
like, that they don't really know what they are changing or why, and
that they don't understand the business's problem, which is to get
new features soon.

In short, that's a beginner's request and I would not be inclined to
support it.

> Assuming the answer to my questions is that TDD is THE part of XP that
> flattens the curve (or at least a significant part of it), then TDD
> has the same key technical premise as XP. But unless I am mistaken,
> when TDD is discussed/advocated as a stand-alone technique, outside
> XP, I don't think I hear people mentioning the technical premise. I
> don't think I hear people using the idea of the flat curve to justify/
> explain TDD.

The curve never goes flat. The XP practices, done well, permit a
team to produce features at roughly a constant rate over a long
period of time. TDD is a big part of this. It isn't all of it, and
you have to do it bloody well to get the benefits.

> When Ralf said that doing design through refactoring is wasteful/
> painful, that it is faster/cheaper to refactor the design model
> instead, I decided to suggest to him that he should view the cost of
> slowly refactoring from passing test to clean design as the reasonable
> price to pay for the benefits that result from TDD's flattening of the
> cost of change curve: much reduced risks and the attending increase in
> project value.

I don't follow that but I think it's because I don't buy the cost of
change curve argument as a strong motivator in any case.

> Here is a passage from Extreme Programming Explained that acknowledges
> the cost, but balances it with the payoff:

> "When implementing a program feature, the programmers always ask if
> there is a way of changing the existing program to make adding the
> feature simple. After they have added a feature, the programmers ask
> if they now can see how to make the program simpler, while still
> running all of the tests. This is called refactoring. Note that this
> means that sometimes you do more work than absolutely necessary to get
> a feature running. But in working this way, you ensure that you can
> add the next feature with a reasonable amount of effort, and the next,
> and the next. You don't refactor on speculation, though; you refactor
> when the system asks you to. When the system requires that you
> duplicate code, it is asking for refactoring. If a programmer sees a
> one-minute ugly way to get a test working and a ten-minute way to get
> it working with a simpler design, the correct choice is to spend the
> ten minutes. Fortunately, you can make even radical changes to the
> design of a system in small, low-risk steps"

OK ...

> I have not replied to Ralf yet because I am still digesting his claims
> that by doing the design before the coding, he also experiences a flat
> cost of change curve, and that rather than designing through
> refactoring, he says he can pay less by refactoring the design model,
> and then modifying the code to reflect the new design. I find your
> answers at the top of this post, and in other posts useful in
> addressing these claims.

Ralf isn't wrong that it is easier to refactor a paper design than a
code design. It /is/ easier. It's not wrong to think on paper. It
is, however, less than ideal to think very long without testing
one's ideas in code. Speculative design is easy to get a bit wrong
in many different ways. In the example Ralf bravely did, we saw
partial abstractions plus over-design. When we combine that kind of
thinking with the concrete code, we get faster feedback on the
design. When we know how to TDD and refactor well, we don't need to
stop thinking and we can make better decisions as to how quickly to
move to code.

Ron Jeffries
www.XProgramming.com
When you blame others, you give up your power to change.
-- Robert Anthony

Ron Jeffries

unread,
May 16, 2011, 10:40:03 PM5/16/11
to software_cr...@googlegroups.com
Hello, Olivier. On Monday, May 16, 2011, at 2:55:39 PM, you wrote:

> One thing that usually helps me is to think about the model behind the
> code that comes out of the TDD and check if this model is visble just by
> reading the code.
> I should have done that with this program but I did not and the model
> ("the digits in base N for a given number is the concatenation of the
> digits representing the part of the number grouped in packs of N units
> and the single digit for the remaining units") remained hidden.

Exactly ... and this is where Ralf is on a good track. It is often
useful to use a "paper" model to help us see what we have done, or
what we should do.

My only concern with Ralf's position is not the use of external
models. It is that I believe he under-values the power of TDD /
Refactoring. Since TDD / Refactoring pays off for me and many
others, that leads me to think he's doing something else.

Ralf: Note that I'm answering email randomly. I know you have a
reply to me that I've not responded to and I'll do that shortly.
This one precedes that one and therefore does not include whatever
you most recently said.

Ron Jeffries
www.XProgramming.com
Make it real or else forget about it -- Carlos Santana

George Dinwiddie

unread,
May 16, 2011, 11:54:28 PM5/16/11
to software_cr...@googlegroups.com
Hi, Olivier,

On 5/16/11 5:54 PM, Olivier Azeau wrote:
> Putting several developers to work on the same feature is, to me, an
> issue with TDD because design emerges from coding and, at some point,
> the multiple designs have to fit with each other.
> I did not figure out any other way than starting with a bit of design
> before coding ;-)

I've found it works quite well with the developers communicating during
coding. Have you tried that?

Ralf Westphal

unread,
May 17, 2011, 1:27:45 AM5/17/11
to software_craftsmanship
On 16 Mai, 20:31, Curtis Cooley <curtis.coo...@gmail.com> wrote:
> I'm not sure what red green { refactor red green } looks like. Is the
> first red on paper? Hmm, I hope not.

No, sure Red Green is not on paper. How could it? Writing with red and
green pens? ;-)

When I say

Red Green { Refactor Red Green }

I´m just expressing, that refactoring should be done before you add
new functionality.
It should always be done with a clear task at hand to add customer
value.
Because if you refactor after you´ve written code, it can be an effort
without end. There´s always a bit more to refactor, code can become
ever more cleaner - until you´re caught in questions of style (think
collective code ownership and different people working on the same
piece of code).

To avoid the pitfall of doing refactoring for refactoring´s sake I
prefer to let the implementation of a new feature (or fixing of a bug)
start with refactoring.

While doing TDD (on the alpha-end kata) this does not make much of a
difference. You go thru the cycle very quickly and finishing a small
piece of functionality means starting with the next small piece.

Still I find it important to group the actions differently to
emphasize that refactoring is a tool with a purpose.

Also I find refactoring easier if I know what for to do it. If I have
some concrete functional change in mind, then I can see much more
clearly towards which structure to refactor - and I know when to stop.


> session, then TDD, I've finished my task, and been proud enough to
> share. Like George said, I "feel" much more efficient and effective
> when I build features TDD.

I know. This has been stated here by many. And I´m doing TDD myself -
sometimes.

But I can assure you, I not only feel proud after having coded stuff
the test-first way (that´s what I always do), I also feel relieve when
seeing before me a tangible model of the code I´m gonna write. Half
the work´s done, no, even more. Implementation usually is a piece of
cake. Quite uninteresting even.

And it´s so much easier to be able to stand with any number of
colleagues around a whiteboard and be able to design in a way that
right away leads to evolvable structure. No being alone while
designing has as many benefits as not being alone when checking code
during a review.


>
> If you have a new way to model that I can practice and learn that will
> make me more efficient at building maintainable code than TDD, I'm all
> ears. Just saying "do more modeling up front" isn't it, though,
> because I've done that and then went to TDD.

If you´re really open to learning more about how - let me say - TDD
could be complemented, then let´s think about how I could show you
what I mean.
The form of a forum like this seems a bit limiting to me.

Am I just saying "do more modelin up front"? No, there´s more to it.
But explicit design is very important to me.

Please suggest a way of communicating to dive deeper. Because only
seeing is believing :-)


>
> I always try to remember the goal when I write code. The goal is
> maintainability. No other measure of good design matters, because the
> goal is keeping it easy to add new features.

We´re on the same page here. 100%. This is the driving force behind
whatever I´ve said.


> Again, it's viscosity working in your favor. And I'll say it again: If
> you have a new way to build maintainable code better then TDD, please
> share.

I´d love to. I´m constantly doing so. That´s in fact my job.
If you like I´d be happy to invest time into, for example, a screen
sharing session with you.


>
> This has been a fascinating conversion, a little tense at times
> perhaps, but very interesting. Thanks all!

Yes, a little tense sometimes. And I apologize for having contributed
to this tension :-|
Tension hampers learning. But then, tension sometimes - as is the case
here, I believe - is the result of passionate people trying to get the
other "see the light" they´re seeing.

-Ralf

Ralf Westphal

unread,
May 17, 2011, 1:33:08 AM5/17/11
to software_craftsmanship
On 16 Mai, 23:52, Curtis Cooley <curtis.coo...@gmail.com> wrote:
> I couldn't agree more with what you just wrote, and it means I
> misrepresented what I meant. TDD helps me write maintainable code
> because it helps me keep the design simple. I can see how designing
> for maintainability could lead to over-designed code, but I would
> argue that over-designed code is less maintainable than simple TDD
> code.

Could you (or anybody) please give a definition of "overdesigned
code"?

We know what clean code is: code which is true to principles like SRP,
SoC, SLA, LoD, LSP etc.

But what are criteria for "overdesigned code"?

-Ralf

Ralf Westphal

unread,
May 17, 2011, 1:58:07 AM5/17/11
to software_craftsmanship
> I have not replied to Ralf yet because I am still digesting his claims
> that by doing the design before the coding, he also experiences a flat
> cost of change curve, and that rather than designing through
> refactoring, he says he can pay less by refactoring the design model,
> and then modifying the code to reflect the new design. I find your
> answers at the top of this post, and in other posts useful in
> addressing these claims.

Thx for taking me so seriously, Philip!

To help you, let me explain a bit more, what I mean:

There is a kind of code refactoring you want to avoid, and there is
another kind you cannot avoid.

To provide some kind of functionality code needs a structure. Some
structures a better than others.
We´re looking for the optimal structure in terms of understandability,
changeability, testability.

If code should provide functionality A a certain structure is optimal.
If code should also provide functionality B the structure sure needs
to change to stay optimal.
And the for C another change is necessary.

Each change to keep an already optimal structure optimal in the face
of new functionality is refactoring. That´s unavoidable, good
refactoring.

Bad refactoring I call refactoring that´s needed to transform a
suboptimal structure into an optimal one.
That´s what typically is necessary in brownfield code. Brownfield code
by definition is much less than optimal. So you have to invest bad
refactoring effort to get to a point where good refactoring even
becomes possible.

Now, what I prefer is, to produce code that´s understandable,
changeable, and testable in the first place.

Let me say: I find that easier and much, much more group friendly, and
better communicable with a design on paper. At least until a certain
level of detail. I sure won´t write any lines of code on a whiteboard
and call that design. No, the visual language used for design should
not be imperative like source code.

Designing before coding is only half the truth, to me. Not just any
sketch on a whiteboard is helpful.
The design also should be done in a certain way to be easy to
translate into code, and to be understandable and evolvable and lead
to high testability.

Let me sum up what I mean by saying:
-I want to be able to design software in a group
-I want to be able to communivate designs easily to newcomers
-I want to be able to very easily translate design into code (yes, a
translation is needed since design by definition, I´d say, is on a
higher level of abstraction than code)
-I want designs to be easily changeable
-I want to be able to describe a solution on any (!) number of levels
of abstraction
-I want to be able to easily keep design and code in sync
-I want to be able to easily try out different designs for different
scopes of functionality

And I´ve found a away to reach all those goal. But, alas, it´s not
object oriented design - although I´m of course using object oriented
languages to implement it.

So to reap all the benefits I had to let go of certain practices and
concepts I had become used to. This was a process of several years and
I´m still right in the middle of it. But I´ve tasted the sweetness of
collaborative design of clean structures :-)

Like Olivier let me invite you to a real time online discussion (or
phone conversation) to talk about this more closely (including desktop
sharing).

Processes are best shown, not written about.

-Ralf

Ron Jeffries

unread,
May 17, 2011, 6:37:33 AM5/17/11
to software_cr...@googlegroups.com
Hello, Ralf. On Monday, May 16, 2011, at 10:33:08 PM, you wrote:

> On 16 Mai, 23:52, Curtis Cooley <curtis.coo...@gmail.com> wrote:
>> I couldn't agree more with what you just wrote, and it means I
>> misrepresented what I meant. TDD helps me write maintainable code
>> because it helps me keep the design simple. I can see how designing
>> for maintainability could lead to over-designed code, but I would
>> argue that over-designed code is less maintainable than simple TDD
>> code.

> Could you (or anybody) please give a definition of "overdesigned
> code"?

Code is over-designed to the extent that it contains more classes,
methods, or other entities than are required by its present level of
function. A simple example is the existence of unused code, put in
because "we're gonna need it".

Kent Beck's definition of "Simple Code" is

1. Runs all the tests;
2. Contains no duplication;
3. Expresses all our design ideas;
4. Minimizes the number of classes, methods and other entities.

Over-designed code violates #4 by having more entities than are
required to express the design, or #3 by having more design
expression than required to support the current tests.

An example in the number conversion example would be the insertion
of an abstract superclass and a single concrete subclass, before the
code actually needs to support multiple numeric bases.

Someone designing on paper might will discover the perfectly good
design of using a simple concrete subclass for each numeric base,
perhaps just containing the list of digits for that base, or any
such implementation, inheriting from an abstract superclass. It
would be almost impossible for most of us to build a single-base
version without putting in the abstract superclass and the single
subclass we really need. We just couldn't resist.

Until the day (or hour or minute) that that code gets the second
concrete class, it is over-designed for its capability.

A good TDDer, Kate Oneal, thinking about this problem as she went
along, might see the same design. Kate would not put in the abstract
superclass / concrete subclass in response to her single base tests:
she //might// build a single concrete class.

Kate might even build the list of digits in line in the conversion
class: I believe Olivier's program may have done that. At some point
during the implementation of the original numeric base, she would
allow herself to "notice" that inside the conversion class there was
a numeric base idea trying to get out. She might, at that point,
extract a concrete "Base13" class.

Then she would stop. Kate knows as well as we do that for the next
numeric base she is going to need the abstract / two concrete
structure. But she doesn't need it now. So she doesn't put it in.

Then she writes the first base-seven test. Quite likely, it runs.
Soon she expresses a number bigger than seven in her base seven
tests ... and surprise! (not really) she "discovers" the need for
the abstract / concrete structure.

Then Kate probably does one of two things:

1. She comments out the red > 7 test, gets back to green, then puts
in the abstract class and the concrete base 13 class. She then
uncomments the > 7 test, goes red, and uses the red bar to implement
the other concrete class.

Or, 2, she implements the > 7 test by putting in some little bit of
hackery, such as an if statement in the base 13 class that checks
the desired base somehow, and returns the base 7 list:

if ( base == 13 ) return digitsOneThruD;
else return digitsOneThru7;

This makes the test go green. Kate then goes Oh wow look, this
design is starting to suck (but she's not really surprised), and she
refactors the if statement into the two classes.

(Replace Conditional with Polymorphism,
http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html)

The up-front design person, Gil, says

"How wasteful! We knew all along that we needed the abstract /
concrete structure. We should have put it in at the beginning."

Kate responds

"Yes, we knew that. The TDD ritual is to wait for the code to tell
us, whether we know or not. This gives us some things that we
like:

"First, we never have more code than we need to get to the current
green. This minimizes the code ... and minimizes the time to get
to green. We can ship on any green, as soon as we have enough
function.

"Second, by practicing recognizing this need -- pretending that we
don't see this obvious design -- we become skilled at getting
design ideas from the code. Since much of the code we will
encounter in our lives will have design flaws, this skill at
recognizing the need, and responding to it with the right
refactoring, serves us well."

The design person, Gil in this case, always replies that it seems
wasteful to him, since obviously and admittedly the TDD way went
through one or more unnecessary steps:

"With your silly TDD way, you had to type in code and then change
it. That's just plain waste! With my way, I just type in the
correct code to begin with. That's far more efficient."

Kate smiles, having been here a million times before. She says:

"Perhaps not. If I can spend less time in up front design than I
used to, I get my first tests running sooner. Think of it this
way: there is simply less code to type in to get base 13 running.
With that, plus the shorter time I spend in up front design, I can
get base 13 running faster than I could if I first spent more time
up front, and then spent more time typing it in because it's a
longer solution.

"Second, any up front design is speculative. I expect that it will
work, and because I'm a good designer, I am usually right. But I
won't know how well that design really fits until I begin to build
it, and to use it.

"Gil, probably in your programming life, you've been handed a
bunch of classes to use to build something. If your life has been
like mine, you found that those classes were useful, but hard to
use and didn't really quite fit your problem. Early on, if your
experience is like mine, your use of those classes was a pain.
They were too complex to use readily."

Gil has had that experience too, and nods. Kate goes on:

"I have learned that even when I do my own design, if I create the
abstractions first, they often do not quite fit my desired usage.
They get in the way a bit, slowing down my learning and my
implementation. So I've found that starting with the simple design
and evolving it as I need it works better for me."

Gil replies, as they always do:

"OK but if you were better at up front design, I still think you
would go faster by the end, because you wouldn't have to do all
that extra editing."

Kate replies cheerfully:

"Better at up front design, like you, I suppose you mean? Maybe
so. But its not clear, is it? Another perfectly possible outcome
is that a programmer using TDD would go faster to any given green
bar, because they never write a line of code prior to that moment
that they do not need.

"If each refactoring happens at the earliest necessary moment, it
will be quite small, and generally the IDE's refactoring tools
will do it in a few keystrokes. The TDD pracitioner starts out
ahead, by working simply. They might stay ahead forever, by
refactoring promptly, always ensuring that they have the minimal
code for the moment."

Now Gil is pissed off.

"You're saying that you can design better than I can using this
stupid TDD way and that you're smarter than I am because you can
design and code at the same time. I can design your pretty ass
right into the ground."

Kate says,

"I'm not saying that. I'm saying that I'm pretty good at design
and pretty good at TDD, and that for me, I go faster with a bit
less up front design than I used to use. That lets me hit the
ground running -- if I were into running which I am not -- and
then my simultaneous use of the design and building of the design
gives me better results. I get faster feedback about how good my
design is because I use it sooner.

"I'm totally sure that if you had exactly the same design skill
that I have, and exactly the same TDD skill, you'd get the same
results. But of course our skills aren't quite the same.

"If your design skills really are substantially better than mine
-- and thank you for the complement about my ass but I'll stay
above ground for a while longer if you don't mind -- then even
with my head start getting to the first green bar, you might catch
up by the final green, through saving all the typing I do to
refactor. Depending how quickly you could get the first up front
design right, or how quickly you could go back and forth between
paper and code, you might come out ahead.

"But I do start sooner, and I switch to paper less frequently.
This gives me time to do a little more typing. And, just possibly,
because I always build the least code I can to do my current job,
I might inject fewer stupid coding mistakes, or discover them
sooner because my TDD tests tell me. So I have less switching
overhead, and maybe less debugging overhead. I might stay ahead
forever because of lower overhead.

"Maybe not in this case, since you are a god among designers, but
in many cases it's also possible that I do design just as well as
the next person, but that I'm somehow more facile with TDD than
they are. If that's the case, again I'd stay ahead forever, simply
because I start sooner and don't slow down due to under design.

"But honestly the comparison of your design powers with my silly
way of doing things doesn't matter to me. I've studied design more
than most people and done TDD thoughtfully for a long time. For
me, it works best. I've seen it work best for a lot of other
people, and my intuitive feeling is that unless someone designs at
some incredibly high level, and is perhaps also really slow at
editing ... well anyway, my feeling is that for people about like
me, TDD will work better when they've come to use it as I do.

"But that's just my feeling. I'm just saying that it works for me,
and I have a pretty good sense of why. I wanted to share that with
you. Do with it as you will. It makes me better to work the way I
do, and that's why I do it."

Gil says, "Kate, you argue like a demon from hell. But I'm still not
convinced TDD is better for me."

Kate replies,

"Thank you. I am the descendent of a long line of litigators, but
I decided to get honest work instead. And I don't know whether TDD
is better for you. Everyone is different. All I know is that I
have worked long and hard learning design and becoming facile with
TDD, and it's better for me. I know a lot of people who have done
the same and had the same discovery.

"Maybe you're past that point and you are different. Or maybe that
discovery still lies before you. It may not matter at all. Your
work is good, and fast. Learning to shift more of your time from
paper design to TDD design might make you better still, or it
might not. Maybe you'll find my experience tantalizing enough to
push further to find out more about what's true for you, or maybe
you won't. Either way, you get to decide."

Ron Jeffries
www.XProgramming.com
To be on the wire is life. The rest is waiting. --Karl Wallenda

Esko Luontola

unread,
May 17, 2011, 7:55:25 AM5/17/11
to software_craftsmanship
On May 17, 8:27 am, Ralf Westphal <i...@ralfw.de> wrote:
> I´m just expressing, that refactoring should be done before you add
> new functionality.
> It should always be done with a clear task at hand to add customer
> value.
> Because if you refactor after you´ve written code, it can be an effort
> without end. There´s always a bit more to refactor, code can become
> ever more cleaner - until you´re caught in questions of style (think
> collective code ownership and different people working on the same
> piece of code).

If you skip the refactoring step after getting a test passing and
refactor it only after the next time that you come back to the code
(possibly days or weeks later), then it will be much harder to
remember what was your intent when writing the code and since the code
is not refactored to show the intent, it will be much slower to
refactor it - you will first need to reverse engineer the code and
understand how it works. I think it's much better to spend that 5
minutes removing the duplication and improving the names, right after
getting the test pass, while it's still fresh in your memory.

Also I don't think that refactoring is "an effort without end". When
you do it a couple minutes after every test, there won't be much
refactoring to do, because the code will not drift far away from a
clean state.

Could it be that you've experienced teams which keep on adding useless
abstractions and design patterns to the code and call it
"refactoring"? I would call that "over-engineering" which gets the
code further away from a clean, simple state. Instead they should just
stick to the basics: http://www.jbrains.ca/permalink/the-four-elements-of-simple-design

David Wilde

unread,
May 17, 2011, 8:21:37 AM5/17/11
to software_cr...@googlegroups.com
It shouldn't be that difficult to work out the intent of the code because the unit test should describe this.

Customer value is always a difficult subject with refactoring. It would be nigh on impossible to express the customer value of an individual refactoring effort no matter how soon it is performed. The challenge is harness a relationship with the customer that means that they appreciate the overall value of attempting to create an environment where each developer will comfortably and confidently improve any piece of code that they come across without feeling as though they could cause damage to the overall system. I see TDD as a means to improve the synergy of the team in creating the simplest, most maintainable system. 

From Wikipedia: Synergy, in general, may be defined as two or more things functioning together to produce a result not independently obtainable. That is, if elements A and B are combined, the result is greater than the expected arithmetic sum A+B.


David

Ron Jeffries

unread,
May 17, 2011, 9:43:33 AM5/17/11
to software_cr...@googlegroups.com
Hello, David. On Tuesday, May 17, 2011, at 5:21:37 AM, you wrote:

> It shouldn't be that difficult to work out the intent of the code because
> the unit test should describe this.

The tests describe /what/. Intention is about /how/.

> Customer value is always a difficult subject with refactoring. It would be
> nigh on impossible to express the customer value of an individual
> refactoring effort no matter how soon it is performed.

Yes. The business value of a post-hoc refactoring effort is very
difficult to identify, primarily because it delivers no feature
value now and only promises (or hints at) faster feature development
later.

The best option is to have the code's design always just as good as
the present level of function calls for, neither too much, which
reflects wasted (not yet paid-off) effort, or too little, which
slows us down. Of these two, a little over-design is far less
harmful than insufficient design, because usually (for some
definition of usually) it will pay off pretty soon. It's possible to
create amazing structures that are unnecessary forever, but a
customer's impatience for stories can probably hold that off.

If, however, we give our code to the customer with an inadequate
design, we are developing the habit of handing it over too soon, and
we are slowing ourselves down, step by step, for the future.

Cleaning dirty code up is something that we need only do once.
Working with dirty code slows down every feature that passes through
that area, forever. So keeping the code clean is cheaper overall
than letting it slide.

> The challenge is
> harness a relationship with the customer that means that they appreciate the
> overall value of attempting to create an environment where each developer
> will comfortably and confidently improve any piece of code that they come
> across without feeling as though they could cause damage to the overall
> system. I see TDD as a means to improve the synergy of the team in creating
> the simplest, most maintainable system.

Yes, TDD does that. And the best way that I know to harness the
ability to change the code as needed is to clean up the code we're
working on. If the design has slipped a bit in some area, then the
next time we do a feature in that area, we clean things up a bit.
It's like the boy scout rule of leaving the campground cleaner than
you found it. Over time, the areas we work in will become quite
clean, and if other areas that we never visit never get cleaned up,
no harm is done because we're not slowed down by them.

Ron Jeffries
www.XProgramming.com
For best results, avoid doing stupid things. -- Clifford Stoll (Acme Klein Bottle)

David Wilde

unread,
May 17, 2011, 10:09:20 AM5/17/11
to software_cr...@googlegroups.com
Thanks Ron,

I've always seen intention as being the /what/ myself so this might be the source of my confusion. As in "What is the intended purpose of the code?" As I see it if this cannot be determined from the tests then something is wrong with the tests. This is what I meant from my previous post. I'd rather not shift this thread to a discussion on the English language as the thread seems to have covered a lot already! 

Otherwise I think that everything you have replied with is a better version of what I was trying to say!

David




--

Kaleb Pederson

unread,
May 17, 2011, 10:58:50 AM5/17/11
to software_cr...@googlegroups.com
On Mon, May 16, 2011 at 2:52 PM, Curtis Cooley <curtis...@gmail.com> wrote:
...
> I couldn't agree more with what you just wrote, and it means I
> misrepresented what I meant.

I don't think you misrepresented it at all, I just didn't think it was
sufficiently defined to help some of the less-experienced TDDers, like
myself perhaps.

> TDD helps me write maintainable code
> because it helps me keep the design simple. I can see how designing
> for maintainability could lead to over-designed code, but I would
> argue that over-designed code is less maintainable than simple TDD
> code.

Aside from the Martin's APPP I haven't seen much that details how to
balance simple design and adequate refactoring... but perhaps I don't
know exactly what I'm looking for either.

> You've made me start to contemplate the meaning of maintainable, and
> that's a good thing! Off the top of my head, I meant maintainable in
> the sense that it's easy to understand, fix, and extend. I guess that
> it conforms to the XP rules of simplicity?

The c2 wiki Minimum Number of Classes
(http://c2.com/cgi/wiki?MinimumNumberOfClassesAndMethods) quotes Ward
Cunningham:

"Better to create the one class needed now and let the future
programmer refactor it into the classes needed in the future. I am
suspicious of the one responsibility rule because I've seen beautiful
code that violates it."

> The reason we care about design is so we don't make a mess. We don't
> want to make a mess because someday we'll have to go back and fix or
> extend the code. I guess that's the goal? Don't make a mess?

Perhaps. Maybe the balance is being able to say, "this is fine for now
but we can easily refactor to XX if we ever need to do YY or ZZ." Of
course, fine means no/minimal duplication and all the normal things.

Thanks for your thoughts Curtis.

Curtis Cooley

unread,
May 17, 2011, 1:22:14 PM5/17/11
to software_cr...@googlegroups.com
On Mon, May 16, 2011 at 10:27 PM, Ralf Westphal <in...@ralfw.de> wrote:
>> If you have a new way to model that I can practice and learn that will
>> make me more efficient at building maintainable code than TDD, I'm all
>> ears. Just saying "do more modeling up front" isn't it, though,
>> because I've done that and then went to TDD.
>
> If you´re really open to learning more about how - let me say - TDD
> could be complemented, then let´s think about how I could show you
> what I mean.
> The form of a forum like this seems a bit limiting to me.
>
> Am I just saying "do more modelin up front"? No, there´s more to it.
> But explicit design is very important to me.
>
> Please suggest a way of communicating to dive deeper. Because only
> seeing is believing :-)
>

If someone came up to me, at a users group meeting for example, and
said something like, "I've heard about TDD and I'd like to practice,
but I don't know where to start."

I could say something like, "TDD is basically a three step process,
red green refactor, that is repeated until your problem is solved.

Red means don't write a line of production code until you have a
failing test. Starting out I would suggest writing small simple tests.

Green means write the simplest production code you can think of to get
the test to pass. For example, if your test is 'assert 4, foo.bar()'
then just have bar() return 4.

Refactor means improve the code you have so far, making it reveal its
intent, while keeping the tests passing. Just starting out I would
suggest focusing on duplication. Remove any and all duplication you
can find. For example, the 4 is probably in the code and in the test
and is duplication of information. It probably means more than 4. It
could be an id, or a ranking, but it probably means more than 4.
Refactor it out and make the intent clear.

Repeat until you've solved the problem you sat down to solve."

Is there a simple, for dummies, way I can practice what you are
proposing? You suggested red green {refactor red green} but I don't
see the paper modeling step in there. That's why I asked if the first
red green was on paper, since you said we should always model first.

Gleaning what I can from the mass of information in this thread, my
take so far on your technique is:

1. Solve the whole problem on paper/whiteboard using models
2. Refactor the models until they reveal intent
3. Code the model in the desired language.

Is that close?

Ralf Westphal

unread,
May 17, 2011, 2:08:25 PM5/17/11
to software_craftsmanship
On 17 Mai, 13:55, Esko Luontola <esko.luont...@gmail.com> wrote:
> If you skip the refactoring step after getting a test passing and
> refactor it only after the next time that you come back to the code
> (possibly days or weeks later), then it will be much harder to
> remember what was your intent when writing the code and since the code
> is not refactored to show the intent, it will be much slower to
> refactor it - you will first need to reverse engineer the code and
> understand how it works.

Hm... that to me seems against what TDD is supposed to deliver: clear,
understandable design.
If I have a hard to to figure out the intend after a couple of weeks
and that´s because I left in just a bit of mud after my last green
test... then the rest of the code can´t really be self-describing.

>I think it's much better to spend that 5
> minutes removing the duplication and improving the names, right after
> getting the test pass, while it's still fresh in your memory.

Of course you can do that - but I still want to make people senstive
for the possibility of doing too much refactoring.

If there is a danger of overengineering in up-front design, then there
is also a danger of over-refactoring.
I´ve seen so many projects proud of having "refactored to patterns" -
but, alas, the code was hardly "intent revealing".

Only if you have a clear goal of what to do next in mind, then you
know how refactored code should look like.
(And I don´t mean just better names.)

-Ralf

Adam Sroka

unread,
May 17, 2011, 2:17:05 PM5/17/11
to software_cr...@googlegroups.com

Ralf,

I just want to say that I admire what you are doing here. It takes courage to stand up for a controvercial position especially when you are faced with so many experienced practitioners.

Most of the arguments I have heard against TDD are either of the "it's too slow" or "it will never reveal an optimal solution" variety. These are easily defused by anyone with the experience to do it well.

The argument you are presenting seems different though. I am not sure I have really grokked your position yet, but I am glad you are offering it. We need these kinds of debates so that we can continue to move the state of the art forward and not rest on our laurels (*not* to suggest that anyone here is doing that.)

Adam Sroka

unread,
May 17, 2011, 2:23:18 PM5/17/11
to software_cr...@googlegroups.com

Just to be clear, is the essence of your argument here that TDD refactoring does not necessarily lead to a more intent revealing design, and that we can waste a lot of effort refactoring in the wrong direction?

This is true, of course. When I learned TDD I was told to always refactor with the intent of conforming to Kent Beck's four rules of simple design. Thus, if I wasn't refactoring to express intent I was doing it to eliminate duplication. And if I wasn't doing that, or adding new behavior test first, or deleting code I didn't need, then I shouldn't be doing it.

Is that different from what you are saying? If so, how is it different? 

On May 17, 2011 11:08 AM, "Ralf Westphal" <in...@ralfw.de> wrote:

Ralf Westphal

unread,
May 17, 2011, 2:34:05 PM5/17/11
to software_craftsmanship
On 17 Mai, 19:22, Curtis Cooley <curtis.coo...@gmail.com> wrote:
> Gleaning what I can from the mass of information in this thread, my
> take so far on your technique is:
>
> 1. Solve the whole problem on paper/whiteboard using models
> 2. Refactor the models until they reveal intent
> 3. Code the model in the desired language.
>
> Is that close?

That´s close ;-)

Add to that:

-Do steps 1 to 3 iteratively. Don´t take up too many requirements for
modelling. Do it in small increments.
-Talk about the model with your colleagues. It´s easy since they are
on a whiteboard and are focused. Models are higher level designs than
code.
-Code the model in the programming language of your choice with or
without pair programming, but do it test-first. Or, if you like, for
each "functional unit" you modelled do it with TDD.

Modelling is not coding. So there´s enough "design" left for
coding :-)

But the whole thing hinges on how hard it is to model. I certainly don
´t use OOAD or UML for that. And my code using OO languages certainly
looks different from your OO code. But, well, what can I say: My code
always reflects the model 99%. And I even can reproduce the model from
code. Due to the modelling the code reflects major principle like SRP,
SoC etc.

When I introduce a new feature, I stand at a whiteboard with my
colleagues and with can discuss the best way to do it on a higher than
code level. (While knowing the code looks like the model we´re talking
about.)

Like with XP, several practices need to come together to make this
real. One is a certain way of modelling, another a certain way of
translating models, yet another is strict component orientation, plus
moving forward in very small increments. Spike solutions are also a
part of the picture.

As I said in another posting: coding is the ultimate constraint of the
software production process. So we need to keep coding focused on
coding, we need to ensure coding produces bug free code, and we need
to ensure the best input to coding we can muster, that is clearly
defined requirements with acceptance test cases + as much design as
reasonably possible + a clear separation of tasks between programmers.

I strongly believe in WIP=1. So at each moment all developers are
working on just 1 feature, that is a longitudinal cut thru an
application. Whatever they do must not overlap and must not cause
conflicts when checking it into the repo. Collective code ownership is
good; collaborative modelling as well as reviews support it. And any
developer can work on any piece of the code. But at every moment each
developer is focused only on one component which is isolated
physically and conceptually from others. Only that way decoupling can
be enforced.

And I can tell you: Developers love to work this way. It takes them
maybe a day or two to switch to focussing that much - but then they don
´t want to go back.

-Ralf

philip schwarz

unread,
May 17, 2011, 6:12:46 PM5/17/11
to software_craftsmanship
Hi Adam,

>What would you do with that answer if you got it?
If the answer was yes, I would consider taking the benefits/
disadvantages that result, when doing TDD, from the application of the
strategies made viable by the flat curve, and look at whether it was
possible/reasonable to argue that the disadvantages (e.g. the alleged
wastefulness of the refactoring done in TDD to go from working code to
clean code) were the acceptable small price to be paid in exchange for
the considerable benefits.

Philip.

On May 17, 1:29 am, Adam Sroka <adam.sr...@gmail.com> wrote:
> On Mon, May 16, 2011 at 5:08 PM, philip schwarz
>

philip schwarz

unread,
May 17, 2011, 6:46:19 PM5/17/11
to software_craftsmanship
@Adam

> Part of the challenge of adopting XP piecemeal is that the practices
> support each other very nicely. There is a synergistic effect that
> happens when you are doing just enough of each of them that doesn't
> seem to happen when you do one or two in isolation.

Yes, here is a diagram illustrating the synergy:
http://c2.com/cgi/wiki?ExtremeProgrammingEnablingChart and

And here is how "Extreme Programming Refactored: The Case Against XP"
puts it: "This is a fundamental problem with XP...it is a symbiotic
process - that is, you really need to do all of XP or none at all.
There's no in-between (unless you perform some very careful and
deliberate tailoring). The theory is that each of these individually
flawed practices reinforce each other to produce something stronger.
Unfortunately, this can also work in the other direction: Stop doing
one and the chain unravels."

But in XP Explained, Kent Beck singles out testing as a potential
special case: "Any one practice doesn't stand well on its own (with
the possible exception of testing). They require the other practices
to keep them in balance".

Any particular thoughts on the viability of TDD on its own?

On May 17, 1:29 am, Adam Sroka <adam.sr...@gmail.com> wrote:
> On Mon, May 16, 2011 at 5:08 PM, philip schwarz
>

philip schwarz

unread,
May 17, 2011, 6:51:44 PM5/17/11
to software_craftsmanship
@Ralph

> your statement implies: Ron is good at TDD

From Wikipedia: "Ron Jeffries is one of the 3 founders of the Extreme
Programming (XP) software development methodology"

On May 15, 4:24 pm, Ralf Westphal <i...@ralfw.de> wrote:
> On 15 Mai, 12:34, Ron Jeffries <ronjeffr...@acm.org> wrote:
>
> > You seem to care deeply about programming skill.
>
> Sure I do.
>
> > I suggest that you
> > start thinking of TDD and refactoring in terms of a skill that is
> > potentially good to have, and that you learn them well enough
>
> Sorry to say, but this seems to imply you know about my TDD skills
> well enough to recommend I improve on them.
> How come?
>
> Do you think just because I´m not all for TDD I´m not good at doing
> TDD?
>
> I´d say there are other possible explanations:
> a. I´m good at TDD and still am dissatisfied with it´s results.
> b. I´m not good at TDD, but TDD nevertheless is not the pinnacle of
> software design, and even someone outside the "TDD believe system" can
> sense that.
>
> Also your statement implies: Ron is good at TDD (because TDD is the
> best way to design software); thus whoever is not doing TDD is wrong
> (or at least in danger of malpractice because he´s not applying what´s
> broadly recognized as the pinnacle of design).
>
> Hm... this does not feel good, Ron.
> This does not sound like the scientific method.
>
> -Ralf

philip schwarz

unread,
May 17, 2011, 7:17:52 PM5/17/11
to software_craftsmanship
@Ron

>The cost of change topic is, in my opinion, mostly a red herring. A
>sufficient reason for doing the simplest thing is that doing a more
>complex thing (obviously) takes longer. A sufficient reason behind
>YAGNI is that investing prior to the moment one needs the investment
>is wasteful. Similarly for LRM.

Noted.

philip schwarz

unread,
May 17, 2011, 7:36:31 PM5/17/11
to software_craftsmanship
@Ron
Yes, fully agree. Am I right in thinking that you blogged about this
not too many months ago?

By the way, the analogy is out of "The Pragmatic Programmer", and this
is what precedes it:

"So, you go to your boss and client and say, 'This code works, but I
need another week to refactor it.' We can't print their reply. Time
pressure is often used as an excuse for not refactoring. But this
excuse just doesn't hold up: fail to refactor now, and there'll be far
greater time investment to fix the problem down the road - when there
are more dependencies to reckon with. Will there be more time
available then? Not in our experience. You might want to explain this
principle to the boss using a Medical Analogy:"

philip schwarz

unread,
May 17, 2011, 7:52:20 PM5/17/11
to software_craftsmanship
Hi Kaleb,

very important passage you quoted there, and here is the closing
message of that great chapter:

"In many ways, the Open/Closed Principle is at the heart of object-
oriented design. Conformance to this principle is what yields the
greatest benefits claimed for object-oriented technology: flexibility,
reusability, and maintainability. Yet conformance to this principle is
not achieved simply by using an object-oriented programming language.
Nor is it a good idea to apply rampant abstraction to every part of
the application. Rather, it requires a dedication on the part of the
developers to apply abstraction only to those parts of the program
that exhibit frequent change. Resisting premature abstraction is as
important as abstraction itself."

On May 16, 10:13 pm, Kaleb Pederson <kaleb.peder...@gmail.com> wrote:
> Hi Curtis,
>
> On Mon, May 16, 2011 at 11:31 AM, Curtis Cooley <curtis.coo...@gmail.com> wrote:
>
> ...
>
> > I always try to remember the goal when I write code. The goal is
> > maintainability. No other measure of good design matters, because the
> > goal is keeping it easy to add new features. TDD clicked right away
> > with me in terms of the goal because TDD makes you maintain the code.
> > Again, it's viscosity working in your favor. And I'll say it again: If
> > you have a new way to build maintainable code better then TDD, please
> > share.
>
> I suppose this is automatically implied for many people, but when
> reading Bob and Micah Martin's /Agile Principles, Patterns, and
> Practices in C#/ (APPP) it really struck me that it's not nearly as
> simple as focusing on maintainability. Indeed, I had often focused too
> much on maintainability; I had used too many design patterns for the
> sake of maintainability when a few functions would have been simpler
> and sufficient. It probably didn't take me much longer to use those
> design patterns, but I wasted time. I was attempting to anticipate
> changes that would never come.
>
> APPP puts it this way, '"Fool me once, shame on you.  Fool me twice,
> shame on me."  This is a powerful attitude in software design.  To
> keep from loading our software with needless complexity, we may permit
> ourselves to be fooled once. This means that we initially write our
> code expecting it not to change. When a change occurs, we implement
> the abstractions that protect us from future changes of that kind.  In
> short, we take the first bullet and then make sure that we are
> protected from any more bullets coming from that particular gun" (pg
> 129).
>
> I think there are many barriers to doing TDD well, like the above.
> Despite following the three laws of TDD, I wasn't doing TDD
> particularly well.  How much is too much refactoring, for example? I
> overdid it, and I recognize that now. I had to learn to trust myself
> enough to leave the code as-is until a sufficiently strong stimulus
> came along at which point I could refactor it to a more reasonable
> design against real "changes of that kind."
>
> --
> Kaleb Pederson
> Blog -http://kalebpederson.com
> Twitter -http://twitter.com/kalebpederson
>
>
>
>
>
>
>
>
>
> > This has been a fascinating conversion, a little tense at times
> > perhaps, but very interesting. Thanks all!
> > --
> > Curtis Cooley
> > curtis.coo...@gmail.com
> > blog:http://ponderingobjectorienteddesign.blogspot.com
> > ===============
> > Leadership is a potent combination of strategy and character. But if
> > you must be without one, be without the strategy.
> > -- H. Norman Schwarzkopf
>

philip schwarz

unread,
May 17, 2011, 8:03:32 PM5/17/11
to software_craftsmanship
>It is, however, less than ideal to think very long without testing
>one's ideas in code. Speculative design is easy to get a bit wrong
>in many different ways.

Yes. Here are two sentences by Kent Beck:

1. Coding is when your fuzzy, comfortable ideas awaken in the harsh
dawn of reality.
2. Coding is where our design guesses are tested

Raoul Duke

unread,
May 17, 2011, 8:16:29 PM5/17/11
to software_cr...@googlegroups.com
On Tue, May 17, 2011 at 5:03 PM, philip schwarz
<philip.joh...@googlemail.com> wrote:
>>It is, however, less than ideal to think very long without testing
>>one's ideas in code. Speculative design is easy to get a bit wrong
>>in many different ways.
>
> Yes. Here are two sentences by Kent Beck:
>
> 1. Coding is when your fuzzy, comfortable ideas awaken in the harsh
> dawn of reality.
> 2. Coding is where our design guesses are tested

i think part of this is what programming language you use -- the
faster it lets you get code done, the easier it is to use code to test
things and yet not be rat-hole-ing and wasting effort. if you are in
some bad morass tar pit of a programming language (and you probably
don't even realize it, until you've tried other setups and given them
quality learning time) then that's a drag, and might push people away
from using code as a tool to face reality.

sincerely.

George Dinwiddie

unread,
May 17, 2011, 8:44:01 PM5/17/11
to software_cr...@googlegroups.com
On 5/17/11 7:36 PM, philip schwarz wrote:
> By the way, the analogy is out of "The Pragmatic Programmer", and this
> is what precedes it:
>
> "So, you go to your boss and client and say, 'This code works, but I
> need another week to refactor it.'"

A man-week of work is not a refactoring. It might be a restructuring,
but in my experience it's more likely bug-fixing. People call almost
any change to the code "refactoring" these days. That doesn't make it true.

Ron Jeffries

unread,
May 17, 2011, 9:35:32 PM5/17/11
to software_cr...@googlegroups.com
Hello, David. On Tuesday, May 17, 2011, at 7:09:20 AM, you wrote:

> I've always seen intention as being the /what/ myself so this might be the
> source of my confusion. As in "What is the intended purpose of the code?" As
> I see it if this cannot be determined from the tests then something is wrong
> with the tests. This is what I meant from my previous post. I'd rather not
> shift this thread to a discussion on the English language as the thread
> seems to have covered a lot already!

I'm kind of regretting rising to the what/how debate. We can
certainly think of it, then, as a different level of what:

Acceptance test level what: Given the user's name, return the
corresponding account.

Now we decide to implement this with a binary search. Somewhere in
the code we have a method

findAccountGivenName(string name) // this, too, is a what
SearchPackage.binsearch(accountTable, nameOffset, name);
// this is a "how" with respect to findAccount, at least as
I'd say it, not a "what". Of course it says what we are doing,
binary searching, and / but it answers the question "how do we
find the account?"

Strictly speaking, I would agree that when I write a line by
intention, I am saying /what/ I, the programmer, want to do next. The
lines of intention, in a row, explain /how/ the overall method
works.

> Otherwise I think that everything you have replied with is a better version
> of what I was trying to say!

Still not the best, obviously. :)

Ron Jeffries
www.XProgramming.com
Fear is the mindkiller. --Bene Gesserit Litany Against Fear

Esko Luontola

unread,
May 18, 2011, 9:54:34 AM5/18/11
to software_craftsmanship
On May 17, 2011 11:08 AM, "Ralf Westphal" <i...@ralfw.de> wrote:
> If there is a danger of overengineering in up-front design, then there
> is also a danger of over-refactoring.
> I´ve seen so many projects proud of having "refactored to patterns" -
> but, alas, the code was hardly "intent revealing".
>
> Only if you have a clear goal of what to do next in mind, then you
> know how refactored code should look like.
> (And I don´t mean just better names.)

So you are talking about refactoring which introduces design patterns,
and not the kind of refactoring which is made to follow Simple Design?


On May 17, 9:23 pm, Adam Sroka <adam.sr...@gmail.com> wrote:
> Just to be clear, is the essence of your argument here that TDD refactoring
> does not necessarily lead to a more intent revealing design, and that we can
> waste a lot of effort refactoring in the wrong direction?
>
> This is true, of course. When I learned TDD I was told to always refactor
> with the intent of conforming to Kent Beck's four rules of simple design.
> Thus, if I wasn't refactoring to express intent I was doing it to eliminate
> duplication. And if I wasn't doing that, or adding new behavior test first,
> or deleting code I didn't need, then I shouldn't be doing it.

When I do refactoring, it's usually one of these situations:

1. After getting a tests to pass: Remove the duplication and improve
the names (i.e. Simple Design). Fix any obvious design smells while
they are still small (for example Primitive Obsession gets the harder
to fix the more widespread it is). This usually takes just a couple of
minutes and at most one hour. Very faint design smells I would leave
lying around until they ripen enough for me to know how to fix them
(but not too long, until they begin to rotten)

2. Before/during implementing a new feature: If the system's design
does not allow a feature to be added easily, I would first refactor
the system into a direction where adding that feature will be easier.
If this is the second instance of a similar feature, I would refactor
the code to follow the Open-Closed Principle, so that in the future
adding similar features will be trivial (Agile Software Development,
Principles, Patterns, and Practices; page 105). This kind of
refactoring might take from half an hour up to a couple of hours.

3. When our understanding of what would be the correct design
improves: Within many weeks or months of development, we usually get
inspirations on how the system would better be organized. We realize
that our current design is not what we currently understand that what
the design should be like. This is the original definition of
Technical Debt. Working towards the new design will then be done
incrementally at the same time as developing new features - when we
touch a class that does not conform to the target design, we will
refactor it. This kind of refactoring might take many weeks or months
to completion, but it is done incrementally in small steps, maybe at
most a couple of hours at a time.

Could it be that Ralf is complaining about developers who do type 2
refactoring without adding features, or type 3 refactoring in big
steps?

George Dinwiddie

unread,
May 18, 2011, 11:56:07 AM5/18/11
to software_cr...@googlegroups.com

Very nice description, Esko. You should publish this somewhere more
enduring than a mailing list.

It is loading more messages.
0 new messages