Board index » delphi » Polymorphism: just another big word?

Polymorphism: just another big word?


2006-01-07 05:03:09 PM
delphi16
I've written a system (in Delphi of course) which has the ability to
dynamically load packages.
The packages are structured in such a way that they allow not only
adding functionality to the system, but they also allow changing the
functionality of the system.
One aspect of changing functionality shows up in the object factories.
An object factory might be asked to construct a TShape descendant based
on information on a database.
The base system might have a factory which knows how to construct a
TCircle, a TSquare and a TTriangle.
By loading in a new package, the factory can be overridden so that if
the database asks for a dodecahedron, that can be constructed as well.
Without the new package, a specification for a dodecahedron in the
database will give a runtime-error: exception "I don't know how to make
this" or something more informative.
So far so good.
The specific business problem that I have been given is that some
stations should refuse to construct TSquares, and others should refuse
to construct TCircles.
That sounds easy. Build a NoCircles package which overrides the factory
and raises an exception if the spec is for a TCircle. Also, build a
NoSquares package which does much the same thing, but refuses to create
a TSquare. The factory can just throw an exception which will end up
with an error message along the lines of "Please try this at the Circle
counter. Circles are not for sale here, they're way too round."
A station that should not allow TSquares just needs to load the
NoSquares package, and so-on. No code changes are required to the base
system, everything is binary compatible, and for ease of testing a
system can be switched from allowing TSquares to not allowing TSquares
and back again just by loading and unloading the NoSquares package in
much the same way that you can load and unload component packages in
Delphi itself.
Obviously I am just using shapes as an example to protect the guilty,
and the real requirements are slightly more complex but do not change
the concept at all.
The problem happens in that the system used to load data into the
database is NOT written in Delphi, is not OO, and is controlled by some
very highly paid experts.
These experts tell me that they do NOT want to see the program reacting
to data in different ways, and have proposed instead a set of inclusion
lists which will need to be sent to each station saying which TShapes a
station is ALLOWED to construct. In the real-life system, this means
hundreds of thousands of records being sent to each database just to say
that TTriangles are fine!
The business requirement is that certain stations DO react differently
to certain data.
This is the first time that I have been able to use polymorphism at an
APPLICATION level (i.e. the app itself changes its behaviour) with such
enormous benefit, and I am surprised at a) the experts don't seem to get
it and b) the effort they're prepared to expend to ensure that it can't
work 'coz their system can not do it.
The inclusion list system also doesn't work in the case of a
dodecahedron, 'coz just sticking it into a database list doesn't make
the factory become suddenly capable of constructing one. That would
require a new factory package, but that is about all that is required.
My little loadable packages are tiny: about 4K apiece, and the installer
puts the correct ones into the load list. Everything else is Delphi
magic.
I'm not sure whether or not I am going to win this argument because as we
all know, the customer is always right.
If you can think of any good ways of talking the customer out of using
inclusion lists instead of the polymorphic app, I'd be delighted to
hear them.
Scout
 
 

Re:Polymorphism: just another big word?

Quote
If you can think of any good ways of talking the customer out of using
inclusion lists instead of the polymorphic app
I must say that at first glance I am not sure I would be in favour of your approach
either. I'd not tend to use inheritance to deal with what sound like
configuration issues. I'd want a more transparent and easily configurable
solution. An inclusion (or possibly exclusion) list sounds rather more
straightforward to me. There are ways and ways of doing that too, of course.
Maybe you might want to chat about this over in oodesign
Cheers,
Jim Cooper
__________________________________________
Jim Cooper XXXX@XXXXX.COM
Skype : jim.cooper
Tabdee Ltd www.tabdee.ltd.uk
TurboSync - Connecting Delphi to your Palm
__________________________________________
 

Re:Polymorphism: just another big word?

