Friday, April 24, 2015

The IoC Framework Folly

I've been around long enough to live through several Things That Will Save Us All.

First was the OLE. Look it up, kids. It was cumbersome and not well adopted, but we still have remnants of it in OleDB data access drivers.

Than there was the XML. It was for some reason to be used everywhere. I was thinking: OK, just another way to serialize data.. Why is it presented as revolutionary and adopted without much reflection? Recently Json was adopted with about as much fervor.

And today - I think it's fair to say the verdict is in - the Thing That Will Save Us All is DI/IoC frameworks. By now I saw a few projects making heavy use of IoC frameworks and all projects using them have the same basic setup: everything is an interface regardless of how many implementations are planned for the interface, and completely irrespective of whether the interface was ever planned to define a service (for both the provider and a client). Everything gets injected even if the instantiated real dependency dependency graph has no externalities like a database or a remote production system. In addition to that, polimorphism is murdered and inheritance is done via composition of the base interface. And so on and so forth.

And for what end? Testability, of course. Ok. I am very pro-testability. But, testability is only *one* of meany avenues of achieving high quality of code. Testability demands that more dependencies are exposed, to make code more unit-testable (mockable). But this is not a pure asset - it's a trade-off. It comes with a cost. More dependencies exposed means lower level of abstraction of the component or the API. APIs are lairs, say TDD extrimists, because API hide dependencies, which makes them not terribly well-testable. Fair enough. But that's exactly the point: APIs should hide as many dependencies as practical. Not hide all of them, which would lead to the very low testability, and not exposing all of them, making the API hairy and busy. For example Entity Framework hid too many dependencies until v.6, making it impossible to inject a custom connection string factory. That's where more exposed dependencies would be better. But then look at WCF, which, for all intents an purposes, is a specialized IoC framework, with tons of different interfaces, and where everything is pluggable (injected) and dependency declaration shifted to the .config file. As far as I can tell, most developers hate WCF because of its complexity. That is a fair criticism. But when I come across an engineer who loves IoC but hates WCF, I turn into Louis Black inside: an engineer should be able to understand that WCF and IoC frameworks have very similar architecture and share trade-offs.

Finally, if you ask me what I think about IoC, you better be able to clarify: the pattern or a framework. And don't say "both", please. Because IoC the pattern was popular ever since Windows Programmer's Guide told us to handle WM_xxxx events to write any Windows program, and before that a virtual function was introduced to masses by Bjarn Stroustrup, and before that the function pointer was gifted to the world by K&R, etc. And IoC frameworks have unfortunately become The Way We Do Things Today: often used mindlessly as a proof of engineering sophistication to the same extent Apple gear came to signify creativity. There is only one universally-valuable design principle: no pattern is universal.

No comments:

Post a Comment