Robert Martin compares GOOS outside in approach with his inside out approach

1,333 views
Skip to first unread message

philip schwarz

unread,
Jun 19, 2013, 6:17:30 PM6/19/13
to growing-object-o...@googlegroups.com
He started the comparison here and will continue in an upcoming 'advanced TDD' episode of Clean Code

Philip

Uberto Barbini

unread,
Jun 20, 2013, 3:46:21 AM6/20/13
to growing-object-o...@googlegroups.com
Having tried both, my experience is that emphasizing iterations
testing results usually in more solid test suites (==less false
positive and easier to maintain) than testing state only. For some
people it's also more difficult, at least from the feedback I have
from my team-mates.

But the main point I think is that "walking skeleton" helps to
identify system problems outside the code base in the organization.
Most of the projects I saw failing, it was because of non functional
requirements, not for misinterpretation of the domain.


Uberto
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "Growing Object-Oriented Software" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to growing-object-oriente...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

Nat Pryce

unread,
Jun 20, 2013, 5:13:16 AM6/20/13
to growing-object-o...@googlegroups.com
I don't agree with him that working outside-in also requires lots of mocks.  I think the two techniques are orthogonal.  I've used an outside-in approach without any mocks -- when using functional programming, for example.  And I've used mocks when starting with the domain model, when modelling the domain as messaging protocols in a Tell Don't Ask object-oriented style.

--Nat

On 19 June 2013 23:17, philip schwarz <philip.joh...@googlemail.com> wrote:
He started the comparison here and will continue in an upcoming 'advanced TDD' episode of Clean Code

Philip

--
 
---
You received this message because you are subscribed to the Google Groups "Growing Object-Oriented Software" group.
To unsubscribe from this group and stop receiving emails from it, send an email to growing-object-oriente...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

George Collins

unread,
Jun 20, 2013, 9:20:40 AM6/20/13
to growing-object-o...@googlegroups.com
I think when he says working outside-in requires mocks, is if you're testing various parts in isolation from the outside in. If you have skeletal versions of all the parts making up the system, then they can take the place of mocks in supporting the 'surface' being exercised by the test. Does that resolve the contradiction?

GC


On Thursday, June 20, 2013 10:13:16 AM UTC+1, Nat wrote:
I don't agree with him that working outside-in also requires lots of mocks.  I think the two techniques are orthogonal.  I've used an outside-in approach without any mocks -- when using functional programming, for example.  And I've used mocks when starting with the domain model, when modelling the domain as messaging protocols in a Tell Don't Ask object-oriented style.

--Nat

On 19 June 2013 23:17, philip schwarz <philip.joh...@googlemail.com> wrote:
He started the comparison here and will continue in an upcoming 'advanced TDD' episode of Clean Code

Philip

--
 
---
You received this message because you are subscribed to the Google Groups "Growing Object-Oriented Software" group.
To unsubscribe from this group and stop receiving emails from it, send an email to growing-object-oriented-software+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.
 
 

Nat Pryce

unread,
Jun 20, 2013, 6:17:43 PM6/20/13
to growing-object-o...@googlegroups.com
On 20 June 2013 14:20, George Collins <georgex...@gmail.com> wrote:
I think when he says working outside-in requires mocks, is if you're testing various parts in isolation from the outside in. If you have skeletal versions of all the parts making up the system, then they can take the place of mocks in supporting the 'surface' being exercised by the test. Does that resolve the contradiction?


I think that you're also saying that working outside-in and using mocks are two orthogonal issues.

--Nat
 
GC


On Thursday, June 20, 2013 10:13:16 AM UTC+1, Nat wrote:
I don't agree with him that working outside-in also requires lots of mocks.  I think the two techniques are orthogonal.  I've used an outside-in approach without any mocks -- when using functional programming, for example.  And I've used mocks when starting with the domain model, when modelling the domain as messaging protocols in a Tell Don't Ask object-oriented style.

--Nat


On 19 June 2013 23:17, philip schwarz <philip.joh...@googlemail.com> wrote:
He started the comparison here and will continue in an upcoming 'advanced TDD' episode of Clean Code

Philip

--
 
---
You received this message because you are subscribed to the Google Groups "Growing Object-Oriented Software" group.
To unsubscribe from this group and stop receiving emails from it, send an email to growing-object-oriented-software+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
http://www.natpryce.com

--
 
---
You received this message because you are subscribed to the Google Groups "Growing Object-Oriented Software" group.
To unsubscribe from this group and stop receiving emails from it, send an email to growing-object-oriente...@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
http://www.natpryce.com

Matt Wynne

unread,
Jun 22, 2013, 6:41:05 PM6/22/13
to growing-object-o...@googlegroups.com
On 20 Jun 2013, at 10:13, Nat Pryce <nat....@gmail.com> wrote:

