Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to break apart layers in a strict-layered architecture and promote modularity without causing unnecessary redundancy?
    primarykey
    data
    text
    <p>I've received the go-ahead to start building the foundation for a new architecture for our code base at my company. The impetus for this initiative is the fact that:</p> <ul> <li>Our code base is over ten years old and is finally breaking at the seams as we try to scale.</li> <li>The top "layers", if you want to call them such, are a mess of classic ASP and .NET.</li> <li>Our database is filled with a bunch of unholy stored procs which contain thousands of lines of business logic and validation.</li> <li>Prior developers created "clever" solutions that are non-extensible, non-reusable, and exhibit very obvious anti-patterns; these need to be deprecated in short order.</li> </ul> <p>I've been referencing the <a href="http://msdn.microsoft.com/en-us/library/ff650706.aspx" rel="noreferrer">MS Patterns and Practices Architecture Guide</a> quite heavily as I work toward an initial design, but I still have some lingering questions before I commit to anything. Before I get into the questions, here is what I have so far for the architecture:</p> <p>(High-level)</p> <p><img src="https://i.stack.imgur.com/KWZbT.png" alt="High-level"></p> <p>(Business and Data layers in depth)</p> <p><img src="https://i.stack.imgur.com/VM5M4.png" alt="Business and Data layers in depth"></p> <p>The diagrams basically show how I intend to break apart each layer into multiple assemblies. So in this candidate architecture, we'd have <em>eleven</em> assemblies, not including the top-most layers.</p> <p>Here's the breakdown, with a description of each assembly:</p> <ul> <li><code>Company.Project.Common.OperationalManagement</code> : Contains components which implement exception handling policies, logging, performance counters, configuration, and tracing.</li> <li><code>Company.Project.Common.Security</code> : Contains components which perform authentication, authorization, and validation.</li> <li><code>Company.Project.Common.Communication</code> : Contains components which may be used to communicate with other services and applications (basically a bunch of reusable WCF clients).</li> <li><code>Company.Project.Business.Interfaces</code> : Contains the interfaces and abstract classes which are used to interact with the business layer from high-level layers.</li> <li><code>Company.Project.Business.Workflows</code> : Contains components and logic related to the creation and maintenance of business workflows.</li> <li><code>Company.Project.Business.Components</code> : Contains components which encapsulate business rules and validation.</li> <li><code>Company.Project.Business.Entities</code> : Contains data objects that are representative of business entities at a high-level. Some of these may be unique, some may be composites formed from more granular data entities from the data layer.</li> <li><code>Company.Project.Data.Interfaces</code> : Contains the interfaces and abstract classes which are used to interact with the data access layer in a repository style.</li> <li><code>Company.Project.Data.ServiceGateways</code> : Contains service clients and components which are used to call out to and fetch data from external systems.</li> <li><code>Company.Project.Data.Components</code> : Contains components which are used to communicate with a database.</li> <li><code>Company.Project.Data.Entities</code> : Contains much more granular entities which represent business data at a low level, suitable for persisting to a database or other data source in a transactional manner.</li> </ul> <p>My intent is that this should be a strict-layered design (a layer may only communicate with the layer directly below it) and the modular break-down of the layers should promote high cohesion and loose coupling. But I still have some concerns. Here are my questions, which I feel are objective enough that they are suitable here on SO...</p> <ol> <li>Are my naming conventions for each module and its respective assembly following standard conventions, or is there a different way I should be going about this?</li> <li>Is it beneficial to break apart the business and data layers into multiple assemblies?</li> <li>Is it beneficial to have the interfaces and abstract classes for each layer in their own assemblies?</li> <li><strong>MOST IMPORTANTLY</strong> - Is it beneficial to have an "Entities" assembly for both the business and data layers? My concern here is that if you include the classes that will be generated by LINQ to SQL inside the data access components, then a given entity will be represented in three different places in the code base. Obviously tools like AutoMapper may be able to help, but I'm still not 100%. The reason that I have them broken apart like this is to A - Enforce a strict-layered architecture and B - Promote a looser coupling between layers and minimize breakage when changes to the business domain behind each entity occur. However, I'd like to get some guidance from people who are much more seasoned in architecture than I am.</li> </ol> <p>If you could answer my questions or point me in the right direction I'd be most grateful. Thanks.</p> <hr> <p>EDIT: Wanted to include some additional details that seem to be more pertinent after reading Baboon's answer. The database tables are also an unholy mess and are quasi-relational, at best. However, I'm not allowed to fully rearchitect the database and do a data clean-up: the furthest down to the core I can go is to create new stored procs and start deprecating the old ones. That's why I'm leaning toward having entities defined explicitly in the data layer--to try to use the classes generated by LINQ to SQL (or any other ORM) as data entities just doesn't seem feasible.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload