Levels of Context Independence in GOOS and POODR

452 views
Skip to first unread message

philip schwarz

unread,
Feb 2, 2014, 7:06:00 PM2/2/14
to growing-object-o...@googlegroups.com
For those of you who have read POODR, it seems to me that the book articulates two levels of context independence, the first one being the level articulated in GOOS, and which is achieved by using third-party-connect (dependency injection), and the second one being achieved by (in what superficially at first might appear a reversal of LoD) getting collaborations to shift from A telling 
B HOW to bring about what A wants, to A asking B WHAT it wants, and trusting B to do the right thing to bring it about.

Here are a couple of extracts on context independence from GOOS: 

"A system is easier to change if its objects are context-independent; that is, if each object has no built-in knowledge about the system in which it executes. This allows us to take units of behavior (objects) and apply them in new situations. To be context-independent, whatever an object needs to know about the larger environment it’s running in must be passed in. Those relationships might be “permanent” (passed in on construction) or “transient” (passed in to the method that needs them).
In this “paternalistic” approach, each object is told just enough to do its job and wrapped up in an abstraction that matches its vocabulary. Eventually, the chain of objects reaches a process boundary, which is where the system will find external details such as host names, ports, and user interface events."

"The effect of the “context independence” rule on a system of objects is to make their relationships explicit, defined separately from the objects themselves. First, this simplifies the objects, since they don’t need to manage their own relationships. Second, this simplifies managing the relationships, since objects at the same scale are often created and composed together in the same places, usually in mapping-layer factory objects.
Context independence guides us towards coherent objects that can be applied in different contexts, and towards systems that we can change by reconfiguring how their objects are composed."

POODR also values context independence:

"The context that an object expects has a direct effect on how difficult it is to reuse. Objects that have a simple context are easy to use and easy to test; they expect few things from their surroundings. Objects that have a complicated context are hard to use and hard to test; they require complicated setup before they can do anything. The best possible situation is for an object to be completely independent of its context."

But what POODR does next is distinguish between a first level of context independence, achieved by using dependency injection, and a further
level:

"An object that could collaborate with others without knowing who they are or what they do could be reused in novel and unanticipated ways. You already know the technique for collaborating with others without knowing who they are—dependency injection. The NEW PROBLEM here is for Trip to invoke the correct behavior from Mechanic without knowing what Mechanic does. Trip wants to collaborate with Mechanic while maintaining context independence."

Before we look at a few more extracts from POODR to show how Metz solves the 'NEW PROBLEM', and especially for the benefit of those who haven't read the book, or who won't want to go into any more detail, Metz's solution is to shift from telling a collaborator how to behave, to asking a collaborator for what one wants and trusting the collaborator to deliver:

"This blind trust is a keystone of object-oriented design. It allows objects to collaborate without binding themselves to context and is necessary in any application that expects to grow and change.
...
When messages are trusting and ask for what the sender wants instead of telling the receiver how to behave, objects naturally evolve public interfaces that are flexible and reusable in novel and unexpected ways."

Met'z solution is the final of three approaches she explores, which she says "represent a movement towards increasingly object-oriented code and as such they mirror the stages of development of the novice designer"

"If objects were human and could describe their own relationships", she says that in the three approaches the objects would describe their relationships as follows:
  • “I know what I want and I know how you do it;”
  • “I know what I want and I know what you do”
  • “I know what I want and I trust you to do your part.”
For those who have read the book and are interested, let me restate 'THE NEW PROBLEM' before we look at a couple more extracts:

"The NEW PROBLEM here is for Trip to invoke the correct behavior from Mechanic without knowing what Mechanic does. Trip wants to collaborate with Mechanic while maintaining context independence."

Here is how POODR elaborates the 'NEW PROBLEM'

"At first glance this seems impossible. Trips have bicycles, bicycles must be prepared, and mechanics prepare bicycles. Having Trip ask Mechanic to prepare a Bicycle
seems inevitable. However, it is not. The solution to this problem lies in the distinction between what and how, and arriving at a solution requires concentrating on what Trip wants. What Trip wants is to be prepared. The knowledge that it must be prepared is completely and legitimately within the realm of Trip’s responsibilities. However, the fact that bicycles need to be prepared may belong to the province of Mechanic. The need for bicycle preparation is more how a Trip gets prepared than what a Trip wants." 

POODR then shows an activity diagram that solves the problem and says:

