1

Typically I have started new projects with a solution containing:

  • Web project: contains the ASP.NET MVC or Web API controllers, Javascript code etc. Makes calls to class library

  • Class library1: contains DbContext, EF data model, a class with CRUD methods to interface with Db via the DbContext and various "utility" methods

  • Class library2: contains only POCO classes. This library is referenced by both the web project and library1

Ok, that works well, but when the amount of "business logic" starts to increase, this gets kinda messy, since I start putting in more rules that the business gives you. Makes me think there needs another "layer" or library where we put "business logic" that really is above/beyond just getting a data returned as a filtered list of POCO objects. Things such as checking attributes of orders based on some rules defined by some group within the business.

My question then is: would you force every call from the client layer to go through the business library (see image below case #2), even for simple cases where you just need a simple list of lookup values of some sort?

enter image description here

1 Answer 1

2

This question is likely to attract opinionated answers. My take on is - yes I would force everything to go through the business library.

To have consistency more than anything else really, this way you can be sure:

  • A new member of your team is not trying to understand why some of the DB operations are happening through a different layer compared to other ones.
  • When you (or some other developer) are adding / removing functionality that belongs to interacting with DB, the location of it is well known.
  • When there's a problem regarding the DB layer / access / queries - simpler to locate the problem.
  • If you are testing that layer / methods - we find it to be more convenient to have everything in the same place. (Testability definitely increases) We still split the stuff across files.
  • We use Dependency Injection - so if you need DB access, you just inject the interface which sets up the connection for you and you're done.
  • Depending on how your setup is, if you're logging DB related stuff separately (monitoring the QoS of queries separately as an example) this also ensures that you don't end up adding that custom logging all over the code for those simple lookups.
  • Makes the dependency chain more manageable.

Now - this is not to say that it doesn't get complicated, it does. However there are further ways which you can split things, you don't necessarily need to have a gigantic DBContext class which is handling N number of different queries, depending on our design, we might end up splitting it with partial classes so different functionalities end up on different files, their tests also map to different files; we think this improves overall maintainability.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.