I don’t know that it is possible to write anything like a unitary software system in a way that is truly loosely coupled. It’s not that you can’t make boxes and lines that are cleanly separated in all sorts of pretty ways, though that’s hard enough. The problem is that even if you manage to do that, what you end up with is actually still pretty tightly coupled.
What do I mean?
Well, let me use Visual Studio as an example. It’s made up of all kinds of extensions which communicate through formal interfaces. Putting aside the warts and just looking at how it was intended to work it seems pretty good. You can make and replace pieces independently, there is a story for how now features light up; it’s all pretty good. Yes, it could be better but let’s for the moment idealize what is there. But is it loosely coupled, really?
Well the answer is heck no.
These systems all share resources in fundamental ways that actually tie them together pretty tightly. It starts with the address space, each extension can be victimized by the others, and it goes on. In fact every important resource on the machine is subject to direct interference between nominally isolated extensions. Is this avoidable?
I don’t think it is actually. I think unitary software systems are fundamentally tightly coupled when you look at them through a performance lens. And that is why I’m so often telling people that they need to look at their overall system and see if, when it’s all put together, it has any hope of working the way you want. Two subsystems that both (loosely) use 2/3 of the L2 cache are going to use 4/3 of a cache… that’s not good. There may be no lines between them in the architecture diagram but they are going to destroy each others ability to work.
So, does that about wrap it up for agile then? Should we just waterfall our way to victory?
Everything you’ve ever read about requirements changing and not over-designing systems that are loosely specified (much less loosely coupled) still applies, but just because you’re going agile and you want to keep your flexibility is no reason to not think about what it’s all going to look like when you put it all together. Some kind of blend is needed.
If you do run into problems that loose architecture is going to help you. But waiting until you’re done and counting on your agility to save you at the finish line isn’t so smart either. Agile development doesn’t prohibit you from planning out the parts that need planning and understanding your key constraints. In fact I think it encourages this – knowing your constraints keeps you honest and lets you make adjustments smartly as you go.
Performance is never loosely coupled. Don’t be fooled by your diagram, the profiler doesn’t know where your little boxes and lines are. Trust me :)