How can I avoid combinatorial explosions in tests, and should I even try?

1,669 views
Skip to first unread message

Rick Pingry

unread,
Aug 25, 2011, 7:26:23 PM8/25/11
to Growing Object-Oriented Software
We have a situation that seems painful that we seem to come up with
constantly. It involves dealing with any kind of boolean logic that
is even moderately complex. The examples that we read about, even in
GOOS, seem to have little or no boolean logic to deal with. We are
not sure if we are doing something wrong, or perhaps if we have a
problem at a fundamental level.

Please allow me to give our real-world example:

We are working on a document management system. The user story I am
working with says (among other things) that I need to provide a link
on a page for a document if that document has "anonymous access"
priveledges.

The vast majority of the code is not under any kind of tests, and
indeed is written very functionally (not OO) with gobs of explicit and
implicit dependencies. Legacy Code in every since of the word (we
have Feathers' "Working Effectively With Legacy Code" and we love
it). In that code, there is a Document class with some static and non-
static functions. We decided that this story was not about
refactoring Document (it is huge and would certainly involve a
rippling effect with all of its dependencies), so we wrote an Adapter
that we could use.

So I have a class called DocOverviewURLGenerator. It has
responsibilities to write these various URL's for document (including
this anonymous access one) for a collaborating adapter on this
document. I have a test suite DocOverviewURLGenerator_Tester that has
tests that show the appropriate URL is created if there is anonymous
access, and no URL for that part if there is not. All is well so far,
and I seem to be at the right level of abstraction. I don't think it
is the responsibility of this class to determine if the document has
anonymous access, so I create an interface with a function
IsAnonymousAccess(), and I mock it out to tests both paths.

So, now I need to write the concrete IsAnonymousAccess() function in
the adapter. According to the specification, a document has anonymous
access if ...
1 The Document is Approved AND
2 The Document has Level 1 OR Level 2 Security AND
3 The document has anonymous access in at least one site (I know
this means nothing to you, but bear with me)

So, a very simple and common situation, we have 3 conditions AND
together. That one in the middle is 2 conditions OR'd together, which
gives 4 permutations, and lets just say that the 3rd condition has 8
permutations. That means the total permutations are 2*4*8 = 64. Does
this mean that I need to write 64 tests?

My gut tells me no. It seems that I need to break things up. So, do
I write a class of function that has this one function and calls 2
functions on a collaborator (that I can mock)? This "top-level" check
would have 8 permutations to test, then 4 more for the security
condition, and 8 more for the site condition, or 8 + 4 + 8 = 20.

(Breaking down the top level from 3 to 2 does not help me much. I
would have only 4 permutations (any time you have a boolean expression
with 2 parts, you have 4 permutations, 2*2). So if I broke that up, I
would have 4+4 = 8, rather than 2*2*2 = 8.)

So, if I go from the top, I have 64 tests. The only way I know to
break it up is to craete gobs of little interfaces that I can mock
with concrete classes, each with a single function that has a boolean
function that has no more than 3 parts, so I can get down to 20
tests. 64 tests or 20 tests with lots of little interfaces and
classes, Just so I can prove that I can correctly write:
return (A && (B || C) && D);

REALLY? How in the world does all of that extra work (probably 20X as
much work or more) really help me in this? Does it help me write
better code? The test smells drive me to write the proliferation of
classes and interfaces with single simple boolean functions, but is
that really better? I don't find it better in any other way besides
it making me have less tests. Any change in the future would cause
even MORE work and harder to read code that has implementation details
split across a zillion little classes.

As I am writing this, I did come up with one other methodology besides
using all of these tiny interfaces with mocks. I could use extract
method to break out each simple function. Doing so makes sense
because I can give them a name and they are all still nicely contained
in a single class. I could then make a class in my tests that
override each function as needed to do all of the tests rather than
using a mock object. I seem to recall Feathers recommending that kind
of action in his book. I have tried it before and I call it using a
"Lite Mock", but I have noticed that it gets me in trouble later on.
On a side note, do any of you use this kind of technique?

But the fact remains that there is still a whole lot of work for what
does not feel like a great benefit. I would like to say that this
kind of thing does not happen, but it DOES, almost every day!

I have read that your tests should be testing behavior and not
implementation. I completely understand that from the position of my
top level class DocOverviewURLGenerator. Knowing how it determines if
a document has anonymous access seems like an implementation detail.
But is it? It is a part of the written specification of the system as
a whole. If I extract the functionality into another class, like I
did, it is not a detail, but rather a core part of what the class
does. At some level the code needs to be tested, right?

If it does NOT need to be tested, at what point do I make the
distinction?

Or perhaps I am doing everything wrong all together? Perhaps there is
some kind of OOP that I don't understand?

Thanks for any help. It seems that this should be pretty common. Are
there any KATAs or TDD examples out there that cover this kind of code?

Luca Minudel

unread,
Aug 26, 2011, 4:24:51 AM8/26/11
to Growing Object-Oriented Software

Rick I'm assuming that you are talking about unit tests instead of
acceptance tests since you are talking about mocks and not external
systems impersonators.
Did I understood correctly?

Steve Freeman

unread,
Aug 26, 2011, 4:46:39 AM8/26/11
to growing-object-o...@googlegroups.com
so, speculating wildly....

It seems like the explosion in combinations comes from the 8 permutations that determine anonymous access, so perhaps that behaviour should be pulled into a separate object. That might be a collaborator, and hence mockable, if it pulls in external resources, or an embedded policy object if it just works with values. For a mocked collaborator, you only have to test its true and false results in the client, and test its implementation separately. Similarly, for a policy object, you can write high level tests for its true and false cases, and then write direct tests that work through its 8 combinations. Alternatively, perhaps the whole anonymous decision should be extracted to a helper object.

I prefer not to extract and override (although many people recommend it). Over time, I find it makes it hard to see the boundaries of the class and it's harder for the IDE to provide help. I tend to keep methods either public or private, and limit the use of protected. I prefer to write nested helper classes that implement these decisions. Normally, they're only used by the containing class, and I can write direct tests for them without leaking structure.

I get your point about deferring everything. My style is to have more smaller objects than many people are used to. That said, a lot of them are supporting classes that are local to a containing class, which avoids some of the mock-tastic codebases I've seen (and have sometimes been responsible for).

Does that help at all?

A public example would be a good idea.

S.

On 26 Aug 2011, at 00:26, Rick Pingry wrote:
> We have a situation that seems painful that we seem to come up with
> constantly. It involves dealing with any kind of boolean logic that
> is even moderately complex. The examples that we read about, even in
> GOOS, seem to have little or no boolean logic to deal with. We are
> not sure if we are doing something wrong, or perhaps if we have a
> problem at a fundamental level.
>
> Please allow me to give our real-world example:

> [...]


> Thanks for any help. It seems that this should be pretty common. Are
> there any KATAs or TDD examples out there that cover this kind of code?
>

Steve Freeman

Winner of the Agile Alliance Gordon Pask award 2006
Book: http://www.growing-object-oriented-software.com

+44 797 179 4105
Twitter: @sf105
Higher Order Logic Limited
Registered office. 2 Church Street, Burnham, Bucks, SL1 7HZ.
Company registered in England & Wales. Number 7522677

Lance Walton

unread,
Aug 26, 2011, 7:43:58 AM8/26/11
to growing-object-o...@googlegroups.com
If i may diverge slightly :-)

I have a strong dislike for lots of local classes unless they are anonymous. My preference is to recognise a new package, make the original class public in that new package, and make all of the supporting classes package visible, top-level classes in that package.

So I tend to get lots of little classes / interfaces organised into lots of little packages.

I don't think that changes the amount of mocking, or how mocking is used.

Regards,

Lance

Alex Baranosky

unread,
Aug 26, 2011, 8:15:45 AM8/26/11
to growing-object-o...@googlegroups.com
Hi Rick,

One other possibility is to use some form of tabular/parameterized test. There would be 5 columns (A, B, C, D and Result).  If you really don't feel like adding more subclasses, I would go with this option, because it doesn't force you to use more levels of indirection, solely to satisfy your tests.

Alex

Rick Pingry

unread,
Aug 26, 2011, 12:40:28 PM8/26/11
to Growing Object-Oriented Software
Thanks for the quick feedback everybody! I did not hear anyone
advocate only testing a subset of the possibilities, so I will assume
that it is indeed important to test all of the permutations, either
exhaustively (all 64), or at certain junctures.



@Luca,
Yep, unit tests. While I did try once, I have not gotten past the
time and expense of writing true GOOS style acceptance tests. I am
able to run what I am writing pretty quickly and easily, so I just
wrote (at least in my head) a manual acceptance test based on the
specification.

@Steve,
I did break that outside layer out, so I was able to test just the 2
possibilities, then made what you called the policy object. It sounds
like you are ok for creating lots of little classes, in this case
inner classes. Do you then mock at each level to keep the
combinations down or do you provide all of the 64 combinations? Also,
do you find that TDD is causing you to go overboard in breaking up
classes into TOO small of a granularity? Is it harder to maintain so
many classes, or even be able to read them? From a pragmatic view, do
you have some nice tools that helps you write so much extra code
quickly?

I love that TDD helps me tease out responsibilities. When I listen to
how hard it is to write the test, I can name a new responsibility and
move from there. In this case, my gut tells me that TDD is going
overboard, making so many classes I fear would be harder to maintain,
not easier. It seems to be artificially breaking up classes not based
on responsibility, but due to our inability to concisely express tests
that have so many permutations.

I also have the situation where my partner and I are the only ones in
the company even attempting TDD. We are trying to get our processes
down so we can become advocates. Having several hundred lines of code
+ test code to show what we could have done in a dozen or so is not
going to sell it for anyone (not even us).

@Alex
I really like your idea. I know that it breaks the letter of the law
to have a single assertion per test, but I really love that it can
concisely express something that is concisely expressed in the
specification. I am imagining a test that looks like a truth table.
Does anyone have a good experience with writing a tabular test like
this in nunit that, when it fails, shows the failed permutation(s)?

If that were written concisely enough, we could provide all 64
options. I think I do like the extract method mechanism when I can
come up with a good name for the method. I can keep it in the class
if it makes sense as a part of the responsibilities of the class. The
question then would be whether or not to override. I have run into
trouble on some occasions when trying to do this, but I think in all
cases it was where the overridden method changed state or called a
collaborator. I think I would be ok in situations where I am merely
querying for a value.

Thanks again for all the help. I will post the results after I get it
done.

Erlis Vidal

unread,
Aug 26, 2011, 1:37:40 PM8/26/11
to growing-object-o...@googlegroups.com

Single assertion per test is something I've listen before, but IMO this is too restrictive. This has big impact on the test organization strategy chosen. If you are grouping your tests methods using "Testcase Class per Fixture" [all tests methods in the same class has same setup phase] then one assertion per test looks pretty natural, but is not always the case with other organization strategies.

Remember, it is not the rule what matters, is the intention behind the rule, and here what matters is having well focused tests and not testing multiple paths, so "one assertion per test" is a good rule for a novice.

 
I am imagining a test that looks like a truth table.
Does anyone have a good experience with writing a tabular test like
this in nunit that, when it fails, shows the failed permutation(s)?


NUnit introduced parametrized tests in version 2.5. I've use it before and is pretty good. They even can generate the combination for you, take a look here

http://www.nunit.org/index.php?p=parameterizedTests&r=2.5

I like the implementation you have with NUnit because it solve a drawback in Tabular Tests: "Defect localization"

If you implement the combination by yourself, lets say

[Test]
public void ShouldWorkWithAllCombination() {
      VerifyItWorkWith( true, true, true );
      VerifyItWorkWith( true, true, false );
      VerifyItWorkWith( true, false, false );
       ...
}

when this test fail, you will be force to use the debuger, because you don't know what was the combination that fails. NUnit implementation for this, will create a new TestCase for each combination, giving you the results for each one. I think you will be fine with it.
 
If that were written concisely enough, we could provide all 64
options.  I think I do like the extract method mechanism when I can
come up with a good name for the method.  I can keep it in the class
if it makes sense as a part of the responsibilities of the class.  The
question then would be whether or not to override.  I have run into
trouble on some occasions when trying to do this, but I think in all
cases it was where the overridden method changed state or called a
collaborator.  I think I would be ok in situations where I am merely
querying for a value.

Thanks again for all the help.  I will post the results after I get it
done.

No problem, our pleasure
Erlis

Raoul Duke

unread,
Aug 26, 2011, 2:08:48 PM8/26/11
to growing-object-o...@googlegroups.com
hi,
furthermore, i have found stuff like
http://docs.python.org/library/itertools.html
terribly useful when i wrote my test that required 3 things to be true
before success, but order didn't matter, so i auto-generate all
possible ways of setting it up, and assert along the way that 2 of 3
isn't sufficient but 3 of 3 is.
sincerely.

Raoul Duke

unread,
Aug 26, 2011, 2:07:09 PM8/26/11
to growing-object-o...@googlegroups.com
perhaps of tangential use? see,

FITnesse et. al.
QuickCheck et. al.
Subtext et. al.

sincerely.

Rick Pingry

unread,
Aug 26, 2011, 4:32:11 PM8/26/11
to Growing Object-Oriented Software

>
> Remember, it is not the rule what matters, is the intention behind the rule,
> and here what matters is having well focused tests and not testing multiple
> paths, so "one assertion per test" is a good rule for a novice.
>
LOL, I still feel like a novice, and have been for about a year now.

> > I am imagining a test that looks like a truth table.
> > Does anyone have a good experience with writing a tabular test like
> > this in nunit that, when it fails, shows the failed permutation(s)?
>
> NUnit introduced parametrized tests in version 2.5. I've use it before and
> is pretty good. They even can generate the combination for you, take a look
> here
>
> http://www.nunit.org/index.php?p=parameterizedTests&r=2.5
>
OH! The NUNIT parameterized tests look awesome! Just what I was
looking for, thanks!

