473,322 Members | 1,522 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,322 software developers and data experts.

Design Question

We have developed two objects called "customer" and "salesrep". For
simplicity, assume that these two objects will talk directly to a
database. The database has three tables: customers, customersalesreps
(allows multiple salesreps to be associated with a customer), and
salesreps. The customer object has business rules that allow
manipulation of customer information (add,update,delete,select,etc).
The salesrep object has business rules that allow manipulation of
salesrep information (add,update,delete,select,etc).

Question 1: Where is the proper place to put a method called
"AddCustomerSalesrep" that adds a new salesrep to the
customersalesreps table with the customerid and salesrepid? Is it in
the customer or salesrep object? (Or is it in a third object we
should create called "customersalesrep"?)

Question 2: Assume one of the business rules desired is to validate
the salesrepid prior to adding a new salesrep to a customer. Also
assume that the salesrep object already has a method called
"issalesrepvalid" which takes a salesrepid and makes sure it exists in
the salesreps table. If we put AddCustomerSalesrep in the customer
object, would we want to validate the salesrepid by having the
customer object instantiate the salesrep object and call the method
called "issalesrepvalid"? Does this break the principle of
encapsulation or is there a better way to design this?

Thanks in advance for any insight.
Jul 21 '05 #1
22 2056
On 22 Apr 2004 19:45:03 -0700, Nunaya wrote:

I was about to fire off a response about
Java naming conventions when I noticed the
range of groups to which you were x-posting.

comp.object,
microsoft.public.dotnet.general,
comp.lang.java.programmer,
comp.lang.c++

Well. You are important!
...Or so you seem to think.

Please do not cross-post to 4
separate groups in future.
<http://www.physci.org/codes/javafaq.jsp#xpost>

Your choice of groups also underlines
just how _not_ language specific the
question is..

Why not decide which platform best
suits the problem and ask your OO
qn.s in a related group?

[ If this is a 'This V. That' troll,
please take it off to some group
that may give a toss.
...Try .advocacy in the various flavors. ]

F'Ups set to comp.object, as that seems
the closest tailored to the question.

--
Andrew Thompson
http://www.PhySci.org/ Open-source software suite
http://www.PhySci.org/codes/ Web & IT Help
http://www.1point1C.org/ Science & Technology
Jul 21 '05 #2
On 22 Apr 2004 19:45:03 -0700, Nunaya wrote:

I was about to fire off a response about
Java naming conventions when I noticed the
range of groups to which you were x-posting.

comp.object,
microsoft.public.dotnet.general,
comp.lang.java.programmer,
comp.lang.c++

Well. You are important!
...Or so you seem to think.

Please do not cross-post to 4
separate groups in future.
<http://www.physci.org/codes/javafaq.jsp#xpost>

Your choice of groups also underlines
just how _not_ language specific the
question is..

Why not decide which platform best
suits the problem and ask your OO
qn.s in a related group?

[ If this is a 'This V. That' troll,
please take it off to some group
that may give a toss.
...Try .advocacy in the various flavors. ]

F'Ups set to comp.object, as that seems
the closest tailored to the question.

--
Andrew Thompson
http://www.PhySci.org/ Open-source software suite
http://www.PhySci.org/codes/ Web & IT Help
http://www.1point1C.org/ Science & Technology
Jul 21 '05 #3
On 22 Apr 2004 19:45:03 -0700, nu********@yahoo.com (Nunaya) wrote or
quoted :
Question 1: Where is the proper place to put a method called
"AddCustomerSalesrep" that adds a new salesrep to the
customersalesreps table with the customerid and salesrepid? Is it in
the customer or salesrep object? (Or is it in a third object we
should create called "customersalesrep"?)


add-type methods belong in the containing class, since the containing
class is the one that knows how to keep track of what has been added.

--
Canadian Mind Products, Roedy Green.
Coaching, problem solving, economical contract programming.
See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
Jul 21 '05 #4
On 22 Apr 2004 19:45:03 -0700, nu********@yahoo.com (Nunaya) wrote or
quoted :
Question 1: Where is the proper place to put a method called
"AddCustomerSalesrep" that adds a new salesrep to the
customersalesreps table with the customerid and salesrepid? Is it in
the customer or salesrep object? (Or is it in a third object we
should create called "customersalesrep"?)


add-type methods belong in the containing class, since the containing
class is the one that knows how to keep track of what has been added.

--
Canadian Mind Products, Roedy Green.
Coaching, problem solving, economical contract programming.
See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
Jul 21 '05 #5
On 22 Apr 2004 19:45:03 -0700, nu********@yahoo.com (Nunaya) wrote or
quoted :
Question 2: Assume one of the business rules desired is to validate
the salesrepid prior to adding a new salesrep to a customer. Also
assume that the salesrep object already has a method called
"issalesrepvalid" which takes a salesrepid and makes sure it exists in
the salesreps table. If we put AddCustomerSalesrep in the customer
object, would we want to validate the salesrepid by having the
customer object instantiate the salesrep object and call the method
called "issalesrepvalid"? Does this break the principle of
encapsulation or is there a better way to design this?


The salesman class should be the only thing that knows the rules for
what constitutes a valid salesman. You want to keep that logic in one
place. If you allow it to disperse it will be impossible to maintain.

Salesman constructors AUTOMATICALLY invoke the validation routine and
throw an exception if you try to create a bad one. It now becomes
impossible for an invalid salesman object to exist. Now everyone else
can trust Salesman objects.

