OOAD Design issue

I have two tables: tblCustomer, tblProduct:

tblCustomer:
    Id: Integer, auto-increament
    Name: Varchar(30)
    ....

tblProduct
    Id: Integer, auto-increament
    Name: Varchar(50)
    customerId: Integer
    ....

And two classes: Customer, Product:

public class Product
{
    private int id;
    private int name;
    /* Other stuffs */
}

public class Customer 
{
    private int id;
    private String name;
    private String phoneNumber;

    /* get-set and others stuffs */

    public static boolean add(Customer cus) {
        /* This is for insert a customer to tblCustomer */
    }

    public boolean addProduct(Product pd) {
        /* This is for insert a product to tblProduct with current customer Id */
    }
}

When customer register account, it call:

Customer cus = new Customer(/* ... */);
Customer.add(cus);

and when customer buy a product:

Product pd = new Product(/* ... */);
currentCustomer.addProduct(pd);

But my teacher said it not correct in OOAD (and even OOP) because Customer.addProduct is operate on tblProduct table, is it right? What is good design for this case?

** Update: ** Product haven't a pre-defined yet, when a customer buy a product, the store will make it and delivery to customer, so two same products is rare happen, so is tblCustomerProduct need?

Answers


Add a DAO tier that will contain the logical part of the methods save, delete, update, etc.

Here is how I usually do:

  • basepackage.domain: contains all your entities (data only, no logical part - in your case Product and Customer)
  • basepackage.dao: contains all your DAOs, only used to access the data, basically one per entity, each one containing methods such as findAll() : List<E>, findOne(K id) : E, save(E e) : void, etc.
  • basepackage.service: contains all your services, the logical part of the app. The services are the only ones that are calling the DAOs.
  • basepackage.presentation (or basepackage.web for a webapp): contains the HMI/web services/... implementation.

What your teacher probably means is that you need a third table, named something like "CustomerProduct". This table contains the links between customers and which products they've bought.

tblCustomerProduct:
    Id: Integer, auto-increament
    CustomerId: Varchar(30)
    ProductId: Varchar(30)

so, when a customer buys a product, you add this data to the table CustomerProduct. This will remove redundant data and also make deletion alot easier


Your teacher is right. It is not good Design because A class that you create should be cohesive. So that it should be responsible for doing the things that it can do. Here in your product class you have added customer id which is essentially a bad practice because A customer may purchase multiple products. This design will fail in that case. And also Product class doesn't need to know anything about the customer. All it has to know about is itself.

The relation between customer and product is an association which can be expressed as "customer buys product". So that customer id should not be there in product table.

Regarding the currentCustomer.addProduct(pd); method, it is not well suited because it is more suitable to product class rather than customer class.

The simple solution to your problem can be create a new class which can relate product and the customer.

For e.g.

CustomerProduct

customerid
productid

Inside this class you can add method like "AddProductForCustomer" and can write your database logic which will maintain the consistency.

Hope this clears your doubt.


In the table, the customer is assigned to a product, but in the method you give a customer and add a product.

So I would go for either a method pd.setCustomer(currentCustomer) instead of currentCustomer.addProduct(pd)

Or change the customer field in the product table to a products field in the customer table.


Need Your Help

Changing the font in Aquamacs?

osx emacs lisp aquamacs

I've recently had a need to do a bit of lisp editing and I found the nifty Ready Lisp package for OS X, which is great, except Aquamacs automatically uses a proportional font (which is idiotic, IMH...

How can I XML serialise to a memory stream and get the same results as if I'd serialised to a file stream?

c# xml-serialization character-encoding stream

I am working on an application that stores its documents in XML using the C# serialisation / deserialisation.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.