Re: Design Problem Aggregation
From: H. S. Lahman (h.lahman_at_verizon.net)
Date: 05/12/04
- Next message: Topmind: "Re: Why is OO Popular?"
- Previous message: Topmind: "Re: Does Agile Development have to be OO?"
- In reply to: Merlin: "Re: Design Problem Aggregation"
- Next in thread: Robert C. Martin: "Re: Design Problem Aggregation"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Wed, 12 May 2004 21:52:05 GMT
Responding to Merlin...
> Thank you both for your suggestions. What has been suggested works
> well if no
> class sits between BASE and A or BASE and B.
>
> In order to make things clear, discard the original classes and
> consider the following scenario.
>
> Imagine we have the following classes
>
> BASE, A, B, C, D, E, F, G, H, I, and J (class diagram will help)
>
> Classes A, D, F, G, J inherit from BASE.
>
> Class B inherits from A
Something else also has to inherit from A or else B is an identity set
with A.
>
> Class C inherits from B
Ditto.
>
> Class E inherits from D
Ditto.
>
> Classes H and I inherit from G
>
> Class H has a member (aggregation by value) of type C.
> Class I has a member (aggregation by value) of type E.
I'm not sure I know what you mean here. In C++ would it be
class H : BASE
{
private:
C myC; // embedded implementation
...
}
-OR-
class H : BASE
{
private:
C* myC; // relationship implementation.
...
}
It sounds like the former but, if so, I would ask: what does this have
to do the problem since embedded objects are hidden as part of the
container's implementation?
If it is the latter, then you seem to be implementing:
1 1
[H] ---------------- [C]
and
1 1
[I] ---------------- [E]
If so, is the multiplicity correct on the [H] and [I] sides?
>
>
> Class J has a member that is container that can accept objects of type
> G. As G is the base class of H and I we can add to the container
> objects of type H or I. I have made the container type safe in this
> way.
I assume you are using 'container' here in the sense of a collection
class for a 1:* relationship(?)
This seems to implement:
* 1 1 *
[H] -------------- [J] ----------------- [I]
I'm not sure why there is a need for the complexity of [G]. Why not
separate containers for [H] and [I] references.
>
> J is not a container, it has a member that is a container. My design
> requires this. Also J does indeed inherit from BASE.
Your design or the problem space? B-)
If it is you design, I am deeply suspicious of the complexity of the
inheritance tree. Since every leaf subclass instance if also a root
superclass instance, that means that the root superclass' members
collectively contain all the properties of the entire tree. Thus
complex inheritance trees with many specialized subclasses usually
indicate a lack of cohesion in the root superclass. That is, the tree
as a whole has too many responsibilities. Of course there is no way to
judge this when we are only talking about As and Bs, rather then a real
problem.
>
> I wanted J to be a collection of objects of type C or E but never F or
> even BASE so I introduced an abstract class G and made the container
> of that type so it would only accept objects of base type G. However,
> although this looks ok, I am not happy with the extra work it has
> created.
I agree. [G], [H], and [I] seem like a lot of trouble to implement
* 1 1 *
[C] ------------------ [J] ---------------- [E]
Unless there are special rules about pairing particular Cs and Es that
[J] collects, I would just use two simple collection classes to
implement the relationships. Since only C and Es are included in the
respective collections, one gets the exclusion of Fs automatically.
>
> As I need to access the interface to C and E, I need to repeat all
> that interface in H and I. C and E have many member functions and I
> dont want to rewrite all that interface in H and I and delegate the
> calls to the aggregate.
You definitely don't want that sort of interface daisy chaining; it
completely trashes encapsulation.
I am getting the impression that you are trying to use subclassing as
some kind of relationship instantiation. Relationship implementation,
instantiation, and navigation is orthogonal to class semantics like is-a
relations. In addition, object collaborations are peer-to-peer.
So when objects from different classes need to collaborate they navigate
to the right instance to address messages via traversing a relationship
path. That path and the pointers or collection classes along the way
are quite independent of the semantics of the classes along the way.
[Full automatic code generators typically treat relationship navigation
as aspects and insert quite generic code into the classes. For example,
referential attributes will typically be named after the relationship
identifier rather than the class.]
So far all you have described (ignoring the identity set problems for
[B], [C], and [E] above) is:
[BASE]
A
|
+---------+--------+----------+
| | | | 1
[A] [D] [F] [J] -----+
| * | * | 1 |
| | | |
| +-------------------+ |
| |
+-------------------------------------+
So if a client who has a J in hand needs to access that J's As, the
client would access the collection class and cycle though contained As.
Neither J nor the collection class would have to know anything about
A's interface; only the client who is directly collaborating with the As
would need that.
*************
There is nothing wrong with me that could
not be cured by a capful of Drano.
H. S. Lahman
hsl@pathfindermda.com
Pathfinder Solutions -- Put MDA to Work
http://www.pathfindermda.com
(888)-OOA-PATH
- Next message: Topmind: "Re: Why is OO Popular?"
- Previous message: Topmind: "Re: Does Agile Development have to be OO?"
- In reply to: Merlin: "Re: Design Problem Aggregation"
- Next in thread: Robert C. Martin: "Re: Design Problem Aggregation"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|