Jim Cooper writes:
Quote
I must say that at first glance I am not sure I would be in favour of your
approach either.
I tend to agree with your assessment. It seems like a configuration
solution and would be much simpler to implement in that manner, IMHO.
--
David Farrell-Garcia
Whidbey Island Software LLC
Posted with XanaNews 1.17.6.6
 

Re:Polymorphism: just another big word?

Scout writes:
Quote

A station that should not allow TSquares just needs to load the
NoSquares package, and so-on. No code changes are required to the
base system, everything is binary compatible, and for ease of testing
a system can be switched from allowing TSquares to not allowing
TSquares and back again just by loading and unloading the NoSquares
package in much the same way that you can load and unload component
packages in Delphi itself.
[...]
These experts tell me that they do NOT want to see the program
reacting to data in different ways, and have proposed instead a set
of inclusion lists which will need to be sent to each station saying
which TShapes a station is ALLOWED to construct. In the real-life
system, this means hundreds of thousands of records being sent to
each database just to say that TTriangles are fine!
This may not be what you want to hear, but I think I have to agree with the
"experts" in this case. Think about it - how many different packages to you
propose to have? One that has everything, one without squares, one without
circles, one without triangles AND squares, one with just Octagons, one with
... How can this possibly be more efficient and manageable than some rows in
a database? I'd deploy a single package with *all* the currently known
shapes. When new shapes need to be deployed, that can be done by dropping in
*additional* packages that the application can detect and load (rather than
overwriting the base package).
I don't get the "hundreds of thousands of records being sent to each
database just to say that TTriangles are fine!" - doesn't it take just one
record to say this station can make triangles, and likewise one record for
every other item? You don't tell us what the real objects are, but if I were
to guess, for the sake of argument, products for sale in a retail store,
then there are two basic strategies - on start up go and get all product
info allowed for that station, or let the station query on demand to see if
it can process a particular product. I'd favour the latter because that
way, part way through the day, I could decide to allow Station A to process
product X and Station A will get that the very next time someone brings
product X there.
--
Wayne Niddery - Logic Fundamentals, Inc. (www.logicfundamentals.com)
RADBooks: www.logicfundamentals.com/RADBooks.html
"The purpose of morality is to teach you, not to suffer and die, but to
enjoy yourself and live." - Ayn Rand
 

Re:Polymorphism: just another big word?

In article <43bff6d6$XXXX@XXXXX.COM>, XXXX@XXXXX.COM
says...
Quote

This may not be what you want to hear, but I think I have to agree with the
"experts" in this case. Think about it - how many different packages to you
propose to have? One that has everything, one without squares, one without
circles, one without triangles AND squares, one with just Octagons, one with
... How can this possibly be more efficient and manageable than some rows in
a database? I'd deploy a single package with *all* the currently known
shapes. When new shapes need to be deployed, that can be done by dropping in
*additional* packages that the application can detect and load (rather than
overwriting the base package).

Fortunately the business rules are quite succinct, so there are only
ever going to be three types of package
Quote
I don't get the "hundreds of thousands of records being sent to each
database just to say that TTriangles are fine!" - doesn't it take just one
record to say this station can make triangles, and likewise one record for
every other item? You don't tell us what the real objects are, but if I were
to guess, for the sake of argument, products for sale in a retail store,
then there are two basic strategies - on start up go and get all product
info allowed for that station, or let the station query on demand to see if
it can process a particular product. I'd favour the latter because that
way, part way through the day, I could decide to allow Station A to process
product X and Station A will get that the very next time someone brings
product X there.

