From: Frank Fredstone on
I'm still struggling with OO concepts. I've read several books and
studied various OO languages, but I don't really feel I have a good
grasp of the concepts.

I like the sound of the "tell, don't ask" model, where networks of
objects are asked to perform the work they are responsible for, rather
than asking objects to give you information (like a string) that you
do something with. But, I get confused when I try to apply the idea to
a program design.

The only way I can think of avoiding asking objecs for information is
if the program consists of nothing but one object of class "Program"
with one method called "execute" that does everything.

I've seen an example of bad design:

AssociativeArray c = object.getEmployees()
for each employee in employees:
c.put(employee.name(), employee)

the "tell don't ask" version of which could be:

object.addEmployees(employees);

So, "object"'s class supports the "tell model", by allowing you to
tell it to add employees rather than asking it for a map to modify.

But, doesn't that mean that "employees"'s class has to support the
"ask model", so that it "object" can get each of the "employee" objects and
their names?

Is there a way to actually use "tell" insead of "ask", through
out. Or, how do you categorize when you should use "tell" and when you
should use "ask"?
From: Frank Fredstone on
ram(a)zedat.fu-berlin.de (Stefan Ram) writes:

> Frank Fredstone <none(a)not.no> writes:
>>AssociativeArray c = object.getEmployees()
>>for each employee in employees:
>> c.put(employee.name(), employee)
>>the "tell don't ask" version of which could be:
>>object.addEmployees(employees);
>
> One possibility:
>
> employees.add_all_pairs_of_name_and_employee_to_map( c );
>
> Or using the notation [x|f(x)] for a block object ith the
> parameter �x�:
>
> employees.for_each_employee_do[ e | e.with_name_do[ n | c.put( n, e ); ]]
>
> The blocks are passed into the objects as arguments to the
> operations �for_each_employee_do� and �with_name_do�,
> so the objects do not return values such as �e� or �n�.

Well, your examples uses different objects (employees and
a map) instead of (object and employees).

But, if I change your first example to

employees.add_all_pairs_of_name_and_employee_to_object(object)

I suppose that uses the "tell model" for both classes.

It seems disconcerting to me that Employees would have to have a
method specifically for interfacing with "object" objects, though. If
there became a reason to have an ineraction between an Employeees
object and some other object, would I then have to modify Employees to
have a method specifically for that other class? For example:

employess.add_employee_to_some_other_object(some_other_object)
employees.add_employee_to_yet_another_object(yet_another_object)

From: Wavemaker on

"Frank Fredstone" wrote:
> I'm still struggling with OO concepts. I've read several books and
> studied various OO languages, but I don't really feel I have a good
> grasp of the concepts.
>
> I like the sound of the "tell, don't ask" model, where networks of
> objects are asked to perform the work they are responsible for, rather
> than asking objects to give you information (like a string) that you
> do something with. But, I get confused when I try to apply the idea to
> a program design.

My take on the "tell, don't ask" approach is that objects announce
(tell) when something happens. This could be, for example, when they're
finished with a task or an event outside of the system occurs and its
their job to let interested parties know about it.

> But, doesn't that mean that "employees"'s class has to support the
> "ask model", so that it "object" can get each of the "employee"
> objects and
> their names?

In my opinion, it's ok to have "getters" that expose an object's
properties. One wants to be careful not to overdo it; you'd like the
interface for a class to be as narrow as possible, but sometimes it just
makes sense to have a getter for a particular property. A "Name"
property seems reasonable for an Employee class. The question I'd have
would be whether or not to make this property mutable (probably not).
But then it's hard to judge what kind of interface a class should have
in a vacuum. You really need to know more about the overall problem
being solved. But as a general rule, I don't have a problem with a class
providing a few properties that can be queried through "getters."

In other words, I don't have a problem with an object being asked to
give more information about itself.


From: H. S. Lahman on
Responding to Fredstone...

I agree with Wavemaker; the OO view of "tell; don't ask" is necessarily
different than the procedural view...