Exactly what I was looking for. I was concerned with the test
localization issue as well.

Thanks Much!

Steve Freeman

unread,
Aug 26, 2011, 5:47:21 PM8/26/11
to growing-object-o...@googlegroups.com
On 26 Aug 2011, at 17:40, Rick Pingry wrote:
> @Steve,
> I did break that outside layer out, so I was able to test just the 2
> possibilities, then made what you called the policy object. It sounds
> like you are ok for creating lots of little classes, in this case
> inner classes. Do you then mock at each level to keep the
> combinations down or do you provide all of the 64 combinations? Also,
> do you find that TDD is causing you to go overboard in breaking up
> classes into TOO small of a granularity? Is it harder to maintain so
> many classes, or even be able to read them? From a pragmatic view, do
> you have some nice tools that helps you write so much extra code
> quickly?

I probably wouldn't mock the policy object. I'd make sure it was tested properly, and then just exercise a couple of examples of its use at the higher level. Don't forget that these are all just examples of use to help us understand the domain and to give us a degree of confidence. That's why we don't test every possible integer value.

I don't mind many smaller classes (to some limit). Each one describes a chunk of behaviour that I can forget about once it's packaged up. What I /can't/ deal with is behaviour scattered throughout discursive code that is difficult to understand and to factor.

Tools: you /are/ using Resharper right? I wouldn't even consider working in .Net without it.


> I love that TDD helps me tease out responsibilities. When I listen to
> how hard it is to write the test, I can name a new responsibility and
> move from there. In this case, my gut tells me that TDD is going
> overboard, making so many classes I fear would be harder to maintain,
> not easier. It seems to be artificially breaking up classes not based
> on responsibility, but due to our inability to concisely express tests
> that have so many permutations.

in the end there's some judgement involved and you have to find your own balance. The permutation techniques others have described might be just the job here. I'm just wondering if there's a type missing here that describes these 8 permutations and that is relevant elsewhere. Could it have a meaningful name?

> I also have the situation where my partner and I are the only ones in
> the company even attempting TDD. We are trying to get our processes
> down so we can become advocates. Having several hundred lines of code
> + test code to show what we could have done in a dozen or so is not
> going to sell it for anyone (not even us).

It shouldn't be several hundred. I find I distinguish these days between "outer" types, which have all the official code paraphernalia, and "inner" types, which are more terse and sometimes break a few rules.


> @Alex
> I really like your idea. I know that it breaks the letter of the law
> to have a single assertion per test

see other responses. This is a training-wheel rule, to get people started. It's better interpreted as one concept per test.

S.

Steve Freeman

unread,
Aug 26, 2011, 5:49:29 PM8/26/11
to growing-object-o...@googlegroups.com
On 26 Aug 2011, at 12:43, Lance Walton wrote:
> If i may diverge slightly :-)

I thought you already had :)

> I have a strong dislike for lots of local classes unless they are anonymous. My preference is to recognise a new package, make the original class public in that new package, and make all of the supporting classes package visible, top-level classes in that package.

sometimes I do that. In Java I find myself writing static inner classes that might one day be candidates for promotion. The outer class is like the nested scope that packages should have been.

> So I tend to get lots of little classes / interfaces organised into lots of little packages.

I often find that the interfaces end up in different ("higher") packages than their implementations. They represent a protocol and so are more general.

S

J. B. Rainsberger

unread,
Aug 27, 2011, 4:35:45 PM8/27/11
to growing-object-o...@googlegroups.com
On Thu, Aug 25, 2011 at 20:26, Rick Pingry <rpi...@gmail.com> wrote:

> REALLY?  How in the world does all of that extra work (probably 20X as
> much work or more) really help me in this?  Does it help me write
> better code?

Not being rude, I promise: it's a 64-row truth table. It takes 10
minutes with a spreadsheet. What's hard about it? Occasionally it
happens that a single boolean expression is complicated and you have
to decide whether to test it.

If you don't test it, then extract the function f that maps n booleans
onto a single boolean, put it behind an interface, then the rest of
the system only cares about two cases: f answers true, f answers
false.

If you want to feel comfortable changing the implementation of f
without changing its observable behavior, then you need to test it at
some point. Test it now or test it later; that's a true technical debt
question.
--
J. B. (Joe) Rainsberger :: http://www.jbrains.ca ::
http://blog.thecodewhisperer.com
Author, JUnit Recipes
Free Your Mind to Do Great Work :: http://www.freeyourmind-dogreatwork.com
Find out what others have to say about me at http://nta.gs/jbrains

Rick Pingry

unread,
Aug 28, 2011, 11:41:25 AM8/28/11
to Growing Object-Oriented Software
Yeah, the whole parameterized nunit stuff that Erlis pointed me to was
exactly what I needed. I can see writing the truth table.
Sorry, I thought I had posted back that that was the answer for me,
but apparently it got lost in the Ether. :)

As for tools, I have seen the use of resharper, and it is amazing. I
am just now making the cross between C++ desktop app & ActiveX control
development and C# ASP.NET Web App, so I have not made the purchase
yet, but I am sure I will (trying to talk the company into the value
of it).

Without something like parameterized truth tables and resharper, you
are foced to write 64 little test functions, or break out interfaces
and mocks all the way down and have 20 tests. Either way, easily 20x
the work. Still hard to sell to my friends who are used to the "code
and pray" mentality (which I suppose I am still trying to break myself
of). In the moment, that line of logic does not seem complex enough
to feel like you could break. Famous last words I know, but as you
all well know, this is the kind of thing you are up against when you
are trying to sell yourself and your team on the program (when it is
hard enough just to get them to buy you resharper). Even 10 minutes
feels like way too much work when you want to get on to doing the next
feature. Since this kind of stuff is common, I know we need to get a
process in place that handles it quickly and effectively. I think
parameterized tests and resharper are just what the Dr. ordered.

So, JBrains... How does doing it in Excel help me? Is there a testing
strategy I am not aware of? Are you talking about using FitNesse or
some acceptance testing? I thought it all needed to be unit tested
anyway? or perhaps you were just making a point that even 64
permutations is not all that large.

Matteo Vaccari

unread,
Aug 29, 2011, 2:22:08 AM8/29/11
to growing-object-o...@googlegroups.com


On Fri, Aug 26, 2011 at 6:40 PM, Rick Pingry <rpi...@gmail.com> wrote:
> Thanks for the quick feedback everybody!  I did not hear anyone
> advocate only testing a subset of the possibilities, so I will assume
> that it is indeed important to test all of the permutations, either
> exhaustively (all 64), or at certain junctures.

Looking at your example, the tests that *I* would write would be as follows:


According to the specification, a document has anonymous
access if ...
1 The Document is Approved      AND
2 The Document has Level 1 OR Level 2 Security    AND
3 The document has anonymous access in at least one site

approved        level1sec       level2sec       atLeastOneSite  result?
T               T               F               T               T
T               F               T               T               T
T               T               T               T               T
F               T               T               T               F
T               F               F               T               F
T               T               T               F               F

That's six tests total.  I would maybe use a parameterized test, or (more likely) something like

@Test void anonymousAccess() {
  checkAnonymousAccess(T, T, F, T, T);
  checkAnonymousAccess(T, F, T, T, T);
  // ...
}

I feel that these tests cover all the possibilities that I would care about if I were you (given what I know about your problem, of course.)  

You say that the third condition (at least one site has anonymous access) has 8 permutations.  You might separate the tests for that condition in another test.  All we care about in the above test is whether the third condition is true or false.  I don't think we have to check all the combinations at all.

Perhaps if I were a tester I would try other combinations at random.  I may write a program that generates all permutations and tests them.  But the kind of tests that we need to do as developers are meant for supporting development, not to try very hard to break the system.

Matteo

loedolff

unread,
Aug 29, 2011, 11:22:26 AM8/29/11
to growing-object-o...@googlegroups.com
IMHO, a truth table is a little bit of an overkill for this particular logic problem.  There are exactly 2 conditions under which IsAnonymousAccess must return true:

- The Document is Approved  AND  The Document has Level 1 AND  The document has anonymous access in at least one site
- The Document is Approved  AND  The Document has Level 2 AND  The document has anonymous access in at least one site

So you only need to verify that anonymous access is granted for those two cases.  You can loop through all the other cases and make sure that IsAnonymousAccess returns false for all other cases.

The function to test if "The document has anonymous access in at least one site" might warrant a separate test.  But you can mock it out when testing IsAnonymousAccess (no need to include all of the "The document has anonymous access in at least one site" permutations when testing IsAnonymousAccess).


J. B. Rainsberger

unread,
Aug 29, 2011, 8:12:50 PM8/29/11
to growing-object-o...@googlegroups.com
On Sun, Aug 28, 2011 at 12:41, Rick Pingry <rpi...@gmail.com> wrote:

> Without something like parameterized truth tables and resharper, you
> are foced to write 64 little test functions, or break out interfaces
> and mocks all the way down and have 20 tests.

I don't know what Resharper does in this situation, but I would use
the Parameterised Test Case pattern to write one test with 64 cases as
rows in a table. (Worst case, as literal rows in a 2d array.)

> So, JBrains... How does doing it in Excel help me?  Is there a testing
> strategy I am not aware of?  Are you talking about using FitNesse or
> some acceptance testing?  I thought it all needed to be unit tested
> anyway?  or perhaps you were just making a point that even 64
> permutations is not all that large.

One option: Excel, export to CSV, write a single test to load the data
and generate a test for each row. Another option: Fit ColumnFixture --
using Fit doesn't make it an acceptance test.

64 permutations is tedious, but not difficult. We have tools to make
that less tedious.

Nat Pryce

unread,
Aug 30, 2011, 8:46:07 AM8/30/11
to growing-object-o...@googlegroups.com

Luca Minudel

unread,
Aug 30, 2011, 9:28:32 AM8/30/11
to Growing Object-Oriented Software

Rick , here is my feedback then.

Lot of answers in this thread, did not get the time to read all of
them carefully and check that I understood properly, so no intention
w/ this post to contract other ideas at all.



Sometime it happen to me too to have say one method S that have
different behaviour and another method T that also have different
behaviour and then a method say A that call and combine S and T.
So if S has say 3 behaviour and T has 7 behaviour then A have to test
7x3=21 behaviours to be tested. The combinatorial explosion. And when
4 more behaviours are added to T we get 11x3=33 behaviour that are 12
new tests to be writen.

I take this as a suggestion to extract S or T or both on different
classes. So that I can test separately the 3 behaviours of S (say 3
tests), the 11 behaviours of T (say 11 tests) and then test that A
delegates properly the work to S and T (say 1 test mocking S and T).
Doing so overall are 14 tests. When 1 new behaviour is added to S or
T only 1 new tests is needed: no more combinatorial explosion.


In similar situations I start extracting S, T or both. A look at the
design usually suggest me what is the more meaningful way to do it.
Then I see if it make sense to extract S or T to one class of their
own or use an instance (i.e. with the command pattern or the prototype
pattern) or use more fine grained reuse patterns like (i.e. delegates
in C# or lambda expressions).



I tend to split/extract as much as needed to avoid this scenario of
unit tests combinatorial explosion. If I go too far (splitting 1
single responsibility to 2 different classes) soon or late I will find
myself violating the LoD between the original class and the extracted
one.
So personally I prefer to take the risk to make a mistake and then
monitor the violation of LoD.
Sooner or later, when my understanding of the domain improve and the
underling concepts emerges, the right organizations of the
responsibilities usually become clear to me and having lot of small
objects help me this process.

Code design is a very personal activity based on the incremental
creation of mental models of the problems, while I think that no one
can argue the intermediate steps that each one follow in this mental
process, still there is room to discuss the results we reach after a
significant number of steps/refactoring/refinements/iterations. Here
the tension, the tread-off between SRP and LoD should help to analyse
the result.


HTH, Luca


On Aug 26, 6:40 pm, Rick Pingry <rpin...@gmail.com> wrote:
> Thanks for the quick feedback everybody!  I did not hear anyone
> advocate only testing a subset of the possibilities, so I will assume
> that it is indeed important to test all of the permutations, either
> exhaustively (all 64), or at certain junctures.
>
> @Luca,
> Yep, unit tests.  While I did try once, I have not gotten past the
> time and expense of writing true GOOS style acceptance tests.  I am
> able to run what I am writing pretty quickly and easily, so I just
> wrote (at least in my head) a manual acceptance test based on the
> specification.
>
> ...

J. B. Rainsberger

unread,
Aug 30, 2011, 6:01:14 PM8/30/11
to growing-object-o...@googlegroups.com

I think that opening Excel and cranking through the 64 cases in a
truth table would reveal this information within a few minutes, which
explains why, when in doubt, I just start doing that. :) ("Hey, look
at all these duplicate rows…")

J. B. Rainsberger

unread,
Aug 30, 2011, 6:01:32 PM8/30/11
to growing-object-o...@googlegroups.com
On Tue, Aug 30, 2011 at 09:46, Nat Pryce <nat....@gmail.com> wrote:

> L

L?! Bastard!

Steve Freeman

unread,
Aug 31, 2011, 9:54:00 AM8/31/11
to growing-object-o...@googlegroups.com
On 28 Aug 2011, at 16:41, Rick Pingry wrote:
> As for tools, I have seen the use of resharper, and it is amazing. I
> am just now making the cross between C++ desktop app & ActiveX control
> development and C# ASP.NET Web App, so I have not made the purchase
> yet, but I am sure I will (trying to talk the company into the value
> of it).

if your company is even dithering, they don't understand software development! Frankly, unless you're hard up, if they won't, I'd buy my own copy and take with me to the next job.

> Without something like parameterized truth tables and resharper, you
> are foced to write 64 little test functions, or break out interfaces
> and mocks all the way down and have 20 tests. Either way, easily 20x
> the work.

Sorry, I don't see that. As we said before, the one-assert-per-test is only a good idea to break old habits. You can write parameterised tests in good ol' fashioned code by calling a helper method. The real point, however, is to use the test writing to help you think about the domain and make sure you've covered it properly. It's amazing how much addressing code from it's externally visible effects clarifies understanding.

> Still hard to sell to my friends who are used to the "code
> and pray" mentality (which I suppose I am still trying to break myself
> of). In the moment, that line of logic does not seem complex enough
> to feel like you could break. Famous last words I know, but as you
> all well know, this is the kind of thing you are up against when you
> are trying to sell yourself and your team on the program (when it is
> hard enough just to get them to buy you resharper). Even 10 minutes
> feels like way too much work when you want to get on to doing the next
> feature.

