Search code examples
architectureviewn-tier-architecturebusiness-logic

Enterprise Architecture for ViewModel / Business Logic


This is a high-level project organization question.

What is the "proper" way to organize a project/solution (Visual Studio) which will contain many sub-applications?

This must be a common problem in large, enterprise-size projects. Can anyone point me to white-papers/books/links to help with deciding how to structure this?

Learn Enterprise Architecture in 24 Hours would be perfect, but doesn't seem to exist.

Our first attempt followed a 3-tier service architecture, but in addition to generic business functions (ProcessOrder(..), BalanceAccount(..), etc.) we also need application-specific data.

Following n-tier architecture, all applications would still need to go through BLL -> DLL to get any info (ViewModel, app-specific data).

Some model classes (BOM) are generic enough to be used throughout (Order, Bill, Account, Client, etc.)

One option is to lump all business entities under the same Enterprise.BOM project and have multiple namespaces - some global at root, some application specific for ViewModel classes.

Then BLL and DAL tiers would follow the same organization - each application gets its own namespace and thing which are used everywhere are put at root namespace.

But as number of applications grows it will be a challenge to reuse existing objects/processes (i.e. every application might need to do something with Bill info, but shouldn't define its own Bill class and instead use existing classes from BLL/DAL).

Another direction being mandated from the top is to develop everything in SOA-izable way: "application" effectively becoming the views / workflows with all process-business logic defined in BLL so "applications" (basically UI) can be replaced with a service tier to expose functionality to outside systems.

If relevant, we're a .NET shop with Rules Engine for some stuff but no Workflow (although it's possible in a year or two so future WS integration is important).

Thanks in advance!


Solution

  • Learn Enterprise Architecture in 24 Hours would be perfect

    I wouldn't trust it even if it did exist :) Keep in mind that there is no one true way to architect an enterprise. There isn't a single pattern that's better than all the rest in every situation. Your enterprise is going to find its own way. There will be trade-offs, there will be compromises, etc. Some things will make sense to the developers, some things will make sense to the users, some things will make sense to management... But everything should make sense to the business.

    That being said, take any advice here with a grain of salt.

    A good rule of thumb when organizing your code is to ask yourself "whose code is this?" That is, for anything you're writing, what part of the overall system cares about it? That's where that code belongs. If it's code that specifies some UI behavior, it doesn't belong in the DAL. If it's code that maintains core business logic, it doesn't belong in the UI. And so on.

    One approach that tends to work for me is Domain Driven Design. As a process, I tend to approach it like this:

    1. Define the business models. This is where everything should make the most sense to the most people. This is your "ubiquitous language." Everyone in the company knows what an Order is. They all know what should happen when you call Order.Submit() on one. This is your BLL and all it cares about is business logic. There should be no UI concerns, no data persistence concerns, nothing of that kind. This is the core assembly which defines the business logic and is re-used across any application in the domain.
    2. Define your data persistence. This is where your business models meet the database. It could be one database, multiple databases, a mix of databases/filesystems/services/etc., and so on. (Now, true persistence ignorance is something of a holy grail of domain-driven design. Your models may have to make some compromises for your infrastructure. It happens.)
    3. Define your applications. These can be user interfaces, web services, etc. From the perspective of the domain core, it doesn't matter. Business logic is business logic, it's maintained throughout the domain no matter what's using it. If a specific application needs to override business logic in a specific way, do it in the application. Presenting data to users, gathering data from users, that's what the applications care about.

    Now, some applications will want to use more customized objects. Maybe one application wants to use the Order class, but re-shape it in some way. Perhaps even combine it with other classes. This is fine. This is a concern of that application. Internally it would have its own mini-domain in which it defines its custom models and has its own custom DAL to translate those models to/from the core domain models. This would be more of a "ViewModel" in that it belongs squarely in that application, not in the business logic.

    Think of each application as a miniature domain. From the perspective of the overall domain, each application is part of the UI. From the perspective of the application itself, the overall domain is the infrastructure behind the application's persistence.

    So in general you might see my Visual Studio projects organized like this:

    Project: MyBusiness.Domain
      Folder: Models
      Folder: Services
      Folder: Repositories
    Project: MyBusiness.Infrastructure.DAL
      Reference: MyBusiness.Domain
      Folder: Repositories
    Project: MyBusiness.Infrastructure.AddressService
      Reference: MyBusiness.Domain
      Folder: Services
    Project: MyBusiness.Application.Intranet
      Reference: MyBusiness.Domain
      Folder: Controllers
      Folder: Views
      Folder: ViewModels
    Project: MyBusiness.Application.CustomerIntegrationService
      Reference: MyBusiness.Domain
      Folder: ServiceDTOs
    

    And so on. I use an IoC container (StructureMap is my personal favorite, but there are many others) to wire up the dependencies. With the exception of the Models, almost everything in the Domain project is just an interface. There can be multiple Infrastructure projects implementing those interfaces and each Application project can configure which ones it wants to use when wiring up the IoC container.

    This approach keeps the concerns pretty cleanly separated. You can have as many applications using the domain core as you want, and you can have as many dependency implementations (including test mock implementations) as you want.

    I hope this helped and didn't just end up going off on some tangent. I'll admit, it's a little difficult to picture exactly what you're asking in the question.