This is the fundamental principle of my homebrew Abundance language I
cooked up back in 1979. NEVER allow bad data into your system.
AUTOMATICALLY validate the hell out of it BEFORE it gets in. Then from
then on, trust it. It is infinitely easier to keep bad data out than
to get rid of it once it is in, or have business logic code cope with
imperfect data.



--
Canadian Mind Products, Roedy Green.
Coaching, problem solving, economical contract programming.
See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
Jul 21 '05 #6
On 22 Apr 2004 19:45:03 -0700, nu********@yahoo.com (Nunaya) wrote or
quoted :
Question 2: Assume one of the business rules desired is to validate
the salesrepid prior to adding a new salesrep to a customer. Also
assume that the salesrep object already has a method called
"issalesrepvalid" which takes a salesrepid and makes sure it exists in
the salesreps table. If we put AddCustomerSalesrep in the customer
object, would we want to validate the salesrepid by having the
customer object instantiate the salesrep object and call the method
called "issalesrepvalid"? Does this break the principle of
encapsulation or is there a better way to design this?


The salesman class should be the only thing that knows the rules for
what constitutes a valid salesman. You want to keep that logic in one
place. If you allow it to disperse it will be impossible to maintain.

Salesman constructors AUTOMATICALLY invoke the validation routine and
throw an exception if you try to create a bad one. It now becomes
impossible for an invalid salesman object to exist. Now everyone else
can trust Salesman objects.

This is the fundamental principle of my homebrew Abundance language I
cooked up back in 1979. NEVER allow bad data into your system.
AUTOMATICALLY validate the hell out of it BEFORE it gets in. Then from
then on, trust it. It is infinitely easier to keep bad data out than
to get rid of it once it is in, or have business logic code cope with
imperfect data.



--
Canadian Mind Products, Roedy Green.
Coaching, problem solving, economical contract programming.
See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
Jul 21 '05 #7
nu********@yahoo.com (Nunaya) wrote in
news:81**************************@posting.google.c om:
We have developed two objects called "customer" and "salesrep". For
simplicity, assume that these two objects will talk directly to a
database. The database has three tables: customers, customersalesreps
(allows multiple salesreps to be associated with a customer), and
salesreps. The customer object has business rules that allow
manipulation of customer information (add,update,delete,select,etc).
The salesrep object has business rules that allow manipulation of
salesrep information (add,update,delete,select,etc).

Question 1: Where is the proper place to put a method called
"AddCustomerSalesrep" that adds a new salesrep to the
customersalesreps table with the customerid and salesrepid? Is it in
the customer or salesrep object? (Or is it in a third object we
should create called "customersalesrep"?)
Who's going to assing or remove customers to sales reps? If you have a
path in the system in which, for example, you first locate a sales person
and then decided that he needs some more work, you may have a

assignCustomer(customer): void
removeCustomer(customer): void

in SalesRepresentative. If you have a path in which u select a customer
and assign to it a representative, you'll have assign/removeSalesRep
(salesRep) in Customer.

If both paths exist, you'll have both.
Question 2: Assume one of the business rules desired is to validate
the salesrepid prior to adding a new salesrep to a customer. Also
assume that the salesrep object already has a method called
"issalesrepvalid" which takes a salesrepid and makes sure it exists in
the salesreps table. If we put AddCustomerSalesrep in the customer
object, would we want to validate the salesrepid by having the
customer object instantiate the salesrep object and call the method
called "issalesrepvalid"?


No. You must not need a SalesRep to query if exist - it's a complete
waste and quickly leads to partially initialized objects and bad things
like that. Stuff like that needs a "registry" approach - that is, key-
based lookup ops. listKey(), hasKey(), getByKey() are typical. A
SalesRegistry object (maybe itself retrievable via some more generic
discovery/lookup method) will serve well as a service responsible for
tasks like answering to "does this id exist?" without unnecessarily
coupling.

Jul 21 '05 #8
nu********@yahoo.com (Nunaya) wrote in
news:81**************************@posting.google.c om:
We have developed two objects called "customer" and "salesrep". For
simplicity, assume that these two objects will talk directly to a
database. The database has three tables: customers, customersalesreps
(allows multiple salesreps to be associated with a customer), and
salesreps. The customer object has business rules that allow
manipulation of customer information (add,update,delete,select,etc).
The salesrep object has business rules that allow manipulation of
salesrep information (add,update,delete,select,etc).

Question 1: Where is the proper place to put a method called
"AddCustomerSalesrep" that adds a new salesrep to the
customersalesreps table with the customerid and salesrepid? Is it in
the customer or salesrep object? (Or is it in a third object we
should create called "customersalesrep"?)
Who's going to assing or remove customers to sales reps? If you have a
path in the system in which, for example, you first locate a sales person
and then decided that he needs some more work, you may have a

assignCustomer(customer): void
removeCustomer(customer): void

in SalesRepresentative. If you have a path in which u select a customer
and assign to it a representative, you'll have assign/removeSalesRep
(salesRep) in Customer.

If both paths exist, you'll have both.
Question 2: Assume one of the business rules desired is to validate
the salesrepid prior to adding a new salesrep to a customer. Also
assume that the salesrep object already has a method called
"issalesrepvalid" which takes a salesrepid and makes sure it exists in
the salesreps table. If we put AddCustomerSalesrep in the customer
object, would we want to validate the salesrepid by having the
customer object instantiate the salesrep object and call the method
called "issalesrepvalid"?


No. You must not need a SalesRep to query if exist - it's a complete
waste and quickly leads to partially initialized objects and bad things
like that. Stuff like that needs a "registry" approach - that is, key-
based lookup ops. listKey(), hasKey(), getByKey() are typical. A
SalesRegistry object (maybe itself retrievable via some more generic
discovery/lookup method) will serve well as a service responsible for
tasks like answering to "does this id exist?" without unnecessarily
coupling.