I know you're doing your best, but this doesn't make sense to me. Development cost must include all the way to fixing the bugs. A little bug in a condition like this can cost hours and hours to find in a deployed system.

In the meantime, I wouldn't necessarily try to convert the world. One alternative is to adopt the practice yourself until you have some experience and start showing that it's never your code that breaks just before the big demo.

S.


Matt Wynne

unread,
Aug 31, 2011, 5:43:21 PM8/31/11
to growing-object-o...@googlegroups.com

On 31 Aug 2011, at 14:54, Steve Freeman wrote:

> On 28 Aug 2011, at 16:41, Rick Pingry wrote:
>> As for tools, I have seen the use of resharper, and it is amazing. I
>> am just now making the cross between C++ desktop app & ActiveX control
>> development and C# ASP.NET Web App, so I have not made the purchase
>> yet, but I am sure I will (trying to talk the company into the value
>> of it).
>
> if your company is even dithering, they don't understand software development! Frankly, unless you're hard up, if they won't, I'd buy my own copy and take with me to the next job.

+1

Working in visual studio without resharper is like trying to cut someone's hair with nail scissors. You owe it to yourself to work with decent tools.

>> Without something like parameterized truth tables and resharper, you
>> are foced to write 64 little test functions, or break out interfaces
>> and mocks all the way down and have 20 tests. Either way, easily 20x
>> the work.
>
> Sorry, I don't see that. As we said before, the one-assert-per-test is only a good idea to break old habits. You can write parameterised tests in good ol' fashioned code by calling a helper method. The real point, however, is to use the test writing to help you think about the domain and make sure you've covered it properly. It's amazing how much addressing code from it's externally visible effects clarifies understanding.
>
>> Still hard to sell to my friends who are used to the "code
>> and pray" mentality (which I suppose I am still trying to break myself
>> of). In the moment, that line of logic does not seem complex enough
>> to feel like you could break. Famous last words I know, but as you
>> all well know, this is the kind of thing you are up against when you
>> are trying to sell yourself and your team on the program (when it is
>> hard enough just to get them to buy you resharper). Even 10 minutes
>> feels like way too much work when you want to get on to doing the next
>> feature.
>
> I know you're doing your best, but this doesn't make sense to me. Development cost must include all the way to fixing the bugs. A little bug in a condition like this can cost hours and hours to find in a deployed system.
>
> In the meantime, I wouldn't necessarily try to convert the world. One alternative is to adopt the practice yourself until you have some experience and start showing that it's never your code that breaks just before the big demo.

And practice the practice. Work on an open-source project, or just build something for fun in your spare time. That way when you do it at work you'll be good at it, and you won't feel guilty like you're learning a new skill on the job. Though as jbrains can tell you, you shouldn't feel at all bad about learning on the job.

cheers,
Matt

--
Freelance programmer & coach
Author, http://pragprog.com/book/hwcuc/the-cucumber-book (with Aslak Hellesøy)
Founder, http://relishapp.com
+44(0)7974430184 | http://twitter.com/mattwynne

Colin Vipurs

unread,
Sep 1, 2011, 3:50:14 AM9/1/11
to growing-object-o...@googlegroups.com
I second Steve on that one. Years ago I worked on a messaging bridge
between a front and backend system and it was the only part of the
system that had significant testing in a system that was riddled with
bugs. The finger was always pointed at that part of the code when a
bug surfaced, yet it was never that code that was broken.

> In the meantime, I wouldn't necessarily try to convert the world. One alternative is to adopt the practice yourself until you have some experience and start showing that it's never your code that breaks just before the big demo.
>

--
Maybe she awoke to see the roommate's boyfriend swinging from the
chandelier wearing a boar's head.

Something which you, I, and everyone else would call "Tuesday", of course.

Raoul Duke

unread,
Sep 1, 2011, 1:22:50 PM9/1/11
to growing-object-o...@googlegroups.com
+1 more :)

Erlis Vidal

unread,
Sep 1, 2011, 1:43:25 PM9/1/11
to growing-object-o...@googlegroups.com
my biggest issue is the misunderstanding around TDD, nowadays I use the terminology "verification code" more than "unit tests", I was told once that I'm forbidden to write any tests, test is the job of tester and that the test code was twice long in LoC than the code in production (the manager was actually reading my tests wow). Just remembering days like that, makes me really sad.

Now I don't write tests, that's the tester job (which they are not doing, by the way) I just write verification code :) 

Steve Freeman

unread,
Sep 1, 2011, 5:50:18 PM9/1/11
to growing-object-o...@googlegroups.com
and you're still working there? :)

S.

Seb Rose

unread,
Sep 1, 2011, 11:04:43 AM9/1/11
to growing-object-o...@googlegroups.com
Earlier on in this thread, Steve said:
"I prefer not to extract and override (although many people recommend
it). Over time, I find it makes it hard to see the boundaries of the
class and it's harder for the IDE to provide help. I tend to keep
methods either public or private, and limit the use of protected. I
prefer to write nested helper classes that implement these decisions.
Normally, they're only used by the containing class, and I can write
direct tests for them without leaking structure."

Would anyone be able to provide a (small) concrete example of this in action?


Cheers
Seb
--
ACCU - Professionalism in Programming - http://accu.org

http://www.claysnow.co.uk
http://twitter.com/#!/sebrose
http://uk.linkedin.com/in/sebrose

Lance Walton

unread,
Sep 1, 2011, 5:59:23 PM9/1/11
to growing-object-o...@googlegroups.com
Why not 'specification code'?

Lance

On 1 Sep 2011, at 18:43, Erlis Vidal wrote:

J. B. Rainsberger

unread,
Sep 1, 2011, 8:14:06 PM9/1/11
to growing-object-o...@googlegroups.com
On Thu, Sep 1, 2011 at 14:43, Erlis Vidal <er...@erlisvidal.com> wrote:
> Now I don't write tests, that's the tester job (which they are not doing, by
> the way) I just write verification code :)

"They're automated assertion; you know, like design by contract. You
*have* read Meyer haven't you? You haven't? Eiffel? Really? Where did
you get your degree?!"

That should shut them up.

Josue Barbosa dos Santos

unread,
Sep 2, 2011, 6:34:21 AM9/2/11
to growing-object-o...@googlegroups.com
On Thu, Sep 1, 2011 at 6:59 PM, Lance Walton
<lance.c...@googlemail.com> wrote:
> Why not 'specification code'?
+1

--
Abraços,
Josué
http://twitter.com/josuesantos

Anthony Green

unread,
Sep 4, 2011, 6:10:17 AM9/4/11
to growing-object-o...@googlegroups.com

Erlis Vidal wrote:
> my biggest issue is the misunderstanding around TDD, nowadays I use the
> terminology "verification code" more than "unit tests", I was told once
> that I'm forbidden to write any tests, test is the job of tester and
> that the test code was twice long in LoC than the code in production
> (the manager was actually reading my tests wow). Just remembering days
> like that, makes me really sad.

In case it ever happens to you again:

http://www.infoq.com/news/2011/03/Ensuring-Product-Quality-Google

Erlis Vidal

unread,
Sep 4, 2011, 9:00:43 AM9/4/11
to growing-object-o...@googlegroups.com
Thanks for the link,

And thanks to Steve and @jbrains for their answers too.

This guy has destroyed the team, he was introduced (don't know why, we were self-managed team already) and everything  is a nightmare now... I'm seriously following Steve advice right now.

Erlis

Steven Solomon

unread,
Sep 5, 2011, 10:24:54 AM9/5/11
to growing-object-o...@googlegroups.com
Why not keep writing tests and have to git instances one to manage the codebase and another the tests. this way everyone against tests is blissfully ignorant, yet you can maintain your code quality

philip schwarz

unread,
Sep 7, 2011, 5:54:39 PM9/7/11
to Growing Object-Oriented Software
Hi Steve,

you wrote: "I prefer not to extract and override (although many people
recommend it)"

A few days ago someone on twitter said: "TDD fans: is designing code
to simply facilitate easy testing a bad thing? See https://gist.github.com/1186095
for example of what I'm struggling with."

Do the following two comments I left there align with your statement
above and with the GOOS approach?

https://gist.github.com/1186095#gistcomment-49016
https://gist.github.com/1186095#gistcomment-49021

Philip

On Aug 26, 9:46 am, Steve Freeman <st...@m3p.co.uk> wrote:
> so, speculating wildly....
>
> It seems like the explosion in combinations comes from the 8 permutations that determine anonymous access, so perhaps that behaviour should be pulled into a separate object. That might be a collaborator, and hence mockable, if it pulls in external resources, or an embedded policy object if it just works with values. For a mocked collaborator, you only have to test its true and false results in the client, and test its implementation separately. Similarly, for a policy object, you can write high level tests for its true and false cases, and then write direct tests that work through its 8 combinations. Alternatively, perhaps the whole anonymous decision should be extracted to a helper object.
>
> I prefer not toextractand override (although many people recommend it). Over time, I find it makes it hard to see the boundaries of the class and it's harder for the IDE to provide help. I tend to keep methods either public or private, and limit the use of protected. I prefer to write nested helper classes that implement these decisions. Normally, they're only used by the containing class, and I can write direct tests for them without leaking structure.
>
> I get your point about deferring everything. My style is to have more smaller objects than many people are used to. That said, a lot of them are supporting classes that are local to a containing class, which avoids some of the mock-tastic codebases I've seen (and have sometimes been responsible for).
>
> Does that help at all?
>
> A public example would be a good idea.
>
> S.
>
> On 26 Aug 2011, at 00:26, Rick Pingry wrote:
>
> > We have a situation that seems painful that we seem to come up with
> > constantly.  It involves dealing with any kind of boolean logic that
> > is even moderately complex.  The examples that we read about, even in
> > GOOS, seem to have little or no boolean logic to deal with.  We are
> > not sure if we are doing something wrong, or perhaps if we have a
> > problem at a fundamental level.
>
> > Please allow me to give our real-world example:
> > [...]
> > Thanks for any help.  It seems that this should be pretty common.  Are
> > there any KATAs or TDD examples out there that cover this kind of code?

J. B. Rainsberger

unread,
Sep 8, 2011, 3:34:31 PM9/8/11
to growing-object-o...@googlegroups.com
On Wed, Sep 7, 2011 at 18:54, philip schwarz
<philip.joh...@googlemail.com> wrote:
> Hi Steve,
>
> you wrote: "I prefer not to extract and override (although many people
> recommend it)"
>
> A few days ago someone on twitter said: "TDD fans: is designing code
> to simply facilitate easy testing a bad thing? See https://gist.github.com/1186095
> for example of what I'm struggling with."

I commented there. I'll copy the comment here.

Extract-and-override is almost always a step towards introducing a new
Collaborator. See "Replace Inheritance with Delegation" in Fowler's
_Refactoring_. Introducing the Collaborator inverts the dependency,
increasing context independence by pushing dependency on the runtime
environment up a level of the call stack. That all sounds good to me.

Steve Freeman

unread,
Sep 8, 2011, 3:42:23 PM9/8/11
to growing-object-o...@googlegroups.com
I think I tend to "introduce collaborator and extract". Introduce an empty inner class, with an instance in the outer class. Move the behaviour to the inner class--no externally visible changes yet. Then pull the inner class out of the outer, and pass it in through the constructor.

S.

On 8 Sep 2011, at 20:34, J. B. Rainsberger wrote:
> On Wed, Sep 7, 2011 at 18:54, philip schwarz
> <philip.joh...@googlemail.com> wrote:
>> Hi Steve,
>>
>> you wrote: "I prefer not to extract and override (although many people
>> recommend it)"
>>
>> A few days ago someone on twitter said: "TDD fans: is designing code
>> to simply facilitate easy testing a bad thing? See https://gist.github.com/1186095
>> for example of what I'm struggling with."
>
> I commented there. I'll copy the comment here.
>
> Extract-and-override is almost always a step towards introducing a new
> Collaborator. See "Replace Inheritance with Delegation" in Fowler's
> _Refactoring_. Introducing the Collaborator inverts the dependency,
> increasing context independence by pushing dependency on the runtime
> environment up a level of the call stack. That all sounds good to me.

Steve Freeman

Rick Pingry

unread,
Sep 9, 2011, 12:01:08 PM9/9/11
to Growing Object-Oriented Software
So, when does the overriden class become "big enough" to become its
own inner class, and then a collaborator for the original class?
Perhaps related to the interface becoming simpler than the sum of its
parts or something? It seems if you jumped and did this every time,
then you would have gazillions of little one method classes, right?

