Re: Exposing contained types.. Especially LISTS
- From: "H. S. Lahman" <h.lahman@xxxxxxxxxxx>
- Date: Wed, 19 Dec 2007 21:17:03 GMT
Responding to Veloz...
To make sure I am understanding you - you are saying if A contains an
instance of B, and you want clients to have access in some way to B's
functionality, then A should expose B as a public type (or at least be
able to return a reference to B when asked) so that clients can deal
directly with B and not have to "ask A to ask B" for the things it
needs.
Just to be clear, if other objects than A need to collaborate with B, then B should be a peer object and A should contain only a reference to it (or some other implementation of the relationship to a peer B). B's responsibilities should not be available through A's interface (i.e., by A acting as a middleman in collaborations).
Concretely, if a Test Product contains a List (of Feature Groups) then
we are saying client of Test Product should be able to interact with
the List without having A be the middleman, right?
Yes.
This makes perfect sense to me... but there are other posts out there
saying that A should "hide" B (as an implementation detail) and
surface its own interface, which might in some cases delegate to B,
privately. I think that's what was confusing me...
The problem lies in the OOPLs. They are 3GLs and they must necessarily make compromises with the hardware computational models. Thus all the OOPLs are inherently procedural and employ procedural message passing, procedural scope, and procedural block structuring because that is what 3GL abstraction of the computer is about. (Though some OOPLs, like Smalltalk, do a good job of hiding it.) So the 3GL type systems marry message and method via a procedure signature.
As I mentioned, that leads to substantial problems with physical coupling than can make the code difficult to maintain. A large portion of dependency management refactoring guidelines are aimed at mitigating that physical coupling. (Dependency management is largely irrelevant in UML OOA/D models because they use class systems rather than type systems and separate message and method.)
The notion of "hiding" B is rooted in a desire to mitigate physical coupling by using encapsulation. That is fine up to a point. A lot of refactoring technique involve creating abstract classes and "buffer" objects (e.g., the Facade pattern) to hide the details from clients. But those classes are just providing generic access and they are dedicated to that generic access.
However, when A exposes B's properties in its interface, one really isn't hiding B; instead one is just duplicating B in A's interface. IOW, A already has a unique suite of responsibilities in the problem solution before one worries about dependency management refactoring. In effect, one is adding B's properties to those that A already has. That is what is creating the problem because one is trashing A's cohesion.
That is quite different than providing a facade or delegation to hide /details/. Consider a typical POS web site where the user navigates a hierarchy of pages. One can describe that hierarchy with a single class:
0..1 child of
[Page] ----------------+
| 0..* |
| parent of | R1
| |
+-------------------+
The R1 relationship captures everything one needs to know about the hierarchy. Now one can navigate up and down the tree easily using accessors in [Page]. But that gets tricky when one needs to keep track of where one has been (e.g., for a depth-first traversal). So a common solution is:
[Tree]
| 0..1
| root of
|
| R2
|
| 1 0..1 child of
[Page] ----------------+
| 0..* |
| parent of | R1
| |
+-------------------+
Now all the [Page] does is hold page data and referential attributes to instantiate R1. The traversal algorithm is encapsulated in [Tree] and it keeps track of where it has been.
This is a case where the clients now all talk to [Tree] to navigate the tree (e.g., via getNext, get(linkID), or whatever). Inserting the [Tree] class to encapsulate the traversal algorithm makes the solution more robust. It also very effectively hides the details of the tree organization from clients (e.g., the tree might actually be implemented as a B-Tree or Red-Black tree). To that extent "hiding" [Page] is a Good Thing.
But you will note that [Tree] is a new class expressly created to do the hiding and it has no other responsibilities than traversing the structure, which is inherent in the implementation of the tree. IOW, [Tree] is a delegation of responsibilities of [Page] in the first diagram. The result is a new [Tree] class and a simplified [Page] class. Also critical to dependency management, [Tree] provides a more generic interface for clients so that they do not have to know how the tree is actually implemented. Thus one creates [Tree] to hide details of [Page] from clients.
OTOH, note that the clients still talk directly to [Page] to do page collaborations (e.g., getItemName or getPrice). They just get the Page reference from Tree. IOW, [Tree] is a smart list collection. But they don't talk to [Tree] about [Page] responsibilities. They only talk to [Tree] about tree navigation responsibilities, which are no longer embedded in [Page] accessors.
If I was going to provide a pithy summary of this distinction it would be: don't hide detail by adding responsibilities to other objects that already have disparate responsibilities in the solution. Which is just another way of saying the Separation of Concerns Rules.
*************
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
.
- Follow-Ups:
- Re: Exposing contained types.. Especially LISTS
- From: Veloz
- Re: Exposing contained types.. Especially LISTS
- From: Daniel T.
- Re: Exposing contained types.. Especially LISTS
- References:
- Exposing contained types.. Especially LISTS
- From: Veloz
- Re: Exposing contained types.. Especially LISTS
- From: H. S. Lahman
- Re: Exposing contained types.. Especially LISTS
- From: Veloz
- Exposing contained types.. Especially LISTS
- Prev by Date: Re: Interfaces everywhere?
- Next by Date: Re: Layer integrity versus polymorphism
- Previous by thread: Re: Exposing contained types.. Especially LISTS
- Next by thread: Re: Exposing contained types.. Especially LISTS
- Index(es):
Relevant Pages
|