Jul 21 '05 #9
nu********@yahoo.com (Nunaya) wrote in message news:<81**************************@posting.google. com>...
We have developed two objects called "customer" and "salesrep". For
simplicity, assume that these two objects will talk directly to a
database. The database has three tables: customers, customersalesreps
(allows multiple salesreps to be associated with a customer), and
salesreps. The customer object has business rules that allow
manipulation of customer information (add,update,delete,select,etc).
The salesrep object has business rules that allow manipulation of
salesrep information (add,update,delete,select,etc).

Question 1: Where is the proper place to put a method called
"AddCustomerSalesrep" that adds a new salesrep to the
customersalesreps table with the customerid and salesrepid? Is it in
the customer or salesrep object? (Or is it in a third object we
should create called "customersalesrep"?)

Question 2: Assume one of the business rules desired is to validate
the salesrepid prior to adding a new salesrep to a customer. Also
assume that the salesrep object already has a method called
"issalesrepvalid" which takes a salesrepid and makes sure it exists in
the salesreps table. If we put AddCustomerSalesrep in the customer
object, would we want to validate the salesrepid by having the
customer object instantiate the salesrep object and call the method
called "issalesrepvalid"? Does this break the principle of
encapsulation or is there a better way to design this?

Thanks in advance for any insight.


Well .. I see you cross-posted to quite a few news-groups, but here is
how I would handle the problem using the C++ Standard Template Library
(STL).

I would use std::map objects for the customer and salerep lists, and
then a std::multimap to create an associative array relating your
salesreps and customers. So then you might have:

#include <map>
#include <string>

// typedefs for generating unique simple, ID's for customers and
salesreps
typedef int CustID;
typedef std::string RepID;

class customer { /* your def here */};
class salesrep { /* your def here */};

typedef std::map<CustID, customer> CustList;
typedef std::map<RepID, salesrep> RepList;

CustList customers;
RepList salesreps;

typedef std::multimap<const customer *, const salesrep *>
ContactsByCust;
typedef std::multimap<const salesrep*, const customer*> ContactsByRep;

ContactsByCust cbc;
ContactsByRep cbr;

I have defined the multimap contact-lists using pointers because
otherwise the multimap would store copies, which would be independent
of the customers and salesreps in your other lists. Also, since
lookup is only guaranteed to be fast for the key type (first template
arg.), I defined two lists .. to be used depending whether you want to
search by customer or by salesrep.

Now adding an association between a customer and salesrep (both of
whom already exist) could be handled as follows:

void add_contact(CustID cust, RepID rep) {
CustList::const_iterator c=customers.find(cust);
if (c==customers.end()) throw "customer not found"; // or better
error-type

RepList::const_iterator r=salesreps.find(rep);
if (r==salesreps.end()) throw "salesrep not found"; // or better
error-type

cbc.insert(ContactsByCust::value_type(&(*c).second , &(*r).second));
cbr.insert(ContactsByRep::value_type(&(*r).second, &(*c).second));
}

A list of customers associated with a given salesrep might be obtained
using:

void get_cust_list(const salesrep *r) {
typedef std::multimap<const salesrep *, const customer
*>::const_iterator CI;

std::pair<CI, CI> cust_list=cbr.equal_range(r);
for (CI i = cust_list.first; i!=cust_list.second; ++i) {
const customer& cust=*(*i).second;

// code using cust
}
}

Now, the above functions probably seem pretty hard to read if you are
new to programming with the STL ... this (rather extreme) notational
obfuscation is one of the knocks against the C++ STL. However, once
you can understand it, it really is pretty convenient ... at least you
will not have to define your own data-structures. Also, it is pretty
simple to define "context-functions", which hide the unwieldy STL
notation inside helper functions, which have simpler semantics. FYI,
the above code compiles without errors or warnings under gcc 3.3.1.

My favorite reference for understanding the STL is Stroustrup's "The
C++ Programming Language" 3rd. edition, chapters 16-19 in particular.
There is also a (fairly) complete reference at
http://www.sgi.com/tech/stl .. even though it is specifically about
the SGI implementation, it gives plenty of useful general info too.

While this might not be completely suitable for your application,
hopefully it will at least point you in the right direction.

HTH, Dave Moore
Jul 21 '05 #10
nu********@yahoo.com (Nunaya) wrote in message news:<81**************************@posting.google. com>...
We have developed two objects called "customer" and "salesrep". For
simplicity, assume that these two objects will talk directly to a
database. The database has three tables: customers, customersalesreps
(allows multiple salesreps to be associated with a customer), and
salesreps. The customer object has business rules that allow
manipulation of customer information (add,update,delete,select,etc).
The salesrep object has business rules that allow manipulation of
salesrep information (add,update,delete,select,etc).

Question 1: Where is the proper place to put a method called
"AddCustomerSalesrep" that adds a new salesrep to the
customersalesreps table with the customerid and salesrepid? Is it in
the customer or salesrep object? (Or is it in a third object we
should create called "customersalesrep"?)

Question 2: Assume one of the business rules desired is to validate
the salesrepid prior to adding a new salesrep to a customer. Also
assume that the salesrep object already has a method called
"issalesrepvalid" which takes a salesrepid and makes sure it exists in
the salesreps table. If we put AddCustomerSalesrep in the customer
object, would we want to validate the salesrepid by having the
customer object instantiate the salesrep object and call the method
called "issalesrepvalid"? Does this break the principle of
encapsulation or is there a better way to design this?