On Sep 8, 1:42 pm, Steve Freeman <st...@m3p.co.uk> wrote:
> I think I tend to "introduce collaborator and extract". Introduce an empty inner class, with an instance in the outer class. Move the behaviour to the inner class--no externally visible changes yet. Then pull the inner class out of the outer, and pass it in through the constructor.
>
> S.
>
> On 8 Sep 2011, at 20:34, J. B. Rainsberger wrote:
>
>
>
>
>
>
>
>
>
> > On Wed, Sep 7, 2011 at 18:54, philip schwarz
> > <philip.johann.schw...@googlemail.com> wrote:
> >> Hi Steve,
>
> >> you wrote: "I prefer not to extract and override (although many people
> >> recommend it)"
>
> >> A few days ago someone on twitter said: "TDD fans: is designing code
> >> to simply facilitate easy testing a bad thing? Seehttps://gist.github.com/1186095

zodi...@gmail.com

unread,
Sep 9, 2011, 12:25:42 PM9/9/11
to growing-object-o...@googlegroups.com, Growing Object-Oriented Software
I regularly end up with such classes and I consider it to be a good thing. I think I jump ahead and go straight for the collaborator but that's usually because in my tests I just think 'I dont care or don't want to know about this logic right know' and carry on with a mocked interface which my CUT drives the interface for.

I find with this I end up with systems composed of very small but focused objects that can be easily swapped and reused.

Steve Freeman

unread,
Sep 10, 2011, 7:09:50 PM9/10/11
to growing-object-o...@googlegroups.com
sorry, I got lost there. who are you asking about overridden classes?

S.

Rick Pingry

unread,
Sep 10, 2011, 9:31:49 PM9/10/11
to Growing Object-Oriented Software
Wow, it sounds like you guys are extracting classes, all the time. 2
questions...

1. Do you move the tests from the old test to the new class?
2. How does having a zillion one-method classes make the code any
better? Sounds to me like it would make it harder to maintain, harder
to read. Can't responsibilities be broken up too much? Is there not
a level when a class is too small to be considered a class?

Steve Freeman

unread,
Sep 11, 2011, 4:35:59 AM9/11/11
to growing-object-o...@googlegroups.com
On 11 Sep 2011, at 02:31, Rick Pingry wrote:
> Wow, it sounds like you guys are extracting classes, all the time.

er, yes.

> 2 questions...
>
> 1. Do you move the tests from the old test to the new class?

if it's a supporting class, it's tested through the outer. If it grows big enough to be promoted, then write some detail tests to go with it and leave a few coherence tests to make sure everything fits together.

> 2. How does having a zillion one-method classes make the code any
> better? Sounds to me like it would make it harder to maintain, harder
> to read. Can't responsibilities be broken up too much? Is there not
> a level when a class is too small to be considered a class?

probably, but I see more of the opposite problem. Complex code that could be clarified by pulling out a concept. A classic example is building up and manipulating a collection of objects. In Java, this usually results in an explosion of angle brackets, whereas a better solution is to create a specialised collection object and move some of the control there.

S.

Lance Walton

unread,
Sep 11, 2011, 5:34:28 AM9/11/11
to growing-object-o...@googlegroups.com
If there are a bunch of methods dealing with a set of fields, extract them into a new class (cohesion).

You may need to do this by moving some of the fields and passing one or two as parameters. This may lead to observations of data clumps. Create new classes and see if methods should move again.

You often see a lot of behaviour around one field in a class. That definitely needs to be recognised with it's own class.

Where no fields are used by a method, use your judgement about whether to extract it. Err on the side of lots of small classes for a while.

Regards,

Lance

Nat

unread,
Sep 12, 2011, 7:25:23 AM9/12/11
to growing-object-o...@googlegroups.com

On Sunday, September 11, 2011 2:31:49 AM UTC+1, Rick Pingry wrote:
2.  How does having a zillion one-method classes make the code any
better?  Sounds to me like it would make it harder to maintain, harder
to read.  Can't responsibilities be broken up too much?  Is there not
a level when a class is too small to be considered a class?

Given that anonymous functions (aka closures) is merely a convenient syntax for creating an object with one method, I guess my code does have many more one-method objects than any other kind.  But I don't usually create a named class to define them.  I'll introduce a named class to represent a concept that has a bunch of polymorphic operations.

Vasily Kirichenko

unread,
Sep 12, 2011, 2:55:37 PM9/12/11
to growing-object-o...@googlegroups.com
Given that anonymous functions (aka closures) is merely a convenient syntax for creating an object with one method, I guess my code does have many more one-method objects than any other kind.  But I don't usually create a named class to define them.  I'll introduce a named class to represent a concept that has a bunch of polymorphic operations.

> Given that anonymous functions (aka closures) ismerely aconvenient syntax
> for creating an object with one method, I guess my code does have many more
> one-method objects than any other kind.  But I don't usually create a named
> class to define them.  I'll introduce a named class to represent a concept
> that has a bunch of polymorphic operations.

I think, closures don't highlight roles of an OO system, but "old plane" interfaces do. Quick glance at a class which implement some interfaces is enough to immediately realize what roles the class plays:

# explicit role
class UserRequestListener
  def join_auction(item)
  end
end

# no doubts, this class is listening for user requests
class SniperLauncher < UserRequestListener
  def initialize(auction_house, sniper_collector)
    @auction_house = auction_house
    @sniper_collector = sniper_collector;
  end

  def join_auction(item)
    auction = @auction_house.auctionFor(item)
    sniper = AuctionSniper.new(item, auction)
    auction.add_auction_event_listener(sniper)
    @sniper_collector.addSniper(sniper)
    auction.join
  end
end

class Main
  # all other methods...

  def add_user_request_listener_for(auction_house)
     @ui.add_user_request_listener(SniperLauncher.new(auction_house, @portfolio))
  end
end

What it would look like if it were a closure? Something like this, I think:

class Main
  # all other methods...

  def add_user_request_listener_for(auction_house)
    @ui.add_user_request_listener lambda { |item|
      auction = auction_house.auction_for(item)
      sniper = AuctionSniper.new(item, auction)
      auction.add_auction_event_listener(sniper)
      @portfolio.add_sniper(sniper)
      auction.join item
    }
  end
end

Hmm... it's clear, however, that this piece of code is a user request listener... :) OK, then I have another question - how it would be 'emerged' by TDD process? I think, it's just impossible - the code block is entirely private for the class (BTW, those closures look very similar to Steve Freeman's 'internal peers' (private Java classes, as I understand them)). Although you say in GOOS that we shouldn't test collaboration with internal peers, the lambda above is not a completely trivial one, and I really like to test it in some way. But it's impossible. 

If my example is inadequate, show us some your real code that uses closures instead of one-method classes (with tests!), please.

Steve Freeman

unread,
Sep 13, 2011, 7:02:48 AM9/13/11
to growing-object-o...@googlegroups.com
On 12 Sep 2011, at 20:55, Vasily Kirichenko wrote:
> What it would look like if it were a closure? Something like this, I think:
>
> class Main
> # all other methods...
>
> def add_user_request_listener_for(auction_house)
> @ui.add_user_request_listener lambda { |item|
> auction = auction_house.auction_for(item)
> sniper = AuctionSniper.new(item, auction)
> auction.add_auction_event_listener(sniper)
> @portfolio.add_sniper(sniper)
> auction.join item
> }
> end
> end
>
> Hmm... it's clear, however, that this piece of code is a user request
> listener... :) OK, then I have another question - how it would be 'emerged'
> by TDD process? I think, it's just impossible - the code block is entirely
> private for the class (BTW, those closures look very similar to Steve
> Freeman's 'internal peers' (private Java classes, as I understand them)).
> Although you say in GOOS that we shouldn't test collaboration with internal
> peers, the lambda above is not a completely trivial one, and I really like
> to test it in some way. But it's impossible.

In this case, this is "assembly" code which we tend not to unit test, but rely on integration or even acceptance testing. What we want to know is that this part of the system hangs together, rather than that there's an object that responds in a particular way to an event.

S.

Rick Pingry

unread,
Sep 13, 2011, 10:33:00 AM9/13/11
to Growing Object-Oriented Software
> In this case, this is "assembly" code which we tend not to unit test, but rely on integration or even acceptance testing. What we want to know is that this part of the system hangs together, rather than that there's an object that responds in a particular way to an event.
>

Oooh, ooooh!
Could you please speak to that a bit, Steve, or refer to some part of
the book (perhaps I glossed over)...

Could you define some of the rues for when code is considered
"assembly" code? From the second sentence, I am getting the
impression that there are classes that are "wiring" whereas other
classes might be more about logic. Should we be breaking classes up
that way? Hmm, my gut tells me something is wrong with that, but I
cannot put my finger on it.

Thanks
-- Rick

Steve Freeman

unread,
Sep 15, 2011, 9:43:40 AM9/15/11
to growing-object-o...@googlegroups.com
On 13 Sep 2011, at 15:33, Rick Pingry wrote:
>> In this case, this is "assembly" code which we tend not to unit test, but rely on integration or even acceptance testing. What we want to know is that this part of the system hangs together, rather than that there's an object that responds in a particular way to an event.
>>
>
> Oooh, ooooh!
> Could you please speak to that a bit, Steve, or refer to some part of
> the book (perhaps I glossed over)...

I think there's some relevant material in the "teasing apart Main" chapter>

> Could you define some of the rules for when code is considered


> "assembly" code? From the second sentence, I am getting the
> impression that there are classes that are "wiring" whereas other
> classes might be more about logic. Should we be breaking classes up
> that way? Hmm, my gut tells me something is wrong with that, but I
> cannot put my finger on it.

a lot of the code we build has most of the behaviour implemented by a combination of reasonably small objects with collaborators and immutable value objects -- "classic" OO. Then we usually have a layer or so on top of that which tries to be a declarative declaration of what the overall behaviour will be. jMock is an example of this. The advantage is that we end up with a system that is made up of multiple independent components which we can reconfigure to support new features.

What troubles you about this approach? How do you think it might fail?

Evgeni Dzhelyov

unread,
Sep 15, 2011, 9:59:35 AM9/15/11
to growing-object-o...@googlegroups.com
I often hear critique on this approach from people that are exposed to
the lower layer and don't understand its purpose
or don't grasp the concept of building their own more declarative
layer on top of that.

I'm working with web technologies and there is big arguing about the
jQuery interface.
Most people find jQuery so great because of most outer API and refuse
to learn about other frameworks that provide more
modular and separated design and imho are much better structured then
jQuery. And when I told them that you can always create
your own layer that mimics the jQuery API, they never seems to hear it.

I think maybe this is more about psychological barrier than actual
technical arguments against such modular approaches.

Nat

unread,
Sep 15, 2011, 11:13:44 AM9/15/11
to growing-object-o...@googlegroups.com
The trouble is, building that upper layer is difficult.  JMock is a tiny API, but even that went through years of evolution driven by feedback from many people.

The high-level API is the first thing people see.  It's a library's selling point. For example, Mockito could have used much of the lower-layer mechanics of jMock and skinned it with a different API.  Instead they started with the API (because that's what users care about) and evolved the flexible underpinnings just like we did, and copied some code from jMock into their project when they needed to.

--Nat

Rick Pingry

unread,
Sep 16, 2011, 11:25:12 AM9/16/11
to Growing Object-Oriented Software
Funny, I am reading the book over again, (and learning more this
time), and I just came to the section in chapter 7 called "Building Up
to Higher-Level Programming", which is just what you are talking
about.

So, you say that declarative layer on the top, the part I presume that
is used by "main". So, main becomes a composer of sorts, composing
the various objects with their collaborators.
I think I got it, thanks.

Raoul Duke

unread,
Sep 16, 2011, 1:35:57 PM9/16/11
to growing-object-o...@googlegroups.com
On Fri, Sep 16, 2011 at 8:25 AM, Rick Pingry <rpi...@gmail.com> wrote:
> Funny, I am reading the book over again, (and learning more this
> time), and I just came to the section in chapter 7 called "Building Up
> to Higher-Level Programming", which is just what you are talking
> about.

presumably top-down could also be done in a TDD fashion since the top
is the DSL that is basically the acceptance tests for the underlying
low-level implementation layer, and one can keep refactoring and
evolving the levels?

Rick Pingry

unread,
Sep 20, 2011, 4:08:42 PM9/20/11
to Growing Object-Oriented Software
Yeah, I agree. I think it is finally <FINALLY> starting to gel in my
head that the TDD is not so much about writing regression tests as it
is about designing. It is now starting to sink that when they said
its about design, they mean it is about designing INTERFACES at each
level that show how classes collaborate. To make them collaborate at
each level as if the code you wanted already existed. (Yes, I know
you are all saying, well DUH! didn't we way that about a zillion
times!, maybe it is just me, but I seem to have these epiphanies that
are rather obvious to everyone else. It seems to hammer home a
concept that I thought I already knew and understood, but apparently
didn't,oh well).

Would that idea of defining interfaces apply at this level as well?

So, to follow Raoul's lead, when you are talking about this layer, the
layer that is actually used in "main" (whatever that may be, perhaps
your aspx code behind or whatever), It seems you should lay out the
code the way you want it to look there declaratively, attaching the
adapters that talk to the various boundaries, then perhaps write tests
that look the same way? Those may look much like the acceptance tests
like Raoul said, but they are not end-to-end GOOS style. They still
won't connect to real web stuff and databases.

Is that OK?

-Or- is that not as helpful, because you do the declarative stuff in
main, writing it as if the code you already wanted already existed,
then start with TDD one level below that? Just the exercise of
writing it in main that way IS the design, so testing it is not as
valuable?

On Sep 16, 11:35 am, Raoul Duke <rao...@gmail.com> wrote:

Steve Freeman

unread,
Sep 26, 2011, 6:49:22 PM9/26/11
to growing-object-o...@googlegroups.com
There are two ways to get to such a DSL, one is to refactor the implementation level like crazy until it starts to make sense. The other is to write the code you want to see and then fill it in. I've done both and I don't know which is better.

I tend not to unit-test an outer assembly layer because what I really want to know is if everything works together, not just what's plugged into what. If I'm going outside-in, this tends to happen naturally.

Not sure if I'm answering you, I kinda lost the thread.

S.

Steve Freeman

Winner of the Agile Alliance Gordon Pask award 2006
Book: http://www.growing-object-oriented-software.com

+44 (0) 797 179 4105
M3P Limited. http://www.higherorderlogic.com


Registered office. 2 Church Street, Burnham, Bucks, SL1 7HZ.

Company registered in England & Wales. Number 03689627

Andrew Premdas

unread,
Oct 2, 2011, 9:53:50 PM10/2/11
to growing-object-o...@googlegroups.com
On 20 September 2011 21:08, Rick Pingry <rpi...@gmail.com> wrote:
> Yeah, I agree.  I think it is finally <FINALLY> starting to gel in my
> head that the TDD is not so much about writing regression tests as it
> is about designing.  It is now starting to sink that when they said
> its about design, they mean it is about designing INTERFACES at each
> level that show how classes collaborate.  To make them collaborate at
> each level as if the code you wanted already existed.  (Yes, I know
> you are all saying, well DUH! didn't we way that about a zillion
> times!, maybe it is just me, but I seem to have these epiphanies that
> are rather obvious to everyone else.  It seems to hammer home a
> concept that I thought I already knew and understood, but apparently
> didn't,oh well).

Personally I don't think this is correct. TDD is (or at least was)
about designing and exercising the interface of the class. BDD extends
this to say we are specifying the behaviour of the class. If we do a
good job of this we will have

1. A class that does what it says (what it says is its public interface)
2. An executable specification that describes/documents what the class
says it does
3. An executable specification that when run and green proves that the
class does what it says

In a way none of this really has anything to do with how the class
collaborates. But classes written in this way are much easier to
collaborate with. So an emergent benefit of doing good TDD is the
creation of better collaborators.

"Designing INTERFACES at each level that show how classes collaborate"
is something else I think, and implies thinking about more than one
class at a time. I would see this as more of a refactoring activity,
but some might want to 'architect' it. It isn't the point or a primary
focus of TDD as I understand it

All best

Andrew

--
------------------------
Andrew Premdas
blog.andrew.premdas.org

Raoul Duke

unread,
Oct 2, 2011, 11:28:11 PM10/2/11
to growing-object-o...@googlegroups.com
On Sun, Oct 2, 2011 at 6:53 PM, Andrew Premdas <apre...@gmail.com> wrote:
> "Designing INTERFACES at each level that show how classes collaborate"
> is something else I think, and implies thinking about more than one
> class at a time. I would see this as more of a refactoring activity,
> but some might want to 'architect' it. It isn't the point or a primary
> focus of TDD as I understand it

tdd is whatever you want it to be, probably :-)

i think there are plenty of people out there who see OO as being more
about the mu, the communications, the collaborations, than about
one-interface-at-a-time. presumably they could use tdd in their
approach.

sincerely.

Matteo Vaccari

unread,
Oct 3, 2011, 1:28:46 AM10/3/11
to growing-object-o...@googlegroups.com
Hi Andrew,

you seem to imply that a class has _one_ interface.  One of the things I learned from GOOS and from Robert Martin's books is that interfaces "belong" to the user of a class, not to the class that implements them.  This implies that 

a) a class often implements different interfaces for different roles, 
b) it's difficult to design interfaces without referring to the code that will call that interface.

What do you think?

Matteo

Andrew Premdas

unread,
Oct 3, 2011, 3:25:02 AM10/3/11
to growing-object-o...@googlegroups.com

Well physically a class has one interface, in that it has a number of
methods that can be called, and you can easily write unit tests for.
The design part of TDD early on was focused on making this better by
using it in the creation of unit tests before implementing it. So the
process is about first calling the code in a test - not first calling
the code in some interface design activity that is focused on more
than one class. Now Robert Martin and GOOS could be talking about this
in which case your implication a) is not correct. You have said the
interface belongs to the user of the class - (not users) if there is
only one user to consider then there is one interface, one role and
this should be exercised first by the creation of unit tests.