Unfortunately, neither I nor the experts are allowed to change anything
in the interface between the 2 systems, so we have to control inclusion
or exclusion via an attributes table that already exists and has an
interface. What I was trying to avoid was having to put records into
the attributes table for every other record in, lets say, the products
table.
As an example, the TCircles could be tyres (or tires). Tyres can only
be sold at the tyre bay station, and the tyre bay station can only sell
tyres. The intention is that if you scan a pair of socks at the tyre
bay station, you are asked to take them elsewhere. If you scan the
label from a tyre anywhere other than the tyre bay station, you get
asked to take it to the tyre bay.
All this should require is a lookup on the attribute table to see if
this thing is a tyre. The exclusion or inclusion logic is different for
the same record depending on whether or not the station is in the tyre
bay.
If only 1% of the products are tyres, then only a few attribute records
need to be sent, one for each tyre type.
Another type of product might be one which needs to be weighed, and only
a few stations have weigh-scales. Once again, if the weighable
attribute is set on only those products, the amount of data that needs
to be transferred is minimized.
Effectively this means that since the TTriangles are not weighable, not
tyres, and make up 95% of the 250 odd thousand item list, sticking the
Tyre or Weighable attribute into the table for each of those other 5%
makes for much less data needing to be transferred.
Since the Tyre attribute is both an inclusion and an exclusion attribute
(depending on where you are) it becomes difficult to deal with in a
data-only situation.
It IS a configuration thing. If you want to deal with tyres, then load
the Tyres package a.k.a. TCircles only.
The factories in the packages don't overwrite the factory in the base
package, they override it. They still have the option of calling the
inherited factory method, and do so in most cases, but can behave
differently depending on what they find in the attributes table.
Since each station can have different factory packages loaded, ALL
stations can share the same database and still get the desired
inclusion/exclusion logic.
Thanks Jim, David and Wayne for your comments. I am going to have to
think about this some more.
 

Re:Polymorphism: just another big word?

Scout writes:
Quote

Effectively this means that since the TTriangles are not weighable,
not tyres, and make up 95% of the 250 odd thousand item list,
sticking the Tyre or Weighable attribute into the table for each of
those other 5% makes for much less data needing to be transferred.

Since the Tyre attribute is both an inclusion and an exclusion
attribute (depending on where you are) it becomes difficult to deal
with in a data-only situation.
A single attribute can not be interpreted depending where you are or the data
is not readable *in the database*. There must also be another attribute in
the database representing the stations saying whether they are to include or
exclude based on the attribute, or else there needs to be *both* include and
exclude attributes that can be identified as such.
Quote
Since each station can have different factory packages loaded, ALL
stations can share the same database and still get the desired
inclusion/exclusion logic.
You say thre are only a few combinations to deal with, but you *know* this
is going to change over time meaning you will need to keep updating/adding
packages to every station - *that is a deployment nightmare*. No matter how
many database records there may need to be to manage this, it is still only
data taking up a little disk space and, assuming it is a decent database,
performance should not be a problem even if there are millions of rows.
Let's look at data requirements a little more. I am assuming there is an SQL
database involved here as this makes the logic pretty easy and ensuring you
only need to keep the minimum possible records, i.e. in most cases there'll
be neither inclusions or exclusions for an item meaning all stations can
deal with it.
In the case where one or a few stations *cannot* deal with a few items, you
would use exclusion flags, where a station can only deal with one or a few
items, like the tire station, you would use inclusion. What's key here is
that a single station cannot have both inclusion and exclusion flags, that
cannot make any sense. Either you are going to tell a station what it can
deal with or what it cannot deal with, not both.
The logic each station needs to perform for any item brought to it is:
- Are there any flags for this station and this item?
- If so (it will be one or the other), act according to the flag found
- If not, then are there any inclusion flags *at all* for this item
- If so, then I cannot deal with it (it is exclusive to some other
stations(s)).
- If not then I can
In SQL, this is a maximum of two very fast statements and, if this is too
much then they can be hidden in a simple stored procedure the station can
call.
So in the case of the tire station, it will see an inclusion flag for tires.
All other stations will not find an inclusion flag for themselves but will
see that an inclusion exists and so will reject dealing with it. They do not
need exclusion flags for tires. In all cases you can maintain minimal flags
for an item and there is no need for the station to load 1000s of records at
the start to figure this out.
--
Wayne Niddery - Logic Fundamentals, Inc. (www.logicfundamentals.com)
RADBooks: www.logicfundamentals.com/RADBooks.html
"Bandwagons are like streetcars, there'll be another along in a few
minutes."
 

