Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

n-layer business/service layer design

I’m trying to reevaluate our n-layer architecture and would love to get some suggestions based on your experiences. Here is our typical .NET n-layer (sometimes n-tier) design.

Project.UI
Project.Services
Project.Business
Project.Model
Project.DataAccess

DataAccess typically consists of Entity Framework 4 and Repository classes. I attempt to follow the Aggregate Root concept in order to avoid having a repository for table, easier said than done in my experience. I tend to have ~70% match between Repositories and Tables.

Model usually consists of my Entity Framework 4 entities, I've been using Self-Tracking EF entities with success.

Business is what I struggle with the most. I typically have a Manager class for every Repository. This class will contain methods like .Add() which will perform business validation before forwarding down to repository.Add().

Services, typically I will only implement this if in fact I am looking to create a web service based solution. This layer will be tasked with marshaling requests/responses between DTOs and entities. And most importantly provide the more coarse grained interface. For example a TradingService.SubmitTrade(), which is really a facade for a business transaction which might include AccountManager.ValidateCash(), OrderManager.SubmitOrder(), etc.

Concerns
My business layer is very entity centric, really it's just the glue between the entities and the repository, with validation in between. I've seen many designs where the Service Layer is what holds a reference to the repositories (in essence skipping the "business layer"). In essence it serves the same purpose as my Business layer, it does the validation, however its' responsibility (and naming) is a higher level, more coarse grained business transaction. Using the example above the TradingService.submitTrade() will not delegate to any business manager classes, it would itself query the necessary repositories, perform all the validation etc.

I like my design in a sense that I can reuse a business layer method in multiple service calls, however I hate the fact that for every repository I have a matching business layer manager, creating tons of extra work. Maybe the solution is a different type of grouping at the Business Layer level? For example combine individual Manager classes like PhoneManager and EmailManager (note I have Phone entities and Email entities) into a logical Manager class such as ContactsManager (note I don't have a "Contact" entity type). With methods such as ContactManager.GetPhones() and ContactManager.GetEmail(), etc.

I guess more than anything I am wondering how others organize and delegate responsibilities, whether they have the Service layer, Business layer, both, etc. What holds the ORM context reference, etc.

like image 596
e36M3 Avatar asked Nov 06 '22 03:11

e36M3


1 Answers

I tend to do what you outlined near the end of your concerns, and at the business layer group things into managers that make more logical sense from a business point of view.

Using Contacts for example, I certainly wouldn't have a PhoneManager or EmailManager. "ContactsManager" is a more useful grouping to me, accomplishing pretty much the same thing only with a lot fewer managers to deal with. From a business point of view, phone numbers and emails are just small pieces of a Contact anyway. Just because they have their own tables and entities doesn't mean they need their own manager. That doesn't mean that you can't reuse them. If you have a need to do work with email addresses in several places, ContactsManager can have the relevant methods.

What we tend to have in our environment is a database/entity layer, then a business layer that sits on the server and handles business rules and business logic. That business layer is exposed as a service via WCF to the client (or at least, stuff relevant to clients is).

It sounds like you already know what you want to do, so I'd suggest doing a bit of prototyping work on it and see how it works for you. :)

like image 153
Tridus Avatar answered Nov 15 '22 12:11

Tridus