Amarjit
Amarjit

Reputation: 311

MVC with DAO/VO - Which DAO should the Controller talk to?

Background:

I have a design pattern problem that I was hoping someone may be able to solve. I program in PHP but I believe DAO/VO is popular in Java.

I have been using MVC for many years now. I designed a shopping that was MVC but used procedural programming. Thus recently I decided to develop the cart again, using OO.

Problem:

The problem I was faced with was that my Product class did not make sense to have a RetrieveAll() method. E.g. If I had 10 products listed, from which instance would I call the RetrieveAll() method? I would have 10 choices.

Solution:

Thus, I found the DAO/VO pattern. Unless I have not researched this pattern enough - I believe that each DB table must have a Model + DAO. No model or DAO should know about another set of models or DAO's. Thus being encapsulated. The pattern makes perfect sense, pulling the database layer away from the Model.

However. In the shopping cart, my products are assigned categories. A category could be electronics, clothing, etc.

There are 3 tables: - Category (pid, name) - Category Item (iid, name) - Category Link (pid, iid)

From an MVC approach, it doesn't make sense of which DAO the controller should be talking to?

Should it be:

Please see here for example (image)

Upvotes: 3

Views: 4037

Answers (3)

Buddhi
Buddhi

Reputation: 2324

return type can be considered when deciding which dao method should go to which dao class, hence which dao should the controller talk to:

Implement one DAO class per Data Entity is more cleaner,

CRUD operations should go in to Dao classes, C-Create, R-Read, U-Update, D-Delete

Read operations are not like Create, Update, Delete, most of the time Read operations have different flavors when considering what they return.

for Read operations, return type can be considered when deciding which dao method should go to which dao class

following are some Business Entities and there Dao

Exchange -> ExchangeDao
Company -> CompanyDao
Stock -> StockDao

Upvotes: 1

MikeSW
MikeSW

Reputation: 16378

I'm not an expert in DDD either , but this is my opinion. This is the situation where the repository patern is applied. Basically, the Domain doesn't know nor care about DAO or anything else rpesistence related. At most knows about the repository inteface (which should be implemented at the infrastructure level).

The controller knows about the domain and the repository. The repository encapsulates everything db related, the application knows only about the repository itself (in fact the interface as the actual implementation should be injected). Then within the repository you have DAOs however you see fit. The repository receives and sends back only application/domain objects, nothing related to db acess implementation.

In a nutshell, anything db related is part and it's an implementation detail of the repository.

Upvotes: 1

Dmitry Kudryavtsev
Dmitry Kudryavtsev

Reputation: 17604

I'm not sure what do you mean by VO. Is it value object?

I'm a huge fan of the DDD (domain driven design) approach (though I don't consider my self as guru in it). In DDD you have so called Services. Service Is an action that operates on your domain and returns data. Service encapsulates the manipulation with you Domain data.

Instead of having the controller to do all the domain logic like what items to retrieve, what DAO's to use and etc (why controller should care about the Domain anyway?), it should be encapsulated inside the Domain it self, in DDD case inside a Service.

So for example you want to retrieve all the Category items of the category "electronics". You could write a controller that looks like this (forgive me if the code have invalid syntax, its for the sake of example):

public function showItemsByCategoryAction($categoryName) {
  $categoryId = $categoryDAO->findByName($categoryName);
  if(is_null($categoryId)) {
    //@TODO error
  }

  $itemIds = $categoryLinkDAO->getItemsByCategoryId($categoryId);
  if(empty($itemIds)) {
    //@TODO show error to the user
  }

  $items = $categoryItemDAO->findManyItems($itemIds);

  //@TODO parse, assign to view etc
}

This introduces at least two problems:

  1. The controller is FSUC (Fat stupid ugly controller)
  2. The code is not reusable. If you would like to add another presentation layer (like API for developers, mobile version of the website or etc), you would have to copy-paste the same code (expect the part of the view rendering), and eventually you will come to something that will encapsulate this code, and this is what Services are for.

With the Services layer the same controller could look like

public function showItemsByCategoryAction($categoryName) {
  $service = new Item_CategoryName_Finder_Service();
  $items = $service->find($categoryName);

  if(empty($items)){
    //@TODO show empty page result, redirect or whatever
  }

  $this->getView()->bind('items', $items);
}

The controller is now clean, small, and all the Domain logic is encapsulated inside a service that can be reused anywhere in the code.

Now some people believe that the controller should know nothing about DAOs and communicate with the Domain only by using Services, other says that its ok to make calls to DAOs from the controller, there are no strict rules, decide what suits better for you.

I hope this helps you! Good luck :)

Upvotes: 3

Related Questions