Thanks in advance for any insight.


Well .. I see you cross-posted to quite a few news-groups, but here is
how I would handle the problem using the C++ Standard Template Library
(STL).

I would use std::map objects for the customer and salerep lists, and
then a std::multimap to create an associative array relating your
salesreps and customers. So then you might have:

#include <map>
#include <string>

// typedefs for generating unique simple, ID's for customers and
salesreps
typedef int CustID;
typedef std::string RepID;

class customer { /* your def here */};
class salesrep { /* your def here */};

typedef std::map<CustID, customer> CustList;
typedef std::map<RepID, salesrep> RepList;

CustList customers;
RepList salesreps;

typedef std::multimap<const customer *, const salesrep *>
ContactsByCust;
typedef std::multimap<const salesrep*, const customer*> ContactsByRep;

ContactsByCust cbc;
ContactsByRep cbr;

I have defined the multimap contact-lists using pointers because
otherwise the multimap would store copies, which would be independent
of the customers and salesreps in your other lists. Also, since
lookup is only guaranteed to be fast for the key type (first template
arg.), I defined two lists .. to be used depending whether you want to
search by customer or by salesrep.

Now adding an association between a customer and salesrep (both of
whom already exist) could be handled as follows:

void add_contact(CustID cust, RepID rep) {
CustList::const_iterator c=customers.find(cust);
if (c==customers.end()) throw "customer not found"; // or better
error-type

RepList::const_iterator r=salesreps.find(rep);
if (r==salesreps.end()) throw "salesrep not found"; // or better
error-type

cbc.insert(ContactsByCust::value_type(&(*c).second , &(*r).second));
cbr.insert(ContactsByRep::value_type(&(*r).second, &(*c).second));
}

A list of customers associated with a given salesrep might be obtained
using:

void get_cust_list(const salesrep *r) {
typedef std::multimap<const salesrep *, const customer
*>::const_iterator CI;

std::pair<CI, CI> cust_list=cbr.equal_range(r);
for (CI i = cust_list.first; i!=cust_list.second; ++i) {
const customer& cust=*(*i).second;

// code using cust
}
}

Now, the above functions probably seem pretty hard to read if you are
new to programming with the STL ... this (rather extreme) notational
obfuscation is one of the knocks against the C++ STL. However, once
you can understand it, it really is pretty convenient ... at least you
will not have to define your own data-structures. Also, it is pretty
simple to define "context-functions", which hide the unwieldy STL
notation inside helper functions, which have simpler semantics. FYI,
the above code compiles without errors or warnings under gcc 3.3.1.

My favorite reference for understanding the STL is Stroustrup's "The
C++ Programming Language" 3rd. edition, chapters 16-19 in particular.
There is also a (fairly) complete reference at
http://www.sgi.com/tech/stl .. even though it is specifically about
the SGI implementation, it gives plenty of useful general info too.

While this might not be completely suitable for your application,
hopefully it will at least point you in the right direction.

HTH, Dave Moore
Jul 21 '05 #11
"Roedy Green" <se*@mindprod.com.invalid> wrote in message
news:n6********************************@4ax.com...
On 22 Apr 2004 19:45:03 -0700, nu********@yahoo.com (Nunaya) wrote or

Question 2: Assume one of the business rules desired is to validate
the salesrepid prior to adding a new salesrep to a customer. Also
assume that the salesrep object already has a method called
"issalesrepvalid" which takes a salesrepid and makes sure it exists in
the salesreps table. If we put AddCustomerSalesrep in the customer
object, would we want to validate the salesrepid by having the
customer object instantiate the salesrep object and call the method
called "issalesrepvalid"? Does this break the principle of
encapsulation or is there a better way to design this?


The salesman class should be the only thing that knows the rules for
what constitutes a valid salesman. You want to keep that logic in one
place. If you allow it to disperse it will be impossible to maintain.

Salesman constructors AUTOMATICALLY invoke the validation routine and
throw an exception if you try to create a bad one. It now becomes
impossible for an invalid salesman object to exist. Now everyone else
can trust Salesman objects.


What if someone deletes a Salesman row from the database after you've
succesfully constructed your C++ Salesman object? How could we design our
system to ensure that this does not happen? Or if that's too hard to do,
how to deal with the fact that the Salesrep object that once was valid no
longer is, and so what would a call to Salesman::AssociateCustomer(const
Customer&) do?
Jul 21 '05 #12
"Roedy Green" <se*@mindprod.com.invalid> wrote in message
news:n6********************************@4ax.com...
On 22 Apr 2004 19:45:03 -0700, nu********@yahoo.com (Nunaya) wrote or

Question 2: Assume one of the business rules desired is to validate
the salesrepid prior to adding a new salesrep to a customer. Also
assume that the salesrep object already has a method called
"issalesrepvalid" which takes a salesrepid and makes sure it exists in
the salesreps table. If we put AddCustomerSalesrep in the customer
object, would we want to validate the salesrepid by having the
customer object instantiate the salesrep object and call the method
called "issalesrepvalid"? Does this break the principle of
encapsulation or is there a better way to design this?


The salesman class should be the only thing that knows the rules for
what constitutes a valid salesman. You want to keep that logic in one
place. If you allow it to disperse it will be impossible to maintain.

Salesman constructors AUTOMATICALLY invoke the validation routine and
throw an exception if you try to create a bad one. It now becomes
impossible for an invalid salesman object to exist. Now everyone else
can trust Salesman objects.


