“Should I split my ASP.NET MVC
project into multiple projects?” That’s a question that I get a lot! Almost
every week! The short answer is: NO!
I’m not entirely sure
how this trend started but I’ve seen some developers split an ASP.NET MVC
project into multiple projects: a web project containing the presentation
logic, plus two additional class libraries, often named [MyProject].BLL and [MyProject].DLL.
Tiers?
Also, it’s often
incorrectly assumed that this structure makes an application multi-tier or
3-tier. What is a
multi-tier application? It’s an application whose parts are physically
distributed to different computers in a network. Web applications are often
inherently multi-tired. In a web application we often have the following
tiers:
1. Client/Presentation
Tier: That’s the piece running inside the user’s browser.
2. Middle/Application/Logic Tier: That’s the part built with ASP.NET MVC (or
other similar server-side frameworks) running in a web server.
3. Data Tier: That’s the database, file system or any other kind of storage.
When we’re talking
about ASP.NET MVC, we’re only talking about the application or middle tier. Separating an ASP.NET MVC
project into three projects does not result in addition of new tiers in your
architecture. You
don’t deploy the DAL class library to a different computer! Most of the time
(if not always) all these 3 projects (Web, BLL and DAL) are compiled and
deployed in the same process on one machine; that is your web server. So, when
someone visits your web site, these three DLLs are loaded inside a process (or
more accurately an AppDomain) managed by IIS.
Layers vs Tiers
Layers and tiers
are used interchangeably by some but they are fundamentally different. Layers are about logical
separation, tiers are about physical separation: distributing pieces of a
software application to different computers.
Layer is something conceptual in a developer’s head. A class library is not a layer, neither is a folder. You can put
classes in a folder or a class library that belong to different layers and be
dependent upon each other. This is a sign of bad architecture and coupling. Putting these classes under a folder or a class library
like BLL and DAL does not immediately result in software with clean
architecture and good separation of concerns.
Despite that, my
argument is that these folders (BLL and DAL)
can and should reside in the main web project and moving them into a separate
class library does not add any values. It doesn’t magically create layers in
your applications.
There are 2 cases for splitting a project into smaller
projects: reusability and independently deploying those projects.
Reusability
One reason for
separating a project into multiple class libraries is re-usability. I’ve yet to
see the BLL or DAL part of a web application re-used in another application. This is what text
books from 90s used to tell us! But most if not all modern applications are too
specific and even in the same enterprise I’ve never seen the same BLL or DAL parts re-used
across multiple applications. Most of the time what you have in those
class libraries is purely to serve
what the user sees in that particular application, and it’s not
something that can be easily re-used (if at all).
Deployability
Another reason for separating a project into multiple
class libraries is about deployability. If you want to independently version
and deploy these pieces, it does makes sense to go down this path. But this is often a use case
for frameworks not enterprise applications. Entity Framework is a good
example. It’s composed of multiple assemblies each focusing on different areas
of functionality. We have one
core assembly which includes the main artefacts, we have another assembly for
talking to a SQL Server database, another one for SQLite and so on. With this
modular architecture, we can reference and download only the parts that we need.
Imagine if Entity
Framework was only one assembly! It would be one gigantic assembly with lots of
code that we won’t need. Also, every time the support team added a new feature
or fixed a bug, the entire monolithic assembly would have to be
compiled and deployed. This would make this assembly very fragile. If
we’re using Entity Framework on top of SQL Server, why should an upgrade
because of a bug fix for SQLite impact our application? It shouldn’t!
That’s why it’s designed in a modular way.
In most web
applications out there, we version and deploy all these assemblies (Web,
BLL and DAL) together. So, separating a project into 3 projects does not
add any values.
Use Cases
for Physical Separation
So, when do you
actually need to physically separate a project into multiple projects? Here are
a couple of scenarios:
1- Multiple presentation layers: Let’s say you’ve built an order processing application.
This application is a desktop application used by staff at your organization.
You decide to build a web interface for this application so the staff can
access it remotely. You want to re-use the existing business logic and data
access components. As I explained earlier, one reason for physical
separation is re-usability. So, in this case, you need to physically separate
this project into three projects:
·
OrderProcessing.Core (contains
both the BLL and DAL)
·
OrderProcessing.Web
·
OrderProcessing.Desktop
Note that even here I
don’t have two projects (BLL and DAL). I have one project, OrderProcessing.Core, that
encapsulates both the business and data access logic for our order processing
application.
So, why didn’t I
separate this project into two separate projects (BLL and DAL)? Because
the whole purpose of this DAL is to provide persistence for what we have in BLL.
It’s very unlikely that it’ll be used on its own in another project.
Also, following the
dependency inversion principle of object-oriented design, the dependency should
be from DAL to BLL, not the other way around. So, this means, everywhere you
reference the DAL assembly, you should also reference the BLL assembly. In
other words, they’re highly cohesive and inseparable. When you separate things
that are cohesive, you run into issues later down the track.
2- Multiple applications under a single
portal: Another use case that
one of the readers suggested is where you have multiple small applications that
are hosted in a single portal. So,
from the end user’s point of view these applications are not separate; they are
all different domains of the same application. But from development point of
view, each application is independent from the others. Each application
can have its own persistence store; one can use Excel, another can use SQL
Server, and the other can use Oracle.
In this scenario, it’s likely that these applications are
developed by different developers/teams. They’re often independently developed,
version and deployed, hence the second reason for physical separation.
For this scenario, we could have a solution with the
following projects:
·
OrderProcessing.Core (a class library)
·
Shipping.Core
·
CustomerSupport.Core
·
MainPortal (an ASP.NET MVC project)
Once again, you don’t
see the BLL/DAL separation here. Each class library (eg OrderProcessing.Core)
includes both the business and data access logic for its own domain.
The Bottom Line
Here are a few things
I hope you take away from this article:
·
Layers are not tiers.
·
Tiers are about physical
distribution of software on different computers.
·
Layers are conceptual.
They don’t have a physical representation in code. Having a folder or an assembly called BLL or DAL
doesn’t mean you have properly layered your application, neither does it mean
you have improved maintainability.
·
Maintainability is about clean code, small methods, small
classes each having a single responsibility and limited coupling between these
classes. Splitting a project with with fat classes and fat methods into BLL/DAL
projects doesn’t improve the maintainability of your software.
·
Assemblies are units
of versioning and deployment.
·
Split a project into
multiple projects if you want to re-use certain parts of that in other
projects, or if you want to independently version and deploy each project.
No comments:
Post a Comment