Re: Re: Communicating design
Hello, Ralf. On Tuesday, July 5, 2011, at 4:42:34 PM, you wrote:
> Well, there is a web browsable version. See here:
>> Well, it does constitute duplication, which generally indicates
>> something odd about the design. I think back when we cared about
>> coupling and cohesion we called this "sequential coupling" and
>> considered it not as good as it might be.
> As long as Martin Fowler is not averse against multiple traversions of
> lists, I guess I can indulge in the same practice
You can, even if Martin was averse: you get to sin your own sins.. I
don't recall Martin ever mentioning to me that going over lists
multiple times was better than doing it only once. Tends to take 3X
as long ...
>> I am concerned, however, that the /design/ kind of drives us to
>> processing the data three times. That's not obviously a "good"
>> design right out of the box, is it?
> Please define "good". "Good" is just a quality you attribute to a
> solution satisfying requirements. In this discussion the requirements
> surely are principles. So which principles do you see violated? And
> since not all principles/values can be equally supported, why do you
> prioritize your principles/values like you do?
What principle of "good" design do you see that recommends doing
things three times that could only do once?
> To feel forced to not run over a simple list several times tastes like
> premature optimization - which Donald Knuth thinks to be the root of
> much evil, if I remember correctly.
I would suggest that Knuth, of all people, would be disinclined ever
to produce an algorithm that on its face was looping 3x instead of
But Knuth is not here. What aspect of good design do you think makes
a three-pass algorithm better than a one-pass one?
>> Yes. And tests are valuable. When one does this incrementally with
>> TDD, it is possible to produce the same bug if one both has no test
>> example and does not think deeply enough to realize that the order
>> of processing makes a difference.
> I agree.
>> I'm not sure whether TDD makes it easier to spot this problem or FD
>> does. I likely spotted it from long experience with the bowling
>> kata, not from my skills at TDD.
> See, I did not have any experience with it.
> So please forgive me to have run into this bug.
I do, certainly. It is a subtle issue. And we must observe that FD
didn't cause us to discern it.
>> A data object is a prima facie violation of LoD if any calculation
>> is ever made upon the data. In this case we have calculated base
>> score by ripping the little rolls out of the Frame and calculating
>> elsewhere. This is a violation of cohesion.
> I beg to disagree. Please have look at the LoD definition and point
> out the paragraph stating what you愉e saying.
> Maybe you want to allude to encapsulation or information hiding as
> more basic principles instead?
"The fundamental notion is that a given object should assume as
little as possible about the structure or properties of anything
else (including its subcomponents)."
The code as written assumes that the frame has two rolls. It is
possible to assume less, namely that the frame knows how to return
its base score. QED.
> But let me answer you like this: For high cohesion you have to have an
> idea what the makes some code to belong closer together than other.
> You have to define the concern code belongs to.
> As far as I can see there are three concerns in this kata:
> 1. handling frames: creating frames from a list of int, making
> statements about frames (e.g. is a strike frame), holding a frame
> 2. calculating scores, e.g. for strikes, spares
> 3. calculating the total score
> These are different concerns because they can change independently,
I would suggest that we should try to produce a good design for now,
not a design that will be good if the International Bowling
Federation decides to change the rules of a century-old game.
That said ...
> 1. frames could contain 3 instead of 2 rolls or a frame with two rolls
> with the same number of points is considered special. this all should
> have little impact on other concerns.
Yes. And if that happened, the Frame would have to be changed, to
contain the additional role, plus the code in BowlingGame that for
some reason pulls out the rolls and adds them up and puts the value
/back in the Frame/.
If that calculation were in the Frame, then only one class would
need to be change for these rules changes.
> 2. strikes could be calculated differently, e.g. by adding the next 3
> rolls instead of 2. or for each consecutive strikes a bonus is
> granted. this all should not impact other concerns.
Yes, that should be in the Frame, it seems to me. As it stands, if I
recall, the test for isStrike is in the Frame and the calculation of
what to do if it is is in BowlingGame (if I recall).
These two ideas, whether it is a strike and what the score is, it
seems to me, should be together, somewhere. If not, at least two
classes will have to change.
> 3. totalling could change in so far as to also add the bonus rolls for
> a spare/strike frame at the end. this should not impact other
Yes ... game totals probably should be in the Game. Frame scoring,
it seems to me, is logically part of the Frame.
> When I say "should not impact other concerns" I mean the changes
> necessary should be confined to a concern specific functional unit.
Yes. I believe that two of the three changes you propose would in
fact impact more than one unit.
> But if you put "everything" into frame to make it an intelligent
> domain object... how愀 the separation of concern principle served?
I'm not proposing putting EVERYTHING into frame. But it seems to me
that just as "IsStrike" is about the frame, so is the calculated
frame base score.
Now of course with this design we really /cannot/ put the strike and
spare bonus in the frame ... they do not have the information about
how to get to the next frames to pull their data.
I would take this fact as an indication that the Framing structure
In addition, there is the odd code that we have to write to deal
with strike bonuses in case the next frame is a strike. I would look
for a way to remove the conditionals from that code, which are, by
the way, duplicated with other tests for IsStrike.
And it happens that there is a good way to accomplish that, so I
know that a simpler and more cohesive structure is possible. Given
that one is possible, our design and coding approach is duty-bound
to lead us to it, it seems to me.
>> OK, but as noted above it reduces cohesion by not putting
>> functionality on the object that has the facts.
> As you see from the changes to the code I took your hints to heart
> Some functionality has been moved to Frame.
> This serves the separation of concerns.
> (I don愒 care much for LoD when considering data classes - as does Bob
> Martin in Clean Code, if I remember correctly.)
The devil and I can quote scripture to our own purpose as well. I
think we can do better to look at the code and consider how to
change it to include less duplication of code, less duplication of
operation, more cohesion, less coupling.
And, I might immodestly note, I can hold my own in programming with
both those individuals. So consider quoting me. :)
>> existed anyway due to a change in requirements. The function must go
>> somewhere. If we add it to the object in question we always know
>> where to look and where to put things.
> This I find to be a common, hm, illusion. A function has to go nowhere
> as FP is showing very clearly - or do you want to call millions of FP
> programmers dumb?
Even FP programmers have to add code to add functionality. And even
FP programmers have to add it somewhere reasonable. And, by the way,
this is not much of a an FP design.
If new functionality is to be added, then code must be placed
somewhere. It is best when where a function should go is more
obvious, not so good if it is less obvious. I believe it is less
than obvious that IsStrike is a frame topic but score of frame is
> Also, if I put a function on class A that does not mean it belongs
> there in an absolute sense. Also it does not mean I惻l find it if I
> need to. People struggle heavily to assign functions to classes. This
> struggle to me is a sign of a problem, not a solution. I want to be
> able to design pretty much struggle free. That愀 why in FD there is no
> need to assign functionality to any larger unit of code.
> Functionality, behavior is nested in the sense of a stratified design.
> But that is not assignment of functionality.
Well, ultimately, even if we have this lovely diagram, we do need to
know where to look in the code to find things to change or add.
>> OK ... I would prefer that if people write in an OO language that
>> they take advantage of the facilities that language offers.
> I悲 say I惴 pretty much using what C# has to offer. And once you see
> the EBC translation of the model the C# usage will be even heavier.
> On the other hand: an OO language is just a tool. Just because it
> offers some capabilities does not mean I should use them. Take
> multiple inheritance in C++ for example.
True, we need not use everything. Nor have I proposed using
But since C# is an OO language, its most powerful ability to
encapsulate information is in the OO style. In the code in hand,
some of the possible encapsulation has not as yet taken place. I
believe that some of that distance between what's possible and what
we have is due to the FD design style.
In addition, it seems to me that some of the function is just flat
in the wrong place. The existence of calculator classes like the
Extension is a common signal that better encapsulation is possible.
>> a lot of pushback from programmers using Java or C#, which I should
>> take as evidence that I'm not programming in the style they expect
>> to see. Since other people have to maintain our code, we need to
>> write it in a form they expect to see. This is, of course, a local
>> issue to some degree.
> This sounds reasonable to me. If you end up with C style for such a
> small problem that would not turn me down per se.
No, nor me. Even then, I like to have things where people will
expect to find them.
>> I do think, however, that the current designed flow is neither the
>> most obvious flow nor the simplest possible flow for bowling.
> You愉e striving for an absolute again. To me that愀 premature
> optimization again.
Why would we not strive for excellence? There's no way to get there
other than to try.
And it seems you're talking about some new kind of "optimization".
I'm not proposing these changes because it would be faster. I'm
proposing them because the code would be simpler. Simpler code takes
less time to write and contains fewer chances for error.
> "Most obvious" or "simplest possible" are no goals for me if I惴 under
> pressure in a project.
That's really too bad, because simplicity is probably our best
chance at going fast, and our best chance at getting maintainable
Here are a few articles about that:
> Balancing most important principles (and non functional requirements)
> in a "good enough" manner is enough for me.
> I want to be quick and I want to use the power of many brains and I
> want a communicable design and it should be easy to modify.
Those are good things. I personally always wind up with "good
enough", but I like to ensure that "good enough" is "better and
better" over time.
Thus I am grateful for the chance to discuss this code with you, and
for your ability to be somewhat open about how to improve it even
beyond its current "good enough" state.
>> powerful thought processes ... and do not readily communicate with a
>> large number of programmers who have not encountered those languages
>> and design paradigms.
> I惴 showing these kinds of diagrams regularly to many uninitiated
> developers - and I hardly ever find someone not understanding them
> right away. That, however, does not mean they agree with the
> approach But they understand the functionality/design.
Oh yes, don't get me wrong. I do think the diagrams are clear. They
are not unlike other flow-oriented diagrams from the past and, like
those, they do help communicate some ideas. And, like all diagrams,
they probably obfuscate other ideas.
>> I understand that you think that ... and I want to see where the
>> code wound up. My primary concern about design up front is that it
>> is free of feedback from reality. If it's a couple of minutes,
>> everyone does it (I hope) and I don't much care how they draw the
> That愀 fundamentally right. But I find the conclusion wrong: "Hence
> you need to start coding as quickly as possible."
If I said those words, I misspoke. I think we should code at the
earliest /responsible/ moment, because feedback from the code has
value. And the earliest moment can be earlier, and therefore the
learning can occur sooner, if my skill in coding and morphing code
> Reason: Designs exist on different levels of abstraction. The lower
> the abstraction level, the harder to determine if the design is right
> by just talking about it. So as long as you愉e not getting into too
> much details it愀 ok not to code right away. That愀 what my model is
> doing. It愀 on a high enough level to "prove" its correctness (not
> optimality) by talking about it.
Sure. But errors in the code come from more sources than just the
design. In particular, they arise when the code is not as simple as
we could readily make it. As such, a perfect design, if there could
be such a thing, does not imply a perfect program. And if the design
leads to code that is more complex than it could readily be, the
design is actually pushing errors into the code.
Fatalism is born of the fear of failure, for we all believe that we carry
success in our own hands, and we suspect that our hands are weak. -- Conrad
You received this message because you are subscribed to the Google Groups "software_craftsmanship" group.
To post to this group, send email to software_craftsmanship@...m.
To unsubscribe from this group, send email to software_craftsmanship+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/software_craftsmanship?hl=en.