What if someone deletes a Salesman row from the database after you've
succesfully constructed your C++ Salesman object? How could we design our
system to ensure that this does not happen? Or if that's too hard to do,
how to deal with the fact that the Salesrep object that once was valid no
longer is, and so what would a call to Salesman::AssociateCustomer(const
Customer&) do?
Jul 21 '05 #13
"Dave Moore" <dt*****@rijnh.nl> wrote in message
news:30**************************@posting.google.c om...
I would use std::map objects for the customer and salerep lists, and
then a std::multimap to create an associative array relating your
salesreps and customers. So then you might have:


Very good solution. This seems an interesting way of using multimap to
represent many-to-many relationships (ie. each customer can have many
salesreps, and each salesrep can have many customers).

Suppose one sales rep could have many customers, but one customer would have
exactly one sales rep -- a one-to-many relationship. What would be a good
STL structure?

And if one customer could have zero or one sales rep (ie. its SALES_REP_ID
foreign key field is nullable), then what would be a good STL structure for
this?

In addition, we also need a sync function to sync the STL data structure to
the underlying database.
Jul 21 '05 #14
"Dave Moore" <dt*****@rijnh.nl> wrote in message
news:30**************************@posting.google.c om...
I would use std::map objects for the customer and salerep lists, and
then a std::multimap to create an associative array relating your
salesreps and customers. So then you might have:


Very good solution. This seems an interesting way of using multimap to
represent many-to-many relationships (ie. each customer can have many
salesreps, and each salesrep can have many customers).

Suppose one sales rep could have many customers, but one customer would have
exactly one sales rep -- a one-to-many relationship. What would be a good
STL structure?

And if one customer could have zero or one sales rep (ie. its SALES_REP_ID
foreign key field is nullable), then what would be a good STL structure for
this?

In addition, we also need a sync function to sync the STL data structure to
the underlying database.
Jul 21 '05 #15
On Fri, 23 Apr 2004 16:49:16 GMT, "Siemel Naran"
<Si*********@REMOVE.att.net> wrote or quoted :
Salesman constructors AUTOMATICALLY invoke the validation routine and
throw an exception if you try to create a bad one. It now becomes
impossible for an invalid salesman object to exist. Now everyone else
can trust Salesman objects.


What if someone deletes a Salesman row from the database after you've
succesfully constructed your C++ Salesman object? How could we design our
system to ensure that this does not happen? Or if that's too hard to do,
how to deal with the fact that the Salesrep object that once was valid no
longer is, and so what would a call to Salesman::AssociateCustomer(const
Customer&) do?

In a transaction system, any the persistent effects of any partly
completed transaction gets automatically backed out by the womb. See
http://mindprod.com/jgloss/transaction.html

Without a transaction manager, you could wait until you have both
objects created before you add to any persistent store.

In any case if you have two objects that have to stay in sync, you
always have the possibility that one of the persistent saves (POD,
SQL, EJB) could fail. You need to catch exceptions and recover
manually from all the horrible things that might happen.
Unfortunately, you will unlikely ever fully exercise this code during
debugging. It will only fail at the JavaOne demo before the reps from
HP who are considering bundling your product.

Unless you have a very simple system, if you have networks of
interconnected persistent objects that have to stay in sync, you
pretty well have to use some sort of transaction management to cover
all the myriad ways you could fail.

--
Canadian Mind Products, Roedy Green.
Coaching, problem solving, economical contract programming.
See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
Jul 21 '05 #16
On Fri, 23 Apr 2004 16:49:16 GMT, "Siemel Naran"
<Si*********@REMOVE.att.net> wrote or quoted :
Salesman constructors AUTOMATICALLY invoke the validation routine and
throw an exception if you try to create a bad one. It now becomes
impossible for an invalid salesman object to exist. Now everyone else
can trust Salesman objects.


What if someone deletes a Salesman row from the database after you've
succesfully constructed your C++ Salesman object? How could we design our
system to ensure that this does not happen? Or if that's too hard to do,
how to deal with the fact that the Salesrep object that once was valid no
longer is, and so what would a call to Salesman::AssociateCustomer(const
Customer&) do?

In a transaction system, any the persistent effects of any partly
completed transaction gets automatically backed out by the womb. See
http://mindprod.com/jgloss/transaction.html

Without a transaction manager, you could wait until you have both
objects created before you add to any persistent store.

In any case if you have two objects that have to stay in sync, you
always have the possibility that one of the persistent saves (POD,
SQL, EJB) could fail. You need to catch exceptions and recover
manually from all the horrible things that might happen.
Unfortunately, you will unlikely ever fully exercise this code during
debugging. It will only fail at the JavaOne demo before the reps from
HP who are considering bundling your product.

Unless you have a very simple system, if you have networks of
interconnected persistent objects that have to stay in sync, you
pretty well have to use some sort of transaction management to cover
all the myriad ways you could fail.

--
Canadian Mind Products, Roedy Green.
Coaching, problem solving, economical contract programming.
See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
Jul 21 '05 #17
On 22 Apr 2004 19:45:03 -0700, nu********@yahoo.com (Nunaya) wrote:
We have developed two objects called "customer" and "salesrep". For
simplicity, assume that these two objects will talk directly to a
database. The database has three tables: customers, customersalesreps
(allows multiple salesreps to be associated with a customer), and
salesreps. The customer object has business rules that allow
manipulation of customer information (add,update,delete,select,etc).
The salesrep object has business rules that allow manipulation of
salesrep information (add,update,delete,select,etc).