> I'm still struggling with OO concepts. I've read several books and
> studied various OO languages, but I don't really feel I have a good
> grasp of the concepts.
>
> I like the sound of the "tell, don't ask" model, where networks of
> objects are asked to perform the work they are responsible for, rather
> than asking objects to give you information (like a string) that you
> do something with. But, I get confused when I try to apply the idea to
> a program design.

This view is just plain wrong in the OO world. OO methods are
/supposed/ to access the knowledge they need on an as-needed basis
because the OOA/D model of behavior communication is asynchronous. That
implies an arbitrary delay is possible between when a message is
generated and when the response is executed. (That's because the OOA/D
must be unambiguously implementable in inherently asynchronous and/or
concurrent environments at OOP time as well as synchronous environments.)

However, data integrity becomes a mess with that model if it is passed
in messages because of the potential delay. So in OOA/D knowledge access
is always synchronous (getters/setters are aka synchronous services).
That's the only way to ensure timely data and the OOP implementation
must provide infrastructure to ensure accessing the data behaves as-if
it were synchronous, even in distributed implementations. That makes it
much easier to manage scope for data integrity during OOP. So the method
always asks for the data it needs and in a well-formed OO application
messages very rarely carry data packets. (There are data packets only
when requirements demand "snapshots", such as processing data from
multiple sensors that in from the same time slice.)

