Object design question

P

Peter Richardson

Hi,

I'm wondering if someone can help me with some design questions I have. I'm
trying to create a class in C# to represent my customers. I know how to
create teh Customer class and all, but my problem comes with some conceptual
issues I have:

Let's say I have a business layer and a data layer. I use a seperate
assembly to host the business objects that I pass from one to another. That
is, I have for example:

public class Customer {

private string Name;
private string Surname;


.... public properties
}

Now, here are my questions:

1. Should this class call methods that in turn call the data layer to load
the values up by passing itself as reference? That is, should I have a
method for example Load that does something like:

DAL.Load(Self);

and DAL (Data access layer) accepts as parameter a Customer class that it
loads up?

Or should I in turn have another "wrapper", for example a CustomerLogic
class that creates a customer object, creates a DAL object and passes one
from the other and in turn my UI for example calls methods on this new
class? As in:

CustomerLogic.LoadCustomerByID(100) where this becomes:

public Customer LoadCustomerByID(int ID) {

DAL dal = new CustomerDAL();
Customer customer = new Customer();

customer = dal.Load(ID);
return customer;
}

Which is better? From one point of view, I think the first solution is
better since it's encapsulating the customer object and doing all the work
from there. However, with this solution I face the following dilema:

What happens if I want to load for example 20 customers? Should I make a
static method of Customer class that returns a Collection<Customer>?

With the second approach I could just create a method of CustomerLogic that
does that.

2. My second question is related to the first. Let's say now that a Customer
has several email addresses. I then make a property that points to another
class. However, it would be ideal to load this property in lazy mode, i.e.
when first read, that way consuming little memory. So that's not a problem
with the first approach since again, Customer is all encapsulated and I read
the emails from within the Customer class.

However, with the second approach, I'm now left ot creating a new method in
CustomerLogic that then loads the email addresses.

Alternatively I could read it all in the Load method.

Lastly, I assume that reading related objects should be done at the DAL
layer and not at the BL correct? Because if not, when I change my backend, I
would probably need to change my BL also, unless of course I'm using
interfaces to define behaviour. In other words, if I have two tables that I
want to map to an object, do I do this mapping in the DAL or do I read the
tables invididually by making seperate calls to the DAL from the BL?

Sorry for the long post, but it's really causing me roadblocks.
 
G

gary

Hi Peter,

Here's how I'd go about it, and this is by no means the "correct" or
"only" answer; but I'd go with model, view, controller. So, a user
would press a button on the form, say it was labelled "Load all
Customers". That form would have a controller and that controller would
would trap that event and call LoadCustomers() on the
ApplicationController. The ApplicationController would maintain a
collection of Customers. If the collection of customers was empty (or
some time out had expired) the ApplicationController would call the
data layer to fetch the customers, something like
DAL.LoadAllCustomers(); The ApplicationController would then populate
its collection of Customer objects and return it to the FormController
which would populate a grid for example.

Thereafter, if a particular Customer was required, say because of a
double click in the grid, then that event would be trapped by the
FormController and the ApplicationController would be asked for the
Customer, like so, ApplicationController.GetCustomerById(100). The
ApplicationController would then search the collection of customers for
the specific customer with id = 100 and return it to the
FormController, which would, in turn, update the form.

Hope this helps.
 
P

Peter Richardson

Hi Gary,

Thanks for the reply. So what you're basically saying is use the second
approach where you have another object that handles the customers? And what
about for example the email addresses, this ApplicationController would take
care of loading them?

Wouldn't that also make the ApplicationController a master of all trades?
Having to deal with all types of entities?



Btw, what's the difference between MVC that you mention and MVP?
 
G

gary

Hello Peter,
Thanks for the reply. So what you're basically saying is use the second
approach where you have another object that handles the customers? And what
about for example the email addresses, this ApplicationController would take
care of loading them?

