I'm interested in perceived "best practice", tempered with a little dose of reality here.
In a web application, do you allow your web tier to directly access the DAL, or should it go through a BLL first?
I'm talking specifically of scenarios where there's no "business logic" really involved -- such as a simple query : "Fetch all customers with surname of 'Atwood'". Scenarios where there's any kind of logic absolutely are gonna go through the BLL, so lets call that moo.
While you could encapsulate this method inside a BLL object, it seems to be somewhat pointless when often the signature will be exactly the same as that of the DLL object, and the code probably as simple as a one liner delegating the query off to the DLL.
If you choose the former -- employing a BLL object -- what do you call these objects? (Assuming they do little more than provide a query layer into the DLL). Helpers? QueryProviders?
Thoughts please.
Regards
Marty
In my opinion, you should ALWAYS use a BLL (Business Logic Layer) between your web tier and your DAL (Data Access Layer).
I appreciate that for some of the more "simple" queries, the BLL will closely mimic the DAL (e.g. Fetch all countries, Fetch all Product Types etc.), but to honest, even in your example:
(Fetch all customers with surname of
'Atwood')
there is "business logic" being expressed here - A desire for the data records to be filtered by surname, if nothing else!
By implementing a BLL from the start of a project it becomes incredibly easy to insert either validation or additional "logic" as and when the need may arise (and if your project is a commercial application, that need will almost certainly arise eventually if it isn't there at the beginning of the project). Adding in additional logic such as:
Fetch all customers who have spent
over $10000 this year
or
Don't allow customers with the surname of 'Atwood'
to purchase items over $1000
becomes significantly easier when a true BLL is involved, rather than trying to crowbar this logic into the web tier.
Bear in mind that with the kinds of queries above, we're almost certainly talking about multiple entities and database tables that will have to join together with specifically defined relationships in order to implement this functionality. Trying to achieve this by directly manipulating the DAL becomes messy since you'll be dealing with multiple entities and classes. A BLL here would greatly simplify your web tier code, since the BLL will encapsulate those entity relationships behind a greatly simplified interface.
This "separation of concerns" becomes increasing important when and if the need to change the user interface arises.
On at least two separate occasions now, I've worked on commercial web applications with a web site user interface, and have been eventually asked (due to business need arising from clients seeking greater integration within their software products) to produce a web service interface offering the exact same functionality as the web site.
Had I embedded any business logic within my web tier, I would have had to duplicate and re-write that logic when implementing my web service. As it was, I ensured that all business logic was encapsulated within BLL classes, which meant that I simply had to design a series of web service interface method calls, and plug these up against calls to methods on the BLL classes (I actually used the Facade Design Pattern in places to simplify the web service API).
In all, I can think of no reason to NOT include a BLL layer between my DAL and my web tier.
At it's easiest, when the BLL closely "mimics" the DAL, yes, there does appear to be a duplication of code and functionality, however, whilst being a little more typing, this also makes it relatively easy to implement.
When it's more involved (such as when significant business logic exists from the very beginning), the separation of concerns helps to reduce repetition (the DRY principle) whilst at the same time significantly simplifying future and ongoing maintenance.
Of course, this assumes you're doing all this "by hand". If you so desire, you can significantly simplify the DAL/BLL/UI layers by utilizing an ORM of which there are many!
(i.e. LINQ-to-SQL/Entities, SubSonic, NHibernate etc.)
I disagree with most the posts here.
I call my data layer in the web tier. If there is nothing in between the WEB/UI tier there is no point creating a layer "just in case." It's pre optimization. It's a waste. I can't recall a time the business layer "saved me." All it did was created more work, duplication and higher maintenance. I spent years subscribing to the Business Layer --> Data Layer passing entities between the layers. I always felt dirty creating pass through methods that did nothing.
After being introduced to Domain Driven Design by Eric Evans, I do what makes sense. If there is nothing in between the UI and the Data Layer then I call the Data Layer in the UI.
To allow for future changes I wrapper all my Data Layer classes in interfaces. In the UI, I reference the interfaces and I use dependency injection to manage the implementation. After making these changes, it was like a breath of fresh air. If I need to inject something in between the data layer and UI, I create a service.
Another thing I did, was to reduce the number of projects. Before I would have a project for the Data Layer, Business Logic, Business Entities and some type of UI Project -- what a pain.
I have two projects: The core project(entities, business logic and data layer) and UI projects (web, web services, etc...)
For more information I recommend looking at these guys:
- Develop with Passion
- Jeffrey Palermo
- David Laribee
You need to distinguish BLL objects (what the heck are these anyway? Domain objects anyone?) and Services. Your domain objects should have nothing to do with your data access layer. As far as web tier goes, it can treat your repositories (think IRepository
) just like any other service it can freely use.
So the bottom line is: yes, web tier can use DAL directly provided it is property encapsulated and is represented as a standard Service Layer service.
Even when it is on;y one line in the BLL making a similar call to the DLL, the abstraction allows you to add business logic in that layer without having to affect any other layers. It might not look like this is likely now, but whoever has to support the application after you will thank you for using patterns like this when changes do come about.
As for naming, I have my core object, say a NameChange, then I will have a BLL object that is a person that accepts a name change object, then I will have a DAL/Entity object called a Person. The business Person object is within the BLL namespace, and the DAL/Entity Person object is in the DB namespace (I would have chosen DAL if I'd built it originally).
We refer to this layer as a Controller Class [layer] which encapsulates the DAL from the web tier. The controller layer may or may not have any business logic whatsoever, it does helps to segregate the DAL from the presentation layer and keep them independent [to some extent].
We've tended to use the facade pattern for access, though our project that we use it on is sizable, I think it may prove overkill on a smaller project.
Essentially:
UI -> BusFacade -> BusinessLogic -> DalFacade -> DataAccessLayer
the facade makes for a nice/clean approach from the UI, and forces you to standardise on your naming conventions as that single point of entry has a number of methods.
BusFacade.GetCmsSiteMap()
BusFacade.GetProductGroup()
etc.etc.
While it would be possible to go directly from Presentation layer to DAL, you're skipping the BLL which often requires authentication...