As to part b) a fundamental part of TDD is design the interface
through the mechanism of writing unit tests. The unit test doesn't
refer to the code that will call the interface, it is the "first" code
to call the interface.

One point I'm trying to highlight is that the core activity of TDD is
writing a unit test that exercises the interface of an object 'before'
writing the code that implements that functionality. This activity is
as much a design activity as a test activity. My final, perhaps more
controversial point, is that when you are doing this you shouldn't be
doing anything else, in particular thinking about layers, other
objects, hierarchies, exposing interfaces etc. etc. save that for
later

All best

Andrew

Andrew Premdas

unread,
Oct 3, 2011, 3:49:27 AM10/3/11
to growing-object-o...@googlegroups.com
On 3 October 2011 04:28, Raoul Duke <rao...@gmail.com> wrote:
> On Sun, Oct 2, 2011 at 6:53 PM, Andrew Premdas <apre...@gmail.com> wrote:
>> "Designing INTERFACES at each level that show how classes collaborate"
>> is something else I think, and implies thinking about more than one
>> class at a time. I would see this as more of a refactoring activity,
>> but some might want to 'architect' it. It isn't the point or a primary
>> focus of TDD as I understand it
>
> tdd is whatever you want it to be, probably :-)
>

That makes it meaningless. TDD has a history, and pretty much was a
simple practice of writing unit tests first then writing
implementation code. It would be sad of that initial idea was lost as
it still has great value.

> i think there are plenty of people out there who see OO as being more
> about the mu, the communications, the collaborations, than about
> one-interface-at-a-time. presumably they could use tdd in their
> approach.
>

Absolutely, but TDD is not OO. Its a practice that is useful in
"Growing" objects, but you could grow functions with it also.
Personally I think when you are doing TDD you should do TDD and not do
anything else. Having written your unit test, and perhaps created a
first simple implementation then you can switch context to doing
something else. Just to clarify this, I would see this point of focus
being a few minutes. If you want to spend time doing other OO things
before or after this then thats fine by me.

Allowing TDD to become some sort of global term that can mean anything
devalues it. Perhaps keeping a very simple definition of TDD and
seeing it as a tool/technique/practice that is part of a development
workflow makes it more useful

All best

Andrew

> sincerely.

Uberto Barbini

unread,
Oct 3, 2011, 4:17:50 AM10/3/11
to growing-object-o...@googlegroups.com
> Well physically a class has one interface, in that it has a number of
> methods that can be called, and you can easily write unit tests for.

Matteo was talking about Interfaces in Java meaning (called also
protocols in other languages).
You're talking here about class interface in C++like meaning, that is
the list of public methods and fields correct?
If not why do you say "physically a class has one interface"?

> The design part of TDD early on was focused on making this better by
> using it in the creation of unit tests before implementing it. So the
> process is about first calling the code in a test - not first calling
> the code in some interface design activity that is focused on more
> than one class. Now Robert Martin and GOOS could be talking about this
> in which case your implication a) is not correct. You have said the
> interface belongs to the user of the class - (not users) if there is
> only one user to consider then there is one interface, one role and
> this should be exercised first by the creation of unit tests.

you completely lost me here. can you make your point with some code example?


>
> As to part b) a fundamental part of TDD is design the interface
> through the mechanism of writing unit tests. The unit test doesn't
> refer to the code that will call the interface, it is the "first" code
> to call the interface.

actually if we're talking about interfaces in Java meaning, you start
exactly with creating the interface during testing on some other class
which need the interface to work.

I'm bit confused so let's do an example:

RiskCalculator -> your interface with method calculateRisk()
CustomerRiskCalculator -> your concrete class which accept a customer
in the constructor.

Ideally, which come first in your opinion?

And when you create RiskCalculator the first time?


> One point I'm trying to highlight is that the core activity of TDD is
> writing a unit test that exercises the interface of an object 'before'
> writing the code that implements that functionality. This activity is
> as much a design activity as a test activity.

ok but how do you write code to "exercise" the functionality?

you can create the first time the RiskCalculator interface when you're
writing some class (in TDD) which need it or you can start from
scratch with the test TestRiskCalculator

>  My final, perhaps more
> controversial point, is that when you are doing this you shouldn't be
> doing anything else, in particular thinking about layers, other
> objects, hierarchies, exposing interfaces etc. etc.  save that for
> later

later when? once you finalized the interface?
the whole point I think is to let your design to emerge by strictly
testing the behaviour and the expected state changes of your objects
using TDD.


Uberto

Luca Minudel

unread,
Oct 3, 2011, 5:50:49 AM10/3/11
to Growing Object-Oriented Software
On Oct 3, 5:28 am, Raoul Duke <rao...@gmail.com> wrote:
>
>
> tdd is whatever you want it to be, probably :-)
>

A comment about this. maybe little OT, but interesting I think.


While working at a paper (TDD with Mock Objects: Design Principles and
Emerging Properties) I talked with co-workers and other people that
wrote book articles or blog posts about TDD.
At some point I understood that we were discussing about TDD while we
had different definitions in our minds for TDD. I understood we were
also thinking about different practices connected to the definitions.
And we also had different assumptions about the surrounding context
(for example are we talking about properly skilled and trained
developers, are there proper feedback loops in-place that bring
actions and consequences under the same learning horizon so people can
learn, have developers a purpose the will to succeed and the authority
to manage risks?).

After putting some effort in clarifying the differences and
understanding each other, the conversations/discussions turned into
profitable ones.
Only after this point some difference in the opinions become a source
of inspiration while other differences helped to clarify the
boundaries between different approaches.


There is a lot of energy and passion in discussions about TDD.
After this experience I learned to get engaged in discussions were
people is aware of misunderstandings and is willing to understand each
other. And to let it go otherwise.



Luca

Andrew Premdas

unread,
Oct 3, 2011, 7:03:28 AM10/3/11
to growing-object-o...@googlegroups.com
On 3 October 2011 09:17, Uberto Barbini <ube...@ubiland.net> wrote:
>> Well physically a class has one interface, in that it has a number of
>> methods that can be called, and you can easily write unit tests for.
>
> Matteo was talking about Interfaces in Java meaning (called also
> protocols in other languages).

Was he? That wasn't clear to me. Nor was it particularly clear that
the references to GOOS and Robert Martin were about interfaces in the
java sense

> You're talking here about class interface in C++like meaning, that is
> the list of public methods and fields correct?
> If not why do you say "physically a class has one interface"?
>

Yes thats what I'm talking about.


>> The design part of TDD early on was focused on making this better by
>> using it in the creation of unit tests before implementing it. So the
>> process is about first calling the code in a test - not first calling
>> the code in some interface design activity that is focused on more
>> than one class. Now Robert Martin and GOOS could be talking about this
>> in which case your implication a) is not correct. You have said the
>> interface belongs to the user of the class - (not users) if there is
>> only one user to consider then there is one interface, one role and
>> this should be exercised first by the creation of unit tests.
>

Does this make sense now that you know I am not talking about java
interfaces and am assuming that neither are GOOS or Robert Martin?

> you completely lost me here. can you make your point with some code example?
>
>
>>
>> As to part b) a fundamental part of TDD is design the interface
>> through the mechanism of writing unit tests. The unit test doesn't
>> refer to the code that will call the interface, it is the "first" code
>> to call the interface.
>
> actually if we're talking about interfaces in Java meaning, you start
> exactly with creating the interface during testing on some other class
> which need the interface to work.
>

Well I wasn't, hence the confusion. There was TDD before interfaces in
Java. I see interfaces in java as a bit of a 'cludge' to allow a form
of multiple inheritance. They are more of a technical implementation
detail than a fundamental OO construct. The idea of programming to an
interface not an implementation and jave interfaces themselves often
get confused. The first is a general OO idiom. the second is a java
specific implementation detail. I considered it more likely that we
were talking about the first.

> I'm bit confused so let's do an example:
>
> RiskCalculator -> your interface with method calculateRisk()
> CustomerRiskCalculator -> your concrete class which accept a customer
> in the constructor.
>
> Ideally, which come first in your opinion?
>
> And when you create RiskCalculator the first time?
>
>

Incidentally I now program in Ruby, so that changes my perspective and
my java is very rusty. I remember that in java it was difficult to
test interfaces and I used to write interfaces first which I think is
a mistake. I would suggest you initially make a unit test for a
RiskCalculator concrete class and then implement the calculateRisk()
method. I'll do my code examples in RSpec

describe RiskCalculator
describe CalculateRisk
it should ... do
RiskCalculator.new.calculateRisk.should wibble
end

Already this exposes flaws with the example. Why does a RiskCalculator
have a CalculateRisk method - what else is it going to calculate? Why
should I put up with this repetitive interface! What about
RiskCalculator.calculate or Risk.new.calculate? How do I put the risk
into the calculator etc.

All of the above is the design part of TDD, and if you miss it out
then you'll end up with poor designs like
RiskCalculator.calculateRisk().

However assuming the example is lovely once you have done a unit test
and a concrete implementation that passes then you could stop doing
TDD and do another activity that involves pulling out an interface if
thats appropriate. This could be pertinent refactoring, or it could be
pointless twiddling about with unnecessary interfaces, it all depends
on context and timing. However its not TDD (under the definition I'm
promoting).


>> One point I'm trying to highlight is that the core activity of TDD is
>> writing a unit test that exercises the interface of an object 'before'
>> writing the code that implements that functionality. This activity is
>> as much a design activity as a test activity.
>
> ok but how do you write code to "exercise" the functionality?
>

By not thinking about java 'interfaces' when doing TDD. Exercise a
concrete class first.

> you can create the first time the RiskCalculator interface when you're
> writing some class (in TDD) which need it or you can start from
> scratch with the test TestRiskCalculator
>
>>  My final, perhaps more
>> controversial point, is that when you are doing this you shouldn't be
>> doing anything else, in particular thinking about layers, other
>> objects, hierarchies, exposing interfaces etc. etc.  save that for
>> later
>
> later when? once you finalized the interface?