"In this example, Trip merely tells Mechanic what it wants, that is, to be prepared, and passes itself along as an argument. In this sequence diagram, Trip knows nothing about Mechanic but still manages to collaborate with it to get bicycles ready. Trip tells Mechanic what it wants, passes self along as an argument, and Mechanic immediately calls back to Trip to get the list of the Bicycles that need preparing. All of the knowledge about how mechanics prepare trips is now isolated inside of Mechanic and the context of Trip has been reduced. Both of the objects are now easier to change, to test, and to reuse."

Philip

Luca Minudel

unread,
Feb 3, 2014, 4:22:51 AM2/3/14
to growing-object-o...@googlegroups.com
Hey Philip

I've found that example from Sandi Mez's POODR  very interesting too. have found your description accurate and clear.

I share also your perception that in GOOS, dependency injection is the most common technique used to decouple objects, break dependencies, apply DIP and OCP, pursue context independence.
Sandi Mez's trip/mechanic example instead uses the visitor pattern to decouple objects (lets Mechanic define a new operation without changing the Trip and Bike classes on which Mechanic operates).


In the paper 'Endo-Testing: Unit Testing with Mock Objects' by Tim Mackinnon, Steve Freeman and Philip Craig in the chapter 'Effects on coding style' you can read this:
Thirdly, developing with Mock Objects teases out different aspects of functionality into smaller, more specialised classes which are easier to understand and modify. In practice, this means pushing behaviour towards Visitor-like objects [Gamma 1994] that are passed around; we call these Smart Handlers.

In other blog posts and forum discussions or discussions with Steve and Nat, that I cannot remember/reference correctly now, I remember mentioning the visitor patter and the multiple dispatch as a technique to decouple objects (visitor is an implementation of double-dispatch).

I currently lean toward the idea that Sandi Mez's example is congruent with GOOS and its view of context independence. I see Sandi Mez's example as another very interesting example of a coding/design technique to achieve the same goal described in GOOS. There are other techniques too (i.e. publisher/subscriber pattern).

In that example I also find interesting the underling idea that where the coder/designer have less control, less knowledge and understanding and where there are more uncertainties about future changes, the design should achieve a higher level of de-coupling.

Luca

Anthony Green

unread,
Feb 3, 2014, 6:25:13 AM2/3/14
to growing-object-o...@googlegroups.com
"In this example, Trip merely tells Mechanic what it wants, that is, to be prepared, and passes itself along as an argument. In this sequence diagram, Trip knows nothing about Mechanic but still manages to collaborate with it to get bicycles ready. Trip tells Mechanic what it wants, passes self along as an argument, and Mechanic immediately calls back to Trip to get the list of the Bicycles that need preparing. All of the knowledge about how mechanics prepare trips is now isolated inside of Mechanic and the context of Trip has been reduced. Both of the objects are now easier to change, to test, and to reuse."

Sandi talks occasional about about anthropomorphic code.  In 'object theatre' just as in radio theatre, it's from the dialogue we're able to infer the story. Having Trip tell Mechanic to prepare Bicycles we learn nothing about Mechanic, she's been given no lines, but when she's promoted to the centre of the drama for a moment and asks for Trip's bicycles we get to hear her voice. Now we know she's interested in bicycles, our minds can begin to construct a mental profile for her. 

 

Jean Helou

unread,
Feb 3, 2014, 11:34:05 AM2/3/14
to growing-object-o...@googlegroups.com
I am confused ... wouldn't something like that break "tell don't ask"? I was under the impression that "tell don't ask" was a desirable thing to achieve. maybe there are levels in the design at which tell don't ask should be prefererred and others where the opposite applies ?


On Mon, Feb 3, 2014 at 12:25 PM, Anthony Green <anthony.ch...@gmail.com> wrote:
"In this example, Trip merely tells Mechanic what it wants, that is, to be prepared, and passes itself along as an argument. In this sequence diagram, Trip knows nothing about Mechanic but still manages to collaborate with it to get bicycles ready. Trip tells Mechanic what it wants, passes self along as an argument, and Mechanic immediately calls back to Trip to get the list of the Bicycles that need preparing. All of the knowledge about how mechanics prepare trips is now isolated inside of Mechanic and the context of Trip has been reduced. Both of the objects are now easier to change, to test, and to reuse."