Message and method are separated in the OOA/D so that one can eliminate
hierarchical implementation dependencies. The 'tell' part refers to the
fact that all behavior messages are announcements (I'm done). They tell
whoever is listening that something was done that changed the state the
the solution. Then the sender of the message only needs to know what it
did and has no expectation of what will happen as a consequence. IOW,
what the message receiver does with that information is a personal
matter for the receiver. The sender doesn't even need to know who will
receive the message. Routing the messages to the right receiver is done
at a different level of abstraction (e.g., a UML Interaction Diagram).

Conversely the 'ask' part refers to an expectation that a specific
receiver will do something in particular (Please Do This). That is a
no-no in an OO context because for the message sender to have that
expectation it needs to know: (A) that someone specific cares what it
did; (B) they have a specific behavior responsibility; and (C) that
responsibility is what needs to be done next in the overall solution.
All of those break OO encapsulation but the last is especially insidious
because it hard-wires the overall solution sequence into the sender
implementation.

> The only way I can think of avoiding asking objecs for information is
> if the program consists of nothing but one object of class "Program"
> with one method called "execute" that does everything.
>
> I've seen an example of bad design:
>
> AssociativeArray c = object.getEmployees()
> for each employee in employees:
> c.put(employee.name(), employee)
>
> the "tell don't ask" version of which could be:
>
> object.addEmployees(employees);

I agree the example is poor practice, but I don't think it has anything
to do with "tell, don't ask". "object" is clearly a collection class
that implements a 1:* relationship to Employee in the OOA/D. A such its
natural responsibilities are to manage the collection. So it would
logically have "add", "remove", "get", etc. responsibilities when one
abstracted the concept of a collection from the problem space. So there
is no point in having an intermediary collection (AssociativeArray) to
implement those notions.

[BTW, the example seems curious from another standpoint. Why is there a
second collection of Employees ("employees")? That would only be
justified if there were another 1:* relationship to Employee that
involved a different set of employees in the collection. But if that
were true, I would expect there would be some selection criteria to
apply for the subset.

My point here is not to critique the example, but to point out that the
use of collections and their management will depend on the specifics of
the problem. "tell, don't ask" is not relevant here because the problem
space is dictating the relationship collections and the collaborations
that navigate them. IOW, problem space abstraction determines what
collections are needed and what responsibilities they must have. "Tell,
don't ask" only becomes relevant when one constructs the behavior
methods that navigate those relationships during collaborations.]


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

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



From: Frank Fredstone on
ram(a)zedat.fu-berlin.de (Stefan Ram) writes:

> Frank Fredstone <none(a)not.no> writes:
>>>employees.add_all_pairs_of_name_and_employee_to_map( c );
>>Well, your examples uses different objects (employees and
>>a map) instead of (object and employees).
>
> I call an �associative array� a �map�, but this is not
> intended to be another class or object - just another name for
> the same thing.

I didn't state what my example was doing clearly I think.

The example was showing the interaction betwen an object named
"object" of some class (let's say it's Organization) and another
object called "employees" of some class (let's say it's Employees).

Assuming the premise of my post "tell" is good, "ask" is bad, the "bad
way" was for Organization to allow you to ask it for a map to modify:

AssociativeArray c = object.getEmployees()
for each employee in employees:
c.put(employee.name(), employee)

This is supposed to be a typical example of "asking" an object for
something that you modify, rather than "telling" the object to perform
some operation.

The "good way" was for Organization to allow you to tell it to add
emloyees to itself:

object.addEmployees(employees);

My question was then, doesn't that imply that Employees needs to
support the "ask" model though?

I can get from your example that it could be possible for Organization
to allow an "add" operation and then use your

employees.add_to(object)

which is then "tell model", but, an Organization might need to have
things other than employees added to it, so an "add" method might not
be suitable, and the representation of an employee in an Organization
could change to require something other than a map of employees by
name.

I suppose there could be an addEmployee method on Organziation and
Employees.add_to could know that, but then doesn't that mean that
Employee has to support the "ask model"?

>>But, if I change your first example to
>>employees.add_all_pairs_of_name_and_employee_to_object(object)
>
> My first suggestion is intended to replace the statement:
>
> for each employee in employees:
> c.put(employee.name(), employee)
>
> This statement contains �c�, not �object�.
> Therefore, my first suggestion also contains �c�, not �object�.

Right, but "c" only exists in the supposedly "bad way" of doing
things. The problem I was posing was one between "object" and
"employees".

Maybe you are saying that it is a good idea to ask employees for a map
to modify.

"Wavemaker" <jabberdabber(a)BiteMeHotmail.com> writes:

> My take on the "tell, don't ask" approach is that objects announce
> (tell) when something happens. This could be, for example, when they're
> finished with a task or an event outside of the system occurs and its
> their job to let interested parties know about it.

I think this doesn't match what I've been reading referred to as "tell,
don't ask". I keep coming across it while I'm looking into testing and
mock objects, maybe it's a fringe idea.

I've seen "tell, don't ask" expressed in Allen Holub's book 'Holub on
Patterns' in the section "Getters and setters are evil", and on this
web page:

http://www.pragmaticprogrammer.com/ppllc/papers/1998_05.html

By "tell" they seem to mean telling objects to perform some action
rather than asking objects for information that you will then do
something with.

Allen Holub's argument for why it tends to be bad to ask for objects
for information about their state, is that it spreads dependencies on
the internal state of an object around to other objects.

He also argues that the place where getters/setters are not evil is
where you bump up against the "procedural boundary" of the system or
operating system that you are interfacing with. Or, if you need your
objects to be unusually flexible in how they can interact with other
objects, like if you are writing a general class library.

However, this is all to vague for me, and that's really what I'm
asking for is some less vague guidelines that someone can express an
opinion about.

"H. S. Lahman" <h.lahman(a)verizon.net> writes:

> Responding to Fredstone...
>
>> I like the sound of the "tell, don't ask" model, where networks of
>> objects are asked to perform the work they are responsible for, rather
>> than asking objects to give you information (like a string) that you
>> do something with. But, I get confused when I try to apply the idea to
>> a program design.
>
> This view is just plain wrong in the OO world. OO methods are
> /supposed/ to access the knowledge they need on an as-needed basis
> because the OOA/D model of behavior communication is
> asynchronous.

I don't understand what you are describing as synchronous or
asynchronous about either "tell" or "ask" model methods, I think they
are both synchronous.

But, I think you might not be refering to the same thing as I am about
"tell, don't ask". By "tell" I mean methods that tell an object to
perform some processing, like "add an employee to your organization",
and by "ask" I mean methods that ask for data that you can then do
processing with yourself, like "give me a map that I can add employees
to".