views:

221

answers:

5

Upon reviewing a bunch of MVC style web applications, I'm noticing that it's common to have a very large service interface sitting in front of the business layer. The implementation of this interface usually includes a bunch of DAOs. So you have something like:

public class FoodServiceImpl implements FoodService {

  private FruitDAO fruitDAO;
  private VegetableDAO vegetableDAO;
  private MeatDAO meatDAO;

  // ... DAO injection stuff

  public List<Meat> getMeat() {
    return meatDAO.getMeat();
  }

  public void addMeat(Meat meat) {
    meatDAO.add(meat);  
  }

  public List<Fruit> getFruit() {
    return fruitDAO.getFruit();
  }

  // ... tons of methods that mostly just delegate to DAOs

}

Assuming that your DAOs aren't concrete in the first place, why not just expose the DAOs to the next level up?

So instead of:

// assume foodService is injected at runtime
public void controllerMethod() {
  foodService.getFruit();
  foodService.getMeat();
}

You just have

// assume DAOs are injected at runtime
public void controllerMethod() {
  fruitDAO.getFruit();
  meatDAO.getMeat();
}

On one hand it looks kinda nice to have the entire guts of the application wrapped up in a single interface.... on the other hand you can end up with a giant interface whose implementation does nothing much more than delegating to DAOs.

I can see that it's nice to manage all of the DAOs in one place. I can also imagine that this pattern would be useful if the same DAOs were going to be used via multiple services.

Is this considered a "best practice" when starting a web application, or does it only apply when a certain level and type of complexity is expected?

+3  A: 

There is only one reason for making a class: to hide some details of the implementation etc behind a fixed boundary. In this example, you have a service called FoodService, and an implementing class that knows about the various DAOs. So what are you hiding?

It looks like two things:

  1. the fact that you have those kinds of food items
  2. the way they're stored.

If the way they're stored can never change, then you may not need this. But if your DAOs are ever replaced with a different mechanism -- say a distributed Google BigTable -- you might prefer not needing to touch all your code changing the types.

Of course, there's always the chance that you'll start carrying HealthAndBeautyAids, and so need another class. (In fact, might you not be better off having a method that tells you what the kinds of things you can access are and then have methods that access them given type?)

Charlie Martin
Ok, but if the way I access data ever changes, I need only create a different set of concrete DAOs. If I didn't have this service interface I still wouldn't have to change any code since I'm never calling a concrete DAO in the first place. The fact that I have a DAO doesn't mean that I know anything about what the DAO is doing. (I'm not actually using this pattern currently, I'm just seeing it in a lot of sample applications and they don't seem to be doing much with the service but delegating to DAOs)
Boden
What if the change requires that addMeat() has to not only interact with the MeatDAO, but also the VegetableDAO and RecipeDAO? And what if multiple components need to addMeat() functionality?
matt b
If you think there will never ever be a change in the FoodService layer that will change the way you deal with the persistence layer, then there's no possibility of change; it follows you don't need it. I'd bet money against, though.
Charlie Martin
Makes sense, thanks.
Boden
+7  A: 

I think it makes more sense to inject a service layer because it knows about units of work. If your use case requires more than one DAO to participate in a unit of work, a service is required to "own" the transaction.

Besides, it's the essence of service oriented architecture. Forget about WS-*; services map to use cases and business processes.

duffymo
+4  A: 

Assuming the entire backend isn't just one giant CRUD API, you will often see business logic invoked in the service layer. The business logic might be directly in the service methods themselves (a.k.a. "Anemic Domain Model") or the service layer must just be responsible for invoking business methods on the entities passed to/from the DAO layer ("Rich Domain Model"). You might also see things like security or auditing and other kind being done in the service layer. Alternatively, cross-cutting concerns such as security or auditing might be applied to the service layer via Aspect-Oriented Programming (AOP).

cliff.meyers
+2  A: 

MVC is mostly a presentation pattern, most non-trivial systems uses a layered approach where at least you have the presentation layer, the business layer, and the data access layer. In your case, you CAN expose directly the DAOs but keeping a business layer in the middle serves to better encapsulate the business logic and aids to the system extensibility. Suppose you have a new requirement on where to store the meat:

if (meat.expirationDate-today >= 5 days)
   FridgeDAO.store(meat)
else if (meat.expirationDate-today <5 days)
   FreezerDAO.store(meat)
else 
   discard(meat)

If you expose directly the DAOs, you need to add the business logic to the presentation, and you risk having your business logic scatter around and having to rewrite it if you change your presentation technology (or if you want to expose your functionality as webservices). Using an interface as an entry point for the business layer furthers decouples the presentation and the business logic.

GClaramunt
A: 

Best way of doing remoting is not to do remoting at all.

Doing your code in layers is fine, but you do not have to force the layers by creating remoting APIs. Anyone that does that without any real architecture need (i.e. performance analysis, etc.) is just throwing buzzwords around or creating a need where there isn't any.

Remember, a programmer's time costs more than hardware in the bigger picture.

Archimedes Trajano