Sandi talks occasional about about anthropomorphic code.  In 'object theatre' just as in radio theatre, it's from the dialogue we're able to infer the story. Having Trip tell Mechanic to prepare Bicycles we learn nothing about Mechanic, she's been given no lines, but when she's promoted to the centre of the drama for a moment and asks for Trip's bicycles we get to hear her voice. Now we know she's interested in bicycles, our minds can begin to construct a mental profile for her. 

 

--
 
---
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.

philip schwarz

unread,
Feb 3, 2014, 4:43:42 PM2/3/14
to growing-object-o...@googlegroups.com
>In other blog posts and forum discussions or discussions with Steve and Nat, that I cannot remember/reference
>correctly now, I remember mentioning the visitor patter and the multiple dispatch as a technique to decouple
>objects (visitor is an implementation of double-dispatch).
Hi Luca, let me know if you remember more.

In 2011 thread Tell, Don't Ask vs SRP  the group talked about single/double/treble/...dispatch, but I don't see any posts of yours.

In 2012 I came across the following tweet of yours: @lukadotnet Visitor #DesignPattern can be used between two classes also to invert and loose dependencies and adhere to Tell don't ask/LoD.

You talked about Visitor in 2013 thread [GOOS] Re: Fowler: Explaining the principle of Tell Don't Ask (and why I don 't use it in my own programming) :

Putting data and behavior is a guideline I tend to follow from the beginning when coding.
Sometimes I reach the point where the class become too big, I start to realize that the class at some point have more then one responsibility.
When I actively look to extract the extra responsibility, sometime I feel-see in the design the tension between SRP and Tell Don't Ask.
Sometime a different distribution of responsibilities remove this tension.
Other times I discover that it is something inherent with the problem, and then something like a visitor/smart-handler is required. That is a better way then using a getter, still it does not go in the direction of  Tell Don't Ask.

Anyone had similar experiences?
Anyone can figure out a simple example that reproduce this dynamic ?

Philip

philip schwarz

unread,
Feb 3, 2014, 5:00:48 PM2/3/14
to growing-object-o...@googlegroups.com
Hey Luca,

thank you so much for your reply.

>In the paper 'Endo-Testing: Unit Testing with Mock Objects'...In practice, this means pushing behaviour towards Visitor-like objects [Gamma 1994] that are passed around; we call these Smart Handlers.
Thanks for pointing that out.
If you or anyone else has any more material on smart handlers, I am interested in it.

Philip

On Monday, 3 February 2014 09:22:51 UTC, Luca Minudel wrote:

philip schwarz

unread,
Feb 3, 2014, 5:10:20 PM2/3/14
to growing-object-o...@googlegroups.com
>In that example I also find interesting the underling idea that where the coder/designer have less control, less knowledge and understanding and where there are more uncertainties about future changes, the design should achieve a higher level of de-coupling.

That reminds me of the following passages in Sandi Met's talk: GoRuCo 2011 - Sandi Metz - Less - The Path to Better Design:

So now you are in this situation: two objects need to collaborate, you are going to have a dependency. Dependencies will kill you if you get them wrong.
And there is no way to know what is right. It sucks to be you. OK, this is always true. This is design's fundamental condition: you cannot see well
enough to predict the future. And design frankly is OK with it. As a matter of fact, design can help, it offers a solution.
Design says use uncertainty. It is telling you something. There is a piece of information here at a time when information is in short supply.
It identifies unstable places at the center of your domain, that represent the core of your business and are likely to change.
It identifies where you are most at risk: things will change, you can't know how. This is not the time to make a wild guess and implement one
of the future alternatives. It is time to write code that can tolerate change.
So here is the rule: if two objects must collaborate and you don't know which is more stable, you have to make them know as little about each other as possible.
Uncertainty is not a license to guess, it is a directive to decouple.

Philip

On Monday, 3 February 2014 09:22:51 UTC, Luca Minudel wrote:

Luca Minudel

unread,
Feb 4, 2014, 7:48:27 AM2/4/14
to growing-object-o...@googlegroups.com
Hi Philip

thanks for taking the time and digging the archives and finding out relevant and interesting parts.
I searched my emails too and I've found this excerpt from Tim Mackinnon (for those who don't know him, read GOOS afterwards: A brief history of Mock Objects), Steve and Nat were on the same email thread:

I recall when we were hand mocking objects, that is was often easier to focus on returning values because it was just simply quicker to do this ... however the better reading tests are the ones that focus on the expectations of things ... These are the situations where you ask something to do something for you (the needs driven idea that came out in the second paper). I was hoping that the new libraries might make it easier to build and tests compositions - that is setting up situations where rather than returning a collection you accept a visitor and apply some action to it (I think we called it smart handlers in the 1st paper).

