Re: The wisdom of the object mentors (Was: Searching OO Associations with RDBMS Persistence Models)

From: Robert Martin <unclebob_at_objectmentor.com>
Date: Thu, 6 Jul 2006 11:36:58 -0500
Message-ID: <2006070611365819336-unclebob_at_objectmentorcom>


On 2006-07-03 17:43:05 -0500, "topmind" <topmind_at_technologist.com> said:

> Sure, some parameters may be nouns, but which noun gets to be King
> Noun? Rather than arbitrarily promote one, make them *all* parameters.
>
> noun1.doX(noun2, noun3); // artificial promotion of a noun One
>
> Versus:
>
> doX(noun1, noun2, noun3); // equal footing

Let's do some transformations:

doX(n1, n2, n3) -> (n1, n2, n3).doX()

I presume you will agree that this is equivalent and does not promote any of the nouns to special status, nor demote the verb.

(n1, n2, n3) is an instance of object O1

Therefore (n1, n2, n3).doX() -> O1.doX()

Which does nothing to promote any of the nouns above any of the others.  However it *does* recognize that the triplet of (n1, n2, n3) is cohesive and belongs together in the context of doX().

Thus:

class C {
  n1, n2, n3;
  doX(){...}
}

is equivalent to doX(n1, n2, n3);

Now, if there are many functions that are similar to doX(), we could have:

doA(n1, n2, n3);
doB(n1, n2, n3);
...
doZ(n1, n2, n3);

or we could have

class C {
  n1, n2, n3;
  doA();
  doB();
  ...
  doZ();
};

Again, these are equivalent forms. However, the latter has an advantage in that the variables do not have to be carried by the caller. The caller can sequester the variables within an object of type C, and then deal with them as though they were a unit.

Sometimes functions like doX(n1, n2, n3) have different forms such as doX(n4) or doX(n6, n7). They do logically equivalent things, but with different data tuples.

If we keep these functions separate, then the *caller* must know which one to call, and must manage the data to place in the argument list.

For example:

doX(n1, n2, n3);
doX(n4);
doX(n6, n7);

SomeFunction(n1, n2, n3, n4, n6, n7, form) {   ...
  if (form == firstForm)
    doX(n1, n2, n3);
  else if (form == secondForm)
    doX(n4);
  else if (form == thirdForm)
    doX(n6, n7);
  ...
}

However, if you allow that doX is a logical function that can be enacted upon many different argument signatures, then you can place those arguments in classes:

class XDoer {
  abstract doX();
}

class TriadicXDoer implements XDoer {
  n1, n2, n3;
  doX();
}

class MonadicXDoer implements XDoer {
  n4;
  doX();
}

class BiadicXDoer implements XDoer {
  n6, n7;
  doX();
};

SomeFunction(XDoer xd) {
  ...
   xd.doX();
  ...
}

Thus, an object is really just the set of arguments that are being passed into a function. A class provides an interface that allows many such objects to be treated in a logically consistent form.

-- 
Robert C. Martin (Uncle Bob)  | email: unclebob_at_objectmentor.com
Object Mentor Inc.            | blog:  www.butunclebob.com
The Agile Transition Experts  | web:   www.objectmentor.com
800-338-6716                  |
Received on Thu Jul 06 2006 - 18:36:58 CEST

Original text of this message