Re:Polymorphism: just another big word?

Quote
All other stations will not find an inclusion flag for themselves but will
see that an inclusion exists and so will reject dealing with it.
I would have thought it a safe assumption that the product is (at least supposed
to be) processable somewhere :-) You may be able to defer that extra check
(seeing if an inclusion exists) to an admin task.
Cheers,
Jim Cooper
__________________________________________
Jim Cooper XXXX@XXXXX.COM
Skype : jim.cooper
Tabdee Ltd www.tabdee.ltd.uk
TurboSync - Connecting Delphi to your Palm
__________________________________________
 

Re:Polymorphism: just another big word?

Scott:
Interesting problem. I think it is a problem left solved by the
architect of the system, not the programmer.
So, ask the architect how it is supposed to be handled, then code
according to that spec.
One last thing. I am glad to see the post. It was good fun.
 

Re:Polymorphism: just another big word?

In article <43c0a881$XXXX@XXXXX.COM>, XXXX@XXXXX.COM
says...
Quote
A single attribute can not be interpreted depending where you are or the data
is not readable *in the database*. There must also be another attribute in
the database representing the stations saying whether they are to include or
exclude based on the attribute, or else there needs to be *both* include and
exclude attributes that can be identified as such.

I agree that there needs to be an attribute representing the station
saying whether or not it can deal with tyres, all I am saying is that
attribute doesn't need to be in the database, It can be in the registry
on that station which says whether or not to load the tyres factory
package.
Quote
>Since each station can have different factory packages loaded, ALL
>stations can share the same database and still get the desired
>inclusion/exclusion logic.

You say thre are only a few combinations to deal with, but you *know* this
is going to change over time meaning you will need to keep updating/adding
packages to every station - *that is a deployment nightmare*. No matter how
many database records there may need to be to manage this, it is still only
data taking up a little disk space and, assuming it is a decent database,
performance should not be a problem even if there are millions of rows.
I also agree that the situation will change over time, but since all
stations get all packages and can update themselves automatically, I
don't see this as a deployment nightmare. A load/don't load this
package setting ends up being like allowing users the option of loading
Together support in the BDS IDE.
I can see how your data-only approach works, but it doesn't take into
account the fact that some new type of thing that needs to be
constructed might need extra logic such as capturing date-of-birth for
age restricted stuff. The package approach deals with this simply.
Thanks for your comments Wayne. I almost feel I should send you a cheque
for consulting services. (almost).
 

Re:Polymorphism: just another big word?

Scout writes:
Quote
It can be in the
registry on that station which says whether or not to load the tyres
factory package.
Again why *also* store data in the registry that can just as easily be
centralized in the database? Much easier to administer stations from one
spot than having to physically visit each one to mess with registry settings
(yes, I know, it can be automated too, but that is yet more work and
scatters the data and is more error-prone).
Quote
I can see how your data-only approach works, but it doesn't take into
account the fact that some new type of thing that needs to be
constructed might need extra logic such as capturing date-of-birth for
age restricted stuff. The package approach deals with this simply.
Of course not, you will still have to update your packages to add such
functionality to the appropriate classes (plus new classes as required). But
you will only need to deploy the updated/added packages without worrying
about what packages go on what stations or writing complex deployment
software to figure out and automate same.
Quote
Thanks for your comments Wayne. I almost feel I should send you a
cheque for consulting services. (almost).
I was almost going to ask your for your billing address! <g>
--
Wayne Niddery - Logic Fundamentals, Inc. (www.logicfundamentals.com)
RADBooks: www.logicfundamentals.com/RADBooks.html
"Reality is that which, when you stop believing in it, doesn't go
away." - Philip K.{*word*106}
 

Re:Polymorphism: just another big word?

In article <43c1e78f$XXXX@XXXXX.COM>, XXXX@XXXXX.COM
says...
Quote
Scout writes:
>It can be in the
>registry on that station which says whether or not to load the tyres
>factory package.

