Comments

Should you split your ASP.NET MVC project into multiple projects?

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

 

As always, keep it simple!

If you enjoyed this post, please share it with your friends.

Hi, my name is Mosh Hamedani and I am the author of several best-selling courses on Udemy and Pluralsight with more than 130,000 students in 196 countries. You can see the list of all my web and mobile development courses on this website.

Related Posts

Tags: , , ,

46 responses to “Should you split your ASP.NET MVC project into multiple projects?”

  1. Sumant says:

    I think splitting up your app into different layers is the way to go because it makes your application especially mvc apps more testable & maintainable.

    Because what happens otherwise is that your controller methods become huge and if you are using EF then its code also leaks into your controllers.

    The end product is a mix of business logic + database access calls which is not all maintainable or testable.

    Also if you are using a pattern like Unit of work to handle transactions then it’s going to be a mess in your controller.

    Instead of that if you split your app into repository+core then your EF logic can be constrained in your repository and actual business rules in your core with controllers just calling those methods and in that process your controller methods remain clean & lean.

    • admin says:

      Please note the title of the post. I talked about “physical separation” of a project into multiple class libraries. Nowhere I argued against separation of concerns, having proper namespaces and classes each focusing on a single responsibility. What I discussed is that all these namespaces (eg Repositories, Services, etc) can be and should be part of the main project and moving them into separate class libraries does not add any values.

      • Geovani Martinez says:

        The title is “Should I split my ASP.NET MVC project into multiple projects?” – the word “physical” is not in there so hence the confusion from many readers. If it were not for your comment/clarification above I would still think your post was an opposition to “separation of concerns”.

  2. D Campanelli says:

    Yes you should!

  3. Hi Mosh,
    What do you think about abpframework, I heard of this from a coworker but after trying to make it to work, I find it more than a nuissance than a helping tool.

  4. Jahiron Rodriguez says:

    I don’t have many experience, but what I’ve see is that when make multiple tiers is to run the application in multiple servers. So I agree, separating the main project in multiple ones don’t add any value.

  5. L. Faranetti says:

    Hi Mosh,

    Maybe the term n-tier architecture means different things to different people, but majority consensus is that it implies separation of presentation, logic and data layers. Whether or not they actually cross process boundaries is another matter. In the early days of n-tier (1990s) the industry was happy enough to simply separate these into separate projects. Without separating into multiple compiled components, in a project with over a million lines of code, it would be a nightmare because a single checked in compilation error in one area of the project (easy to do on a huge team) would break the build for everyone. To some extent continuous integration techniques help with this, but not completely.

    But the case for re-usability is perhaps the most important issue here. Our ASPNet MVC project does have a business logic layer and a data access layer. Why? Well because it started out as an ASP.Net webforms project, but then we had WCF services that need to call the same business logic. Then we needed Winforms tools that performed administrative tasks, and needed to be sure they were running exactly the same business logic. Later some of this stuff became MVC and WPF and WebAPI, and guess what? It is hard to tell a company they need to throw away tens of millions of dollars of development money out the window, just so that they can rewrite functionality that’s already working well enough. If we had even tried to do that, the project would be dead and about 23 .net developers and many QA staff, dbas etc. would have been laid off and looking for a new job!

    Point is, separating projects is the pinnacle of reusability. Yes, MVC provides a nice separation of concerns and by some definition in inherently n-tier, but whether you call it n-tier or not…..

    …. modularity, in software design, is NEVER a bad thing.

    • Bola says:

      I totally agree with you @L. Faranetti. Separation aids maintainability and you could easily work on or fix a bug in a separate project and deploy it without necessarily redeploying the entire web application

      • admin says:

        I’m keen to know how many web applications you’ve seen whose parts get independently deployed! And I’m not talking about apps with micro services architecture. Just plan old ASP.NET MVC apps!

        • L. Farenetti says:

          To answer this, I will consider two types of projects,

          Type1:
          In the enterprise, where one guy is making relatively small apps (those intended to be short life-span projects) inside an IT department, separating business logic into multiple projects may be overkill. In terms of quantity of how many projects I’ve seen in this category, I’d say over the last 25+ yrs I’ve seen a high number of small internal websites that have one monolithic web app with no plan for separating to additional platforms or re-usability. This type of app is small enough that it’s no big deal to tear it down and rewrite it in a new language or methodology when a new shinier fad comes along.
          I’ve worked on no less than 50 of this type of application through my consulting business over the years, in some cases writing myself, or in other cases taking over someone else’s project or working on very small (2-3 people) teams.

          Type2:
          In commercial, public facing software it’s an entirely different story. These apps tend to be larger, are public-facing, have an indefinite life-span, often have hundreds of thousands or millions of lines of code, involve large teams, better planning, and some people have their entire career invested in one living breathing app. The quantity of these projects, I’ve worked on is fewer than the above, but the size of the project is much larger and the consequences of making bad choices is much greater and overall there is much more at stake. This type of project cannot afford to get caught in an infinite loop of being rewritten or re-architected every time an alternative language or technology becomes popular.
          I’ve worked on maybe 10 of this type of product, but these products are large enough that they are often segmented into multiple applications. An example of this was the app I talked about above, which must have shared business logic between a website, web services, fat client with limited network connectivity, etc.

          I think the point you are making with your question is that Type1 is more common for ASPNet MVC apps? In that case I would agree, but quantity of apps isn’t everything. The number of one-trick-pony apps written in ASPNet MVC is greater than the huge commercial product apps because many large projects came into existence before ASPNet MVC. Developer technology evolves too fast for businesses sometimes. Many shops are just now starting to move toward ASPNet MVC, yet Microsoft is already saying .Net Core is the future. Type1 projects can keep up with this pace, Type2 projects cannot.

          If we measure quantity as the size of the project instead of the number of individual .sln files, I have seen way more code that has business logic embedded in stored procedures! What a horror for MVC purists, right? Yes but some of those systems were rock solid. And in some cases stored procedures were approved and tuned by the database team which was in another building (guys that are not even .Net developers, they specialize in DB tuning and optimization)! And sometimes that database logic is consumed by multiple applications, some of which are not even written on the .Net platform.

          I think you can see where I’m going with this. We as developers tend to form our opinions based on our experiences, but none of us can be in all places at all times, therefore we all have much more limited scope than we realize, regardless of years of experience or total number of apps worked on (or even size and complexity of those apps). And we are known for our strong opinions 🙂

          Please don’t confuse this with the idea that ALL apps need to be separated into multiple projects. That is not my belief, but if starting a new MVC project today, that would be my personal recommendation. If nothing else, I would be vigilant about making sure database logic doesn’t end up in the controllers, for example at least I would want to see a special folder called “Services” or similar that interacted with the models and performed business logic. It doesn’t solve the problem for larger teams, but at least it helps to give that code an increased possibility of a future life, when ASP.Net MVC is no longer the hot ticket.

          Think of it like this, what if the company you’re working for one day decides the business logic or services layer one day needs to be in a different language, like Java, python, ruby, or whatever. Which will be easier to port? Code that is joined at the hip to an ASPNet MVC application, or logic that has no dependency on the web and is already separated into it’s own DLL?

          ASP.Net MVC may be the shiny new technology today, but history has shown that will change over time. MVC does a good job at many things, but it is still far from a state of perfection and this means Microsoft will evolve and change. It’s nice to have an easier migration path to the future for larger projects.

        • L. Faranetti says:

          Well I guess if my posts aren’t going to pass through the moderation filter only because you don’t agree with my opinion, I think maybe your course offerings will no longer pass through my purchase filter. Too bad, I was enjoying them.
          It’s not cool to censor opinions you don’t agree with. Disagreeing on architectural decisions is a normal and healthy part of software development.

          • admin says:

            I never censor! Sometimes it takes time until I approve comments.

          • L. Faranetti says:

            Ok. Thought you were not allowing my posts and mine alone because so much time had passed and they didn’t appear. Apologies.

          • admin says:

            Not at all! Sorry it came across the wrong way. It’s just random. Sometimes I check the comments a couple of times a day, sometimes not for a few days!

  6. Ahmed Amin says:

    Hi Mosh

    Nice Post, you are really amazing ….. 🙂

  7. Jorge Barrientos says:

    Great post Mosh, in my personal opinion I prefer the way you teach the path to develop an MVC App, I have developed in both paths, and splitting the app, in a certain way, just add unnecesary complexity to the project (handle security, interaction between layers and context that the MVC template makes for you), really benefits are unseen.

    • admin says:

      You touched on a great point that I missed in my article: unnecessary complexity that comes with this physical separation. I remember early days EF didn’t like its DbContext to be in a separate project. I’ve come across other examples that whatever framework we used didn’t like the idea of some of its artefacts being in a separate class library. So we’ve done this physical separation and brought unnecessary complexity for what? Just because it looks nice to have 3 projects clearly telling us what parts belong to what layers? Couldn’t we just use folders in the main project? BLL and DAL!

    • L. Faranetti says:

      I agree that it COULD add complexity, especially if separating the business logic is an afterthought (which it shouldn’t be!), but if the strategy is adopted in the early stages, it can be free of this burden.

      For example, security. Authentication and authorization should be the responsibility of the app and not the business logic or data layer, so that should not creep into your BLL or DLL. Your controller actions, in combination with ASP.Net Identity claims for example, are responsible for determining who the user is, and whether or not they are authorized to perform that action (and potentially the result they see in the view). Its an application-specific decision to be made.

      A BLL or DAL should not attempt to answer those questions. You should be able to just pass the UserID into the BLL, and in the spirit of claims based security, it simply takes your word for it that this is the person executing that action. There is no reason not to, since the BLL and DLL cannot be hacked into on their own. The application handles the act of logging in.

  8. Christ kho says:

    Hi Mosh,
    I think it depends on your project, and how scalable it should be, forexample; for SOA architecture, you should separate your business domain in projects and even to different solutions. Correct me, if I am wrong!
    Thank you.

    • admin says:

      Indeed for SOA projects you need to do that for “deployability” requirements. But even there, you may independently version and deploy Sales and Shopping to different nodes, but you wouldn’t have Sales.BLL and Sales.DAL deployed to different nodes!

      The target of my article is those standard ASP.NET MVC web apps with “Web, BLL and DAL” project pattern.

      • Christ Kho says:

        Great, that’s completely correct.
        Thank you for the response.

      • L. Faranetti says:

        Let’s say you have a requirement that’s not really an SOA per se, but you know that some subset of functionality needs to be exposed as a RESTful API, thus is a good candidate for Web API.

        Would you put your API controllers in the same project?

        • admin says:

          Good question! I mentioned two reasons for splitting a project: re-usability and independent deployability. In case of Web APIs, they’re already at the front of your application, and you’re not going to re-use them in another application. So, I’d ask the question: are you going to independently version and deploy this API? Again, in most applications, the entire web application goes through a build process and gets deployed in an automated or manual fashion. I’m not saying this is the case for every project out there. But in most projects, that’s the case.

          The whole point of my article is to think twice and ask yourself this question: “Do you really need to split this project into multiple projects? What values do you get from this physical separation in practical terms?” Just because it looks good or some book told you to do so are not good reasons! Remember, assemblies are units of reuse and deployment.

          • L. Faranetti says:

            Yes, actually in every project I’ve been involved in during the last 5-6 years, there was a requirement that the API was consumable by native mobile applications, and in some cases published to the customers as a RESTful way to access functionality or data.

            This meant it would be a bad idea to create a dependency between the API and the front end code, because the feature set in the API must constantly change, while the API does not have this luxury.

            If the web UI (MVC project with front end code) needs a new version with new functionality in the API, it can be progressed to version 2, version 3, etc. Now what if you have mobile (both phone and tablet) apps that depend on the API as well? All of these apps must be deployed to Apple’s app store, Google Play, Windows store simultaneously, and thousands of customers must download the update at the exact same time! Not only that, all these customers who have connected to API version 1 would find their code broken. Clearly not possible, it would put us out of business, it would break things for lots of customers and cause civil disorder.

            By keeping the UI and API separate, we can publish a new API V2, V3, V4 while keeping the old one up and running for some time period to allow existing mobile installations to continue to work, without breaking changes that affect everyone else. Meanwhile, the web UI, which is deployed much more centrally, can move forward to the latest and greatest API (which actually helps with testing the new API before allowing public availability).

            This of course is making a case for physical separation on the basis of deployability more than reusability, but they are advantages that always seem to complement each other.

            I agree with you that just because a book told us we should do something is not the only reason to do or not to do it, and the same is true for blogs. But, I thought your opinion was that it should never be done? Perhaps I misunderstood your position there.

            The one challenge I’ve seen, is a lot of small apps start out without physical separation, because it is assumed to be a small project or prototype, and thus not needed. But then it grows into something bigger, and by the time it is large, it becomes harder to create clear physical separation, because too many dependencies on the business logic and data access have been incorporated into the primary application!

            So, there is one school of though that says “never say never”, and that by creating the physical separation at the beginning, you open up much more possibility for future deployment or reusability cases. How many apps can we confidently build where we can say “mobile apps will never need to talk to this app”? Not many that I’ve worked on.

            Additionally, even if we never take advantage of the features of physical separation, it gives us good practice for the day we might need to work on extremely large apps in larger commercial software companies (where, in my experience there is always a DLL, BLL etc).

  9. Mark says:

    Ahhh, thank you for removing the giant question-mark I’ve had for all these years. I totally agree with you.

    I remember the first videos I watched many years ago where the instructor was separating projects and then referencing back to the original project. I remember following along thinking … “how is putting these into separate projects helping me?” It never made sense to me, so thank you for this article!

  10. Kshitij says:

    Hi Mosh,

    Sorry my question is in different context.

    I subscribed to your couple of courses on udemy. I would like to know your preference or experience on workflow kind of systems. I see many application has different workflows (simple examples are leave application, performance appraisal, standard request processing systems). All these workflow can be design in BPM tools/framework. Like Microsoft has WF and there are other framework/tool available in market like activi.

    1) What is your thought while designing these kinds of systems?
    2) Have you come across or implemented these systems?
    3) Which framework/tool you prefer to designed these workflow systems which can be easily integrate with asp.net application or web api?
    4) Whats the future of Mircosoft WF?
    5) Advantage of each tool/framework on each other

    I am sure, there are lot of people looking for expert advise on above questions. Also, there are not much help available on same topic.

    Hope you will find time to address me. Thanks in advance.

  11. Robert Tanenbaum says:

    First let me define my terms consistent with visual studio terms. A Project contains multiple objects that compile together as a single deliverable possibly as a library or dll. Projects relate to other projects through defined interfaces. A Solution combines multiple projects into a single deliverable for deployment.

    So I say ONE solution MANY projects for my MVC solution. My solution is a single web site that provides multiple applications to different user groups at my company. Separate projects provide strict separation of concerns and one solution allows them all to be deployed together.

    NOTE the MVC part is just for the UI layer. In the MVC user interface I make use of Areas to keep the controllers, UI models and views for each application separate for easy maintenance.

    You asked for a use case where the business layer or data layer would be reused. I have cases where certain tasks can be started manually by users going to the website MVC to perform but it could also be done by a batch process console application. Same business and data layer, two different UI layers.

  12. Tseng says:

    Your concusion is just plain wrong. It’s only good for hobbist sized projects.

    The main advantage of “physical separation” of the layers is to enforce the separation. When everything is in a single project, it’s easy to accidentally add a Dataaccess layer type inside your business layer class, or some type from WPF/ASP.NET.

    In one project, it’s not obvious, you don’t get any compile errors when doing so. When you have separate projects, then your business layer should have no references to i.e. EntityFramework, ASP.NET, WPF or UWP.

    When you then try to add a type from these unreferenced layers, you get a nice “The type or namespace name ‘IllegaTypeFromOtherLayer’ could not be found (are you missing a using directive or an assembly reference?)” error message thrown on your head by the compiler telling you: “Stop, what you are doing is wrong and violating the separation of conerns and decoupling”

    • admin says:

      Your main project (web project) still needs a reference to DAL project. A junior programmer can simply add a class that belongs to BLL in the DAL project! Who is there to stop it? I used to think like you but if you want to spend a lot of your focus on adding guards so people don’t make silly mistakes, you’ll end up adding more complexity than the value you get out of them. It would be easier and more valuable to educate people than put guards in the code and project structure, because no matter how strict you are, there are always holes that can be utilized to put things in the wrong place. Think about it!

      • L. Faranetti says:

        What would stop it would be the fact that the junior programmer doesn’t even have to have access to the source code of the DAL if we decide that’s too close to the database for him to be changing stuff, until he gains more experience. He can simply reference the compiled assembly in the MVC project, and then the details of the DAL are abstracted out, reducing the complexity and the learning curve.

        Usually when something is modified at the DAL level, on a large app it can affect a lot of people. The closer the code is to the actual database, the higher the risk. Imagine a sizeable software company, that has many products, some in .Net, some in Java, some Python, etc. and all of them access a database with 4000 tables. It’s actually kind of dangerous to turn an inexperienced or new employee loose in a project that allows them to modify a single class that could modify the database structure (like code first and migrations! Update-Database. Ooops! Big problem). Code first and migrations are nice features that work great for getting a project kicked off, but once the code base becomes substantial the database needs serious scrutiny before a change that affects the database is checked into the source code repo.

        To answer your question another thing that could stop the junior programmer from putting logic where it doesn’t belong is to have the repo set up to provide senior guys alerts when that project is changed. Plus a separate project helps the junior programmer think about the boundaries and what goes where. If all domain models are in a separate project, and only view models are in the MVC project, it helps them easily realize the difference instead of starting to add attributes to the view models and creating other problems.

        The techniques that help enable faster for very small projects often are not the same techniques that are ideal for more substantial applications or teams.

  13. Oleg says:

    Hi Mosh!

    I’m glad I found someone who has the same mindset on the subject as my CTO. I’ve been in fights with him for quite a while on this subject.

    In addition to reusability and independent deployability, there is also independent develop-ability. The simplest example I can think of is if I work on small changes, let’s say, in DAL, I don’t want to wait for my BLL classes and MVC/API controllers to recompile every time i make changes only in DAL.

    In a case of a single project how would you enforce contracts between layers?
    If interfaces and their implementations are defined in the same project, it’s so easy to just instantiate a concrete implementation of the interface and use it directly, hence introducing tight coupling.

    Boundaries between layers can be limiting sometimes, but most of the times it’s a manageable drawback, however, having those boundaries have a benefit of enforcing decoupling, which I find very important for a number of reasons, like less regression risks, easier technology swap or update (like moving from ObjectContext to DbContext in EF, for example) and so on.

    How would you address these concerns? Maybe I’m old school, I don’t know…

    • admin says:

      Oleg,

      It might be interesting for you to know that despite what I wrote in this article, I used to be a big believer of separating a project into multiple projects until 2 years ago. In fact, in one of my previous jobs, I suggested an architecture for a project that involved let’s say 5 domains, and for each domain I suggested 3 or 4 projects. So that solution would end up with 15 – 20 projects! One of my colleagues questioned me about the value of such splitting and I told him about all the theories of clean architecture and Uncle Bob and blah blah blah! I certainly had reasons for doing so.

      But over years, I’ve realized that practice and theory don’t always align. I’d rather be pragmatic than follow all principles out there. I used to be a purist and the more I tried to apply all these various theories in their purest form, the more dead ends I saw ahead of me. Because many of these principles simply do not align with each other. They’re introduced by different people in different contexts at different times.

      You argued about enforcing contracts and preventing people from making mistakes (eg instantiating a concrete implementation of a class where they shouldn’t). Read my comment to Tsen’s comment. Now here is my question for you: if you split a project into multiple projects to enforce contracts and apply guards, do you think that junior developer will not be able to make a mistake? He needs to new up a repository implementation and he cannot find it in one of the projects. He simply adds a reference to the other assembly and gets access to that class! As simple as that! Then all your guards are useless! Also, these days, plugins like ReSharper immediately suggest you to add references to other assemblies as you type the name of classes. I haven’t used Visual Studio 2017 but this feature will make it to Visual Studio sooner or later too!

      In one of my projects I promoted the use of repository pattern to encapsulate queries. We had complex queries and many of these queries were duplicated in a lot of places. So, I extracted these fat queries into repository methods and this way not only was the code cleaner and easier to read, but if there was a bug in the query, we had to fix it in one place. All good. Now, who was there to stop someone from using our DbContext and duplicate that query again? No one! If that DbContext was in another assembly, they could still add a reference. Let’s say they couldn’t. They could simply create their own DbContext and use to write that query. See where I am going with this? That’s why I’d rather educate my team members than put guards in front of them. That’s what code reviews are for.

      Also, easier technology swaps happens usually in text books, especially those in 1990s. I’ve never seen this in the real-world, like ASP.NET WebForms get replaced with ASP.NET MVC like a piece of cake! Most projects built with older technologies, often go through a complete re-write with a new shiny stack that is often radically different from the original stack, not in terms of the implementation, but in “philosophy”. Think of how we build SPAs with Angular or React and backend technologies these days. This looks nothing like when we used ASP.NET MVC to render the views on the server and use jQuery or other libraries to add some client-side functionality. And even that looks nothing like how we used WebForms and all these post backs to refresh a page.

      Complete re-writes don’t happen just because of a tightly coupled architecture which doesn’t allow technology swapping. It happens because people also like to start on a fresh canvas, on a green field, without any legacy baggages. They want to revisit the requirements that have been lost and twisted over 5 – 10 years. They want to revisit the UX/UI and use the modern tools and modern ways of building software. ASP.NET Core, Entity Framework Core and Angular 2 are good examples of these. They went through a complete re-write with a new “thinking”. Not just swapping out one component with other. And guess what? I bet they’ll go through another complete re-write in 5 to 10 years because the needs of the world will change and what they’ve architected today may not and most likely will not be applicable 5 – 10 years from now. And take into account that these are frameworks that thousands or tens of thousands of applications are dependent upon. So, these re-writes upset millions of developers but they still happen!

      Swapping ObjectContext with DbContext: if you properly encapsulate Entity Framework with your repository interfaces, then all you have to change is your repository implementations. The rest of your application that replies on repository interfaces will remain unaffected. All these artefacts can be in a single project, if they’re going to be deployed altogether (which is the case for most applications as I explained in my article).

      • L. Farenetti says:

        If you’ve always had the good fortune of being able to re-write applications when a newer technology comes along, I would say you’ve been blessed! In my career I’ve mostly only seen that luxury afforded on smaller and mostly internal facing projects. On larger projects for commercial software, where there are lots of customers across the country using the product set, lots of developers using multiple technologies, and a million+ lines of code total, chasing down Microsoft’s latest offering every few years is rarely feasible. Developers love the latest and greatest (including myself!) but what we want to do and what we must do for the benefit of the company is often different things.

        Think about it, if you have to re-write applications every few years, it would indicate the code being written is not particularly reusable!

        I have seen BLL/DLLs written in C# 3.0 that are still going strong, multiple different app types and UIs and APIS have been built on top of them. Reusable libraries just like the .Net framework itself.

        Microsoft has been adding to, not rewriting the .Net framework for about 15 years. Existing libraries do not and should not change as often once mature, too many outside customers depend on them. Not everyone is publishing libraries to customers but the concept is the same. Microsoft doesn’t reinvent their own wheel every time a new trendy philosophy comes along. .Net Core is a serious and major change, but it’s being changed because there is a very good reason, they need to eliminate the System.Web assembly among other goals.

        Yes, when there is a necessity to rewrite then rewrite.

        Some of those DALs I mentioned before were kept, because Entity Framework and LINQ were unable to perform comparably! Of course not, they are only wrappers on top of the bare metal technology underneath. The DALs were more bare metal ADO.Net and still provide the best performance, even if not the latest and greatest.

        • admin says:

          Again, following my reply to your other comment, are you REALLY going to re-use those BLLs and DALs in other projects? Some would say yes, maybe one day we’ll need that, so better to separate them from now. But this way of thinking often brings extra unnecessary complexity that eventually leads to a “design smell”. It’s exactly like how some developers abuse design patterns for the sake of flexibility.

          What I’ve learned from uncle Bob is: “Fool me once, shame on you, fool me twice, shame on me.” That basically means when you see a kind of change in one part of software, refactor it to make it flexible for changes of “that kind”. He taught me not to over engineer and design for hypothetical scenarios that may never happen. Otherwise, all the baggage to support hypothetical scenarios accumulate and eventually leads to design smell.

          So, back to the BLL/DAL scenario: are these BLL/DAL components going to be really re-used in other projects in this enterprise, or is it just some hypothetical scenario? Please note that here I’m talking about applications, not frameworks. As I explained in my article, frameworks are and should be designed with modularity in mind. But enterprise applications are different. Even if you have a million users, refactoring the internal structure should not impact your users as long as the application works. But for frameworks, that’s not the case. You cannot constantly change the structure of a framework because there are lots of other applications (not end users) depend upon them.

          So, let’s assume these BLL/DAL components are indeed going to be re-used in other applications in the same enterprise. I really doubt that the DAL part would be “independently” re-used in another project, because its main purpose is to support the persistence of what we have in that BLL. So, quite often (if not always), they get re-used together. If they go together, they’re highly cohesive and they should be one deployable unit, one assembly: MyProject.Core. This assembly can be re-used in two different projects: MyProject.Web (built with ASP.NET MVC) and MyProject.Desktop (built with WPF). In this case, MyProject.Core gets reused in two different projects indeed and that’s a perfectly valid scenario.

          I hope that better explains my view and resolves any confusions I might have created! 🙂

          • L. Faranetti says:

            Well one problem with making the BLL and the DAL the same unit is that on a project of large size, it’s very nice to have the option of changing out your data access mechanism. For example, when ODBC is no longer in fashion and you want RDO (for anyone old enough to remember these ;).. And when ADO.Net is no longer preferred, its easy to swap out with Entity Framework, and if you get bought out by a company that requires nHibernate (that happened to me!) you can easily move to that while only modifying the DAL as long as the BLL never goes deeper than dealing with IEnumerables.

            I think you and I have the same Uncle Bob, it’s just that we may be interpreting his words differently 🙂

            I agree, don’t over-engineer and don’t make a lot of assumptions about business requirements that may or may not appear.
            Examples of over-engineering:
            – unneeded complexity, like a lot of properties,methods, models or tables that cannot be directly mapped to requirements
            – object hierarchies that try to address “what might happen one day” with requirements
            – lots of UML or design docs that cannot be mapped to what is known today about user stories

            But, the decision to separate into physical DAL or BLL is an architectural decision that business requirements cannot really help with. To do so early in a project opens up a lot of doors to the future that may or may not be used, but IF they are used, you’ll be thankful to have made the decision. If the separation is needed, but not built in to the project early, it can lead to lots of regrets. We don’t want to tell someone we need to rewrite an app because we don’t write reusable code or that we made some very limiting architectural decisions! At least I would make sure it’s not my decision.

            I have worked on large apps where it was assumed “we can separate this later if needed”, but it became an absolute horror because there ended up being things like a dependency on System.Web in a DLL that needed to be deployed in a smart client scenario after the company grew!

            So, yes I do agree that we must always be cautious not to over-engineer, but we also need to be careful not to burn bridges behind us as we go!

            I really don’t think physical separation adds complexity. If anything, it makes it easier to work on because you always know what goes where, just as in an MVC we know the HTML/Razor is always under the views folder, request handling is in the controllers folder, etc. When working with multiple projects in Visual Studio, the additional projects are really just expanded/collapsed like additional folders, so there is no additional complexity. It encourages putting things in the right place and actually makes it easier to work on, not harder, as the application grows.

            My experience has been that most successful applications do, by their very nature, tend to grow into larger applications than originally expected. Nobody can predict this for most apps, so it’s better to create a pathway to future opportunity by creating physical separation.

            See also my other response about versioning the API separately. This sort of requirement is becoming more the norm than the exception for most customer-facing software, and even internal enterprise apps, for example when different departments might have the need to access the apps data from a mobile app.

  14. Kornél says:

    Shouldn’t when you are working alone at the weekend on a small project that will be used by few users. Maybe a POC project. So, small, quick (and dirty), alone are the keywords for one-big-project conception.

    If you see possibility growing in usage, you can imagine hundreds of customers, you should think in separated layers in well-separated naming classification (e.g. namespace) which can be a foundation of physical/network level separation later. In team-work, a good approach is the vertical and horizontal task/layer separation, this way is supported by multi-project solution architecture.

    Exchangeability and growth. Many projects start on a storage implementation (MSSQL) and finish on another one or more (Oracle+Redis+MongoDb) because of optimization. Entity framework significantly limits the options as many other ORMs as well. Your MVC controller shouldn’t know which storage implementation used in data access, if growing is on the table.

    So, your recommendation about project separation highly depends on the project size and type, future scalability and number of associated developers.

  15. Robert Tanenbaum says:

    Mosh wrote, “I mentioned two reasons for splitting a project: re-usability and independent deployability.”
    There is a third reason: improved maintainability.

    Whenever you can separate the presentation layer from the business layer and the business layer from the data layer as in the typical 3-tier architecture you provide a structure that encourages the loose coupling and strong cohesion and encapsulation of separate concerns that has proven over and over again to create more robust maintainable software.

    And like L. Faranneti as well as my own experience there really are times when you want multiple presentation layers for the same application. And in my case I also want one presentation layer for multiple applications where each application business logic and data logic is in their own projects separated from the MVC controllers and views.

    Also some of the applications on this website use an Oracle database, others use SQL server, and others consume or produce Excel sheets. So having separate .dll projects for each data layer is a very useful.

    There is real value in having separate project areas. It’s easier to assign different sections to different developers. Having defined interface to the .dll allows independent work and clean divisions of code that can be debugged separately and find errors more easily because they tend to be localized. I can also eliminate an application simply by not referencing the .dll and eliminate just that controller if an application becomes obsolete and in a flash the whole system is cleaned up with no repercussions on anything else in the web site.

    And sure, junior programmers can cause damage, but NOT AS EASILY. I have seen junior programmers who went and made every data item global and blew the whole concept of encapsulation out of the water. But if they have so little understanding of variable scope and why it’s important they are going to do even more damage when everything is in the same project space. That’s what code reviews are for.

    So for me, it will (ALMOST) always be one Visual Studio solution with multiple projects.

    • admin says:

      Hi Robert,

      Did you read my comment to L. Faranneti’s comment? The one where I talked about MyProject.Core. I’m going to update the article because I believe it applies to the scenario you mentioned in your comment too.

      You have multiple applications as part of a single website. Sure you may want to develop, version and deploy these applications independently. It’s a good candidate for putting each application into a separate class library. But it doesn’t make sense to have two separate projects for each application: Application1.BLL and Application1.DAL. The reason for that is that Application1.DAL is most often (if not always) used to support persistence of Application1.BLL. It’s very unlikely that you’re going to re-use that assembly on its own.

      I have to disagree with you on multiple projects improve maintainability and separation of concerns. You have maintainable software when you follow the single responsibility principle at various levels: methods, classes and namespaces. Dependency between these classes should always be from details to abstractions. Whether you have all these classes in one assembly or put them into separate assemblies, it has no impact on the as long as you follow the SOLID principles of object-oriented design. SOLID is about your classes and their associations. It doesn’t deal with physical separation into multiple assemblies.

      Assemblies, as I mentioned before, are units of versioning and deployment. You can divide a project into 3 assembles (Web, BLL and DAL) but have really fat classes tightly coupled to each other. So, does physical separation improve the maintainability in this case? Of course not! Once again, physical separation is all about versioning and deployment.

      • L. Farenetti says:

        Well I believe what Robert and I are both saying here is that having physical separation in multiple projects is not a substitute for SOLID principles or other practices that lead to good architecture, but SOLID principles do not attempt to provide answers for some of the things we’ve talked about, like deployment, training junior programmers, web service considerations, multiple presentation layers, one app talking to multiple database types, etc.

        You mentioned in your article update that there is no need for separate BLL and DAL, because the DAL only provides persistence to the BLL. Well that is not always the case. The original purpose for separation between the DAL and BLL is so that you can very easy change the data access mechanism (I mention this in another post but it’s worth mentioning again). Remember ODBC then DAO, then ADO. Then for a while, ADO.Net was the trend. Right now it is Entity Framework. But will it always be EF? Not likely if we look at Microsoft’s history.

        However, I think I understand where your perspective comes from here, because the advent of LINQ and Lambda expressions seem to almost encourage a tight binding between business logic and data (its so convenient that it makes separating them seem like too much extra work). Entity Framework itself is a DAL of sorts, an abstraction of the real database underneath (which is what the DAL was always intended to be). But lets say your application grows to be large, and one day there is a requirement to substitute some other ORM or data access mechanism. If your BLL sticks to business logic, then you only need to modify the DAL.

        Back to SOLID for a moment. If we look at everything that’s being encouraged today, whether it is SOLID or specific terms like separation of concerns, dependency injection, repository patterns, or even MVC itself. Do you know what they all have in common? They are designed to accomplish the SAME THING THEY WERE TEACHING US IN THE 80’s IN SOFTWARE ENGINEERING COLLEGE COURSES!! Two primary goals: loose coupling, and high cohesion. Clean architectures have always revolved around those two principles, even before OOP itself became popular (late 80s early 90s). Those two goals are what is driving every aspect of all of these new emerging patterns and techniques.

        So keeping that in mind, I think whenever you can decouple at logical tiers (presentation, logic, data), it is almost always preferable, and not much more work as long as you adopt it early in the project. If you wait too long, and the business logic gets tightly coupled with the data access, then usually there is nothing to stop the presentation code from getting tightly coupled to the business logic or the data.

  16. Antonio says:

    I think Mosh explained it very good. Actually He refreshed our memory in the first lessons of real software engineering.

    BLL/DAL/BAL or whatever people use is just a common thing in .NET projects, copied and inherit into new projects. Bad practice.

    But anyway, programming is like art. Different style, colors, layers, servers. Just mix it up that fits your purpose and goal. Who cares about rules. And every company has his own convention, regulations. Just like art gallaries, they are dictated by the artist. And I never saw 2 architects with exact the same solution.

  17. I think if you have a project with lets say 300 tables, then it makes sense to split up the entities, repositories, etc by some type of “bounded context” (I use that term loosely) into separate dll projects. Different developers can work on different parts of the application and you can deploy in more of a modular fashion during development or even decide to not develop that “bounded context” of the application for the first version. I like to group like entities together into a separate dll. Plus its about keeping your SANITY when you have a bigger project with over 100 tables.

  18. Hobby Jose says:

    I read this article bit late. Nice article.. From my experience, what developers follow without realizing if it is really required…

  19. sgeorge007 says:

    The 2nd option seems interesting for multi tenant application.
    Have separate projects for each customer. This will help during deployment, deploy one solution instead of deploying whole solution for one customer change.
    Please let me know if anyone has applied a similar approach in multi tenant solution.

Leave a Reply