Repository pattern and/or/vs business logic layer
I have a problem I want to know your opinion.
I am trying to use Repository Pattern. I have a repository object which load data to a POCO. I have also created a Business logic layer which adds a little bit of functionality but basically wraps the POCO. So in the end I have a BLL which loads DAO with usage of repository.
I am not very happy with this solution. I have a three layers but I feel that BLL is not providing enought functionality to keep it there. On the other hand I do not want to put my logic in the rep开发者_运维知识库ository layer nor data access layer?
So my question is where should I put logic for application? Which solution do you use(DAO + repo or DAO + BLL + rep or any other)?
There are two basic ways to think about business rules when designing your domain.
1.) The domain entities are basic POCO/DTOs. And you hand them off to domain services. These services could be as simple as another class, or they really could be actual services sitting on another server.
var user = repository.Find(x => x.UserName == userName);
if (userLogonService.IsValidUser(user, password)) {
userLogonService.UpdateUserAsLoggedOn(user);
}
repository.SaveChanges();
2.) The domain entities contain their own operation logic. This is closer to what many MVC patterns will follow. And since you asked, this is the model that I prefer.
var user = repository.Find(x => x.UserName == userName);
if (user.CheckPassword(password)) {
user.LogOnNow();
}
repository.SaveChanges();
Both are completely valid patterns. #1 has a discrete business operation tier, but suffers from an Anemic Domain Model. #2 can lead to big domain entities if you domain starts to become complicated, or if a model can do a lot of things.
EDIT #1: Response to John Kraft
Oven.Bake(myPizza) vs. myPizza.Bake()
I mostly agree. Do you have a single Oven service, or do you have dozens of available ovens stored in an oven repository where oven is just another domain entity? In #2, the oven is part of the domain. The way I tend to do domain modeling, most nouns are domain entities, unless you are 100% sure that there is exactly one of the thing.
But something does happen to pizza when it is baked.
interface ICanBeBaked {
int BakeMinutes { get; }
int BakeTemp { get; }
void Bake();
}
class Pizza : ICanBeBaked {
int BakeMinutes { get { return 15; } }
int BakeTemp { get { return 425; } }
void Bake() {
// melt cheese!
this.isBaked = true;
}
}
class Oven {
void Bake(ICanBeBaked thingToBake) {
// set the temp, reserve this oven for the duration, etc.
thingToBake.Bake();
}
}
My "DAL" (more of a home-grown ORM, which is another topic) is really a couple of layers in itself; one abstraction that provides repository and some active record pattern support, and below that is the actual data access code.
We have a minimal business layer at this point, but the real reason is that it's thin is that there's way too much (legacy) business logic embedded in web page code-behinds. As that gets refactored, I expect the business layer to grow and grow and grow.
This is fairly standard layering. You don't say why you're unhappy with your current stack, but keep in mind that the core reason for doing this is separation of responsibilities. You might also want to take a look at concepts of Domain Driven Design; it provides lots of food for thought for organizing code around business policies and practices, rather than specifically software issues. It's a very useful analytical tool to have in your toolbox.
精彩评论