Again why *also* store data in the registry that can just as easily be
centralized in the database? Much easier to administer stations from one
spot than having to physically visit each one to mess with registry settings
(yes, I know, it can be automated too, but that is yet more work and
scatters the data and is more error-prone).
Very good question. Why not store it in the database and administer it
centrally?
Simple answer: the database knows which stations can do what, but it is
much easier for support people to ask a user to put a check in the
checkbox that says "Load the Tyres package" (or not) than to try and
replicate a flag from some master database.
Quote

>I can see how your data-only approach works, but it doesn't take into
>account the fact that some new type of thing that needs to be
>constructed might need extra logic such as capturing date-of-birth for
>age restricted stuff. The package approach deals with this simply.

Of course not, you will still have to update your packages to add such
functionality to the appropriate classes (plus new classes as required). But
you will only need to deploy the updated/added packages without worrying
about what packages go on what stations or writing complex deployment
software to figure out and automate same.

As I said earlier, ALL stations receive ALL packages. The only trick is
figuring out which packages a station should load, and that is not very
difficult.
Quote
>Thanks for your comments Wayne. I almost feel I should send you a
>cheque for consulting services. (almost).

I was almost going to ask your for your billing address! <g>

Once again, thanks for your input. With your help, I have re-thought
most of the software design for this problem and I think we have a
working system.
Someone mentioned architects. I wish I was making this up, but I am not.
This customer sent their software architect to our office when we needed
to build a new system. He parked in a tow-away area. His car was towed
away. He actually burst into tears when he discovered that his car was
gone. I have interesting customers.
Scout
 

Re:Polymorphism: just another big word?

Quote
>Again why *also* store data in the registry that can just as easily be
>centralized in the database? Much easier to administer stations from one
>spot than having to physically visit each one to mess with registry
settings
>(yes, I know, it can be automated too, but that is yet more work and
>scatters the data and is more error-prone).
Very good question. Why not store it in the database and administer it
centrally?

Simple answer: the database knows which stations can do what, but it is
much easier for support people to ask a user to put a check in the
checkbox that says "Load the Tyres package" (or not) than to try and
replicate a flag from some master database.
Couldn't you have a little config app (either a web app or a client app to
the database) that the administrator uses to configure these settings? Then
the administrator could make sure the right things are enabled for each
station.
HTH
Lauchlan M
 

Re:Polymorphism: just another big word?

"Scout" <XXXX@XXXXX.COM>writes
Quote
I've written a system (in Delphi of course) which has the ability to
dynamically load packages.

The packages are structured in such a way that they allow not only
adding functionality to the system, but they also allow changing the
functionality of the system.

One aspect of changing functionality shows up in the object factories.

An object factory might be asked to construct a TShape descendant based
on information on a database.

The base system might have a factory which knows how to construct a
TCircle, a TSquare and a TTriangle.

By loading in a new package, the factory can be overridden so that if
the database asks for a dodecahedron, that can be constructed as well.

After all the discussion of how the system know which packages to load
has subsided, the good news is that the polymorphism aspect of the
original solution still chugs happily along and works as designed.
--
Brad.
 

Re:Polymorphism: just another big word?

Quote
Someone mentioned architects. I wish I was making this up, but I am not.
This customer sent their software architect to our office when we needed
to build a new system. He parked in a tow-away area. His car was towed
away. He actually burst into tears when he discovered that his car was
gone.
Well, why not? Having your car towed is much worse than spilling your milk.
Mark J. Wallin
 

Re:Polymorphism: just another big word?

Quote
Scout writes:
This customer sent their software architect to our office when we needed
to build a new system. He parked in a tow-away area. His car was towed
away. He actually burst into tears when he discovered that his car was
gone. I have interesting customers.

When you say "This customer..." do you mean the same customer this issue
relates to?
If so, just curious, what did the architect say to do about this problem?