Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple application architecture advice

I'm attempting to create a small demo web application that is loosely coupled, highly testable, has nice clean code, etc. In short, I'm experimenting with doing things the right way. ;)

I currently have three projects in my Wolfie solution:

  • Wolfie.Core - contains business entities
  • Wolfie.Data - contains data access code, references Core.
  • Wolfie.Web - will be a nancy web site.

As it stands the Core knows nothing about any of the other projects. Data has to reference Core as Core has the types that Data will return. So at this point I find myself realising that Web will need to reference both Core and Data to be able to work as the entity type is in Core and the database calls are in Data.

All of the repository classes in Data have interfaces so that the repositories can be mocked out for testing.

I don't think I want to put any database specific code or references into Core, and I want to keep my entity business rules out of Data.

Is it correct to reference both projects from Web? or would another project between Web and the others be required so that Web only references the one place and isn't then responsible for calling Data methods etc.

What I'm aiming for is an architecture where my core application is independent of both the Data and Web layers.

I hope I've made some sense and I look forward to some helpful replies.

like image 677
DavidGouge Avatar asked Feb 08 '12 20:02

DavidGouge


4 Answers

I think you are striving for a reasonable goal which will create a solid application architecture. I have personally worked on an enterprise web application that used a similar architecture to the one you are describing, and it worked very well for that application.

In that application, the domain business logic was isolated in its own "Domain" assembly (your "Core" assembly) and referenced nothing outside of the .NET framework. In order to connect to external business components, such as the database and other web services, there was an "Infrastructure" assembly (your "Data" assembly). The key for that application is that each implementation in the Infrastructure assembly was interfaced in the Domain assembly, and returned Domain assembly objects (just as you describe). This, of course, necessitated a reference from Infrastructure to Domain.

To tie it all together, a "WebApp" assembly (your "Web" assembly) referenced both the Domain and Infrastructure assemblies and used an IoC container to resolve all of the application dependencies. When requests came in to the WebApp, it would resolve the appropriate "Domain" contract to serve the request which would start the IoC resolution call chain. Outside of registering the Infrastructure implementations, the WebApp assembly does not care that the Infrastructure assembly exists.

The reason this worked so well for that application is that it achieved the goals you stated in your question:

  • There are no external references in the business domain.
  • The business domain application is completely independent of both the web front-end and the database back-end.

This lends a lot of testability to your business domain, and a lot of flexibility to how front-ends interface with your domain. In fact, that flexibility is what makes it so testable. That flexibility has other benefits as well. For instance, with your business domain that isolated, you could easily code up a new CLI or WPF front-end that hooked into a file-system back-end without changing a scrap of business domain code if you wanted to deploy and run your client locally on a machine.

Though that example may seem slightly far-fetched, in the case of the application I was referencing above, the development team is contemplating building a Web Services front-end to complement the already existing MVC website front-end. This is only a realistic possibility for that team because they setup that application like you are describing.

like image 58
Drew Spickes Avatar answered Oct 17 '22 06:10

Drew Spickes


I don't think there's anything inherently wrong with having those two references.

But, I would consider what "Core" is. Is this your domain logic? If so, I'm not sure I would have a situation where your data access assembly knows about your domain logic and your GUI layer knows about both.

If "Core" is domain logic, you can put classes in it (e.g. IRepository Pattern) that know about the "Data" assembly. Your web assembly would then know about "Core", but not "Data".

To facilitate this arrangement, you can create a fourth assembly called "DataTransfer" and define some objects (or, better yet, interfaces) that "Core", "Data" and "Web" all know about and use to communicate with one another. As a matter of fact, if you really want to get decoupled, structuring things with the "Types" assembly containing interfaces can actually make it so that none of your original three assemblies know about each other.

But then, if "Core" is really a library rather than your domain logic, it probably makes sense to go with your current structure and perhaps later revisit it if you add enough functionality to start tacking on more assemblies/layers.

Edit: To help visualize what I mean, I'm talking about a layered situation:

Web
 | 
 v
Core
 |
 v
DataAccess

rather than:

Web
 |  \
 v   \
Core  |
 ^    |
 |    v
DataAccess

You have three references when you could make it work with two. Extra/unnecessary coupling early leads to headaches later.

like image 42
Erik Dietrich Avatar answered Oct 17 '22 06:10

Erik Dietrich


You're making a lot of sense and your reasoning is very sound. It's a very common, reasonable and pragmatic design to have Web layer referencing both Core and Data. You're not creating any circular references and keeping it pretty clean.

like image 3
Yuriy Zubarev Avatar answered Oct 17 '22 06:10

Yuriy Zubarev


The architecture is 1. data 2. business logic 3. client. Data is data. Business logic works on the data. Client connects to the business logic like data->business logic->client. Client doesn't connect to the data directly. 3 layers. data logic client.

like image 1
iefpw Avatar answered Oct 17 '22 06:10

iefpw