Few lines later Tim mention the work of Leiberherr:

I don't think this aspect has been studied in a while - when you return collections I think your tests don't read as cleanly ... This goes against the spirit of Leiberherr (in my opinion). Of course this all builds up "test smells" - so eventually I think it comes to a head. However I can't help but thing there is still more ideas that can be exploited there.

CS Professor Karl J. Lieberherr studied the Low of Demeter, and it's impact on the design. This is a short description of what he defines Adaptive Programming:
Adaptive programming tries to create applications that are easy to maintain and evolve, creating a new abstraction layer in the design and implementation of Object-Oriented Applications. This concept takes encapsulation to a new level allowing changes in the way an object works without changing the interface with other objects. This technique solves the situations where an object takes assumptions about how other objects work and a change in this object takes down that assumption creating a chain effect in the rest of the system.

I find what Lieberherr says about Adaptive programming to be very similar to idea expressed by Sandi Met's for the trim/mechanic example:

> So here is the rule: if two objects must collaborate and you don't know which is more stable, you have to make them know as little about each other as possible.
> Uncertainty is not a license to guess, it is a directive to decouple.

Basically to me it seems that mock objects, GOOS and POODR share a common conceptual framework.


In the paper I mentioned before 'Endo-Testing: Unit Testing with Mock Objects' there are few examples of the use of Visitor patter to obtain that kind of decoupling that Sandi and Lieberherr talks about. I find that Sandi Met's example explain better and more extensively the concept.

I'd like to develop a familiarity with this technique (that uses visitors aka smart handlers aka double dispatch) similar to the familiarity I've with dependency injection.
If I understood correctly you asked for examples.
What if we in this group start to think and code some example similar to trip/mechanic one, and share it and discuss it? Maybe sharing code in some public repositories and maybe discussing the finding at some XTC meeting?

Luca




philip schwarz

unread,
Feb 4, 2014, 4:37:22 PM2/4/14
to growing-object-o...@googlegroups.com
Luca,

thanks for all these additional details.

>In...Unit Testing with Mock Objects' there are few examples of the use of Visitor patter to obtain that kind of decoupling that Sandi and Lieberherr talks about.
I will raed it once again looking out for the examples.


>I find that Sandi Met's example explain better and more extensively the concept.
She does a great job doesn't she?


>I'd like to develop a familiarity with this technique (that uses visitors aka smart handlers aka double dispatch) similar to the familiarity I've with dependency injection.
ditto


>If I understood correctly you asked for examples.
Actually, that request for examples was part of one of your posts that I was quoting verbatim...but yes, I am always interested in examples of techniques.


>What if we in this group start to think and code some example similar to trip/mechanic one, and share it and discuss it?
Seems like a good idea.

Sandi Metz says the "I know what I want and I trust you to do your part” approach to collaborations emerges in the last stage of development of the novice designer. If anyone in the group happens to have a showcase example of refactoring from “I know what I want and I know what you do” to "I know what I want and I trust you to do your part” that they like to show to novice designers, then this could be a great time to share it.

Philip

Luca Minudel

unread,
Feb 5, 2014, 4:07:14 AM2/5/14
to growing-object-o...@googlegroups.com
>> In...Unit Testing with Mock Objects' there are few examples of the use of Visitor patter to obtain that kind of decoupling that Sandi and Lieberherr talks about.
> I will raed it once again looking out for the examples.

Ok, when you do that, if you have time let me know if this sound correct to you:

- In Sandi's example
   - Mechanic is the visitor, and so are TripCoordinator and Driver
   - Trip is the node visited
- In 'Unit Testing with Mock Objects'
   - PrintWriter and PersonHandler are the visitors
   - Person is the node visited

While Trip in Sandi's example has getters (bicycles, customers, vehicle), Person doesn't. Also Person share his internal state (name, age, phone) with the visitor, but this is done only with the visitors in a controlled way.
So from this point of view the handlers from the paper push further the level of encapsulation.

Luca 

philip schwarz

unread,
Feb 9, 2014, 12:40:36 AM2/9/14
to growing-object-o...@googlegroups.com
>Ok, when you do that, if you have time let me know if this sound correct to you
OK
Reply all
Reply to author
Forward
0 new messages