Object Design Question

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Here's what I want to do... sorry for the lengthy description ;-)

I have an inventory tracking system with items that I track stock levels on.
Some items are counted with decimal precision (double) and others are counted
using integers; the database record has a flag that says what kind of item a
particular record is (double or integer). I've created an abstract class
called ItemBase and I implement a concrete class (Item) that inherits from
ItemBase. ItemBase has abstract methods that allow me to get/set the quantity
in stock, or manage collections of items; those methods are implemented in
the concrete class Item. The Item class would be a central part of the
inventory tracking system and I don't want programmers to constantly write
code to check the precision of the number being passed into the methods, I
want to make the counting methods type safe based on the flag in the item's
database record.

Here's an example. When an Item ID is entered into some UI, I want the
client code to be able instantiate an Item object via an Item Factory that
reads the record, figures out what kind of item to build (integer or double)
and hand it back to the client without the client knowing or caring whether
it gets back an integer version or a double version of the Item class. Sounds
easy enough if you're thinking of using generics, but generics requires you
know the type you want when you declare the client instance. Likewise with a
decorator pattern, you have to know in advance what type to create ('cause
even if you decorate a standard Item class with an integer decorator class,
you still have to create your object as the integer decorator in order to
make it's methods visible). I also investigated using Reflection.Emit, but
that doesn't seem like the proper solution either (particularly since it
would make coding more difficult in the long run and clients couldn't code
against an API).

What I want is a completely ignorant client, who gets a type safe Item
object, with integer methods or with double methods, based on what the Item
Factory discovers from the database about the item passed in during object
creation. Anyone have any ideas?

Thanks!
Don
(e-mail address removed)
 
Well...

It seems to me that your programmers will need to know the type either
way, and there's no getting around it. If you somehow created your
concrete class with integer methods or double methods, your programmer
will still need to know the difference when *using* those methods,
otherwise he might call an integer method with a double value, which
doesn't have an implicit cast. If you can somehow abstract the methods
out such that they don't require or return integer or double values,
you could just use an interface and have a factory method that returns
the concrete object cast to the interface. If not, your client needs to
know the difference.

Also, I have some problems with your database architecture. Why, why,
why, why are you tracking quantity with a double-precision value?
Quantity should always be integer value.
 
Thanks for your input Randolpho

On the use of double precision types for inventory counts, there are many
industries that use materials for manufacturing processes that are "measured"
rather than "counted". For example, one company I worked for atomized
precious metals, like gold, for use in soldering paste. The composition of
the end product (solder paste) is a very spcific and that company, rather
than reduce the unit of measure to something they could use as integers
preferred to use decimal inventory quantity. This got them 2 things: they
were able to match their product formulas to the bill of material eaasier and
they were to track the value of their inventory against the daily precious
metal prices, which were in troy ounces. Hope that helps.
 
Ok, I suppose that makes sense. I had constructed in my head all sorts
of scenarios where a short-sighted database developer had concocted
some ludicrous means of measuring an item, where the first decimal
place meant one thing, and the second decimal place meant another
thing, and so on.

I suppose I've just been reading too much of The Daily WTF these days.
:)
 
That would be doable if you totally isolate the actual quantity value
from the client, and for an example only expose it as a readily
formatted string.
 
Can you elaborate on this a bit more please?

Göran Andersson said:
That would be doable if you totally isolate the actual quantity value
from the client, and for an example only expose it as a readily
formatted string.
 
An example, perhaps:

public class Item {

private Item() {} // nope, can't be created that way

public abstract string GetQuantity();

public static Item MakeItem(int quantity) {
return new IntegerItem(quantity);
}

public static Item MakeItem(double quantity) {
return new DouleItem(quantity);
}

}

public class IntegerItem : Item {

private int quantity;

internal IntegerItem(int quantity) {
this.quantity = quantity;
}

public override string GetQuantity() {
return this.quantity.ToString();
}

}

public class DoubleItem : Item {

private double quantity;

internal DoubleItem(double quantity) {
this.quantity = quantity;
}

public override string GetQuantity() {
return this.quantity.ToString();
}

}

You create items:

Item item1 = Item.MakeItem(1.0);
Item item2 = Item.MakeItem(1);

Now you can only use the GetQuantity method on those items, and you
can't tell what data type they contain unless you check for the actual
type of the items, and even then you can't access the internal value.
 
Thank you very much for your example! I think I can use this... I'll try it
tonight...
 
So... the solution is to abstract both the integer and the float into a
string. Hmm...

What happens when somebody wants to set the quantity? They'd have to do
something like MyItem.SetQuantity("1.0"), and SetQuantity would parse
the string as either a float or an integer, depending on the underlying
type. Except... what happens if you call MyItem.SetQuanty("hello
world!")?

Yep.. definitely *not* type-safe, which was an original requirement.

Bottom line -- the programmer using the object needs to know the
difference between an integer quantity and a float quantity.
 
No, I showed how one can isolate the value inside the object, and only
expose methods that uses the value. If you want to change the value it
doesn't make sense to hide the type of the value.
 
From the original post:
ItemBase has abstract methods that allow me to get/set the quantity
in stock, or manage collections of items; those methods are implemented in
the concrete class Item.

The get/set quantity portion implies he wants to modify the value. To
do that in a typesafe way, he cannot hide the value, as the programmer
using the object will need to know what type of value the item uses in
order to use it properly. Hiding it in a string, or even as an object,
is not typesafe.

However, it occurs to me that it's possible to build this system such
that even though the type of quantity for a particular item is not
known at compile time, it is still obtainable during runtime. That
would allow a programmer to use either an integer value or a float
value depending on the situation.

The simplest way would be to have a base class ItemBase that implements
two get/setters -- ValueInt and ValueFloat, and an ItemType property
that indicated whether the Item is an Int or a Float through an enum.
The concrete classes, ItemInt and ItemFloat, would implement one
getter/setter and throw on the other getter/setter. The programmer
could then simply check the ItemType before using the value, and use an
integer or float type as appropriate.

Wow, that pretty much mirrors the original database.
 
On Wed, 3 May 2006 04:58:02 -0700, Don Miller <Don
Here's what I want to do... sorry for the lengthy description ;-)
The quantity can be an int or a double but that value is means nothing
without a unit of measure. Rules based upon UOM can be used to
determine the validity of a quantity. A single item can have multiple
UOMs if the UOM is included as part of a key. The inventory for an
item could be reported as two pallets, three cases and 17 individual
units. With the UOMs known calculating the total number of individual
units won't be complicated. The physical conversion from pallet to
cases or case to items can easily be reflected in the database as
well.

regards
A.G.
 
Excellent point. I do have uom conversions in the design but hadn't thought
of using them in that way (i.e. for determining inventory quantity). After
much consideration, I think what I'm going to do is declare the quantity as
double throughout the app, then when it's determined the item should use
integers rather than doubles, I'll set some internal precision validator and
have the numbers validated against that (should have thought of that LAST
week!).

Thanks all for your comments--I hope I can return the favor some day...
 
That's about as close as I'm going to get I'm afraid. In my strugle to solve
the small problem I kinda lost sight of the bigger problem: what type are the
programmers going to set their code to use?!?!?

It's been a very enlightening discussion and thank you both for your input.
 
Back
Top