I don't agree with him that working outside-in also requires lots of mocks.  I think the two techniques are orthogonal.

philip schwarz

unread,
Jun 23, 2013, 3:16:54 AM6/23/13
to growing-object-o...@googlegroups.com
I went to refresh my mind on what "xUnit Patterns" says about the subject.

When I first looked at Chapter 4 "Philosophy Of Test Automation" ( http://xunitpatterns.com/Philosophy%20Of%20Test%20Automation.html ) I thought it supported the view that the two techniques are orthogonal, because it has separate sections called "Outside-In or Inside-Out?" and "State or Behavior Verification?" and because rather than saying that outside in requires mock objects, it says it requires test doubles. But then I read the opening section of  "State or Behavior Verification?": 

"From writing code outside-in it is a small step to verifying behavior rather than just state. The "statist" view is that it is sufficient to put the SUT into a specific state, exercise it, and verify that it is in the expected state at the end of the test. The "behaviorist" view is that we should specify not only the start and end state of an object but the calls it makes to its dependencies. That is, we should specify the details of the calls to the "outgoing interfaces" of the SUT"

Oh no, the classicist/mockist divide! Wasn't that identified as nonsensical, e.g. in this Jan 2009 Yahoo TDD Group Classic/mockist discussion http://tech.groups.yahoo.com/group/testdrivendevelopment/message/29674 ? Ah, but "xUnit Patterns" was written back in 2007.

Philip

On Thursday, 20 June 2013 10:13:16 UTC+1, Nat wrote:
I don't agree with him that working outside-in also requires lots of mocks.  I think the two techniques are orthogonal.  I've used an outside-in approach without any mocks -- when using functional programming, for example.  And I've used mocks when starting with the domain model, when modelling the domain as messaging protocols in a Tell Don't Ask object-oriented style.

--Nat

On 19 June 2013 23:17, philip schwarz <philip.joh...@googlemail.com> wrote:
He started the comparison here and will continue in an upcoming 'advanced TDD' episode of Clean Code

Philip

--
 
---
You received this message because you are subscribed to the Google Groups "Growing Object-Oriented Software" group.
To unsubscribe from this group and stop receiving emails from it, send an email to growing-object-oriented-software+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.
 
 

philip schwarz

unread,
Jun 23, 2013, 3:31:23 AM6/23/13
to growing-object-o...@googlegroups.com
Recently I have watched again James Shore's Let's Play TDD screencasts, and look what I came across @ 01':50''-2':50'' of episode 23 (http://www.jamesshore.com/Blog/Lets-Play/Episode-23.html):

"So I actually don't use mock object very often. I tend to avoid them. It is the classicist mindset, as opposed to the mockist mindset. some people like to go top-down using mocks to drive the implementation as they go. I don't claim to understand that approach very well, but it is very popular and I think the preeminent book describing that would be Steve Freeman and Nat Pryce's GOOS, I have heard many good things about that book though I haven't read it yet. So if you want to see more of the mockist approach, which is more of a top-down approach that stubs out each layer using mocks, check out his book. Steve Freeman and Nat Pryce were the ones of course who invented the mock object technique, so they really know their stuff. I have used mocks before, never really got it, I need to read their book to understand how they do it, but I prefer not to use mocks....I'm sure there will be an occasion when we actually do want to use them... "

That was September 2010.

I have asked him the following:

.@jamesshore RE your opinions in 01':50''-2':50'' of http://www.jamesshore.com/Blog/Lets-Play/Episode-23.html @unclebobmartin @natpryce 1/4
.@jamesshore Have you read GOOS now? Have your opinions and approach (top-down v bottom-up) changed at all? @unclebobmartin @natpryce 2/2
.@jamesshore Can I read about your latest opinion (or maybe listen to it) anywhere? @unclebobmartin @natpryce 3/4
.@jamesshore @unclebobmartin care to comment @ https://groups.google.com/forum/#!topic/growing-object-oriented-software/GNS8bQ93yOo @natpryce 4/4

Philip

On Thursday, 20 June 2013 10:13:16 UTC+1, Nat wrote:
I don't agree with him that working outside-in also requires lots of mocks.  I think the two techniques are orthogonal.  I've used an outside-in approach without any mocks -- when using functional programming, for example.  And I've used mocks when starting with the domain model, when modelling the domain as messaging protocols in a Tell Don't Ask object-oriented style.

--Nat

On 19 June 2013 23:17, philip schwarz <philip.joh...@googlemail.com> wrote:
He started the comparison here and will continue in an upcoming 'advanced TDD' episode of Clean Code

Philip

--
 
---
You received this message because you are subscribed to the Google Groups "Growing Object-Oriented Software" group.
To unsubscribe from this group and stop receiving emails from it, send an email to growing-object-oriented-software+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.
 
 

philip schwarz

unread,
Jun 23, 2013, 3:46:50 AM6/23/13
to growing-object-o...@googlegroups.com
Other controversial points in "XUnit Patterns" http://xunitpatterns.com/index.html  (2007 - two years before GOOS came out):

"A common application of Behavior Verification is when we are writing our code in an “outside-in” manner. This approach, which is often called need-driven development,involves writing the client code before we write the DOC. It is a good way to find out exactly what the interface provided by the DOC needs to be based on real, concrete examples rather than on speculation. The main objection to this approach is that we need to use a lot of Test Doubles (page 522) to write these tests. That could result in Fragile Tests (page 239) because each test knows so much about how the SUT is implemented. Because the tests specify the behavior of the SUT in terms of its interactions with the DOC, a change in the implementation of the SUT could break a lot of tests. This kind of Overspecified Software (see Fragile Test) could lead to High Test Maintenance Cost (page 265).

The jury is still out on whether Behavior Verification is a better approach than State Verification. In most cases, State Verification is clearly necessary; in some cases, Behavior Verification is clearly necessary. What has yet to be determined is whether Behavior Verification should be used in all cases or whether we should use State Verification most of the time and resort to Behavior Verification only when State Verification falls short of full test coverage." 

Philip 

Uberto Barbini

unread,
Jun 23, 2013, 5:15:53 AM6/23/13
to growing-object-o...@googlegroups.com
> The jury is still out on whether Behavior Verification is a better approach
> than State Verification. In most cases, State Verification is clearly
> necessary; in some cases, Behavior Verification is clearly necessary. What
> has yet to be determined is whether Behavior Verification should be used in
> all cases or whether we should use State Verification most of the time and
> resort to Behavior Verification only when State Verification falls short of
> full test coverage."

My very humble take here:
The second biggest problem with State verification is not "full test
coverage" but brittle tests. That is you find yourself to change a lot
of test for every change in the code.
Minimal example:
Bill.calculate() is used by Table.prepareBill() that is used by Dinner.payFor().
Without mocks/stubs, if we start in the classical way, any change in
the method calculate of Bill will break also tests for Table and
Dinner. I don't see how we can avoid this. Unless we avoid designs
with deep object interactions.

And this is the biggest problem: the design.
Testing state only doesn't work for me as well as testing behavior for
the overall classes design.

Uberto

Nat Pryce

unread,
Jun 23, 2013, 5:45:35 AM6/23/13
to growing-object-o...@googlegroups.com
On 23 June 2013 08:16, philip schwarz <philip.joh...@googlemail.com> wrote:
When I first looked at Chapter 4 "Philosophy Of Test Automation" ( http://xunitpatterns.com/Philosophy%20Of%20Test%20Automation.html ) I thought it supported the view that the two techniques are orthogonal, because it has separate sections called "Outside-In or Inside-Out?" and "State or Behavior Verification?" and because rather than saying that outside in requires mock objects, it says it requires test doubles. But then I read the opening section of  "State or Behavior Verification?": 

"From writing code outside-in it is a small step to verifying behavior rather than just state. The "statist" view is that it is sufficient to put the SUT into a specific state, exercise it, and verify that it is in the expected state at the end of the test. The "behaviorist" view is that we should specify not only the start and end state of an object but the calls it makes to its dependencies. That is, we should specify the details of the calls to the "outgoing interfaces" of the SUT"

Oh no, the classicist/mockist divide! Wasn't that identified as nonsensical, e.g. in this Jan 2009 Yahoo TDD Group Classic/mockist discussion http://tech.groups.yahoo.com/group/testdrivendevelopment/message/29674 ? Ah, but "xUnit Patterns" was written back in 2007.


In my opinion that's incorrect because, when focusing the design (and therefore tests) on messaging protocols, I do not specify anything about the state of an object.  I only test in terms of incoming and outgoing messages to/from the object under test.  State and mutation is implied by the test when the object's response to later messages is affected by earlier messages it has received.  But I don't specify what that state is and how it is represented.  It's an internal implementation detail.

That's why I argue that there are not different kinds of TDD.  There are different design conventions, and you pick the testing techniques and tools most appropriate for the conventions you're working in.  And different parts of the system will probably use different conventions.
 
--
http://www.natpryce.com

Evgeni Dzhelyov

unread,
Jun 23, 2013, 5:57:36 AM6/23/13
to growing-object-o...@googlegroups.com
I'm completely confused by these mockist vs traditionalist and outside-in vs inside-out comparison. 
In my opinion what is described in the GOOS book is far more deep and complete that the other sources on internet.
One example is about external dependencies, it's clearly described that you should not mock object that you don't own, the
reasons are because your design doesn't benefit at all and you are tests are actually useless because you can't verify the proper integration. Still I see plenty of arguments against using mocks exactly when used in these kind of situations.

My understanding for the need of mocks is when you have a design that uses delegation, so if I have an object A that has to delegate some work to object B and I don't have access to B internals or any other return value. Then in order to write _unit_ test I can assert based on the methods called. And that's it. The need for mocks come from the way you design your system and your focus on messages between objects instead of state changes.


Inside-out or outside-in has nothing to do with the testing techniques in my opinion. In reality if you are paid to deliver software systems, it means that you will have to deliver complete and concrete solution that in most cases will integrate
with a lot of 3rd party dependencies and these dependencies will put certain limitations on your overall system architecture.
Doing outside-in allows you to check the really sooner and react accordingly. I have found that I get the most information about problems I haven't yet worked on when I start outside-in. And benefit from inside-out approach only when I have deep understanding of the system.


That's why I argue that there are not different kinds of TDD.  There are different design conventions, and you pick the testing techniques and tools most appropriate for the conventions you're working in.  And different parts of the system will probably use different conventions.

I completely support Nat's statements and I think these exactly what they describe in the book. 

Steve Freeman

unread,
Jun 23, 2013, 5:59:24 AM6/23/13
to growing-object-o...@googlegroups.com
and... if I only allow one convention in my code, it's probably not as well-designed as it could be.

S.

Steve Freeman

unread,
Jun 23, 2013, 6:10:14 AM6/23/13
to growing-object-o...@googlegroups.com
+1 Do the stuff that you need to learn most about first.

S

Nat Pryce

unread,
Jun 23, 2013, 6:12:15 AM6/23/13
to growing-object-o...@googlegroups.com
On 23 June 2013 10:59, Steve Freeman <st...@m3p.co.uk> wrote:
and... if I only allow one convention in my code, it's probably not as well-designed as it could be.


As a colleague used to say: "if all you have is a hammer, everything looks like a thumb." 

--Nat

--
http://www.natpryce.com

Gishu Pillai

unread,
Jun 23, 2013, 6:14:33 AM6/23/13
to growing-object-o...@googlegroups.com
Uberto,

If we would like to eliminate ripple changes from Bill to Table to Dinner, shouldn't we have roles between them?
Given a specific problem, would the roles in the design change whether we design outside in or the other way around ?

IMHO the only difference I've observed is that outside in approach puts the clients first and as a result, the APIs/interfaces are clean, simple and usable. Inside out may take more time to expose the gap between 'what is needed' and 'what you thought was needed'. (Maybe experience prevents that)

-- Gishu

Gian Carlo Pace

unread,
Jun 23, 2013, 6:31:23 AM6/23/13
to growing-object-o...@googlegroups.com

That's why I argue that there are not different kinds of TDD.  There are different design conventions, and you pick the testing techniques and tools most appropriate for the conventions you're working in.  And different parts of the system will probably use different conventions.
I always thought that the same applies to language paradigms: there are different language paradigms (functional OO procedural) and there are parts of the system that needs more oo way and other more a functional take. And I think that this reflects on the testing " type" as well.

There was something about that in this talk of Gary Bernhardt http://www.confreaks.com/videos/1314-rubyconf2012-boundaries

Does this make any sense to you? 
-- 
gk

Nat Pryce

unread,
Jun 23, 2013, 7:28:16 AM6/23/13
to growing-object-o...@googlegroups.com
Definitely.

Thinking of a web-app, an event-driven OO style works well for dispatching incoming HTTP requests, while a functional style works well for converting resources in the application into the representations that are sent in responses.

--Nat


--
http://www.natpryce.com

Matteo Vaccari

unread,
Jun 23, 2013, 11:16:08 AM6/23/13
to growing-object-o...@googlegroups.com
On Sun, Jun 23, 2013 at 11:15 AM, Uberto Barbini <ube...@ubiland.net> wrote:
> The jury is still out on whether Behavior Verification is a better approach
> than State Verification. In most cases, State Verification is clearly
> necessary; in some cases, Behavior Verification is clearly necessary. What
> has yet to be determined is whether Behavior Verification should be used in
> all cases or whether we should use State Verification most of the time and
> resort to Behavior Verification only when State Verification falls short of
> full test coverage."

My very humble take here:
The second biggest problem with State verification is not "full test
coverage" but brittle tests. That is you find yourself to change a lot
of test for every change in the code.
Minimal example:
Bill.calculate() is used by Table.prepareBill() that is used by Dinner.payFor().
Without mocks/stubs, if we start in the classical way, any change in
the method calculate of Bill will break also tests for Table and
Dinner. I don't see how we can avoid this. Unless we avoid designs
with deep object interactions.

Uberto: it seems to me that the problem with the code you describe is that you are testing three things in one test.  This may make your test more brittle; but you seem to assume that there is no way to break the dependencies and test Dinner#payFor() without using mocks.  I think you could make Dinner#payFor testable in isolation with state-based testing, even though you may have to turn around the design.  

You can come up with examples where (state|interaction)-based testing makes testing (more|less) brittle, in all four combinations of this sentence.  It all comes down to knowing how to use well both techniques (not styles, techniques!) so that you can choose the one that fits better your particular situation.

None of the two techniques leads necessarily to more brittle tests.  Both techniques lead to more brittle tests when used poorly or in inappropriate situations.

M

(Aside: do you find the xUnit book useful?  I don't.)

Uberto Barbini

unread,
Jun 23, 2013, 12:14:15 PM6/23/13
to growing-object-o...@googlegroups.com
> Uberto: it seems to me that the problem with the code you describe is that
> you are testing three things in one test.

yes, that's my problem with testing high level objects with state only tests.

> This may make your test more
> brittle; but you seem to assume that there is no way to break the
> dependencies and test Dinner#payFor() without using mocks. I think you
> could make Dinner#payFor testable in isolation with state-based testing,
> even though you may have to turn around the design.

Maybe it's possible, but as general rule I find it very difficult.

>
> You can come up with examples where (state|interaction)-based testing makes
> testing (more|less) brittle, in all four combinations of this sentence. It
> all comes down to knowing how to use well both techniques (not styles,
> techniques!) so that you can choose the one that fits better your particular
> situation.

Still while agreeing with your assertion I think there is both a
technique and a style involved here.
While I'm perfectly fine on state tdd when interactions are not (much)
involved, the so-called "classicists" try to avoid using mocks as far
as possible: "only for full coverage".
As in the previous DinnerTable example, this usually lead to different
design styles.

What I don't really agree is that InsideOut or OutsideIn preference is
really relevant here. I think the difference is in how you design your
objects to keep them testable in isolation.
As confirmation, I think DDD-style is both using mocks and InsideOut approach.

> None of the two techniques leads necessarily to more brittle tests. Both
> techniques lead to more brittle tests when used poorly or in inappropriate
> situations.

Well, who couldn't agree here? :)
The original quotes were along the lines of "if you do outside-in
you'll finish writing a lot of not-so-useful mocks".
Let me rephrase it then, I tend to write brittle tests when I do TDD
using state tests only. I am only reporting my personal experience.

Curiously enough, the more the code is dynamically OO the more I feel
the need of mocks and behavioral testing.


Uberto

Björn Rasmusson

unread,
Jun 23, 2013, 1:10:52 PM6/23/13
to growing-object-o...@googlegroups.com

The quote from XUnit Patterns:
"A common application of Behavior Verification is when we are writing our code in an “outside-in” manner. This approach, which is often called need-driven development,involves writing the client code before we write the depended-on-component, DOC. [...] The main objection to this approach is that we need to use a lot of Test Doubles (page 522) to write these tests."
kind of restates Robert Martins opinion "working 'outside-in' requires a lot of mocks".

One could argue that it is possible to work 'outside-in' with need-driven development and test with real depended-on-components(DOC)/collaborators instead of test doubles, if you accept to interrupt working on the client code, when the needed functionality of the DOC has been identified, to implement (and test) enough of the DOC for the use in the testing of the client code.

When working "inside-out", the assumption is that depended-on-components(DOC)/collaborators will be implemented and tested before clients to them by default. So then there would be no problem to test with the real DOC (instead of test doubles). On the other hand, even if DOC:s are available, it is no problems to test with test doubles (mocks), so working "inside-out" and using mocks has no contradiction.

In the end I agree with many of the people in this discussion that "outside-in" vs "inside-out" and "testing with test doubles" vs "testing with real collaborators" are, if not fully orthogonal, nearly orthogonal.

Regards
Björn

Steve Freeman

unread,
Jun 23, 2013, 3:03:10 PM6/23/13
to growing-object-o...@googlegroups.com
On 23 Jun 2013, at 18:10, Björn Rasmusson wrote:
> The quote from XUnit Patterns:
> "A common application of Behavior Verification is when we are writing our
> code in an “outside-in” manner. This approach, which is often called
> need-driven development,involves writing the client code before we write
> the depended-on-component, DOC. [...] The main objection to this approach
> is that we need to use a lot of Test Doubles (page 522) to write these tests
> ."
> kind of restates Robert Martins opinion "working 'outside-in' requires a
> lot of mocks".

define "a lot". More than in some other code bases, but fewer than may people think.


> When working "inside-out", the assumption is that
> depended-on-components(DOC)/collaborators will be implemented and tested
> before clients to them by default. So then there would be no problem to
> test with the real DOC (instead of test doubles). On the other hand, even
> if DOC:s are available, it is no problems to test with test doubles
> (mocks), so working "inside-out" and using mocks has no contradiction.

Eventually, someone has to break the dependency, so either the intermediate levels are difficult to test or there's some kind of substitution.


> In the end I agree with many of the people in this discussion that
> "outside-in" vs "inside-out" and "testing with test doubles" vs "testing
> with real collaborators" are, if not fully orthogonal, nearly orthogonal.

Perhaps "missing the point" is a better response?

S

philip schwarz

unread,
Jun 25, 2013, 5:41:55 PM6/25/13
to growing-object-o...@googlegroups.com
FYI - James Shore tweeted back the following answers:

* I find myself using mockist style when design has created abstract base classes for other reasons 
* I agree with the thread that UI-first/domain-first/DB-first is orthogonal to mockist/classicist. 
* Still have yet to read GOOS. My approach hasn't changed; I still prefer to design w/o doubles. 

Philip

philip schwarz

unread,
Jun 25, 2013, 6:16:06 PM6/25/13
to growing-object-o...@googlegroups.com
In his new book, Responsible Design for Android - Part 1: Dancing with the SDK, J.B. Rainsberger has the following very interesting section on the the nonsensical classicist/mockist divide:

I end up mixing the two predominant styles of design somewhat
haphazardly. In some places I strive to keep things separate, designing in what some people call
the “London school”, guided by the principles of Presenter-First Design that I first learned from
“Presenter First: Organizing Complex GUI Applications for Test-Driven Development” [1]. In other
places I throw everything into the same spot and use duplication and naming problems to guide my
refactoring, designing in what some people call the “Detroit school”, guided more directly by the
Four Elements of Simple Design [2]. We use the terms “London school” and “Detroit school” to recognise
the people from whom we’ve learned the underlying principles. The book Growing Object-Oriented
Software Guided by Tests, written by distinguished London programmers Steve Freeman and Nat
Pryce, illustrates the “London school” approach centered on strict application of the Dependency
Inversion and Interface Segregation Principles, which involves heavy and highly-effective use of
test doubles. Detroit-adjacent programmers Ron Jeffries and Chet Hendrickson (along with several
non-Detroit-adjacent programmers like Joshua Kerievsky, James Shore and Arlo Belshee) exemplify
the “Detroit school” approach which centers on a more intuitive and direct application of the Four
Elements of Simple Design, in which they avoid test doubles and use the resulting tension to guide
them towards designs that better reflect the Single Responsibility Principle. Many commentators
see this as schism, but I don’t. As you’ve seen in this book so far, I use and value both approaches,
although I don’t agree with some of my colleagues’ disdain for test doubles. I prefer not to make
this an issue of “to mock or not to mock”, since that takes focus away from where I think it belongs.

I distinguish the London and Detroit schools a different way: the Detroit school approach favors
those who like to build big things, then break them apart as they become unwieldy; but the London
school approach favors those who like to build little things, then put them together as they exhibit
properties of belonging together. While I see many authors² claiming that either approach objectively
outperforms the other, I can’t agree. As with most such debates, I find I have better results from
knowing and practising both approaches when they seem to fit the situation. Broadly speaking, I
use the London school approach when I feel confident in making one or two up-front high-level
design (“architecture”) decisions, such as “I will use MVC/MVP to design this part of the system” or
“I will model these interactions as publish/subscribe events instead of direct method invocations”;
I use the Detroit school approach when I don’t feel confident about making those decisions. The
London school approach feels more like methodical, safe, steady design, whereas the Detroit school
approach feels more exploratory or meandering (in the good sense, like wandering through a garden,
unworried about the path, trusting that I’ll get where I need to go). Some critics of the Detroit
school dislike the feeling of having to forget what they already know about design and re-discover
everything from first principles; some critics of the London school feel that test doubles lock their
design in and resist change. I see it another way: the Detroit school allows me to meander safely
when I have a general idea of the destination, but an unclear picture of the route; the London school
encourages me to build tiny things and put them together, and when I find that a piece needs to
change shape, I can throw that piece away and design a new one in its place without paying a
prohibitive cost for it. I think of the London school approach as a shortcut that I can take when I
think I recognise what I need to build and the Detroit school approach on which I can fall back when
I just don’t know what to do next. Thus, I benefit the most from practising both, feeling comfortable
with both, and even feeling comfortable refactoring from one style of design to the other. Please
don’t limit this question in your mind to “mocks suck” or “mocks rock”, no matter how pithy you
find those two slogans.


Philip




On Sunday, 23 June 2013 08:31:23 UTC+1, philip schwarz wrote:

Steve Freeman

unread,
Jun 26, 2013, 12:05:14 PM6/26/13
to growing-object-o...@googlegroups.com
On 25 Jun 2013, at 22:41, philip schwarz wrote:
> FYI - James Shore tweeted back the following answers:
>
> * I find myself using mockist style when design has created abstract base
> classes for other reasons

I don't understand this one.

> * Still have yet to read GOOS. My approach hasn't changed; I still prefer
> to design w/o doubles.

this is just depressing...

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



Evgeni Dzhelyov

unread,
Jun 26, 2013, 12:31:10 PM6/26/13
to growing-object-o...@googlegroups.com
On Wed, Jun 26, 2013 at 12:41 AM, philip schwarz <philip.joh...@googlemail.com> wrote:
FYI - James Shore tweeted back the following answers:

* Still have yet to read GOOS. My approach hasn't changed; I still prefer to design w/o doubles. 

This is strange statement.
What I know for sure is that he prefers to use assert_* type of methods and do state verification, but
he still uses test doubles in his tests. 

Steve, Nat do you consider writing another book or maybe produce screen-casts, video series ?

philip schwarz

unread,
Jun 26, 2013, 5:50:35 PM6/26/13
to growing-object-o...@googlegroups.com
>this is just depressing... 

Here is the section on mocks from James Shore's book: The Art of Agile Development, published two years before GOOS:

Mock objects are a popular tool for isolating classes for unit testing. When using mock objects, your test substitutes its own object (the “mock object”) for an object that talks to the outside world. The mock object checks that it is called correctly and provides a pre-scripted response. In doing so, it avoids time-consuming communication to a database, network socket, or other outside entity.

Beware of mock objects. They add complexity and tie your test to the implementation of your code. When you’re tempted to use a mock object, ask yourself if there’s a way you could improve the design of your code so that a mock object isn’t necessary. Can you decouple your code from the external dependency more cleanly? Can you provide the data it needs—in the constructor, perhaps—rather than having it get the data itself?

Mock objects are a useful technique, and sometimes they’re the best way to test your code. Before you assume that a mock object is appropriate for your situation, however, take a second look at your design. You might have an opportunity for improvement.

Philip

James Shore

unread,
Jun 26, 2013, 9:31:24 PM6/26/13
to growing-object-o...@googlegroups.com
Hi, all. I thought I'd jump in since there's so much speculation about my writing.

First, I don't think tweets are a great way of expressing design philosophies. They're too shallow. So don't read too much into a few out-of-context tweets. Similarly, I don't think what I wrote six years ago in The Art of Agile Development is a good reflection of my opinion about test doubles today. I've learned a lot since then.

I thought that what Joe wrote about the "London school" and "Detroit school" was fairly insightful. It did a pretty good job of reflecting how I think about design: I'm focused on a few fundamental principles (simplicity, removing duplication, enhancing cohesion, and reducing coupling), and I'm constantly working to suppress my preconceptions about what the design should be, instead looking for opportunities to be surprised by new ideas. Joe calls this the "wandering through a garden" approach, and I think that's fair. I call it "reflective design" ( http://www.jamesshore.com/Blog/Reflective-Design.html ) and experiment with taking it as far as I can.

You can see me using this approach in my "Let's Play TDD" series. ( http://www.jamesshore.com/Blog/Lets-Play ). Some people find the first several episodes of that series frustrating because I'm making so many "obviously bad" design decisions. But in fact, I'm wandering through the garden. (And making some dumb mistakes. Live-coding steals about half my brain cells.)

I don't claim to understand the "London School" all that well. I originally ran across mock objects in 2000 via Steve et al's Endo-Testing paper ( stalatest.googlecode.com/svn/trunk/Literatur/mockobjects.pdf‎ ). I loved the idea and immediately applied it (by hand!) very heavily on a not-small Java XP project ( http://cf.agilealliance.org/articles/system/article/file/1028/file.pdf -- that paper doesn't specifically talk about mocks, though). It didn't work out well for us, though, and we eventually evolved to a better design that didn't use mocks.

That said, I don't think we were using mocks in the "London School" style. I have a lot of respect for Steve and Nat, and I believe that they have a style that does work well. One of these days I hope to sit down with one of them and have a face-to-face conversation where we dig into how our contexts are different--not so much about our design approaches, but about the forces that impact our design approaches. Perhaps they work on larger codebases than I do. Or smaller. Or more predictable (as Joe suggested). Or with more up-front design. Or less. Or with more diverse team members. Or more skilled. Or...

As for me, I'm happy to continue wandering through the garden. Every so often, I wonder up to test doubles. ( https://github.com/jamesshore/lets_play_tdd/blob/7285139f76fce50c65311bec6502ad5fa103a867/src/com/jamesshore/finances/ui/_ConfigurationPanelTest.java -- look at bottom three tests. ) And then I wander away again. ( https://github.com/jamesshore/lets_play_tdd/blob/9be53bad9d30d19592c33184dff1577b2027d3e0/src/com/jamesshore/finances/ui/_ConfigurationPanelTest.java -- look at the same three tests. ) Sometimes I do proper interaction testing. ( https://github.com/jamesshore/lets_play_tdd/blob/9be53bad9d30d19592c33184dff1577b2027d3e0/src/com/jamesshore/finances/values/_ValidDollarsTest.java -- search for "RenderTargetStub" ). Sometimes I do something that seems totally gawdawful, except that it cuts the gordian knot of complexity elsewhere. ( https://github.com/jamesshore/lets_play_tdd/blob/9be53bad9d30d19592c33184dff1577b2027d3e0/src/com/jamesshore/finances/persistence/UserConfiguration.java -- look at the writeFile() method, or setObserver().) And sometimes I just throw up my hands and say, "I'm going to let this sit for a while until I come up with a better idea." ( https://github.com/jamesshore/lets_play_tdd/blob/9be53bad9d30d19592c33184dff1577b2027d3e0/src/com/jamesshore/finances/ui/_ApplicationFrameTest.java -- see the tearDown() method.) It all depends on the needs of the design in the moment.

Meanderingly yours,
Jim

PS: You can see a good example of me wandering through the garden starting with episode 188 of http://www.jamesshore.com/Blog/Lets-Play/ and continuing through episode 201. That's a case where I decided to move away from test doubles.

Steve Freeman

unread,
Jun 27, 2013, 8:57:45 AM6/27/13
to growing-object-o...@googlegroups.com
On 27 Jun 2013, at 02:31, James Shore wrote:
> Hi, all. I thought I'd jump in since there's so much speculation about my
> writing.

:) Thanks for joining in.

> First, I don't think tweets are a great way of expressing design
> philosophies. They're too shallow. So don't read too much into a few
> out-of-context tweets. Similarly, I don't think what I wrote six years ago
> in The Art of Agile Development is a good reflection of my opinion about
> test doubles today. I've learned a lot since then.

+1

> I don't claim to understand the "London School" all that well. I originally
> ran across mock objects in 2000 via Steve et al's Endo-Testing paper (
> stalatest.googlecode.com/svn/trunk/Literatur/mockobjects.pdf ). I loved
> the idea and immediately applied it (by hand!) very heavily on a not-small
> Java XP project (
> http://cf.agilealliance.org/articles/system/article/file/1028/file.pdf --
> that paper doesn't specifically talk about mocks, though). It didn't work
> out well for us, though, and we eventually evolved to a better design that
> didn't use mocks.

We've moved on quite a bit too since then (although we got a surprising amount right). I, for one, passed through the golden hammer stage and have come out with a clearer understanding of the boundaries--although there were some entertaining discoveries along the way.

> PS: You can see a good example of me wandering through the garden starting
> with episode 188 of http://www.jamesshore.com/Blog/Lets-Play/ and
> continuing through episode 201. That's a case where I decided to move away
> from test doubles.

I'll take a look. On my side, I'm not a great video watcher since I spend too much time in front of a screen already.

I'm currently engaged in an exchange with Arlo Belshee on an internal company mailing list which is flushing out some interesting differences. Some of it appears to be terminology, but not all. You should encourage him to write it all up in public.

S.

James Shore

unread,
Jun 27, 2013, 2:03:28 PM6/27/13
to growing-object-o...@googlegroups.com
On Jun 27, 2013, at 5:57 AM, Steve Freeman <st...@m3p.co.uk> wrote:

On 27 Jun 2013, at 02:31, James Shore wrote:

PS: You can see a good example of me wandering through the garden starting
with episode 188 of http://www.jamesshore.com/Blog/Lets-Play/ and
continuing through episode 201. That's a case where I decided to move away
from test doubles.

I'll take a look. On my side, I'm not a great video watcher since I spend too much time in front of a screen already.

Me neither, ironically.

https://github.com/jamesshore/lets_play_tdd/compare/73669a9f6cc785794e933fcccd711c6cd43e0198...master shows a diff between the beginning and end of the "migrate away from test doubles" process, if you're interested. A lot of the value of the videos is hearing my live thought process, especially the false starts and second-guessing, but the diff is a lot quicker. :-)

What I find most interesting about the diff is that the UserConfiguration (née SaveFile) class and its tests get a lot bigger. Everything else gets simpler in a bunch of tiny ways. That feels like a design success to me. (And arguably, the UserConfiguration changes are a sensible refinement/consolidation of responsibility.)

I'm currently engaged in an exchange with Arlo Belshee on an internal company mailing list which is flushing out some interesting differences. Some of it appears to be terminology, but not all. You should encourage him to write it all up in public.

Sounds interesting. I'm looking forward to talking to him about it.

Cheers,
Jim

--
James Shore - The Art of Agile
recipient of Gordon Pask Award for Contributions to Agile Practice
co-author of The Art of Agile Development


Philip Schwarz

unread,
Jun 27, 2013, 5:03:48 PM6/27/13
to growing-object-o...@googlegroups.com
>Hi, all. I thought I'd jump in since there's so much speculation about my writing.
Thank you so much for taking the time to help out.

Philip


--
 
---
You received this message because you are subscribed to the Google Groups "Growing Object-Oriented Software" group.
To unsubscribe from this group and stop receiving emails from it, send an email to growing-object-oriente...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages