Re: Internal State vs. Navigating Associations



Responding to McGill...

As a newcomer to OO design, I've been wrestling lately trying to wrap
my mind around the "Tell, Don't Ask" principle and the law of Demeter
for methods. I have been trying to avoid query/decision operations of
this nature:

Bar bar = foo.getFrozzledBar();
if (bar.isFranted()) // do something else

under the assumption (here I am trying to apply "Tell, Don't Ask") that
in this example foo's internal state (bar) is being exposed. Instead I
try to replace the above with a single, more meaningful method on foo,
containing the conditional in some form.

The first thing to note is that "tell, don't ask" is orthogonal to LoD. "Tell, don't ask" is about how one defines the responsibilities of an object while LoD is about what one object knows about another.

The question this has prompted me to ask: in what situations is bar a
part of foo's internal state, and in what situations is it really just
an object to which foo has an association? If bar *is* just an
associated object, is it then OK to navigate the association in the
above fashion?

As you recognize, the crucial question related to "Tell, don't ask" is: what object knowledge properties should be exposed publicly? I submit that "Tell, don't ask" is actually irrelevant because the OO paradigm already provides methodological construction techniques, particularly problem space abstraction, that already minimize what is exposed.

All objects are abstractions of entities from some problem space. When we abstract those entities we abstract intrinsic responsibilities for things the entity needs to know or needs to do _in order to solve the problem in hand_. So, by definition, any characteristic we need to solve the problem in hand must be abstracted as a responsibility. The corollary is that we only abstract characteristics that we need to solve the problem. Therefore we should end up with no more and no less responsibilities than those we need to solve the problem in hand.

There is an issue around public vs. private responsibilities. Certain responsibilities, such as the current last address in a ring buffer, are clearly only relevant to the implementation of an object. Other responsibilities, such as the current color of a traffic light, are clearly responsibilities that relate to collaborations in the overall solution for traffic control software. So the criteria for public vs. private is pretty straight forward. If, in order to solve the problem in hand, some other object needs the information the object in hand is responsible for knowing, that knowledge responsibility is a public responsibility.

There is also an issue around capturing business rules and policies statically in state variables and relationships or capturing them dynamically in behaviors and state machine transitions. However, that is a fundamental design choice. Once the choice is made to use state variables, then those that are necessary to solve the problem in hand become clear.

Having said all that, the example you cite is really another special situation: embedded objects. Since 'bar' is an object with its own responsibilities, the real question is: Is 'bar' a peer of 'foo' or part of its implementation?

If 'bar' is a peer of foo, then all one is really doing is navigating a relationship path, R1 -> R2:

R1 R2
[Client] -------------- [Foo] ----------------- [FrozzledBar]

That is quite normal for an OO application and has nothing to do with either "tell, don't ask" or LoD. That's because relationship implementation, instantiation, and navigation is orthogonal to class semantics. (For example, full code generators for OOA models routinely employ generic aspects to implement relationships that are completely independent of classes.)

Where it would be a problem is if [FrozzledBar] was embedded in [Foo] as part of its implementation. The OO paradigm says that such implementations should be hidden. There are exceptions, though. Common computing space data holders (String, Array, ComplexNumber, etc.) are essentially fundamental data types so they are treated like ADT scalar knowledge attributes. IOW, one evaluates whether they need to be exposed publicly as if they were were ordinary knowledge responsibilities; if they are needed by other objects to solve the problem in hand, they should be exposed.

OTOH, any object that abstracts an entity in a non-computing problem space should almost always be a standalone peer object (i.e., not embedded in another object's implementation). That's because it /is/ an identifiable entity in the problem space just like any other problem space entity that one abstracts.


*************
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman
hsl@xxxxxxxxxxxxxxxxx
Pathfinder Solutions
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
"Model-Based Translation: The Next Step in Agile Development". Email
info@xxxxxxxxxxxxxxxxx for your copy.
Pathfinder is hiring: http://www.pathfindermda.com/about_us/careers_pos3.php.
(888)OOA-PATH



.



Relevant Pages

  • Re: Barack vs. Joe the Plumber
    ... BAR wrote: ... citizens and who cannot vote legally in US elections except ... You want all of the benefits with none of the responsibilities. ... for selective service are all ...
    (rec.sport.golf)
  • Re: Barack vs. Joe the Plumber
    ... BAR wrote: ... citizens and who cannot vote legally in US elections except municipal ... I don't care if you pay taxes here or not. ... You want all of the benefits with none of the responsibilities. ...
    (rec.sport.golf)
  • Re: When opening saved file, colors in bar go back to original
    ... Colors of bars have been changed manually, ... all suddenly change to light blue (which I think is the standard, ... about Microsoft Project ... the Gantt Chart (depending on resources, responsibilities, etc.). ...
    (microsoft.public.project)
  • Re: distorted model! do i need patterns or something!?
    ... When an activity in the customer space is such ... it as a major problem space responsibility that corresponds to the ... That decision will depend on what is most suitable to the problem in hand (e.g., what other responsibilities the underlying problem space Entity might need to solve the problem in hand). ... But at the OOA/D level it is conceptually quite different that either [HotelManager] or. ...
    (comp.software.patterns)
  • Re: we have a "this" keyword, but what if... we also had "component" keyword??
    ... > Now client depends on MyPackage component which serves as a facade. ... But each of these is a standalone object with its own interface. ... responsibilities a Facade object has is re-dispatching messages. ... one of my problems with the original example for Component is that [Foo] ...
    (comp.object)