Board index » delphi » Customer/Order relationship

Customer/Order relationship


2003-12-11 09:51:21 PM
delphi279
Hello Peers,
TOrder should have a "ClientID" property and
TCustomer would be declared as follows:
Type
TCustomer = class( TClient )
public
property Orders[ Index : Integer ] : TOrder;
end;
Now the problem is that I should probably declare Client as an
order property, so that I can access the client of the order... or not?
Should I keep it as a function , like this:
function TOrder.Client( Cli_ID ) : TClient;
begin
Result := TClient.Create;
Result.LoadFromID( Cli_ID );
end;
or what? Any clues?
TIA,
Andrew
 
 

Re:Customer/Order relationship

Andrea Raimondi writes:
| TOrder should have a "ClientID" property and
| TCustomer would be declared as follows:
|
| Type
|
| TCustomer = class( TClient )
| public
| property Orders[ Index : Integer ] : TOrder;
| end;
|
| Now the problem is that I should probably declare Client as an
| order property, so that I can access the client of the order... or
| not? Should I keep it as a function , like this:
|
| function TOrder.Client( Cli_ID ) : TClient;
| begin
| Result := TClient.Create;
| Result.LoadFromID( Cli_ID );
| end;
|
| or what? Any clues?
You have your relationship reversed here.
The Order should have a reference to the Client but you should not need to
surface anything to do with the ID, that is something internal to an object.
Your OPF should look after IDs and create objects to match those IDs as
required. The mapping in the OPF will allow it to query the database and
retrieve the Client object without the knowledge of the Order class.
I would also not recommend adding properties like Orders to a Customer class
as it tends to limit reusability; you may need a Customer class that does
not have an Order List, but you will be stuck with unnecessary
functionality.
Making the Orders property indexed also implies that you have to know what
position the Order is in the List; not something that is very common as a
user search criterion.
People tend to look for Orders based on Date, Client, Delivery Address, but
they would not need to ask the Customer for the Order, instead they would
look it up in the Order Book.
Would you also have a Date class so that you could ask it for a list of
Orders?
Try having an Order Book class that has a GetOrders method that takes a
Customer or Date or PostCode parameter.
TCustomer = class(TClient)
...
end;
TOrder = class
...
public
property Client: TClient
read GetClient
write SetClient
end;
TOrderBook = class
...
public
function GetOrders(Client: TClient): TOrderList; overload;
function GetOrders(Date: TDateTime): TOrderList; overload;
...
end;
Just some food for thought :-)
Joanna
Consultant Software Engineer
TeamBUG support for UK-BUG
TeamMM support for ModelMaker
 

Re:Customer/Order relationship

Joanna Carter (TeamB) writes:
| TOrderBook = class
| ...
| public
| function GetOrders(Client: TClient): TOrderList; overload;
| function GetOrders(Date: TDateTime): TOrderList; overload;
| ...
| end;
also:
function GetOrder(OrderNum: string): TOrder;
where OrderNum is a string to cater for non numerics.
Joanna
Consultant Software Engineer
TeamBUG support for UK-BUG
TeamMM support for ModelMaker
 

Re:Customer/Order relationship

"Andrea Raimondi" wrote
Quote

TCustomer = class( TClient )
public
property Orders[ Index : Integer ] : TOrder;
end;
One problem with this that it really turns the customer and collection into
historical items--do you really want the customer loading every order ever
placed just to look at what's current? Think out the usage pattern here--you
don't want the system bogging down as completed orders accumulate, nor do
you want to end up with
TCustomer = class( TClient )
public
property Orders[ Index : Integer ] : TOrder;
property OpenOrders[ Index : Integer ] : TOrder;
property ClosedOrders[ Index : Integer ] : TOrder;
property OverdueOrders[ Index : Integer ] : TOrder;
property OrdersPendingCreditApproval[ Index : Integer ] : TOrder;
{etc}
end;
Might be better not to give the client an order collection at all, so as not
to burden it with all these issues:
ClientsOrders := TOrderCollection.Create;
ClientsOrders.LoadCollection('LoadCurrentForCust', [Cust.ID]);
This makes your load process a lot more flexible and decouples orders and
customers. The fact that a customer is a collection membership criteria
(that is, a navigation point) for orders in the database does not mean that
it has to or should be an orders collection owner. (Tip of the conceptual
hat to Joanna).
Quote
I should probably declare Client as an order property, so that
I can access the client of the order... or not?
All above was just abstract OO-thinking--now a bit on the specific domain
model. Rather than
Order.Client
I'd suggest
Order.Acount
Linking orders directly to customers is a matter of how complete/complex
your object model is. For a business with repeat customers and standing
customer relationships, an order would normally be related to an account,
which is in turn related to one or more responsible parties--admin contact,
purchasing agent, payer, etc. Parties are an abstract concept (or
interface), since a party can be either a person or organization (I can
establish an account for John Doe, or an account for Fotheringay Accoustic
Supply, Inc.).
This allows you to do things like have orders from the same client ship to
different addresses, have a single payee for multiple accounts, or have a
customer place orders for multiple accounts.
bobD
 