no after you have written at least one unit test and one concrete
implementation that passes.

> the whole point I think is to let your design to emerge by strictly
> testing the behaviour and the expected state changes of your objects
> using TDD.
>

Yes but java interfaces are not objects. So they have no place in my
narrowly defined TDD. Pausing TDD and doing a refactor to extract an
interface is perfectly valid. Writing an interface first isn't!
Writing interfaces before you have tested concrete implementations is
contrary to a TDD workflow.

>
> Uberto

Erlis Vidal

unread,
Oct 3, 2011, 9:26:41 AM10/3/11
to growing-object-o...@googlegroups.com
 Pausing TDD and doing a refactor to extract an
interface is perfectly valid.

Hi guys, the problem I can see here is more about the different meanings TDD has for everyone.

I was reading something really interesting the other day about parallel thinking: One guy painted his car half black, half white. When he was asked why he did that, he said that in a case of an accident, he enjoy a lot seeing how witnesses contradict each other..

For the statement in the first paragraph of this email I can infer that TDD doesn't include refactoring. For others, including me, TDD is not such thing without refactoring...

For me what needs clarification at this point is not what TDD is, but in which side of the car are you standing now, the white or the black?

Regards,
Erlis

J. B. Rainsberger

unread,
Oct 3, 2011, 9:41:56 AM10/3/11
to growing-object-o...@googlegroups.com

I see the side of the car that has refactoring. I see it this way:

test-first programming: tests first, then code
test-driven development: test-first programming + refactoring + choose
tests based on current situation
--
J. B. (Joe) Rainsberger :: http://www.jbrains.ca ::
http://blog.thecodewhisperer.com
Author, JUnit Recipes
Free Your Mind to Do Great Work :: http://www.freeyourmind-dogreatwork.com
Find out what others have to say about me at http://nta.gs/jbrains

Raoul Duke

unread,
Oct 3, 2011, 1:36:51 PM10/3/11
to growing-object-o...@googlegroups.com
On Sun, Oct 2, 2011 at 10:28 PM, Matteo Vaccari <vac...@pobox.com> wrote:
> a) a class often implements different interfaces for different roles,

for whatever it is worth, have you seen DCI a la Coplien and Trygve?

Steve Freeman

unread,
Oct 3, 2011, 2:38:45 PM10/3/11
to growing-object-o...@googlegroups.com

Yes, and I'm still struggling to see quite what point they're making.

Steve Freeman

unread,
Oct 3, 2011, 2:47:23 PM10/3/11
to growing-object-o...@googlegroups.com
On 3 Oct 2011, at 12:03, Andrew Premdas wrote:
> Well I wasn't, hence the confusion. There was TDD before interfaces in
> Java. I see interfaces in java as a bit of a 'cludge' to allow a form
> of multiple inheritance. They are more of a technical implementation
> detail than a fundamental OO construct. The idea of programming to an
> interface not an implementation and jave interfaces themselves often
> get confused. The first is a general OO idiom. the second is a java
> specific implementation detail. I considered it more likely that we
> were talking about the first.

Looks like this is the nub of the disagreement. It's true that interfaces can be implicit or explicit, but the interface construct is one the few things that Java really got right (that and GC). Of course they're not full-on protocols, but they give you a way of talking about them.

> Yes but java interfaces are not objects. So they have no place in my
> narrowly defined TDD. Pausing TDD and doing a refactor to extract an
> interface is perfectly valid. Writing an interface first isn't!
> Writing interfaces before you have tested concrete implementations is
> contrary to a TDD workflow.

Interestingly, Kent Beck likes classes too.

Personally, I couldn't disagree more, and I don't see where we can take the discussion from here.

S.


Steve Freeman

unread,
Oct 3, 2011, 2:55:34 PM10/3/11
to growing-object-o...@googlegroups.com
On 3 Oct 2011, at 08:25, Andrew Premdas wrote:
> Well physically a class has one interface, in that it has a number of
> methods that can be called, and you can easily write unit tests for.
> The design part of TDD early on was focused on making this better by
> using it in the creation of unit tests before implementing it. So the
> process is about first calling the code in a test - not first calling
> the code in some interface design activity that is focused on more
> than one class. Now Robert Martin and GOOS could be talking about this

Would you clarify whether you've read GOOS? The purpose of this list for discussions around the book and its ideas. I have no problem with disagreement as long as I feel confident that we have enough common understanding to know what we're disagreeing about.

Raoul Duke

unread,
Oct 3, 2011, 3:32:45 PM10/3/11
to growing-object-o...@googlegroups.com
On Mon, Oct 3, 2011 at 11:38 AM, Steve Freeman <st...@m3p.co.uk> wrote:
> On 3 Oct 2011, at 18:36, Raoul Duke wrote:
>> On Sun, Oct 2, 2011 at 10:28 PM, Matteo Vaccari <vac...@pobox.com> wrote:
>>> a) a class often implements different interfaces for different roles,
>> for whatever it is worth, have you seen DCI a la Coplien and Trygve?
> Yes, and I'm still struggling to see quite what point they're making.

my take on it is that they are trying to get people to "put down the
polymorphism and walk away" a little bit. i think they feel there are
different ideas of what OO means, just like there are for TDD or any
term on earth, and that the class-based inheritance-using style is not
so good. then they go into their own particular favourite approach to
dialing in the architecture and end up with their DCI stuff. i was
just pointing it out as possible food for thought for Matteo; pointing
out yet another set of people who agree that interfaces and roles are
context sensitive.

sincerely.

Nat Pryce

unread,
Oct 3, 2011, 5:07:34 PM10/3/11
to growing-object-o...@googlegroups.com
On 3 October 2011 12:03, Andrew Premdas <apre...@gmail.com> wrote:
> I see interfaces in java as a bit of a 'cludge' to allow a form
> of multiple inheritance. They are more of a technical implementation
> detail than a fundamental OO construct.

Quite the opposite I think. Most statically typed OO languages
conflate the two concerns of inheritance and subtyping into a single
mechanism. That's a kludge. Interfaces decouple the two concerns.

Even in dynamically typed languages you have the *design* concept of a
role that an object plays, comprising subset of the messages it can
respond to, and those roles are unrelated to where the class sits in
the inheritance hierarchy. There's no explicit representation of
roles in the language. Smalltalk organises the methods of a class
into protocols, but those protocols are just categories in the
browser, not in the type system. Interfaces make those roles explicit
in statically typed languages.

--Nat

--
http://www.natpryce.com

Uberto Barbini

unread,
Oct 4, 2011, 4:28:10 AM10/4/11
to growing-object-o...@googlegroups.com
>>
>> for whatever it is worth, have you seen DCI a la Coplien and Trygve?
>
> Yes, and I'm still struggling to see quite what point they're making.

I had a very interesting discussion with Richard Öberg (of qi4j fame) about DCI.

Now the idea from what he explained to me, is kind of appealing,
Usecase Driven Design I would call it. :)

You define a Context object for every UC (or group of similar UC).

At the start of Context life (constructor or a bind method) you inject
in it the Data (Value Object in GOOS).
The Context will wrap them in their Roles for the UC and the business
logic is contained fully in those Roles (mostly) and in Context
methods (one method for UC outcome).

For example (in pseudocode) for a move balance UC:

public class MoveBalance implements Context {

public MoveBalance(Customer giver, Customer receiver) {

this.giver = giver as Giver;

this.receiver = receiver as Receiver;

}

public moveAmount(MoneyAmount amount) {

giver.decreaseBalance(amount + commisionFee);

receiver.increaseBalance(amount);

}

etc.
---

The main benefit is that as far you move around your Context you have
all the data and the function (aka Roles) needed to finish the UC and
nothing more. Moreover the Context offer you a nice way to control the
flow of the application (aka Interactions).

For sure qi4j Rest architecture is quite a tour-de-force.

I see two problems here: a technical one about weird syntax needed in
static languages to express this paradigm.
But the main one is about the idea you need some "magical" framework
to make an application.

Anyway qi4j is very interesting and I think I will steal an idea or two. :)


Uberto

Uberto

Andrew Premdas

unread,
Oct 6, 2011, 3:53:05 PM10/6/11
to growing-object-o...@googlegroups.com
On 3 October 2011 19:55, Steve Freeman <st...@m3p.co.uk> wrote:
> On 3 Oct 2011, at 08:25, Andrew Premdas wrote:
>> Well physically a class has one interface, in that it has a number of
>> methods that can be called, and you can easily write unit tests for.
>> The design part of TDD early on was focused on making this better by
>> using it in the creation of unit tests before implementing it. So the
>> process is about first calling the code in a test - not first calling
>> the code in some interface design activity that is focused on more
>> than one class. Now Robert Martin and GOOS could be talking about this
>
> Would you clarify whether you've read GOOS? The purpose of this list for discussions around the book and its ideas. I have no problem with disagreement as long as I feel confident that we have enough common understanding to know what we're disagreeing about.

- No I haven't read GOOS
- Its sort of on my reading list but not that high up due to its java'ness
- I programmed in Java for a long time but now I program in Ruby
- I wasn't disagreeing with anything in GOOS, read the OP
- I read the GOOS mailing list because it has some very interesting
posts on OO. If not reading the book means I'm not welcome please let
me know

My points were about TDD and in reply to what I perceived as a
misunderstanding about TDD. I hoped to gain insight and maybe add a
little too - there is no flaming going on here.

All best

Andrew


>
> S.
>
>
> Steve Freeman
>
> Winner of the Agile Alliance Gordon Pask award 2006
> Book: http://www.growing-object-oriented-software.com
>
> +44 797 179 4105
> Twitter: @sf105
> Higher Order Logic Limited
> Registered office. 2 Church Street, Burnham, Bucks, SL1 7HZ.
> Company registered in England & Wales. Number 7522677
>
>
>
>

--
------------------------
Andrew Premdas
blog.andrew.premdas.org

Andrew Premdas

unread,
Oct 6, 2011, 3:58:49 PM10/6/11
to growing-object-o...@googlegroups.com

Well maybe you misunderstood me - I wasn' quite precise enough, I
should have said "Writing an interface first isn't TDD". However if
you think that writing interfaces first is TDD then yes we have a
semantic disagreement about what TDD is. But hey its only semantics,
and I did state I was using a very narrow definition of the term.

All best

Andrew
------------------------
Andrew Premdas
blog.andrew.premdas.org

Andrew Premdas

unread,
Oct 6, 2011, 4:15:37 PM10/6/11
to growing-object-o...@googlegroups.com
On 3 October 2011 22:07, Nat Pryce <nat....@gmail.com> wrote:
> On 3 October 2011 12:03, Andrew Premdas <apre...@gmail.com> wrote:
>>  I see interfaces in java as a bit of a 'cludge' to allow a form
>> of multiple inheritance. They are more of a technical implementation
>> detail than a fundamental OO construct.
>
> Quite the opposite I think.  Most statically typed OO languages
> conflate the two concerns of inheritance and subtyping into a single
> mechanism. That's a kludge.  Interfaces decouple the two concerns.
>
Well perhaps kludge is a bit harsh, or maybe even totally out of order
I'm not sure. Historically weren't interfaces Java's solution to the
complexity of multiple inheritance in C++, in a similar way that GC
was a solution to the complexity of pointers and memory management in
C and C++?

> Even in dynamically typed languages you have the *design* concept of a
> role that an object plays, comprising subset of the messages it can
> respond to, and those roles are unrelated to where the class sits in
> the inheritance hierarchy.  There's no explicit representation of
> roles in the language.  Smalltalk organises the methods of a class
> into protocols, but those protocols are just categories in the
> browser, not in the type system.  Interfaces make those roles explicit
> in statically typed languages.
>

So you would agree then that interfaces are

1. Specific to a small number of OO languages
2. Particular to static OO languages
3. A technical implementation of a more general OO concept of role/protocol

Because I used kludge you probably think I'm slagging of interfaces -
my fault for a bad choice of words. What I'm saying is that the
concept of role is more fundamental than the implementation. I think
also that you can apply the concept of role doing TDD in java before
you specifically write an interface, and that this is beneficial when
doing TDD as you can exercise the test earlier.

all best

Andrew

> --Nat
>
> --
> http://www.natpryce.com

Steve Freeman

unread,
Oct 6, 2011, 5:34:41 PM10/6/11
to growing-object-o...@googlegroups.com
On 6 Oct 2011, at 20:53, Andrew Premdas wrote:
>> Would you clarify whether you've read GOOS? The purpose of this list for discussions around the book and its ideas. I have no problem with disagreement as long as I feel confident that we have enough common understanding to know what we're disagreeing about.
>
> - No I haven't read GOOS
> - Its sort of on my reading list but not that high up due to its java'ness

java is our implementation language, we'd be interested in hearing how other languages affect its ideas.

> - I programmed in Java for a long time but now I program in Ruby
> - I wasn't disagreeing with anything in GOOS, read the OP

I think you are...

> - I read the GOOS mailing list because it has some very interesting
> posts on OO. If not reading the book means I'm not welcome please let
> me know

Glad you find the list useful.

Of course you're welcome. That said, we could move on to the next level in the discussion faster if you were familiar with out material.

> My points were about TDD and in reply to what I perceived as a
> misunderstanding about TDD. I hoped to gain insight and maybe add a
> little too - there is no flaming going on here.

understood. Likewise.

S.


Steve Freeman

unread,
Oct 6, 2011, 6:12:29 PM10/6/11
to growing-object-o...@googlegroups.com
On 6 Oct 2011, at 20:58, Andrew Premdas wrote:
>> Personally, I couldn't disagree more, and I don't see where we can take the discussion from here.
>
> Well maybe you misunderstood me - I wasn' quite precise enough, I
> should have said "Writing an interface first isn't TDD". However if
> you think that writing interfaces first is TDD then yes we have a
> semantic disagreement about what TDD is. But hey its only semantics,
> and I did state I was using a very narrow definition of the term.

