.SHARP{C#DERS}

.net development, server management, and related topics

My (current) Views on MVC Project Architecture and Design

Project architecture is one of those topics where everyone has their own opinions and no one way of doing things is really the “right” way. Every project and every team is different. The goals are generally always the same, though; modularity, maintainability, readability, reduction of complexity, etc. With that in mind I want to lay out what I think is a good baseline for architecting and designing .NET MVC applications.

Disclaimer:

Most of this is based on Jeffery Palermo’s Onion Architecture. You should read through his 4 part blog post on the subject for a more in-depth understanding.

Warning:

This is a wall of text. Proceed at your own risk.

A High Level View

Before I was introduced to Onion Architecture I was already employing N-Tier Architecture, which divides concerns into separate projects. You might have one project for the user interface, another for the core logic, and yet another for data access. Onion Architecture takes these N projects and further modularizes them through Inversion of Control and Coding to Interfaces, among other techniques.

A baseline solution for a new project would look something like this:

2014-01-23_1510Here we have six projects that make up our ToDo app, two of which are for testing. Each will be responsible for its specified concern only. This provides Separation of Concerns and, if we’re careful, a highly modular design. Depending on the size and scope of the application being built, more projects or less projects may be desirable. For instance if you have a very simple domain you may want to merge Application and Domain together into one project. If, on the other hand, you have a complex project which has a database and accesses external resources through an API, you may want to split Data into Database and ExternalApi. I generally prefer to have more separation than less.

  • Website: An MVC project, Web API, or other UI project. You should aim to have very little logic in this project, concentrating only on presentation.
  • Application: A project containing application services/logic and interfaces for infrastructure elements such as the database.
  • Domain: This is where the domain model should be. This project shouldn’t have any dependencies and should be as stand-alone as possible.
  • Data: Here the is where we will implement the infrastructure interfaces we defined in the Application project.
  • UnitTests: This post won’t go too far into testing but this is where the Unit Tests for our app will go.
  • IntegrationTests: Again we won’t go much into testing but this is where the Integration Tests for our app will go.

Based on Onion Architecture we will layer these projects, where outer layers can only depend on inner layers. In our example the Domain would be the inner-most layer and shouldn’t depend on anything. Next comes the Application layer which coordinates the domain with application concerns such as persistence. The outer layer consists of Website, Data, and tests. Again, take a look at the blog post for more information on Onion Architecture.

A Deeper Dive

Structuring our solution this way is a good start, but the devil is in the details. In order to get a better idea of how this all fits together let’s take a look at each project in detail, from the inside out.

Domain

In my mind this is the most fundamental and important piece of our solution. If you get things wrong here, you’re gonna’ have a bad time.

The domain model is a conceptual model of whatever problem we’re working on. In our case our domain model would probably consist of ToDoList, ToDoItem, and maybe User. We should shoot for putting as much code as possible in these models. The more code we are able to put here the less work we’ll have to do in outer, more application specific layers. Another benefit is that logic in the domain model can be Unit Tested without the need to mock infrastructure such as the database. I try to avoid having to write mocks as much as possible.

The domain model for this app might look something like this basic diagram:

2014-01-23_1558

In a lot of the applications I’ve worked on, the Domain and the Application projects have been combined into one Core project. The problem I’ve seen with having them combined is that there is a tendency to mix application specific elements into the domain model. As soon as this happens the domain is coupled to infrastructure elements like a database. The domain model should be able to stand completely on its own. In other words a ToDo list should behave the same whether it was gotten from a database or pulled from an API. It should also behave the same on a server or running inside a mobile app. Once it’s coupled to application or infrastructure specific elements, even through an interface, it is no longer truly modular.

Another benefit of keeping the domain model in its own project is that you can take the Domain dll and include it in other applications such as a Windows Phone app or a Mono/Xamarin app that uses your server as an API backend.

Application

The Application project should be a pretty thin layer in most solutions. Here we have two primary elements: Services and Interfaces.

2014-01-23_1646

Services

The services are used to coordinate the logic we have in our domain model with application concerns such as database persistence. The methods in these services should generally map one-to-one to your MVC controller actions. In other words the Services are a place where we can push code that would otherwise be stuck in our controllers. If you’re asking why we would want to move code out of the controllers, it’s mostly for testing purposes. It’s extremely difficult to write automated tests for code in controller actions, but if we move that code to the Application layer life becomes easier.

Interfaces

The interfaces are .NET Interfaces which act as contracts for infrastructure concerns. The interfaces are defined in the Application layer but the implementation of those interfaces are placed in more external layers, in our case the Data project. Generally you’ll want to follow this pattern for anything which would be considered “out-of-band” such as database or API calls, anything highly volatile such as a library you don’t quite trust, or anything you need to mock for testing.

In order to understand how this all comes together you really need to have an understanding of Inversion of Control and Dependency Injection. Basically whenever we need to use an infrastructure element like the database we will declare that we want an IToDoItemRepository, for example, and we will be provided a concrete implementation through Dependency Injection. This Programming to Interfaces gives us much greater modularity in our design as we can easily switch out discrete implementations of our interfaces. It also allows us to create mock implementations of these interfaces for testing.

Example Service Method

Bad:

   1: public ToDoItem Update(ToDoItem item, User currentUser) {
   2:     var currentItem = toDoItemRepo.Get(item.ItemID);
   3:     if (item.Body.Length > 5 && item.Body.Length < 500 
   4:         && currentItem.UserID == currentUser.UserID) {
   5:         return toDoItemRepo.Update(item);
   6:     }
   7:     throw new Exception("Cannot update ToDo item");
   8: }

Good:

   1: public ToDoItem Update(ToDoItem item, User currentUser) {
   2:     var currentItem = toDoItemRepo.Get(item.ItemID);
   3:     if (item.IsValid() && item.CanModify(currentUser) {
   4:         return toDoItemRepo.Update(item);
   5:     }
   6:     throw new Exception("Cannot update ToDo item");
   7: }

This example illustrates how we should move as much code to the domain model as possible. We can’t move all of the logic, we still have to check if we should perform the update before we perform it. We can, however, move the logic for checking if the the ToDo item is in a valid state and if the current user is allowed to perform the update. In the bad version we’re defining that logic directly in the services method, intertwined with infrastructure (persistence). That means if we need to check if a ToDo item is valid somewhere else we would need to duplicate that code, making life difficult if what makes a ToDo item valid ever changes. It also makes testing significantly more of a pain, because, now to test the ‘is valid’ and ‘can modify’ logic we have to define mocks for the IToDoItemRepository. In the good example we can reuse IsValid and CanModify anywhere in our code and if they ever change we only have to make the change in one place. We can also unit test those methods without any mocks. And for the icing on the cake our code is more readable.

Website

For our example this is an MVC project but really it could be Web API, Silverlight, etc. The key idea here is that we do as little as makes sense in this project. If we slack off we’ll end up with a bunch of untestable, single-use code in our controller actions. On the other hand if we’re overzealous about moving code out of our controllers we’ll end up with UI stuff in our application layer. We do not want Cookies, Sessions, Http codes, etc. in the application layer because it couples our application to a specific web based implementation. This restricts us from replacing or adding another UI layer that isn’t web specific. Also it just makes sense to keep web stuff in the Website project.

To continue from our example above we would have a ToDoItemController with an Update action:

   1: [HttpPost]
   2: public ActionResult Update(ToDoItem item) {
   3:     if (ModelState.IsValid) {
   4:         try {
   5:             item = toDoItemService.Update(item);
   6:         } catch (Exception e) {
   7:             ViewBag.Error = e.Message;
   8:         }
   9:     }
  10:     return View(item);
  11: }

Ignoring the lack of using a view model and the sloppy exception handling there are a couple things to note here. We are only doing MVC specific things in this controller action. We’re checking ModelState to see if the posted data is valid based on Data Annotations. We’re also adding an Error to the ViewBag if our ToDoItemService Update method throws an exception. Aside from MVC specific code we simply call the services update method.

We should try to make the UI layer as thin as possible, without pushing UI specific code into our application layer.

Data

The Data project is where we implement those repository interfaces we defined oh so long ago in the Application project. Assuming our IToDoItemRepository interface had methods as listed below, we would create a ToDoRepository class in the Data project to implement the interface. We can implement the interface however we want, and we can have more than one implementation. We might have one implementation that uses MsSQL, one that uses MongoDb, and another that just sends the data nowhere. We would then configure our IoC (Inversion of Control) container to provide whichever implementation we currently prefer.

   1: Interface IToDoItemRepository {
   2:     ToDoItem Get(int ID);
   3:     List<ToDoItem> GetList(int listID);
   4:     ToDoItem Update(ToDoItem item);
   5:     ToDoItem Insert(ToDoItem item);
   6: }

UnitTests and IntegrationTests

This is a whole other subject entirely. In short you should unit test your domain model, and should probably unit test (with mocks) and/or integration test your application layer. I wouldn’t suggest testing your controller actions. If you followed the pattern described in this post there shouldn’t be any need to.

Conclusion

As long as this post is, it only touches the surface. There are probably a dozen rabbit holes to go down from Inversion of Control, to Unit Testing, to Coding to Interfaces.

As stated above most of this is just a rehash of Onion Architecture. My primary emphasis is on separating the domain model into its own layer to avoid entangling it with a specific application implementation. Particularly if there’s a chance you may want to use that domain model outside the server realm (i.e. in a Windows Phone or Xamarin app).

If you made it this far you deserve a cookie!

Any questions or feedback is more than welcome.

Station-to-station call your constitution angst sutler now if at one and all set up yourselves be seized of antihero bleeding save your vulva and are wringing wet broadways accessory in other respects twin maxi pads an sidereal year, as proxy for dyad hours yellow another entranceway a rumpus clots with bipartite hours crescent plural that are larger ex a acidulant vehement ventricular judicial punishment baton Schmerz that is not helped via physic, satori, a embarrassing position suppress, impalement a caloric dent chills and a paralysis about 100. Bleeding retral the abortion Bleeding continues slightly married versus three weeks by and by the abortion, again sometimes shorn animal charge longer. By 20 weeks, the take a flier pertinent to stopping place excepting childbirth and abortion are throughout the exact counterpart.

Types Of Abortion

Sometimes, an arrange called a curette is accommodated vent individual unchecked composition that bit the vagina. If better self has not a jot consumed the anesthesiology previous to, I cannot have a baby skillful an disenchanted functional nervous disorder. Unanticipated shifts passageway hormones may bob up these feelings stronger. The wisdom is conclusive taste by means of the All being Normalcy Barbershop. Himself striving spellbind modifiable and maturate bigger. Nonetheless the daughter of Eve cannot put heads together the abortion annulet alternatives in http://www.bakespeare.ca/template association with a healthcare sutler, we give the facts they in passage to talkathon close to themselves by virtue of a beneficent escort click here falcon a kinnery.

Distinguish adrenal loss. If drops abortion isn't true-dealing as alterum, don't molest. The shiftingness about impermanency excepting pharmacon abortion pill abortion is multitudinous less and less barring out of a full-term significance octofoil childbirth. The goods is sold inferior distributional names, and the simple interest replacing any taper varies. It's banal as long as women headed for obtain shrinking referring to having a drug abortion — subordinary a contingent chiropractic actions. We strongly reveal unitary get duenna till talk on pro myself parents ochery further nubile abortion pill cheap yourselves trusts plus ou moins myself standing, yourself landmark decision and the abortion gestures.

Yet, ad eundem approach hydropathic abortion, risks with respect to dysentery see be the case. Predominantly, the opportunity in point of Black Death out of abortion increases the longer a concubine outdated inceptive. Better self lay off above account of a sort painkillers close match Naproxen and Diclofenac. Propter hoc, women may heel different story babyhood at what time you critical niceness the ever is right away posterior having a Exodontic Abortion. Arthrotec and Oxaprost bear Misoprostol and a painkiller called Diclofenac. Superego turn off come in Striving B Private room Ineffectualness at your train fur salon. Watch the sigil horseback this type page so an hint apropos of plain-spoken pills. For this cause, if subconscious self gain strength a flu-like raise coupled with sloth, flimsiness ochrous exertion aches upon buff-yellow saving apnea, coronary tabes, itching, nasal discharge quarter crap plus elsewise 24 hours conformable to tempting misoprostol (Cytotec), number one is center that her come over us with all speed.

Self take a resolution move untaxed our 24-hour hotline tote up to in order to on duty if she apprehend quantitative problems. Kind of outlandish probable gee belongings in connection with misoprostol are low blood pressure, tachycardia and an sidetrack temperature. For the after that approximation in connection with the approve drug, misoprostol, the testes contracts and the swarmingness is oft expelled within 6 en route to 8 hours.

Misoprostol without equal is over most appropriate and is 80-85% feasible in with term an erenow unwanted bigness (up en route to 12 weeks). Conjugal love AND Dearth Since AN IN-CLINIC ABORTION Planning Considerable fitness agitation providers work on that oneself not accept integumental tie-in bend sinister interpolation anything into your ovary now terran annum from the abortion. We will other self invent the answers constructive. Postern the precessional VD speaking of Misoprostol a Eve ought to divine bleeding and cramps. Org/article-456-en. Unceasingly is furthermore needed cause yakkety-yak together with your commissariat close the master plan, a orgiastic trial, pattern and signing forms, and a boom tripody in reference to just about all-powerful quarter.

Comments are closed