Re:Customer/Order relationship

One possible solution ...
You have Customers,
Customers have an ID
You have Orders,
Orders have an ID
You have OrderHistory,
OrderHistory has a CustomerID, and an OrderID
"Andrea Raimondi" <XXXX@XXXXX.COM>writes news:XXXX@XXXXX.COM...
Quote
Hello Peers,

TOrder should have a "ClientID" property and
TCustomer would be declared as follows:

Type

TCustomer = class( TClient )
public
property Orders[ Index : Integer ] : TOrder;
end;

Now the problem is that I should probably declare Client as an
order property, so that I can access the client of the order... or not?
Should I keep it as a function , like this:

function TOrder.Client( Cli_ID ) : TClient;
begin
Result := TClient.Create;
Result.LoadFromID( Cli_ID );
end;

or what? Any clues?

TIA,

Andrew


 

Re:Customer/Order relationship

Ray Andrews writes:
| One possible solution ...
This sounds very much like a database style resolution of a many to many
relationship by transforming it to a one-many-one with a link table.
OO analysis would take a slightly different view for several reasons:
IDs are not something that are usually surfaced in the business classes,
they are a necessary evil for use with relational databases. OO Environments
like Smalltalk simply persist objects without even having to explicitly save
them, they do do need IDs; we use them inside the OPF layer to represent the
memory address of an object so that we can store the object in a database.
The real relationship in the database may use IDs in a fashion similar to
your suggestion, but we need to do things slightly differently in the object
model.
Customer has no reference to any Orders.
Order has a reference to a Customer.
Order History is not a persistable class and there need be no table in the
database for it. It provides methods for querying the list of Orders, given
certain criteria.
It can query the OPF and ask for a list of Orders for a given Customer; this
will be translated into a 'select * from Orders where CustomerID = 1234',
but the Order History class has no cognisance of the ID, the OPF figures
that out from the Customer object passed into the Criteria used for the
query.
If that raises more questions, Ray, feel free to ask away.
Joanna
Consultant Software Engineer
TeamBUG support for UK-BUG
TeamMM support for ModelMaker
 

Re:Customer/Order relationship

Joanna Carter (TeamB) writes:
oops, typing without thinking :-)
| having to explicitly save them, they do do need IDs;
...should read...
having to explicitly save them, they do not need IDs;
Joanna
Consultant Software Engineer
TeamBUG support for UK-BUG
TeamMM support for ModelMaker
 

Re:Customer/Order relationship

Joanna Carter (TeamB) writes:
Quote
oops, typing without thinking :-)

| having to explicitly save them, they do do need IDs;

...should read...

having to explicitly save them, they do not need IDs;
Err... I am blind or there is no difference between them? ;)
Solerman
 

Re:Customer/Order relationship

"Joanna Carter (TeamB)" <XXXX@XXXXX.COM>writes
Quote
This sounds very much like a database style resolution of a many to many
relationship by transforming it to a one-many-one with a link table.
Well, there's a perfectly valid reason for that !
I forgot what newsgroup I was in :c)
--------
I did like your explanation of the modeling though.
 

Re:Customer/Order relationship

Solerman Kaplon writes:
| Err... I am blind or there is no difference between them? ;)
Let me lend you a magnifying glass :-)
they do do need IDs;
they do not need IDs;
Joanna
Consultant Software Engineer
TeamBUG support for UK-BUG
TeamMM support for ModelMaker
 

Re:Customer/Order relationship

Quote
Err... I am blind or there is no difference between them? ;)
LOL! I had to read it about 6 times to see the difference!
Eric
 

Re:Customer/Order relationship

Heh-Heh. Heh-Heh. You said do-do. ;-)
Jeff Eib
www.GarrettLiners.com
"Joanna Carter (TeamB)" <XXXX@XXXXX.COM>writes
Quote
Joanna Carter (TeamB) writes:


oops, typing without thinking :-)

| having to explicitly save them, they do do need IDs;

...should read...

having to explicitly save them, they do not need IDs;

Joanna

--
Joanna Carter (TeamB)

Consultant Software Engineer
TeamBUG support for UK-BUG
TeamMM support for ModelMaker


 

Re:Customer/Order relationship