Question 1: Where is the proper place to put a method called
"AddCustomerSalesrep" that adds a new salesrep to the
customersalesreps table with the customerid and salesrepid? Is it in
the customer or salesrep object? (Or is it in a third object we
should create called "customersalesrep"?)

Question 2: Assume one of the business rules desired is to validate
the salesrepid prior to adding a new salesrep to a customer. Also
assume that the salesrep object already has a method called
"issalesrepvalid" which takes a salesrepid and makes sure it exists in
the salesreps table. If we put AddCustomerSalesrep in the customer
object, would we want to validate the salesrepid by having the
customer object instantiate the salesrep object and call the method
called "issalesrepvalid"? Does this break the principle of
encapsulation or is there a better way to design this?

Thanks in advance for any insight.


You are allowing the structure of the database to pollute your
thinking. The structure of the database (i.e. the tables) are details
that you should ignore for the time being. Instead, build your
Customer and SelseRep classes without any knowledge of the database at
all. Don't even admit that there *is* a database. Get your
application working in RAM first, then add the database as your last
step.

This will force you to focus on business rules. It will cause the
structure of your classes and objects to support the business rules
first. Then, later, as you need persistence, you can shim the
database behind the business rules in a way that does not warp the
object model.

-----
Robert C. Martin (Uncle Bob)
Object Mentor Inc.
unclebob @ objectmentor . com
800-338-6716

"Distinguishing between the author
and the writing is the essence of civilized debate."
-- Daniel Parker
Jul 21 '05 #18
On 22 Apr 2004 19:45:03 -0700, nu********@yahoo.com (Nunaya) wrote:
We have developed two objects called "customer" and "salesrep". For
simplicity, assume that these two objects will talk directly to a
database. The database has three tables: customers, customersalesreps
(allows multiple salesreps to be associated with a customer), and
salesreps. The customer object has business rules that allow
manipulation of customer information (add,update,delete,select,etc).
The salesrep object has business rules that allow manipulation of
salesrep information (add,update,delete,select,etc).

Question 1: Where is the proper place to put a method called
"AddCustomerSalesrep" that adds a new salesrep to the
customersalesreps table with the customerid and salesrepid? Is it in
the customer or salesrep object? (Or is it in a third object we
should create called "customersalesrep"?)

Question 2: Assume one of the business rules desired is to validate
the salesrepid prior to adding a new salesrep to a customer. Also
assume that the salesrep object already has a method called
"issalesrepvalid" which takes a salesrepid and makes sure it exists in
the salesreps table. If we put AddCustomerSalesrep in the customer
object, would we want to validate the salesrepid by having the
customer object instantiate the salesrep object and call the method
called "issalesrepvalid"? Does this break the principle of
encapsulation or is there a better way to design this?

Thanks in advance for any insight.


You are allowing the structure of the database to pollute your
thinking. The structure of the database (i.e. the tables) are details
that you should ignore for the time being. Instead, build your
Customer and SelseRep classes without any knowledge of the database at
all. Don't even admit that there *is* a database. Get your
application working in RAM first, then add the database as your last
step.

This will force you to focus on business rules. It will cause the
structure of your classes and objects to support the business rules
first. Then, later, as you need persistence, you can shim the
database behind the business rules in a way that does not warp the
object model.

-----
Robert C. Martin (Uncle Bob)
Object Mentor Inc.
unclebob @ objectmentor . com
800-338-6716

"Distinguishing between the author
and the writing is the essence of civilized debate."
-- Daniel Parker
Jul 21 '05 #19
["Followup-To:" header set to comp.lang.java.programmer.]
On 2004-04-23, Nunaya <nu********@yahoo.com> wrote:
Question 1: Where is the proper place to put a method called
"AddCustomerSalesrep" that adds a new salesrep to the
customersalesreps table with the customerid and salesrepid? Is it in
the customer or salesrep object? (Or is it in a third object we
should create called "customersalesrep"?)

Sounds like the risk of customer calling salesrep calling customer
calling salesrep ad inifitum.

For the past few years, I've been separating my business logic from my
persistence layer using a facade which, in this case, would have the
"assign a salesrep to a customer" method.

That facade will contain the business logic and any checking you want to
do. It will basicly encapsulate the "assign a customer to a salesrep"
use case. Part of the design process, working more top down starting
with "what does my user want to do here", is working out what the
pre-conditions and results of this call should be.

The perisistence layer just becomes dumb persistence below it. My Customer
and Salesrep classes would be plain value objects, and I'd have things
like CustomerFactory (or CustomerDataAcces if you like) to access them.
Even experimenting with object relational mapping tools in Java, I'm
still using this pattern to hide the details from the upper layers.

Only the business logic code will ever access those factories. The
front end, whatever that is, will talk to the business logic code,
and may refer to the value objects. I tended to have my business logic
returning value objects, and accepting IDs.

Question 2: Assume one of the business rules desired is to validate
the salesrepid prior to adding a new salesrep to a customer. Also
assume that the salesrep object already has a method called
"issalesrepvalid" which takes a salesrepid and makes sure it exists in
the salesreps table. [...]


As ever there is more than one solution, and different people each claim
that their's is the right way. In my earlier work I put all the
validation in my business logic layer. Data import ran through that
layer, and it was slow (this was Visual Basic on MS SQL Server by the
way, before some of the newsgroups here blame it on Java). Also, the
database for this application is going to outlast all my front end and
business logic, which is now becoming dated. We've not developed in VB
for years and won't be binding to that code.

