Repository pattern and/or/vs business logic layer - c#

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 repository 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.

Related

Where to put the method. Service layer ( BL ) over repository?

I'm confused about one thing. I've used a repository pattern (not generic) in my previous mvc apps and I used to include some kind of business logic there. At this moment I read about service layer pattern where should be included BL. But now I don't know if there is more abstraction and extra code instead of cleary/readable and efficient code.
I want to implement a method like this
public void ChangeActiveField(bool isActive, int id)
{
var objectToUpdate = _context.FirstOrDefault(x=>x.id==id);
objectToUpdate.IsActive - isActive;
_context.Entry(objectToUpdate).State = System.Data.Entity.EntityState.Modified;
_context.Save();
}
In this code there is a bit of business logic where I change state of one field and after that I update this.
Should I make it in service layer and then use simple repository update method liek this: ?
public class MyService
{
private readonly IMyRepository = _myRepo;
MyService(IMyRepository myRepo) //it's injectable
{
_myRepo = myRepo;
}
public void ChangeActiveField(bool isActive, int id)
{
var myObject = _myRepo.GetMyObject(id);
myObject.IsActive = isActive;
_myRepo.Update(myObject);
}
}
Is it better aproach? Does it make better separation? Or it's too sophisticated and overwrite?
Thank you for your help.
Best regards.
In general repository should encapsulate only the logic of accessing database (initialization of context, transactions, connections and etc.). It is very common to create a generic CRUD repository and reuse it for all your business entities.
All the business related logic should be placed in business layer(service layer).
The major benefits of this approach are:
Testability - you can test your business logic without relying on concrete repository implementation by injecting fake repositories(stubs).
Decoupling - neither your business layer nor your UI are not coupled to specific database, If tomorrow you will decide to migrate your database for example from SQL server to Redis(NoSQL database), your changes will be contained on repository layer only.
Maintainability - there is a clear separation of concerns for each layer: UI - interaction with user, BL - implementation of business logic, Repository - interaction with DB.
In my experience having a business layer (no matter how simple it is at the beginning - it's often grows up together with your project) is always a good idea.
By the way some developers consider repository as an unnecessary layer of abstraction in case that you use EF (in a way EF database context is a repository...).
One thing I've learned, is that the major effort is not a development phase of a project it is it's maintenance and upgrades - and here having a business layer a significant impact.
Disclaimer: It is my subjective opinion based on my experience

Unit of Work through tiers

I'm refactoring an existing MVC.Net application to include the unit of work pattern to make data management a bit more obvious and straight forward.
The application is currently split into
Presentation/UI (MVC Controllers delivering views OR JsonResults for AngularJS)
Business Logic (Containing well... business logic)
DAL (Repositories and EF)
I'm having a hard time trying to figure out how I need to be structuring dependency injection and UoW passing to keep things sensible and testable.
I'm anticipating something like the following to be an example:
public class SomeMVCController : Controller
{
private readonly IStoreFrontLogic _storeFrontLogic;
public SomeMVCController(IStoreFrontLogic storeFrontLogic)
{
_storeFrontLogic = storeFrontLogic;
var uow = new UnitOfWork(User);
_storeFrontLogic.UnitOfWork = uow;
}
public ActionResult SomeRequest()
{
var myViewModel = _storeFrontLogic.OffersForUser();
return View(myViewModel);
}
}
public class StoreFrontLogic : IStoreFrontLogic
{
public UnitOfWork unitOfWork;
public OffersModel OffersForUser()
{
//some logic taking into account the current user in the uow
var prevOrders = unitOfWork.OrdersRepo.GetUsersOrders();
// special offers logic
return specialOffers;
}
}
Does this seem sensible?
I'm not too keen on the requirement to manually push the uow into my logic classes whenever they're required. Is there a more sensible way?
As I said above, this is hard to answer without a specific question or specific domain model but I'll give it a shot.
My understanding of such things is focused pretty heavily through a Domain Driven Design lens.
First of, you should read this series of papers on effective aggregate design. The fact that you need units of work and to do queries from inside your domain classes implies that your model needs work.
Some other thoughts on UOW - having uow produce your repositories is good, but I think you will likely start hitting lots of difficulties with implementation. UoW is super useful in small targeted areas but is very difficult to implement across an entire application. What for example happens when you save? Can you never use EF directly? Is everything thread safe? You might want to simplify what you are trying to achieve.
In your example uow can be scoped to the HttpRequest. Many IoC containers (eg Structuremap) provide a simple way to configure this. You can then have a post-action filter (or even better an OWIN module) to attempt the commit (what happens if there are errors is yet another implementation difficulty to deal with). This will eliminate a lot of the property-assignment nonsense
I'm not sure what type of object is your StoreFrontLogic. It doesn't seem like a domain entity but it contains significant business logic. It could be something similar to a transaction script, but in that case the uow should be fully internal to it.
Is it a stateless service? In that case everything that method uses - orders for user included - should be passed in via a parameter.
If, on the other hand it's an entity then it shouldn't access the database at all, it should already have all orders for the user. Purposeful database denormalization can help quite a bit here.
At the very least pass uow as a parameter to OffersForUser rather than expecting for a property to be set.

Rich domain model. Anti anemic domain model

A lot of discussions, like this and this, go with RICH DOMAIN MODEL
and there are 2 strong reason about amenic, like 1 and 3:
Now let's say that I need to make sure that I need to validate that
the product exists in inventory and throw exception if it doesn't.
so there is a question: If we don't need an object to be dependent on ISomeRepository like service, can we just make this:
public void Order.AddOrderLine(IEnumerable<Product> products, Product product)
{
if(!prosucts.Contains(product))
throw new AddProductException
OrderLines.Add(new OrderLine(product));
}
and call it like this:
Order.AddOrderLine(ISomeRepository.GetAll(), product);
It sounds like there's a missing concept in your domain here. I'd think about introducing some kind of StoreInventory entity, such that products move out of the inventory and into an order (this is called 'picking' in many commerce domains).
interface StoreInventory
{
IEnumerable<Product> AvailableProducts { get; }
Product PickProduct(guid productId); // This doesn't have to be an Id, it could be some other key or a specification.
}
void Order.AddOrderLine(StoreInventory inventory, Product product)
{
if (!inventory.AvailableProducts.Contains(product.Id))
throw new AddProductException();
var item = inventory.Pick(product);
OrderLines.Add(new OrderLine(item);
}
This would seem to be more closely aligned to reality to me. But as always in DDD, only your domain experts can tell you how things are supposed to flow.
This also seems more extensible in the future, for example with this model it would be easy to introduce multiple stores - each with their own inventory.
If you read about DDD, you would see that Repository is core concept of DDD. In DDD, repository is part of domain and says what kind of behavior the domain requires from it's persistence to work. In your case, you could simply pass the repository into the method and have the method pull the necessary data.
public void Order.AddOrderLine(ISomeRepository repo, Product product)
{
if(!repo.ProductExists(product))
throw new AddProductException
OrderLines.Add(new OrderLine(product));
}
// call it like
Order.AddOrderLine(someRepository, product);
I think the problem of your confusion is that repository, or more precisely, it's abstraction, is often tied to the persistence itself. Which is actually misconception caused by misunderstanding of the whole pattern. Correct repository consists of 2 parts: the abstraction, usually represented by interface, which defines what kind of operations the domain requires from the persistence. And the concrete implementation, that implements those operations over used persistence technology.

How can I design a business logic rules to be re-usable between data access and domain "services"

I am using MVC3 with C#, NHibernate as ORM and StructureMap as IoC container
Maybe my terminology is of, but I will try a simple example
Say I have a domain object:
class Product
{
decimal Price;
}
Let's say we allow certain promotions, I now want 2 functions:
GetAllDiscountedProducts() //To list all discounted products
IsDiscounted(Product p) //Check if a given product can be discounted
The business rule to determine if a product is discounted is if it's price is above a certain value, let's say anything above $50 is discountable
Since I am using NHibernate for data-access, I tend to use QueryOver syntax, so GetAllDiscountedProducts could be :
//GetAllDiscountedProducts()
session.QueryOver<Product>().(p => p.Price > 50.00)
But as I used data-access-specific query for the business rule, I would have to duplicate the logic for IsDiscounted
bool IsDiscounted(Product p)
{
return p.Price>50;
}
Is there a way to centralize the business logic?
This is were the Domain layer comes in to the picture . You should have a Product.Domain project that sits in between your Nhibernate Layer and Controller Level . The Product.Domain should have a ProductBLL class that have a method
bool IsDiscounted(Product p)
{
session.QueryOver<Product>().(p => p.Price > 50.00)
}
This method should be used all over the application to get discounted products.
You can have another method that return all Discounted Products.
GetDiscountedProducts()
{
session.QueryOver<Product>().(p => p.Price > 50.00)
}
Remember domain layer is there for centralizing all your domain logic, and there should not be any domain logic either in UI Layer or in Data Layer.
The Domain is the Logic that is the real point of the system. Domain Logic changes should happen only one place , that is the Domain Layer.
Start the Domain Layer by placing the behavior of domain in to separate subroutines and as the system gets more complex, break them into separate classes. As the complexity increases more divide the classes into separate namespaces and starts to use Dependency Injection.
Initially you will have one routine for each user action. Then you bring in more classes and objects. Rather than one routine having all the logic for a user action, each object takes a part of the logic that's relevant to it.
In short development of your domain layer will be evolutionary process.
Please see this post
http://nhibernate.info/blog/2009/09/07/part-8-daos-repositories-or-query-objects.html
it explains how to add a layer on top of the mapping to perform business functions.
you probably want to pass the discount threshold in so that you aren't changing you domain object every time the business changes their mind.

Save Me on a Business Object

I've commonly seen examples like this on business objects:
public void Save()
{
if(this.id > 0)
{
ThingyRepository.UpdateThingy(this);
}
else
{
int id = 0;
ThingyRepository.AddThingy(this, out id);
this.id = id;
}
}
So why here, on the business object? This seems like contextual or data related more so than business logic.
For example, a consumer of this object might go through something like this...
...Get form values from a web app...
Thingy thingy = Thingy.CreateNew(Form["name"].Value, Form["gadget"].Value, Form["process"].Value);
thingy.Save();
Or, something like this for an update...
... Get form values from a web app...
Thingy thingy = Thingy.GetThingyByID(Int32.Parse(Form["id"].Value));
Thingy.Name = Form["name"].Value;
Thingy.Save();
So why is this? Why not contain actual business logic such as calculations, business specific rules, etc., and avoid retrieval/persistence?
Using this approach, the code might look like this:
... Get form values from a web app...
Thingy thingy = Thingy.CreateNew(Form["name"].Value, Form["gadget"].Value, Form["process"].Value);
ThingyRepository.AddThingy(ref thingy, out id);
Or, something like this for an update...
... get form values from a web app ...
Thingy thingy = ThingyRepository.GetThingyByID(Int32.Parse(Form["id"].Value));
thingy.Name = Form["Name"].Value;
ThingyRepository.UpdateThingy(ref thingy);
In both of these examples, the consumer, who knows best what is being done to the object, calls the repository and either requests an ADD or an UPDATE. The object remains DUMB in that context, but still provides it's core business logic as pertains to itself, not how it is retrieved or persisted.
In short, I am not seeing the benefit of consolidating the GET and SAVE methods within the business object itself.
Should I just stop complaining and conform, or am I missing something?
This leads into the Active Record pattern (see P of EAA p. 160).
Personally I am not a fan. Tightly coupling business objects and persistence mechanisms so that changing the persistence mechanism requires a change in the business object? Mixing data layer with domain layer? Violating the single responsibility principle? If my business object is Account then I have the instance method Account.Save but to find an account I have the static method Account.Find? Yucky.
That said, it has its uses. For small projects with objects that directly conform to the database schema and have simple domain logic and aren't concerned with ease of testing, refactoring, dependency injection, open/closed, separation of concerns, etc., it can be a fine choice.
Your domain objects should have no reference to persistance concerns.
Create a repository interface in the domain that will represent a persistance service, and implement it outside the domain (you can implement it in a separate assembly).
This way your aggregate root doesn't need to reference the repository (since it's an aggregate root, it should already have everyting it needs), and it will be free of any dependency or persistance concern. Hence easier to test, and domain focused.
While I have no understanding of DDD, it makes sense to have 1 method (which will do UPSERT. Insert if record doesn't exist, Update otherwise).
User of the class can act dumb and call Save on an existing record and Update on a new record.
Having one point of action is much clearer.
EDIT: The decision of whether to do an INSERT or UPDATE is better left to the repository. User can call Repository.Save(....), which can result in a new record (if record is not already in DB) or an update.
If you don't like their approach make your own. Personally Save() instance methods on business objects smell really good to me. One less class name I need to remember. However, I don't have a problem with a factory save but I don't see why it would be so difficult to have both. IE
class myObject
{
public Save()
{
myObjFactory.Save(this);
}
}
...
class myObjectFactory
{
public void Save(myObject obj)
{
// Upsert myObject
}
}

Categories

Resources