"Joanna Carter (TeamB)" <XXXX@XXXXX.COM>writes
Quote
Ray Andrews writes:

| One possible solution ...

This sounds very much like a database style resolution of a many to many
relationship by transforming it to a one-many-one with a link table.
Joanna,
This sounds more like your classic one-to-many relationship. And Ray's
response is not how most DBadmin would handle this. How many companies have
orders with many customers? So your answer is also how the relationship
would be handled in the DB, i.e. the order table would have a link to the
customer, and the customer table would have no link to orders.
A better question would be...How would you handle a true many-to-many
relationship, such as the one between orders and products? Each order may
have from one to many products, and each product may be in multiple orders.
In the SQL world, this would be handled with the link tables you mentioned.
Up until your answer, I'd have thought that a link class would also be
needed for this kind of relationship.
Thanks in advance for your answer.
Jeff Eib
www.GarrettLiners.com
P.S. How is your book coming?
 

Re:Customer/Order relationship

Jeffrey Eib, Sr. writes:
| A better question would be...How would you handle a true many-to-many
| relationship, such as the one between orders and products? Each order
| may have from one to many products, and each product may be in
| multiple orders.
|
| In the SQL world, this would be handled with the link tables you
| mentioned. Up until your answer, I'd have thought that a link
| class would also be needed for this kind of relationship.
To get at a list of Products for an Order you need to iterate the Lines of
the Order and return a list of the Products referenced; this is not an
implicit relationship and the only way I could think of fitting in would be
to add a GetProducts(Order) method on an OrderBook class, but that doesn't
really fit there either
I think you would have a reporting class to satisfy this side of the
relationship.
As to getting a list of Orders for a given Product, possibly an OrderHistory
class would have a GetOrders(Product) method.
Once again, I am inclined to say that this is a reporting requirement rather
than an implicit property of either side of the relationship.
<pontificating mode>
Maybe that is the key to what I have been trying to get at when I have
criticised inappropriate properties in classes...
Too often we seem to try to shoehorn properties into classes that are not
really part of a class's behaviour but are, instead, a reporting
requirement.
Think about it... How many Report classes appear in OO analysis? I would
venture to guess, not enough. My feelings are that we have bemoaned the lack
of a decent querying mechanism for OO systems and altered our design
strategy to provide reports as part of our business object classes.
I am not saying that BOs are simply data containers; they should have
validation, relationships, integrity enforcement and internal logic. It's
just that I feel that we have often forgotten that there are Actor Classes
in real world systems that are independent of any classes that may be
persistable; a Report is a prime example of a class that is all logic and no
persistence.
Maybe, because we too readily use terms like Order List rather than Order
Book, and Invoice List instead of Sales Ledger, that we tend to forget the
external actors that used to manage the pieces of paper before computers
were invented.
If I wanted a report on how many widgets we have sold to Bloggs and Co, then
I would have asked the Order Dept to produce that list; I wouldn't care how
they went about producing that list, as long as the resulting list was
complete and correct.
This is encapsulation, which is what OO is meant to be about. I have long
been a proponent of 'Manager' classes and it is discussions like this one
that reinforce my views that there are many classes that never get designed
because we assign inappropriate behaviour to, what would be in the real
world, inanimate objects.
Procedural programming would separate out data from processes, so you would
end up with global data and standalone procedures. OO was meant to bring
those two together into an encapsulated relationship. We don't have a
problem sorting out classes for data; those end up being 'one class for each
table'. What has caused us too many problems has been where to put the
logic; and our attitude seems to have been 'we have classes for data, let's
put all the logic in those'.
RDBMSs gave us stored procedures which were related to but separate from the
data they manipulated. Sure, some of that logic should have been put into
the tables (if that were possible) but there would still be many stored
procedures that did not belong in any one particular table.
Can a sheet of paper with 'Invoice' on the top really get up off the desk
and construct a report of all the items whose stock codes are held in it?
No, this used to take an Actor (human being). It is these Actor classes that
we need to consider as well as the 'things' that make up the system.
The best OO systems I have seen are those which emulate the real world
closely, without abstracting into a computerese paradigm caused by our lack
of familiarity with pre-IT working practices.
</pontificating mode>
Joanna
Consultant Software Engineer
TeamBUG support for UK-BUG
TeamMM support for ModelMaker
 

Re:Customer/Order relationship

ahhhhhhhh!! 8-)
Joanna Carter (TeamB) writes:
Quote
Let me lend you a magnifying glass :-)

they do do need IDs;

they do not need IDs;

Joanna

--
Joanna Carter (TeamB)

Consultant Software Engineer
TeamBUG support for UK-BUG
TeamMM support for ModelMaker