views:

391

answers:

5

I've been working through the NerdDinner Tutorial and most of it makes sense. What I'm not sure about is why the Repository is used directly in the Controller and not the Model objects. For instance, if we wanted to implement our own membership system and it had an AccountController with a Login method, what would be the best solution for hooking it up? e.g.

Login(username,password){

    repo = AccountRepository

    account = repo.getLogin(username,password)

    //check account isn't locked

    //check account has been verified etc etc 

    //throw error or proceed to secure area

}

OR

Login(username,password){

    repo = AccountRepository

    account = repo.getLogin(username,password)

    account.login() //business logic is handled in Account (Model)

}

OR

Login(username,password){

    //no reference to repository

    account = Account

    //Account (Model) uses repository and handles business logic
    account.login(username,password) 

}

I'm suggesting having the Account object use the AccountRepository directly, instead of the AccountController getting the information from the AccountRepository and then passing it to the Account object e.g.

NerdDinnner style:

1 Login request comes in
2 AccountController uses AccountRepository to get login details based on request
3 AccountController uses Account object and passes in info from step 1
4 Account object processes request and notifies AccountController

What I'm suggesting:

1 Login request comes in
2 AccountController uses Account object to process login based on request
3 Account object uses AccountRepository to get login details
4 Account object processes request and notifies AccountController

The reason for the latter style is that after login details are returned from the AccountRepository there would be business rules to follow e.g. is account locked, is account verified etc If the first style is used the logic for getting the details and then using them is split over 2 steps. The latter style keeps all the logic together while still using the AccountRepository e.g.

Account.Login(username,password){
    repo = AccountRepository

    account = repo.GetLogin(username,password)

    //check account isn't locked

    //check account has been verified etc etc

    //throw error or proceed to secure area
}

I hope that makes sense.

+4  A: 

The "model" in mvc is a presentational model not a domain model. You can consider the model in MVC as a Data Transfer Object used by the Controller to feed the view engine. The controller is the only actor connected with the service layer.

Andrea Balducci
In the most basic implementation of mvc, the model usually ends up becoming the most basic interpretation of a domain model, to an extent. It's the objects you are working with. Whether or not you choose to make those models smarter than just DTO's as you suggest, would be up to how far you wanted to engineer the application. Granted, we all should strive for pure SOC, but some apps just don't need that level of sophistication.
Chad Ruppert
in small a small domain the presentation model and the domain model can be the same. But if you have a rich domain model or a service driven application you will end up with just simple DTOs.
Andrea Balducci
take a look at http://serialseb.blogspot.com/2009/05/my-mvc-best-practices-talk.html just to have an overview of an extreme use of models. Not so bad :D
Andrea Balducci
+1  A: 

Repository is an infrastructure concern. What you are doing is making your model rely on your infrastructure. That is kind of a backward way of doing it. It means that if you wanted to do things like use dependency injection you would then have to resolve your model from your container which doesn't make much sense to me.

Also the point is not really to keep everything in once place. You should be striving to keep your concerns separated into logical units. This way you can easily identify what part of the application does what. It also lends itself to testing.

Derek Ekins
A: 

I would avoid putting your data access inside of your model. This could quite possibly lead to a dependency in the model on the storage mechanism. I would typically place this logic in the service/business logic layer which would do the speaking to the data layer and models. In your case with only model and controller it would be the controller that does this job.

I think of the domain model as a group of toys or tools, that you pick up, use, manipulate, etc. The toys don't really care where they are stored, nor should they. You should be able to put a toy on the shelf, or in a toolbox. It doesn't affect the toy.

Chad Ruppert
+1  A: 

I would say that it is not the account that performs the login, but you use the account to login to the application, so calling the Login method on the account seems a little bit unnatural.

In Domain Driven Design there is a place for business logic which does not fit into the Account class: this is called a service. You can read more on DDD services e.g. here.

bbmud
+1  A: 

You should at least have another layer (not the controller) that is responsible to interact with a repository interface. Thil allows to change de UI (the controller is a part of it) for another. In this way, it doesn't matter if it's a command line, desktop or web interface.

In ASP.NET MVC I prefer to have the model (not my domain model, the MVC one) in a separate project, not into the MVC one. This allows to share the DTOs (the MVC model) with other kind of UIs.

bloparod