David Abraham
David Abraham

Reputation: 197

Some guidance on ASP.NET MVC 3 architecture required

I am an experienced .NET developer who has primarily been working with webforms. I am familiar with MVC but have not used it commercially yet. I am currently conducting some self-education in this area and am somewhat confused by the differences in opinion on the subject of architecture, let me prefix this question with the understanding that there is not a right or wrong answer but I am simply seeking what is an elegant solution.

I will start out by saying that I am not using the entity framework or any sort of ORM – I would like to directly implement my own business objects and data access code (using ADO, SPROCS etc) to ensure they are optimal, this is a personal preference. This is where I am struggling to find consistent information as it appears most information relates to the use of LINQ to SQL or the Entity Framework.

MY application has been structured with the following projects:

There are only two projects because I am having issues decoupling things; this is the root of my question. My model class library contains…

The issue I have is the dependency between all these layers. It does not feel right at all!

1.The business objects should contain methods that implement the business logic, so aside from the fields and properties there are methods to implement any required logic?

2.The repository classes execute data access code but know about the business objects, this again does not feel right, the data access code should sit in its own class library and know nothing about the objects?

3.The controllers (in the web layer) leverage the repository interfaces but why? They should not contain business logic, the ‘model’ or business object should? The controllers should certainly not contain business logic so again this is not right. I don’t want business logic in repositories as they are hitting the database.

I am struggling to find an elegant architecture for the application, just a basic outline of how to implement my own objects, my own data access code and ensure the application is loosely coupled. Can anyone offer me any guidance please?

Upvotes: 10

Views: 1299

Answers (4)

Pure.Krome
Pure.Krome

Reputation: 86997

I would suggest a few changes to your solution structure.

For example, the projects could be structured as follows:-

Core Library

This would be simple POCO's that represent your domain data and interfaces to any services. There is no business logic here. Just simple properties.

eg.

public class User { public int UserId { get; set; } public string Name { get; set; } }

- Core
      \Entities <-- Poco's
      \Services <-- Interfaces for services

Services

This would be where you contain your business logic. How does a user validate? How do we calculate when a Order should be auto-archived or whatever? Generally, I don't do any database stuff in here.

Repository

This is where you do your basic database stuff. You said you're not using L2S or EF, etc. No probs. I would seriously seriously look at using a Micro-ORM instead, like Dapper or Massive.

Tests

You're doing unit and integration tests, right? i recommend xUnit or nUnit for the testing framework.

Web Application

This is the MVC3 application. I would recommend using StructureMap for your Dependency Injection. (You are using an IoC/DI, right?)

You might think at first -> that's SOOO many projects, right? well, it's easy to split this into TWO projects only.

  1. Web Application
  2. Test project

and the Core Library, Services, Repository all exist in the Web Application project as folders.

Try and not over-engineer the Visual Studio solution. Most people think they need lots of projects and crap loads of abstraction .. because that's what they think everyone else is doing and it's the right thing. Well, that train of thought is very very early 2000's .. and in 2012 - lots of shiz has changed since then.

Try using DI/IoJ, NuGet for downloading these libraries into your solution, Micro-OR/M's for data access and a Testing project.

A few projects to check out, re: how things are layed out :

  1. JabbR.net
  2. RavenOverflow

Upvotes: 6

cbp
cbp

Reputation: 25638

A few points:

  • There is no problem with having 'business logic' in your repositories. In fact most of your 'business logic' is going to be there. Your repositories contain queries, and if those queries are at all interesting then those queries are going to be intimately related to your 'business logic'.

  • There is no problem with having 'business logic' in your controllers. Your controllers are controlling your UI and how your UI works is 'business logic'.

  • By definition, in a layered architecture each layer is aware of the public interface of the layer above it. Your data access can see the public interface of your domain layer. Your UI layer can see the public interface of your service layer.

  • If your project is so small that you can afford to handcode your own data access layer, rather than use an ORM or similar, then having a fully decoupled Starship Enterprise architecture is probably only going to make your life most difficult. (And by this I'm implying that I think you're crazy writing your own data access layer - at least try a light-weight framework like Dapper).

  • Base your choices on your needs. Ask yourself "Why does X need to be decoupled from Y". The answer may be "So I can mock X out when I'm unit testing Y". The answer may be "So I can use X in my other project that doesn't need to know about Y". If you can't find an answer, then YAGNI.

Upvotes: 0

Nope
Nope

Reputation: 22339

I think starting small is good and then as the need arises you start widening your view and start separating out layers as you need them. Why separate your work into 20ish projects if you got 2 models, 1 view and a single table to query and update in a database.

Start small and let the "need" drive the design. If you need to read/write lots of tables in a database it might be time now to start using the repository pattern. You find you are now in need of at least 10 or more different models it might be now time to implement a library to contain DTOs/models and take them out of the web application.

If you for example require to write unit tests or do TDD you find that being able to mock the repository, business and service layer straight away come in handy.

For the sake of argument though, I have seen projects which had similar to the below (but most will not need that level of separation):

  • The web project; consuming a service library and dto library
  • A service library; consuming a business layer library and dto library
  • A business layer library; consuming a repository library, entity library and dto library
  • A repository library; consuming the entity library
  • A entity library
  • A dto library

Most of those were even further broken down into separate libraries, containing interfaces in one and implementations in another and so on. Some projects I have worked on had over 50 libraries to separate most if not everything but it was always based on a requirement or need.

The idea of the above example is to have the web application merely deal with passing DTOs to a service call and receiving DTOs back form a service call.

You can use the DTOs most of the time as Models but sometimes if you need a flat model based on several DTOs you can create your own view-model as a wrapper to flatten out the multiple DTOs.

The service goes of and call a method in a manager, passing a DTO, which resides in the Business layer library. That manager will use the DTO and map it to one or more entities and calls methods on the repository passing those entities. The repository returns entities which the manager uses to construct the DTO to send back.

There is many ways of doing this and I'm sure not a single one is the only right way.

You can achieve further separation and independence using a dependency injection framework like Ninject for example.

The above is merely a single example. It might work great for one group of people while another find it unacceptable. It depends on many factors, the size of the project being one of the main ones.

Aside all that though, always start with a manageable sized architecture you will keep re-factoring over and over as the need arises for change, be it to cater for mocking in unit tests, the number of models has become unmanageable within the web application or now a separate team has to write the service layer and you don't want that to interfere with your development, the service layer might now have to be consumed by a different UI layer and not just your web front-end, etc...

Upvotes: 1

Jason Meckley
Jason Meckley

Reputation: 7591

  1. maybe, if the model requires it. most models are simple dtos with public properties. but you could just as easily encapsulate some of this.

  2. not exactly. a repository is a collection of business objects. it may create instances of these objects from a database.

  3. controllers are the entry point for controlling what happens on the server. reads would load data from the repositories into view models and push the view models into the view. writes would load data from repositories, update the domain and save the changes. then redirect to a read controller action.

most importantly. don't over think the architecture. this happens too much. devs want clean code and actually make it more complicated to maintain, rather than simpler.

whether or not you use a database or ORM is irrelevant, you have the same functionality in your repositories.

Upvotes: 1

Related Questions