yes, we have a disagreement, which is why I suggested reading the book before going on with this discussion, so at least you know where we stand.

S.

Matteo Vaccari

unread,
Oct 7, 2011, 2:38:30 AM10/7/11
to growing-object-o...@googlegroups.com
I think I eventually will read about DCI but for the moment I'm perplexed: regular OO has no problem with an object implementing more than one interface.  Why should there be special syntax for that?  But of course it would be more productive for me to discuss this after I read their stuff.

Matteo


Daniel Yokomizo

unread,
Oct 3, 2011, 7:04:08 AM10/3/11
to growing-object-o...@googlegroups.com

You unit test a class and it has collaborators. These are described as interfaces and mocked/stubbed in this test, as you are interested in  the behavior of the class under test. Eventually these interfaces will be implemented by classes and some integration code will bind the collaboratirs to some of these implementations, but nothing says the implementations and interfaces will be one to one. In the end you may realize a class satisfies many related interfaces all described as collaborators when you were testing other classes.

> As to part b) a fundamental part of TDD is design the interface
> through the mechanism of writing unit tests. The unit test doesn't
> refer to the code that will call the interface, it is the "first" code
> to call the interface.
>
> One point I'm trying to highlight is that the core activity of TDD is
> writing a unit test that exercises the interface of an object 'before'
> writing the code that implements that functionality. This activity is
> as much a design activity as a test activity.  My final, perhaps more
> controversial point, is that when you are doing this you shouldn't be
> doing anything else, in particular thinking about layers, other
> objects, hierarchies, exposing interfaces etc. etc.  save that for
> later
>
> All best
>
> Andrew
>
> --
> ------------------------
> Andrew Premdas
> blog.andrew.premdas.org

Best regards,
Daniel

Dion Stewart

unread,
Oct 7, 2011, 11:04:30 AM10/7/11
to growing-object-o...@googlegroups.com
On Oct 3, 2011, at 1:38 PM, Steve Freeman wrote:

> On 3 Oct 2011, at 18:36, Raoul Duke wrote:
>> On Sun, Oct 2, 2011 at 10:28 PM, Matteo Vaccari <vac...@pobox.com> wrote:
>>> a) a class often implements different interfaces for different roles,
>>
>> for whatever it is worth, have you seen DCI a la Coplien and Trygve?
>
> Yes, and I'm still struggling to see quite what point they're making.
>
> S.
>
> Steve Freeman

I'm glad to hear I'm not the only one who doesn't get DCI. I thought it was me :)


Dion

Erlis Vidal

unread,
Oct 7, 2011, 12:04:41 PM10/7/11
to growing-object-o...@googlegroups.com
The main problem I see with DCI is that even when you feel confident with it, it's extremely hard to implement it in any static language. I feel that a new language has to be created in order to apply DCI properly...

Andrew Premdas

unread,
Oct 7, 2011, 1:01:06 PM10/7/11
to growing-object-o...@googlegroups.com

What you talk about here sounds so complicated! Perhaps we are talking
at different levels of granularity. Personally I never unit test a
class, I work in much smaller chunks, so I will unit test one method
in a class. Once I have a test, and the simplest possible
implementation then I'll stop doing TDD and refactor for a bit. After
that I'll come back to TDD and work on the method a bit more. The best
illustration of this I've seen is Robert Martin's prime factors kata.
This is definitely worth doing at least 10 times. Other good resources
are the beginning of the rspec book. The thing that I think happens
alot in Java is that people spend to much time thinking at too high a
level, and doing to much at once, and that stops you getting the
fundamentals correct. I have nothing against pulling an interface out
of a class when a second implementation comes along, but think most of
the time YAGNI applies and you should save that thinking for later.
I'd be worried by a class satisfying many related interfaces, as that
suggests it doesn't really know what its doing (SRP?), so maybe some
refactoring and higher level thought would be appropriate.

Overall I think programming should be a serious of simple activities
done with precision and care - with occasional breaks to think a
lilttle higher, review and sort out messes. That simplicity, which Bob
Martin so beautifully demonstrates in his kata, is something we can
easily loose

all best

Andrew

Rick Mugridge

unread,
Oct 7, 2011, 7:55:19 PM10/7/11
to growing-object-o...@googlegroups.com
From what I understood from DCI, it seems to me that Scala traits (mixins) are a step in the right direction (and enough for me, as far as a I can see).

Rick Mugridge

unread,
Oct 7, 2011, 8:03:20 PM10/7/11
to growing-object-o...@googlegroups.com
I've found that the GOOS ideas apply equally well in C#, Scala and JavaScript. In Scala they apply whether I'm using the pure functional aspects (lambdas, closures, immutability, matching) or the OO ones. It's not necessary to have static types; so it's still fine in JavaScript (although it takes more discipline, which is true anyway).

Cheers, Rick

philip schwarz

unread,
Oct 8, 2011, 2:05:55 AM10/8/11
to Growing Object-Oriented Software
Hi Andrew,

what do you make of "Classic TDD or 'London School'?" - any opinions/
comments/elaboration on Jason Gorman's post?"
http://groups.google.com/group/growing-object-oriented-software/browse_frm/thread/74e98e21a7c50dc2/f872e86c76fee32a

Philip

On Oct 3, 2:53 am, Andrew Premdas <aprem...@gmail.com> wrote:
> All best
>
> Andrew
>
>
>
>
>
>
>
>
>
> > Would that idea of defining interfaces apply at this level as well?
>
> > So, to follow Raoul's lead, when you are talking about this layer, the
> > layer that is actually used in "main" (whatever that may be, perhaps
> > your aspx code behind or whatever), It seems you should lay out the
> > code the way you want it to look there declaratively, attaching the
> > adapters that talk to the various boundaries, then perhaps write tests
> > that look the same way?  Those may look much like the acceptance tests
> > like Raoul said, but they are not end-to-end GOOS style.  They still
> > won't connect to real web stuff and databases.
>
> > Is that OK?
>
> > -Or- is that not as helpful, because you do the declarative stuff in
> > main, writing it as if the code you already wanted already existed,
> > then start with TDD one level below that?  Just the exercise of
> > writing it in main that way IS the design, so testing it is not as
> > valuable?
>
> > On Sep 16, 11:35 am, Raoul Duke <rao...@gmail.com> wrote:
> >> On Fri, Sep 16, 2011 at 8:25 AM, Rick Pingry <rpin...@gmail.com> wrote:
> >> > Funny, I am reading the book over again, (and learning more this
> >> > time), and I just came to the section in chapter 7 called "Building Up
> >> > to Higher-Level Programming", which is just what you are talking
> >> > about.
>
> >> presumably top-down could also be done in a TDD fashion since the top
> >> is the DSL that is basically the acceptance tests for the underlying
> >> low-level implementation layer, and one can keep refactoring and
> >> evolving the levels?

philip schwarz

unread,
Oct 8, 2011, 2:17:21 AM10/8/11
to Growing Object-Oriented Software
Hi Luca,

you said:

>There is a lot of energy and passion in discussions about TDD.
>After this experience I learned to get engaged in discussions were
>people is aware of misunderstandings and is willing to understand each
>other. And to let it go otherwise.

Before 'letting go', do you every try to show people that there are
misunderstandings? If so, how often do you succeed? In your
experience, what proportion of the developers you come in contact with
are aware of the potential for misunderstandings?

Philip

philip schwarz

unread,
Oct 8, 2011, 4:58:08 AM10/8/11
to Growing Object-Oriented Software
Hi Steve,

you wrote:

> the interface construct is one the few things that Java really got right (that and GC).

as I am sure you already know, someone once asked Gosling: "If you
could do Java over again, what would you change?" Gosling replied:
"I'd leave out classes."

Philip

philip schwarz

unread,
Oct 8, 2011, 5:36:22 AM10/8/11
to Growing Object-Oriented Software
Hi Andrew,

you said:

>I see interfaces in java as a bit of a 'cludge' to allow a form
>of multiple inheritance. They are more of a technical implementation
>detail than a fundamental OO construct.

alas, introductory books like "The Java™ Programming Language, Fourth
Edition" don't help with statements like this:

"An interface defines a type with an abstract contract. An abstract
class also defines a type with an abstract contract. Which should you
use and when?

There are two major differences between interfaces and abstract
classes:

* Interfaces provide a form of multiple inheritance, because you can
implement multiple interfaces. A class can extend only one other
class, even if that class has only abstract methods.

* An abstract class can have a partial implementation, protected
parts, static methods, and so on, whereas interfaces are limited to
public constants and public methods with no implementation.

These differences usually direct the choice of which tool is best to
use in a particular implementation. If multiple inheritance is
important or even useful, interfaces are used. However, an abstract
class enables you to provide some or all of the implementation so that
it can be inherited easily, rather than by explicit forwarding."

Philip

philip schwarz

unread,
Oct 8, 2011, 5:52:46 AM10/8/11
to Growing Object-Oriented Software
Hi Andrew,

you said:

>Personally I don't think this is correct. TDD is (or at least was)
>about designing and exercising the interface of the class. BDD extends
>this to say we are specifying the behaviour of the class. If we do a
>good job of this we will have
>1. A class that does what it says (what it says is its public interface)
>2. An executable specification that describes/documents what the class
>says it does
>3. An executable specification that when run and green proves that the
>class does what it says
>In a way none of this really has anything to do with how the class
>collaborates. But classes written in this way are much easier to
>collaborate with. So an emergent benefit of doing good TDD is the
>creation of better collaborators.
...
>TDD has a history, and pretty much was a
>simple practice of writing unit tests first then writing
>implementation code. It would be sad of that initial idea was lost as
>it still has great value.

what do you make of this: "Classic TDD or 'London School'? - any
opinions/comments/elaboration on Jason Gorman's post?"
http://groups.google.com/group/growing-object-oriented-software/browse_frm/thread/74e98e21a7c50dc2/f872e86c76fee32a

Philip

On Oct 3, 8:49 am, Andrew Premdas <aprem...@gmail.com> wrote:
> On 3 October 2011 04:28, Raoul Duke <rao...@gmail.com> wrote:
>
> > On Sun, Oct 2, 2011 at 6:53 PM, Andrew Premdas <aprem...@gmail.com> wrote:
> >> "Designing INTERFACES at each level that show how classes collaborate"
> >> is something else I think, and implies thinking about more than one
> >> class at a time. I would see this as more of a refactoring activity,
> >> but some might want to 'architect' it. It isn't the point or a primary
> >> focus of TDD as I understand it
>
> > tdd is whatever you want it to be, probably :-)
>
> That makes it meaningless. TDD has a history, and pretty much was a
> simple practice of writing unit tests first then writing
> implementation code. It would be sad of that initial idea was lost as
> it still has great value.
>
> > i think there are plenty of people out there who see OO as being more
> > about the mu, the communications, the collaborations, than about
> > one-interface-at-a-time. presumably they could use tdd in their
> > approach.
>
> Absolutely, but TDD is not OO. Its a practice that is useful in
> "Growing" objects, but you could grow functions with it also.
> Personally I think when you are doing TDD you should do TDD and not do
> anything else. Having written your unit test, and perhaps created a
> first simple implementation then you can switch context to doing
> something else. Just to clarify this, I would see this point of focus
> being a few minutes. If you want to spend time doing other OO things
> before or after this then thats fine by me.
>
> Allowing TDD to become some sort of global term that can mean anything
> devalues it. Perhaps keeping a very simple definition of TDD and
> seeing it as a tool/technique/practice that is part of a development
> workflow makes it more useful
>
> All best
>
> Andrew
>
> > sincerely.

Andrew Premdas

unread,
Oct 8, 2011, 6:24:10 AM10/8/11
to growing-object-o...@googlegroups.com
On 8 October 2011 07:05, philip schwarz

<philip.joh...@googlemail.com> wrote:
> Hi Andrew,
>
> what do you make of "Classic TDD or 'London School'?" - any opinions/
> comments/elaboration on Jason Gorman's post?"
> http://groups.google.com/group/growing-object-oriented-software/browse_frm/thread/74e98e21a7c50dc2/f872e86c76fee32a
>
> Philip
>

Philip,

Thankyou for pointing out that post. What that post does for me is
explain why alot of the stuff I see in this group seems over my head -
too hard and to complicated. But without reading GOOS I can't really
go much further than that. It does strike me though that perhaps from
my point of view London School TDD isn't really TDD at all - its more
in the area of Object Orientated Design. I must point out that this is
a semantic argument about the use of the TDD monikor, not a judgement
about the value of the London School approach.

I think part of the art of programming is doing the right thing at the
right time and I would argue that there are many times when what you
should be doing is classic TDD focused on a single method and test.
Then there are other times when you should be doing different
activities e.g. refactoring, OOD etc. Realising that these activities
are separate different things is useful as it allows you to think
about less and consequently do each task better. I would hope GOOS has
room for doing this classic TDD as one of the many activities that
make up its flavour.

All best

Andrew

Lance Walton

unread,
Oct 8, 2011, 6:51:37 AM10/8/11
to growing-object-o...@googlegroups.com
Andrew,

Many of your posts have indicated that you see refactoring as a separate activity from TDD. How can we square this with the fundamental TDD cycle of RED-GREEN-REFACTOR, described by Kent Beck when he invented the term 'TDD'?

It feels that what you are talking about is 'unit test first' rather than TDD.

Regards,

Lance

philip schwarz

unread,
Oct 8, 2011, 7:02:56 AM10/8/11
to Growing Object-Oriented Software
Andrew,

you said:
>Incidentally I now program in Ruby
...
>without reading GOOS I can't really go much further than that.