No, the ApplicationController would load the Customers only. Let's say
the Customer also has related Orders. I would load them in lazily. So
let's imagine that you had selected a specific Customer from a list and
had opened a view of that customer and then you had clicked to fill a
list with this Customer's Orders. The CustomerFormController would trap
the click event and would ask the Customer object for it's list of
Orders. As this is beging done lazily, the Customer object knows how to
get a list of it's Orders from the data layer, something like
DAL.GetOrdersForCustomerId(12). The Customer then returns that list to
the CustomerFormController who updates the view.

As an aside, email addresses are not a good candidate for objects as
they have no behaviour of their own, they only have knowledge.
Wouldn't that also make the ApplicationController a master of all trades?
Having to deal with all types of entities?

Um sort of, the ApplicationController just responds to events that are
raised at the application level, and acts as a repository for
application wide objects, all Customers, for example.
Btw, what's the difference between MVC that you mention and MVP?

Practically none at all. :)
 
P

Peter Richardson

had opened a view of that customer and then you had clicked to fill a
list with this Customer's Orders. The CustomerFormController would trap
the click event and would ask the Customer object for it's list of

Abstracting the UI for a minute, Controller can be the CustomerLogic I was
referring to previously right? A wrapper class that handles my business
entities?
In the case of using it in a WinForms app for example (or ASP.Net or
whatever), this would be named "Controller"...

get a list of it's Orders from the data layer, something like
DAL.GetOrdersForCustomerId(12). The Customer then returns that list to
the CustomerFormController who updates the view.

This answers I think my other question. The Customer object is actually
making explicit calls (in for example the set acceser for the property) to
load the information from the DAL.
However, this brings out another issue. My Customer object has to be aware
of how the information is persisted. If tomorrow I change the database and
instead of storying the information in two independent tables, I use one
(for the sake of argument), then I would not only need to modify my DAL, but
also make BL (where customer object resides). If not, I would be making
unnecessary calls to the DAL.

And there is my dilema. The idea situation would be for the customer to get
loaded in one call in the DAL. However, this prevents lazy loading.
As an aside, email addresses are not a good candidate for objects as
they have no behaviour of their own, they only have knowledge.

Yes, sorry, just wanted to "simplify" it.
 
G

gary

Peter said:
Abstracting the UI for a minute, Controller can be the CustomerLogic I was
referring to previously right? A wrapper class that handles my business
entities?
In the case of using it in a WinForms app for example (or ASP.Net or
whatever), this would be named "Controller"...

Think of the Controller as being the "glue" between your object model
and the view of a particular model. Google MVC for more information.
This answers I think my other question. The Customer object is actually
making explicit calls (in for example the set acceser for the property) to
load the information from the DAL.
However, this brings out another issue. My Customer object has to be aware
of how the information is persisted. If tomorrow I change the database and
instead of storying the information in two independent tables, I use one
(for the sake of argument), then I would not only need to modify my DAL, but
also make BL (where customer object resides). If not, I would be making
unnecessary calls to the DAL.

No the Customer object has no knowledge of the persistence mechanism
other that it knows there is a DAL. For example, let's say today your
persistence mechanism is SQL Server. If a Customer wanted to lazily
load it's related Orders the code would be something like the
following:-

if(null == ListOfOrders)
{
DAL.GetOrdersForCustomersById(this.id);
}
return ListOfOrders;

Now, imagine that tomorrow you changed your persistence mechanism to be
MySQL then the above code would remain the same, any changes would be
in the data layer.
 
S

sloan

You can find a complete example at:

http://sholliday.spaces.live.com/blog/

5/24/2006
Custom Objects/Collections and Tiered Development

The businessobject shouldn't have any knowledge of what a database is. the
business object is a container for properties/methods and sometimes events.

this is the worst thing you can do

public class Employee
{

public Employee (int empid )
{
//in the constructor, talk to a specific database to load up values
}

}

But I see it done all the time in online examples and among other
developers.

...

Also, at the end of my blog, there is a MS article url ("read all of this
top to bottom") ...

You should read that, its a bird's eye view.

You should search the MS article for "timestamp", and you'll find some ways
to handle the object instance vs the data in the database issue.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top