Nowadays I'm using Oracle, which has very powerful constraint
capability. My first fear of constraints were that I'd not be able to
put the database into an intermediate invalid state that I was going
to put right. Oracle provides defer until commit validation, so I
can do what I want until that point. It also provides arbitrary check
constraints. The constraints in your case sound like simple foriegn key
integrity constraints, and sound worthwhile putting on. It makes the
database more self describing too, which helps in Oracle due to its cost
based optimiser. Another idea may be to check in stored procedures.

If you're using database constraints, then whether to repeat the logic
in the business layer becomes something for debate. If not, then it
would have to be clear that you're relying on the data layer to do this
checking for you, so if the database people change the schema, make
sure they ask. One example I can think of is say you change the design
such that instead of deleting a record, you flag it as dead because you
want to keep history of ex-sales-reps. If you fail to remember that your
foriegn key constraint is all thats keeping your assign function working,
then you're in trouble. (You do test with bad input don't you?)

Conversely, if you do add the logic to the business layer, then you may
be costing speed if you're doing a lot of updates, and you now have to
maintain that knowledge in two places. Of course, you may have some
quite interesting requirments other than "both the sales rep and the
customer must exist". I've also not specified that the business logic
layer need be developed in Java or .Net. We've been using PlSQL in our
latest project. The shape of the design is the same, just the choice of
implementation language at each level is different.

The higher level code doesn't have to know how the "assign rep to
customer" method knows the input is invalid, so when thinking of the front
end side of that interface contract, you don't care. One of the great
things of splitting systems up like this is that, when working on one
bit of it, all you have to think about is what the interface contract,
the design, says that the other bit should do - but you couldn't care
less how the other bit actually does it. One disadvantage is that the
facades, or the middle bit, can become quite big and managing that
complexity can take some thought.

Database constraints at time of commit are not always of help to your
user. This comes back to your bigger design. If the user level use case
for assigning a salesrep to a customer is something like

User has customer details visible (for example has just entered them)
User chooses to assign a salesrep
User selects salesrep from list of suitable candidates

then the user is less likely to feed you wrong data. The only possibility
is a salesrep keeling over between the time the user got the list and
acted on it. This would be the exception, not the norm.

- Richard
--
_/_/_/ _/_/_/ _/_/_/ Richard dot Corfield at ntlworld dot com
_/ _/ _/ _/
_/_/ _/ _/ Time is a one way street,
_/ _/ _/_/ _/_/_/ Except in the Twilight Zone.
Jul 21 '05 #20
["Followup-To:" header set to comp.lang.java.programmer.]
On 2004-04-23, Nunaya <nu********@yahoo.com> wrote:
Question 1: Where is the proper place to put a method called
"AddCustomerSalesrep" that adds a new salesrep to the
customersalesreps table with the customerid and salesrepid? Is it in
the customer or salesrep object? (Or is it in a third object we
should create called "customersalesrep"?)

Sounds like the risk of customer calling salesrep calling customer
calling salesrep ad inifitum.

For the past few years, I've been separating my business logic from my
persistence layer using a facade which, in this case, would have the
"assign a salesrep to a customer" method.

That facade will contain the business logic and any checking you want to
do. It will basicly encapsulate the "assign a customer to a salesrep"
use case. Part of the design process, working more top down starting
with "what does my user want to do here", is working out what the
pre-conditions and results of this call should be.

The perisistence layer just becomes dumb persistence below it. My Customer
and Salesrep classes would be plain value objects, and I'd have things
like CustomerFactory (or CustomerDataAcces if you like) to access them.
Even experimenting with object relational mapping tools in Java, I'm
still using this pattern to hide the details from the upper layers.

Only the business logic code will ever access those factories. The
front end, whatever that is, will talk to the business logic code,
and may refer to the value objects. I tended to have my business logic
returning value objects, and accepting IDs.

Question 2: Assume one of the business rules desired is to validate
the salesrepid prior to adding a new salesrep to a customer. Also
assume that the salesrep object already has a method called
"issalesrepvalid" which takes a salesrepid and makes sure it exists in
the salesreps table. [...]


As ever there is more than one solution, and different people each claim
that their's is the right way. In my earlier work I put all the
validation in my business logic layer. Data import ran through that
layer, and it was slow (this was Visual Basic on MS SQL Server by the
way, before some of the newsgroups here blame it on Java). Also, the
database for this application is going to outlast all my front end and
business logic, which is now becoming dated. We've not developed in VB
for years and won't be binding to that code.

Nowadays I'm using Oracle, which has very powerful constraint
capability. My first fear of constraints were that I'd not be able to
put the database into an intermediate invalid state that I was going
to put right. Oracle provides defer until commit validation, so I
can do what I want until that point. It also provides arbitrary check
constraints. The constraints in your case sound like simple foriegn key
integrity constraints, and sound worthwhile putting on. It makes the
database more self describing too, which helps in Oracle due to its cost
based optimiser. Another idea may be to check in stored procedures.

If you're using database constraints, then whether to repeat the logic
in the business layer becomes something for debate. If not, then it
would have to be clear that you're relying on the data layer to do this
checking for you, so if the database people change the schema, make
sure they ask. One example I can think of is say you change the design
such that instead of deleting a record, you flag it as dead because you
want to keep history of ex-sales-reps. If you fail to remember that your
foriegn key constraint is all thats keeping your assign function working,
then you're in trouble. (You do test with bad input don't you?)

Conversely, if you do add the logic to the business layer, then you may
be costing speed if you're doing a lot of updates, and you now have to
maintain that knowledge in two places. Of course, you may have some
quite interesting requirments other than "both the sales rep and the
customer must exist". I've also not specified that the business logic
layer need be developed in Java or .Net. We've been using PlSQL in our
latest project. The shape of the design is the same, just the choice of
implementation language at each level is different.

