Sorry guys, but it’s time to rant. I see so many people needlessly complicating their architecture and deployment by insisting on using separate assemblies for every layer of the app or even doing the trick where interfaces are in one assembly and the concrete classes are in another assembly. Stop it! It’s a waste of time. Logical de-coupling from UI to business logic to infrastructure to the database is very important, but using separate assemblies doesn’t do anything to guarantee that decoupling. You can separate your assemblies all you want, but making the UI depend on the implementation details of the business code in the other assembly is still harmful tight coupling. Likewise, you can lump data access, the domain model, and even UI concerns in the same assembly and still maintain separation of concerns in every way that really matters to the success of your project. Our Domain Model and our persistence infrastructure is all in one assembly named “DovetailCRM.Core,” but yet there is zero coupling from the Domain Model to the NHibernate mechanism. We could slide another persistence mechanism (assuming that there actually was another POCO-compliant persistence mechanism with rich functionality in existence for .Net) without changing anything in our Domain Model.
Here’s what’s important about coupling between two things (class/module/infrastructure/subsystem/whatever) named X and Y:
- Can I understand X in isolation, or do I also have to understand Y at the same time?
- Can I change X independently of Y? Or to put it differently, will changing X likely break Y or vice versa, ’cause that would be bad?
- Can I test X in isolation without Y hanging around and getting in the way? Or can I verify that X works independently of Y?
- Can I use X with a Z instead of a Y?
- If I want to reuse X in another context, even if it’s in the same application, can I do that without having to drag Y along with me? And all of the things that Y needs for that matter?
I’m very firmly in the camp that says you should only split assemblies by deployment targets, and even then, I don’t think you need to be strict about assembly separation. More assemblies == slower compile times (Don’t believe me? Try it out in VS.Net. I took 56 projects one time and consolidated them down to 10-12 and cut the compile time from 4 minutes to 20 seconds with the same LOC), circular reference problems, and more complicated usage and deployment. Nothing is more irritating to me than using 3rd party toolkits that force you to reference a dozen different assemblies just to do one simple thing. Ok, truth be told, nothing irritates me more than using 3rd party control kits in general — all the worst API’s ever created come from .Net control toolkits.
If you don’t think your team won’t adequately follow the basic separation of concerns rules you’ve determined in your architecture, you’ll be better off doing something like using CQL constraints with NDepend in your automated build script to find coupling violations. Even with the separate assembly strategy you would still need to use static code analysis to find every coupling violation.
One more rant, and I may be leaving the reservation on this one. Obviously, the following rule applies equally to me, but don’t ever assume for a second that just because someone is an MVP/INETA Speaker/MS Regional Director/”Professional .Net Gloryhound” that they know WTF they’re talking about. Remember that all of those awards are mostly based on visibility and successful self-promotion rather than on strict technical merit.
Ok, I’m done now. Thank you for listening, I feel better now.