Some Ruby developers are still discovering GOOS. at 2'30'' into "Why
you Don't get Mock Objects" [1], the speaker says of GOOS: "probably
the best book on mock objects"

[1] http://confreaks.net/videos/659-rubyconf2011-why-you-don-t-get-mock-objects

Philip

On Oct 8, 11:24 am, Andrew Premdas <aprem...@gmail.com> wrote:
> On 8 October 2011 07:05, philip schwarz
>
> <philip.johann.schw...@googlemail.com> wrote:
> > Hi Andrew,
>
> > what do you make of "Classic TDD or 'London School'?" - any opinions/
> > comments/elaboration on Jason Gorman's post?"
> >http://groups.google.com/group/growing-object-oriented-software/brows...

philip schwarz

unread,
Oct 8, 2011, 7:30:50 AM10/8/11
to Growing Object-Oriented Software
Hi Andrew,

you said:

>without reading GOOS I can't really go much further than that

The interwebs exhort you to go and read GOOS now, e.g:

* Michael Feathers on GOOS: "a depth of insight about emergent OO
design which is both rare and extremely valuable"
http://www.amazon.com/review/R2YOYIDRX0YK80/ref=cm_cr_pr_perm?ie=UTF8&ASIN=0321503627&nodeID=&tag=&linkCode=
* GOOS review: TDD is hard http://abeautifulview2011.wordpress.com/2011/07/26/tdd-is-hard/
* "This book is dangerous..." A review of #GOOS
http://www.thetestingplanet.com/2010/12/growing-object-oriented-software-guided-by-tests-%E2%80%93-a-book-review/
* 20 Dec 2010 RT @OlafLewitz: @meikemertsch It is. You won't
understand TDD until you've read this book. #GOOS
* 15 Sep 2010 RT @Sageniuz: Just finished the #goos book! Best book
I've ever read! A must-read 4 every swDeveloper!
* Book Review: Growing Object-Oriented Software, Guided by Tests
http://www.programmergrrl.com/2010/07/book-review-growing-object-oriented.html
* 24 Mar 2010 RT @thirstybear: #GOOS seems to be the book I wish I'd
had when learning OOAD originally.
* Growing Object-Oriented Software Guided by Tests - Book Review
http://kaczanowscy.pl/tomek/2010-01/growing-object-oriented-software-guided-by-tests-book-review

Philip

On Oct 8, 11:24 am, Andrew Premdas <aprem...@gmail.com> wrote:
> On 8 October 2011 07:05, philip schwarz
>
> <philip.johann.schw...@googlemail.com> wrote:
> > Hi Andrew,
>
> > what do you make of "Classic TDD or 'London School'?" - any opinions/
> > comments/elaboration on Jason Gorman's post?"
> >http://groups.google.com/group/growing-object-oriented-software/brows...

philip schwarz

unread,
Oct 8, 2011, 7:50:18 AM10/8/11
to Growing Object-Oriented Software
Andrew,

you said:

>Incidentally I now program in Ruby, so that changes my perspective and
>my java is very rusty. I remember that in java it was difficult to
>test interfaces and I used to write interfaces first which I think is
>a mistake.
...
>I see interfaces in java as a bit of a 'cludge' to allow a form
>of multiple inheritance.

one of the must-read books for all Java Developers is Joshua Bloch's
Effective Java (2nd edition). Item 18 of the book is called "Prefer
Interfaces to Abstract Classes". The item concludes by saying: "To
summarize, an interface is generally the best way to define a type
that permits multiple implementations. An exception to this rule is
the case where ease of evolution is deemed more important than
flexibility and power. Under these circumstances, you should use an
abstract class to define the type, but only if you understand and can
accept the limitations. ..."

Here are the names of the subsections of the item that describe
positive aspects of using interfaces:

* Existing classes can be easily retrofitted to implement a new
interface
* Interfaces are ideal for defining mixins.
* Interfaces allow the construction of nonhierarchical type
frameworks.
* Interfaces enable safe, powerful functionality enhancements

And here are the names of the subsections of the item that describe
negative aspects of using interfaces:

* It is far easier to evolve an abstract class than an interface
* Once an interface is released and widely implemented, it is almost
impossible to change.

Thanks for prompting me to go and read this item again.

philip schwarz

unread,
Oct 8, 2011, 8:23:39 AM10/8/11
to Growing Object-Oriented Software
Andrew,

you said:

>I see interfaces in java as a bit of a 'cludge' to allow a form
>of multiple inheritance.

The first section of "Java Design - building better apps and
applets" (by Peter Coad and Mark Mayfield" is called "Why Java
Design?", and begins as follows:

"Building materials profoundly affect design techniques.
...
In every field of human endeavour, new construction materials are
followed by new design methods; hence, "design with Java."
From a designer's perspective, it's worth taking a closer look at
Java. What new building materials will it give us? How will these
materials affect the way we think about, discuss, trade off, and
improve our designs?

Java was designed to prevent common mistakes in OO design and
programming, especially C++ design and programming.

Java design is profound. It has forever changed how we think about
object models and scenarios. It makes object models and scenario views
pluggable - unplug an object from one class; plug in an object from
another class; and continue on our way, as long as both classes
implement the needed interface. This is very significant indeed.
...
the most significant aspects of Java-inspired design: freedom from
object connections that are hardwired to just one class of objects and
freedom from scenario interactions that are hardwired to just one
class of objects. For systems in which flexibility, extensibility, and
pluggability are key issues, Java-style interfaces are a must. Indeed,
the larger the system and the longer the potential life span of a
system the more significant interface-centric design becomes."

Here are some of the Book's footnotes that comment on how Java
compares with C++ when it comes to interfaces:

"Java expresses inheritance and polymorphism distinctly with different
syntax. C++ expresses both concepts with a single syntax; it blurs the
distinction between these very different mechanisms, resulting in
overly complex, overly deep class hierarchies. (We design with
interfaces regardless of language; Java makes it easier for us to
express that design in source code.)"

"In C++, developers often implement monolithic class hierarchies with
a base class that does nothing more than allow ease of 'pluggability'
via base class pointers. This is a bulky and limited workaround
compared to the elegance of Java interfaces"

"You can dedicate part of your class hierarchies to expressing
interfaces, namely C++ classes that consist only of method signatures.
On the other hand, when designing C++ apps, you can also 'mix in'
behaviours" from multiple superclasses; however, the ever-decreasing
amount of encapsulation within a class hierarchy with multiple-
inheritance behaviour makes this an unwieldy approach (something to
avoid, when possible)"

Philip.

Erlis Vidal

unread,
Oct 8, 2011, 9:21:19 AM10/8/11
to growing-object-o...@googlegroups.com
Hi,

I don't know if I kind of understand what Andrew is trying to say when he mention refactoring as a different activity (let me clarify once more that for me TDD includes refactoring)

Recently Kent wrote a blog describing two types or refactoring, and for me was interesting to see how others (specially Kent) approach some of the issues I face systematically.

This is something I think is worth reading, it maybe gives you some hints on your TDD approach

http://www.threeriversinstitute.org/blog/?p=594

Regards,
Erlis

philip schwarz

unread,
Oct 8, 2011, 9:54:50 AM10/8/11
to Growing Object-Oriented Software
definitely worth reading, which I hadn't got round to yet.

Philip

philip schwarz

unread,
Oct 8, 2011, 12:49:22 PM10/8/11
to Growing Object-Oriented Software
Andrew,

you said:

>I see interfaces in java as a bit of a 'cludge' to allow a form
>of multiple inheritance.

Here are some excerpts from chapter 6 of "Essential Skills for the
Agile Developer": "Interface-Oriented Design":

"Interface-oriented design (IOD) concentrates on the services and
responsibilities of objects or modules, rather than their
implementation. It cleanly separates the specification perspective
from the implementation perspective."

"The Gang of Four recommend that you should “design to interfaces, not
implementations.” Many patterns, such as the Adapter, Façade,
Strategy, and Proxy deal with interfaces. Martin Fowler repeats this
in his recommendation of separating the specification perspective (the
interface) from the implementation perspective. Interfaces are the key
to making decoupled designs that simplify testing and promote
maintainability."

"Martin Fowler suggests that you separate the specification
(interface) perspective from the implementation perspective. Using
interfaces in your design forces that separation."

"Often there is a question as to the differences between an interface
and an abstract class. ... Interfaces and abstract classes both
represent commonality of specification. Abstract classes also include
commonality of implementation. This commonality can include both data
attributes and methods. So, abstract classes couple the specification
perspective and the implementation perspective. It’s possible you may
find that as your code evolves, you have multiple implementations of
an interface where each uses the same helper class to which they
delegate. In that case, you might create an abstract class that
implements the interface and that contains these helper functions.
When the redundancy of always delegating to a helper class outweighs
the effects of the coupling, then the change is justified. This is an
example of emergent design."

philip schwarz

unread,
Oct 8, 2011, 1:23:17 PM10/8/11
to Growing Object-Oriented Software
Andrew,

you said:

>I see interfaces in java as a bit of a 'cludge' to allow a form
>of multiple inheritance. They are more of a technical implementation
>detail than a fundamental OO construct.

Here are some excerpts from Rod Johnson's 2002 book "J2EE Design and
Development":

"The second basic principle of object-oriented design emphasized in
the GoF book is "Favor object
composition over class inheritance". Few developers appreciate this
wise advice.
Unlike many older languages, such as C++, Java distinguishes at a
language level between concrete
inheritance (the inheritance of method implementations and member
variables from a superclass) and
interface inheritance (the implementation of interfaces). Java allows
concrete inheritance from only a single
superclass, but a Java class may implement any number of interfaces
(including, of course, those interfaces
implemented by its ancestors in a class hierarchy). While there are
rare situations in which multiple concrete
inheritance (as permitted in C++) is the best design approach, Java is
much better off avoiding the
complexity that may arise from permitting these rare legitimate uses.
...
let's consider what we want to achieve by inheritance.
Abstract inheritance enables polymorphism: the substitutability of
objects with the same interface at run
time. This delivers much of the value of object-oriented design.
Concrete inheritance enables both polymorphism and more convenient
implementation. Code can be
inherited from a superclass. Thus concrete inheritance is an
implementation, rather than purely a design,
issue. Concrete inheritance is a valuable feature of any OO language;
but it is easy to overuse. Common
mistakes with concrete inheritance include:...#1...#2...#3 Using
abstract classes in place of interfaces. Abstract classes are very
useful when used correctly. The Template Method design pattern is
usually implemented with
an abstract class. However, an abstract class is not an alternative to
an interface. It is usually a
convenient step in the implementation of an interface. Don't use an
abstract class to define a
type. This is a recipe for running into problems with Java's lack of
multiple concrete
inheritance. Unfortunately, the core Java libraries are poor examples
in this respect, often
using abstract classes where interfaces would be preferable."

Andrew Premdas

unread,
Oct 8, 2011, 2:26:59 PM10/8/11
to growing-object-o...@googlegroups.com
On 8 October 2011 18:23, philip schwarz

Philip, I think you've taken my comments a bit out of context. The
kludge comment which I later apologised for,was about the historical
development of Java and the way the technical implementation of Java
interfaces came about and how the idea of an objects interface is more
fundamental to OO than this particular implementation. As I previously
stated I have no problem with using interfaces but suggest that maybe
it would be better if they came out of a refactoring of a concrete
object developed by TDD. In this way the method signature would have
been used in a concrete test earlier and the benefits that TDD brings
to this simple but fundamental task of designing a method signature
would not be lost.

Thanks for all the quotes

All best

Andrew

Andrew Premdas

unread,
Oct 8, 2011, 3:58:36 PM10/8/11
to growing-object-o...@googlegroups.com
On 8 October 2011 11:51, Lance Walton <lance.c...@googlemail.com> wrote:
> Andrew,
>
> Many of your posts have indicated that you see refactoring as a separate activity from TDD. How can we square this with the fundamental TDD cycle of RED-GREEN-REFACTOR, described by Kent Beck when he invented the term 'TDD'?
>
> It feels that what you are talking about is 'unit test first' rather than TDD.
>
> Regards,
>
> Lance
>

Touche Lance. First of all I subscribe very strongly to
RED-GREEN-REFACTOR, and its at the core of how I program, which is
pretty much following the two red-green circles described in the
beginning of the RSpec book. I believe that there is a clear
separation between the red-green part and the refactoring part.
Refactoring is a fundamentally different activity which requires a
context shift

My memories of earlier days of TDD say 1998 1999 are that it was write
a test and implement it and that RED-GREEN-REFACTOR is a later
refinement of this. Martin Fowler's refactoring book came out in 1999,
and kickstarted the refactoring movement. Kent Beck's
extremeProgramming 2000 sees refactoring as one of its 12 engineering
practices. I can't remember when I first heard red-green-refactor, but
I'm sure it was several years later. Are you sure Kent Beck invented
the term TDD and described RGF at the same time?

Alot of this started of with a comment about what TDD is, and one
poster saying that TDD could be defined as pretty much anything. So is
TDD is red/green/refactor or GOOS style development or ...

Kent Beck came up with extreme Programming to tie together a series of
engineering practices into a coherent whole. Is XP TDD?

I was suggesting we could think of TDD as what you've called unit test
first. In that way the term would get back a precise definition. Then
we could see this as a core part of a programming iteration. One such
iteration would be TDD refactor (equivalent to red/green/refactor or
unit test/refactor). The motivation behind this was not to lose the
design benefits gained by using a method signature in an applicable
context (the test) before writing the method signature

But as you've pointed out most people think of TDD as being a term
describing the whole iteration. This is problematic as there are a
wide variety of iterations and a danger of losing the narrow focus
that is required to write a good method signature.

All best

Andrew

It is loading more messages.
0 new messages