views:

219

answers:

8

I have a 'Purchase Order' class. It contains information about a single purchase order. I have a DAO class for database methods.

Where should the responsibility reside for the methods that will load and update the purchase order?

Should the PurchaseOrder class have '.update', 'insert', 'delete', and '.load' methods that use the DAO class directly, or should the PurchaseOrder class be ignorant of the DAO methods and have a POController class that manages these interactions?

The user will only be working on a single PurchaseOrder at a time.

Thanks!

A: 

I would definitely separate the "business logic" (PurchaseOrder) from the database interaction/access. Should you move to a different vendor, etc, you'll have an easier time making changes to the access without potentially interfering with the business implementation, plus you'll have an easier time avoiding adding behavior to the database access layer.

Bob King
+4  A: 

The Purchase Order should be ignorant of the details of its persistence. This is the point of having some sort of data access layer, it handles the management of the object and the object itself can concentrate on just being a purchase order.

This also makes the system easier to test, as you can create mock Purchase orders and test the logic of how the system handles them without getting entangled in persistence issues.

Steve B.
A: 

Personally, I'd create an object that manages the interactions. I can't make a strong case for NOT putting this logic in the PurchaseOrder class itself, but creating this controller object would lead towards more loosely coupled objects.

SpooneyDinosaur
A: 

It depends on how long you think your application will remain in existence. My company's metal cutting application has been continuously developed since 1985 and has been port through multiple changes in computer architectures. In our case we nearly always shove things behind a interface (or controller class using your terms) because we don't what going to be the state of things 5, 10, 15 years down the line.

By using a controller class we can change the underlying APIs without tampering with the levels of business logic and UI tweaks above. These levels represent years of work so it is important to preserve their behavior.

Remember the majority of the lifetime your project is going be in maintenance. Anything you do now to make it easier to change the design later will pay off in enormous time savings down the road.

RS Conley
A: 

The PurchaseOrder class should be ignorant of the DAO. The purchaseOrder class should represent the data itself and nothing more. Use a controller or service manager or whatever you want to call it to persist/load PurchaseOrder records using the DAO. This gives you the most flexibility in your design. You have one place for your data model, one place for your business logic (the controller) on how PurchaseOrders are stored/retrieved and one place where its actually persisted.

oneBelizean
A: 

The key thing to think about here is what you might want to do in the future. Maybe you want to replace your database with another? That's why you should definitely separate your code for interaction with the database from the class that represents the PO. That's basic separation of responsibility, and I hope you've done that already.

Now the question is: do you want a third class (controller) to manage the interaction between the PO and DAO classes? I think that depends on how general you can make the interface to the DAO class. If the DAO interface is general enough that you could write a plug-in replacement for it using a different storage mechanism but without changing the interface, then I would let the PO class interact with it. If not then I would write a controller class.

The other thing to think about is the rest of the structure. Where is the save/load initiated from? If you are going to do a lot of manipulations of the PO (save,load, print, send-to-customer) then it probably makes sense to have a controller that does all of those things rather than integrate the functionality into the PO class. It gives you the advantage that you can add PO operations without having to modify the PO class.

DJClayworth
+1  A: 

I'd keep it simple by making PurchaseOrder an interface and putting all the DAO code in the implementation, then use a factory.

shyam
A: 

Let me walk you through my reasoning:

Class methods
Basic principle: Persistance is a class behaviour and should be a class method
You need separation of concerns, so you put the database nitty-gritty in a DAO class, and use that from the class to implement the methods.
First problem: if you need to support different sets of DAOs you need to create them through a Factory. Second problem: not all persistence behaviours are specifically related to an instance of the class. For example List and Search methods: they return Class lists, not classes, and do not depend on an instance. So they are fundamentally static methods.
Third problem: you want to support inheritance on this class. As such, the persistence details differ from parent to child. If you have static methods, it's going to be a problem.

So you move on to the

Controller
Basic principle: Persistence methods do not belong to a single class, they are larger and thus they should be separated
Separation of concerns is needed again, so you need DAOs. This is a Utility class so methods are all basically static.
First problem: you need a Factory to create the DAOs if you want to support more than one persistence method.
Second problem: you want to support a hierarchy of Classes so you can't use a static class. You need to generate the Controllers through a Factory.
Third problem: you are offering an overcomplicated API to your developers.
Example of client code:

PurchaseOrder po;
PurchaseOrderController poc;
poc = PurchaseOrderControllerFactory.Instance.Create();
po = poc.GetPurchaseOrder(42);
// do stuff
poc.SavePurchaseOrder(po);

then I would start from scratch.

Start from behaviours
Basic principle: Persistence is not a behaviour. Behaviours are larger than persistence.
In your system there will be a Purchase Order subsystem. Your user will be able to interact with it only at high level (use case level). So,the methods will implement Purchase Order use cases. These methods will use DAOs, through a factory if needed, to access the database and do whatever they need to do.
In short, your PurchaseOrder is basically a DTO, a quick way of passing data around. It should not have behaviours.
Example of client code:

// It could be a factory if needed.
PurchaseOrderSystem pos = new PurchaseOrderSystem(); 

List<PurchaseOrder> transacted;
transacted = pos.TransactPurchaseOrders(john, 23);

// Show transacted purchase orders or whatever...
Sklivvz