January 25, 2010

The Danger Of Mislead Solutions: Constructor Over-Injection

Recently Jeffrey Palermo blogged about something he calls "constructor over-injection anti-pattern". This post caused a couple of reactions, in particular Mark Seemann's rebuttal to be mentioned. Mark Seemann already did a nice job arguing against the tight coupling in Jeffrey's proposed solution of (taken from the follow-up)

IOrderShipper shipper = new OrderShipperFactory().GetDefault();

to lazily resolve the IOrderShipper reference. Although I agree with Mark, that those lines are as wrong as possible and introduce an even worse smell than the one Jeffrey tried to cure, I disagree with him, that the problem here is the dependency on a concrete type and that we're dealing with the servicelocator antipattern. The real problem with this solution is that it is only a variant of the singleton pattern. Misko Hevery wrote a nice post, why the singleton pattern is a really bad idea.

What's The Problem?

Let's take a step back and look at Jeffery's original problem. He started with the problem, that it took a long time to instantiate the OrderProcessor because of the constructor-dependency on an IOrderShipper. From the fact, that IOrderShipper is not used by OrderProcessor in 100% of the cases, he draws the conclusion, that IOrderShipper should not be a mandatory argument to the OrderProcessor, thus effectivly turning IOrderShipper into an optional dependency of OrderProcessor.

Is IOrderShipper Really Optional?

What does making IOrderShipper an optional dependency of OrderProcessor buy us? Of course OrderProcessor get's initialized much faster now. But this comes at a price. By removing the dependency from the constructor (or passing it in via .NET 4.0's Lazy<> as some suggested), we are giving up some important advantages.

For one, we won't get any notice if there's anything wrong with the IOrderShipper until it is actually needed. There might be an important resource like a database not available, a configuration error or whatever. Only when the first user enters a valid order, this user will experience an error. This violates the fail fast & early principle.

If everything is configured correctly, this first user also will experience a surprising delay while the system is processing his order, as he has to wait until the IOrderShipper is available. This breaks the principle of least surprise.

The Real Problem: IOrderShipper

After all, it is to expect, that the majority of our users will enter a valid order. The conclusion, that IOrderShipper is an optional dependency, is simply plain wrong when looking at the real world scenario. Thus making IOrderShipper an optional dependency of OrderProcessor due to performance issues when instantiating the object graph is just curing a symptom. It is not about healing the real problem: the terrible performance of instantiating the IOrderShipper.

The lesson I learned from this exercise: always carefully evaluate, that you're drawing the right conclusions from your analysis. It is sometimes too tempting to take the easy path or be mislead and in doing so introduce even bigger problems in the long run than the one currently at hand.

As a sidenote, I absolutely agree with Jeffrey, that IoC containers are just tools and your application's design should not rely on your container's features. After all, non-invasiveness is one of the fundamentals of IoC.

So Constructor Over-Injection Is Not An Issue?

In his second post, Jeffrey introduces even more dependencies into OrderProcessor to proof his point. I have to admit, that services classes sometimes tend to grow and serve as a sort of "feature attractors". In my next post I will look into this problem and provide some thoughts on why this is a problem and how to solve it.

23 comments:

VS2008 project linking shortcut said...

Nice read! I certainly want your thoughts on how to encapsulate an IoC container without resorting to some kind of singleton pattern. I know we have talked about this before, but maybe new thoughts spring to your mind.

A typical scenario here is the various controllers that need access to services to mediate information to the view and back. How should these service instances that typically resides within the container be handed over to the custom code which should not know about the container at all. How can this be made as invasive as possible.

Cheers,
Steinar.

I also thought about the prospect of finding plugin candidates, register

RickyLeadbetter0421嘉容 said...

adult成人情色激情成人聊天網情色影片色情俱樂部性愛影片情趣淫水影音情色限制級照片live show女生自慰影片超屌成人情色留言板淫亂女自慰免費視訊辣妹巨乳鹹濕色情影音聊天自拍走光照片免費情色av圖片亞洲情色論壇淫慾免費裸女圖片裙底風光台灣色情論壇一夜正妹淫娃網情色下載a圖片全裸淫蕩女人情色影音聊天高潮自慰色情圖片成人自拍女生自慰亞洲成人色情dvd舔乳頭女生自慰影片台灣色情網站台灣性樂園sex story情色影音激情聊天室嘿咻情色自拍

SydneyJ21074 said...

一沙一世界,一花一天堂,掌中握無限,剎那即永恆..................................................

秀吉 said...

Haste makes waste...................................................

奈美 said...

快樂,是享受工作過程的結果...............................................................

怡潔向霖 said...

想要推動天下,先要發動自己。..................................................

香昱信張君林 said...

嘩做左推介BLOG 果然人氣勁旺..................................................................

于倫 said...

People throw stones only at trees with fruit on them.............................................................

倫惟倫惟 said...

變天了~~注意身體,別感冒囉!.......................................................

倍汝蔡倍汝 said...

i consder your artical is so nice!............................................................

黃威宇 said...

開心不開心都是一天,祝您能夠笑著面對一切!............................................................

吳庭 said...

聰明人之所以不會成功,是因為他們缺乏了堅忍的毅力。..................................................

許李秀樺靜怡 said...

愛,拆開來是心和受兩個字。用心去接受對方的一切,用心去愛對方的所有。......................................................................

昱吳宏昱吳宏 said...

認識自己,是發現妳的真性格、掌握妳的命運、創照你前程的根源。............................................................

凱許倫 said...

It is easier to get than to keep it.......................................................................

建邱勳 said...

雖天地之大,萬物之多,而惟吾蜩翼之知。..................................................

謝俊林奕宏宏 said...

河水永遠是相同的,可是每一剎那又都是新的。............................................................

淑張福 said...

困難的不在於新概念,而在於逃避舊有的概念。......................................................................

建枫 said...

君子遇窮困,則德益進,道益通。............................. ....................................

國林林林林維 said...

大肚能容,了卻人間多少事,滿腔歡喜,笑開天下古今愁。..................................................

怡靜怡靜怡靜怡雯 said...

感覺很用心經營呢!鼓勵鼓勵............................................................

惠NorrisBradwell041花 said...

很精彩的部落格 期待你的繼續加油..................................................

偉DimpleHolloway043昀 said...

培養健全孩子最好的方法是父母先成為健全的人。......................................................................