Re: Factory or Inheritance for Initialisation?



H. S. Lahman wrote:
Responding to Kognition...

Through refinement of a design, a class inheritance tree has been
reduced to a single class that uses composition. I originally had
class Foo that knows to set the base MaxCount field to a specific
number. Class Bar doesnt need the MaxCount, so it must set the base
MaxCount to Infinity. Classes looked like:

+----------+
| FooBar |
+----------+
| MaxCount |
+----------+
^
|
|--------------+
| |
+----------+ +----------+
| Foo | | Bar |
+----------+ +----------+

Now, the logic that was overridden by the two subclasses has been
pulled out:


+----------+
| FooBar | +----------------+
+----------+------>| FooBarStrategy |
| MaxCount | 1 +----------------+
+----------+

Problem is MaxCount needs to be set for the two types Foo Bar. At
application initialization time, I need two FooBar classes setting up,
one for the Foo instance and one for the Bar instance that existed in
the first diagram. A classes uses the two FooBar classes:

+-------------+ +-------------+
| :SomeClient |-------| :Foo:FooBar |
| ----------- | | ----------- |
+-------------+ +-------------+
|
| +-------------+
+------------| :Bar:FooBar |
| ----------- |
+-------------+

When an instance of FooBar is created that represents the original Foo
instance, MaxCount must be set to 100. When FooBar for a Bar instance
is ceated, MaxCount must be set to Infinity, or UNLIMITED. A colleague
suggested I put the Foo and Bar classes back, and they initialise the
base FooBar during construction:

OK, I think you have come up with yet another normalization issue that
happens to be a tad tricky.


I am wondering if my abstractions are invalid. An action of the system
is to select an item (customer). There are two rules:

1. When selecting customers of a particular type, the number of
attempts is limited.
2. A customer is selected and asked to do something, at which it could
return a negative, resulting in retrying the selecting logic.
3. When it is a Foo type customer, after so many retries, fail the
selection attempt returning false.
4. There is a list of Foo and Bar instances, all initialised with their
own customers - these are encapsulated behind the FooBar class now, so
the client has a list of FooBar instances.
5. The client loops through his FooBar instances asking them to select
a customer.
6. The first FooBar to succeed means the client can finish the looping.
7. You may realise there are two loops - the client loops through the
fooBars he has calling SelectNextItem() on FooBar. Within the FooBar an
number of attempts are made to select a customer before giving up.
This allows the clients loop to move onto the next FooBar instance to
ask *it* to try to SelectNextItem()

Is the value of Foo.MaxCount /always/ 100 while the value of
Bar.MaxCount is /always/ UNLIMITED? If so, then MaxCount has different
data domains for the Foo and Bar contexts. IOW, it may not be
semantically the same attribute, which would prevent it from being a
<common> superclass attribute.


Foo.MaxCount would be configurable. The reason Bar.MaxCount is
UNLIMITED is because there is a major difference. While the looping
within FooBar is the same, the rules are different for Bar because when
a Bar is being referred to, it *must* return TRUE, thats a business
rule. There is a chance it could fail, but that would be an exception.
So yes, at this stage it is ALWAYS UNLIMITED.

Now obviously one could define a single data domain whose possible
values were {100, UNLIMITED}. The problem is the correlation with the
subclasses. Thus the value of MaxCount for any member of FooBar depends
not on the identity of the object itself but on the identity of the set
to which it belongs. IOW, it is depend on the value of MaxCount for
every other member of the set since the value must be the same. This is
a fairly common problem and there are two basic solutions.

(1) Do as your colleague suggests and eliminate the subclasses. Then
one just has a data initialization problem for FooBar that will depend
on context. One would capture any problem space rules, such as Bar
having unique strategies, by simply instantiating relationships
correctly so that your FooBarStrategy flavors are related correctly to
FooBar instances whose value of MaxCount is consistent with the strategy.


My colleague suggested putting the sub-classes back as means of doing
the data initialisation. But I agree that it seems given the design,
until theres an epiphany, the factory could set the data values
relative to the type.

(2) Make MaxCount part of a compound identity for FooBar instances.
IOW, the object identity "key" is {FooBarID, MaxCount}. This is the
normal Data Modeling solution. This is tricky in an OO context because,
unlike Data Modeling, we usually do not have explicit attributes
identities for objects. However, that doesn't mean one can't think of
MaxCount as an element of identity that happens to be explicit. [The
fact that it is the same for all members of the subset is OK because it
is an identity attribute rather than a dependent attribute. (2NF says
the non-identity attributes have the be dependent on the /whole/ key
when it is compound and that will be unique.)]


hmm...Is this not thinking too much about the DB?

You indicate that you have delegated [FooBarStrategy] from [FooBar] and
that implies that [FooBarStrategy] contains everything that made the
[Bar] instances different than [Foo] instances. If so, then I think (1)
is the correct way to think about things. You then have to instantiate
the relationship between [FooBar] and [FooBarStrategy] based on the
value of FooBar.MaxCount to account for context rules.

This is true. Bar has a completely different "strategy" to choosing a
customer than Foo.


Since whoever creates the [FooBar] object will have to know whether to
use 100 or UNLIMITED to initialize the object and the relationship
depends upon that same decision, that suggests you probably want a
factory object to encapsulate that by doing both at the same time. That
is, the factory object understands the context rules and does the
initialization and relationship instantiation in a single method scope.


Ok. Makes sense.

[BTW, (2) can work if [FooBarStrategy] doesn't capture all of the
differences. The relationship is still with [FooBar] but one would
still use a factory to instantiate both it and the FooBar object. That
is, when FooBar is instantiated you have to know which subclass it will
be and that will determine how the relationship to [FooBarStrategy] is
instantiated, regardless of the actual value of MaxCount. IOW, the
object and relationship instantiation are different activities but they
depend upon the same context semantics.]


As far as I can tell,the differences are captured in the strategies, so
it looks like 1 is the option. Thanks.


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

H. S. Lahman
hsl@xxxxxxxxxxxxxxxxx
Pathfinder Solutions -- Put MDA to Work
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
(888)OOA-PATH

.



Relevant Pages

  • Re: Insert with response
    ... FooBar, there's no way and no need to put them in synch. ... column in the foo table to 250 calumns in the bar table. ... set statistics time off ...
    (microsoft.public.sqlserver.programming)
  • Re: Factory or Inheritance for Initialisation?
    ... Class Bar doesnt need the MaxCount, so it must set the base ... Problem is MaxCount needs to be set for the two types Foo Bar. ... application initialization time, I need two FooBar classes setting up, ...
    (comp.object)
  • Re: Factory or Inheritance for Initialisation?
    ... Class Bar doesnt need the MaxCount, so it must set the base ... Problem is MaxCount needs to be set for the two types Foo Bar. ... application initialization time, I need two FooBar classes setting up, ... A customer is selected and asked to do something, ...
    (comp.object)
  • Re: Factory or Inheritance for Initialisation?
    ... Originally the inheritance tree used template method to define the ... As far as FooBar is concerned, Foo and Bar have the same ...
    (comp.object)
  • Re: Factory or Inheritance for Initialisation?
    ... Class Bar doesnt need the MaxCount, so it must set the base ... In the case of Foo, ... application initialization time, I need two FooBar classes setting up, ...
    (comp.object)