In Another Gig Completes, I mentioned planning to start a new project to help track consulting gigs. Here I introduce you to:
Project codename named after Toph from the Avatar: The Last Airbender
As I mentioned before, this project is meant not only to help organize my consulting gigs, but also give me a public project and codebase I can point to. I also hope to use the project as blogging fodder. Speaking of which...
Early Architecture Decisions
I've spent the vast majority of my career joining existing projects. There is always that sense of "that's not the way I would have done it". Well, I finally get to do it my way! It was tempting to go crazy with it and implement everything cool I've been reading about recently - whether needed or not, I might add. In the end I decided to go with a pragmatic approach that is much more likely to be a useful example I can point to when talking to developers as I continue consulting.
Visual Studio Projects
I'm still a fan of and will continue to advocate onion architecture (some might say Hexagonal Architecture). One difference you'll find between Toph and what I normally do though, is the lack of an Infrastructure project.
There seems to be a theme going around the blogosphere that is advocating the removal of unnecessary abstractions and part of the theme has been the combining of projects. The idea is that it is perfectly possible to create an architecturally sound solution without using Visual Studio projects to enforce it. In case you're wondering how they "enforce" it, realize that Visual Studio projects won't allow circular references between two projects - whether by directly referencing each other, or indirectly (A - B - C - A would not compile). Therefore if you have a UI and a Core project with UI referencing Core, you couldn't reference UI from Core. Thus, this usually prevents you from directly doing UI type actions from within Core since you couldn't touch the controllers or view models.
I'm almost always a fan of pragmatic programming. As it turns out, the Infrastructure project never proved that exciting for me as a standalone project. So I just created a namespace within UI called Infrastructure and dumped everything in there. You see, everything usually consider Infrastructure is generally only used during application startup anyway as I'm building up the inversion of control container.
However, I still very much like having my Core separate. It just feels right. So, I decide three projects are all we'll need in this solution
- Toph (I decided there was no reason to call it Toph.Core)
Even if I end up adding another project in the future for scheduled tasks (to be run on some application server somewhere), leaving Infrastructure under UI should still be fine. That's because I generally just invoke endpoints in the UI from those background tasks rather than directly dealing with the domain or application's database.
New projects should always be started with the latest and greatest, right? I went with ASP.NET MVC 4 of course. Specifically, I started with the Internet Application project template.
That template starts with using a local database and using Entity Framework as its ORM of choice. As expected if you know me, I changed that use SQL Server 2012 Express and NHibernate. To do that...
- Delete InitializeSimpleMembershipAttribute. This is the attribute added to AccountController that ensures the database exists and is initialized. There is only one line in there that is needed: WebSecurity.InitializeDatabaseConnection. I moved that into Application_Start
- Delete UsersContext. This is the EF DbContext
- Move UserProfile from the Models directory into the domain and kill the EF attributes
- Add Fluent NHibernate
- Do all the normal NHibernate config and mapping stuff
- Change your connection string
- Create the database with the single UserProfile table
- Run the application
That should do the trick.
The only other things I added to the project were Structuremap and my personal code library RobTennyson.Common.
I also stuck with restricting domain access to a Service Layer like I usually do. One difference I thought I'd toss into the mix this time is a bit of CQS goodness (not full blown CQRS, mind you). We'll see how this turns out as the project grows.
Grabbing a copy and playing
If you're interested in playing around with this, but sure you get the code specifically from this commit: 91a19e9f8b
I'll be moving on with the project of course, but at that exact point, the project is still basically just the default template - well, juiced up a bit, but basically still has nothing to do with the real project in it yet.