The higher level code doesn't have to know how the "assign rep to
customer" method knows the input is invalid, so when thinking of the front
end side of that interface contract, you don't care. One of the great
things of splitting systems up like this is that, when working on one
bit of it, all you have to think about is what the interface contract,
the design, says that the other bit should do - but you couldn't care
less how the other bit actually does it. One disadvantage is that the
facades, or the middle bit, can become quite big and managing that
complexity can take some thought.

Database constraints at time of commit are not always of help to your
user. This comes back to your bigger design. If the user level use case
for assigning a salesrep to a customer is something like

User has customer details visible (for example has just entered them)
User chooses to assign a salesrep
User selects salesrep from list of suitable candidates

then the user is less likely to feed you wrong data. The only possibility
is a salesrep keeling over between the time the user got the list and
acted on it. This would be the exception, not the norm.

- Richard
--
_/_/_/ _/_/_/ _/_/_/ Richard dot Corfield at ntlworld dot com
_/ _/ _/ _/
_/_/ _/ _/ Time is a one way street,
_/ _/ _/_/ _/_/_/ Except in the Twilight Zone.
Jul 21 '05 #21
Nunaya wrote:
Question 1: Where is the proper place to put a method called
"AddCustomerSalesrep" that adds a new salesrep to the
customersalesreps table with the customerid and salesrepid?
The point of recasting a database schema into business objects is to create
methods that make the most sense from what the application/user is trying
to do. Asking questions like 'what is the right place' do not make sense.
You want to create methods that model the business process as much as
possible. It's not necessarily a 1:1 mapping. In fact, you might want to
create objects that are not mirrored directly in the database, but which
apply more to the workflow.
Question 2: Assume one of the business rules desired is to validate
the salesrepid prior to adding a new salesrep to a customer. Also
assume that the salesrep object already has a method called
"issalesrepvalid" which takes a salesrepid and makes sure it exists in
the salesreps table. If we put AddCustomerSalesrep in the customer
object, would we want to validate the salesrepid by having the
customer object instantiate the salesrep object and call the method
called "issalesrepvalid"? Does this break the principle of
encapsulation or is there a better way to design this?


Encapsulation? What does that have to do with it. But I would say, that if
you are defining two objects, which are supposed to discretely represent
your model of the business, and yet you have to have one call the other --
then you've made some serious design and thinking mistakes.

--
W '04 <:> Open
Jul 21 '05 #22
Nunaya wrote:
Question 1: Where is the proper place to put a method called
"AddCustomerSalesrep" that adds a new salesrep to the
customersalesreps table with the customerid and salesrepid?
The point of recasting a database schema into business objects is to create
methods that make the most sense from what the application/user is trying
to do. Asking questions like 'what is the right place' do not make sense.
You want to create methods that model the business process as much as
possible. It's not necessarily a 1:1 mapping. In fact, you might want to
create objects that are not mirrored directly in the database, but which
apply more to the workflow.
Question 2: Assume one of the business rules desired is to validate
the salesrepid prior to adding a new salesrep to a customer. Also
assume that the salesrep object already has a method called
"issalesrepvalid" which takes a salesrepid and makes sure it exists in
the salesreps table. If we put AddCustomerSalesrep in the customer
object, would we want to validate the salesrepid by having the
customer object instantiate the salesrep object and call the method
called "issalesrepvalid"? Does this break the principle of
encapsulation or is there a better way to design this?


Encapsulation? What does that have to do with it. But I would say, that if
you are defining two objects, which are supposed to discretely represent
your model of the business, and yet you have to have one call the other --
then you've made some serious design and thinking mistakes.

--
W '04 <:> Open
Jul 21 '05 #23

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Don Vaillancourt | last post by:
Hello all, Over the years as I design more database schemas the more I come up with patterns in database design. The more patterns I recognize the more I want to try to design some kind of...
9
by: sk | last post by:
I have an applicaton in which I collect data for different parameters for a set of devices. The data are entered into a single table, each set of name, value pairs time-stamped and associated with...
2
by: Test User | last post by:
Hi all, (please excuse the crosspost as I'm trying to reach as many people as possible) I am somewhat familiar with Access 2000, but my latest project has me stumped. So, I defer to you...
6
by: rodchar | last post by:
Hey all, I'm trying to understand Master/Detail concepts in VB.NET. If I do a data adapter fill for both customer and orders from Northwind where should that dataset live? What client is...
17
by: tshad | last post by:
Many (if not most) have said that code-behind is best if working in teams - which does seem logical. How do you deal with the flow of the work? I have someone who is good at designing, but...
17
by: roN | last post by:
Hi, I'm creating a Website with divs and i do have some troubles, to make it looking the same way in Firefox and IE (tested with IE7). I checked it with the e3c validator and it says: " This...
6
by: JoeC | last post by:
I have a question about designing objects and programming. What is the best way to design objects? Create objects debug them and later if you need some new features just use inhereitance. Often...
0
by: | last post by:
I have a question about spawning and displaying subordinate list controls within a list control. I'm also interested in feedback about the design of my search application. Lots of code is at the...
19
by: neelsmail | last post by:
Hi, I have been working on C++ for some time now, and I think I have a flair for design (which just might be only my imagination over- stretched.. :) ). So, I tried to find a design...
8
by: indrawati.yahya | last post by:
In a recent job interview, the interviewer asked me how I'd design classes for the following problem: let's consider a hypothetical firewall, which filters network packets by either IP address,...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.