dotnetjunkie / blog

Files for my weblog
0 stars 1 forks source link

Comments for "In Praise of the Singleton Object Graph" #6

Open dotnetjunkie opened 4 years ago

dotnetjunkie commented 4 years ago

In the section below, you can leave your comments for this blog post: https://blogs.cuttingedge.it/steven/posts/2019/in-praise-of-the-singleton-object-graph/.

Please be aware that a comment posted here will be shown in the comment section of the blog post, using JavaScript. This means that you should consider this a comment directly on my weblog—not as a post on GitHub.

This means that I might

grumpyrodriguez commented 4 years ago

Great conclusion to your recent series Steven. I'm curious about the following statement:

...just as badly designed code often forces the use of mocking frameworks during unit testing.

I get the sense you have a different view of mocking than the one I have, mine being influenced by GOOS (London school). Could you please comment on what you'd consider as justification for mocking? Based on the GOOS approach, all your examples in these blog posts would be using mocks to test relationships between the dependencies, injected as interfaces to constructors.

I'm certainly not trying to disagree or impose my view, I'm just curious on your approach, given how valuable and insightful your posts are. How would you unit test the examples you used in your recent series of blog posts? How would you use mocking or not use it/why?

dotnetjunkie commented 4 years ago

Hi @grumpyrodriguez, using Mock Objects is an essential part of writing unit tests. Using Mock Objects during testing, however, doesn’t require the use of a mocking framework. Although there is nothing inherently wrong with using a mocking framework, my experience is that, as I said in the article, mocking frameworks are often abused to work around badly designed code. On top of that, I experienced mocking frameworks typically reduce the readability of unit tests.

In my code bases I maintain, I like to turn things around: I prevent using mocking frameworks and write my fakes, stubs, spies, and mocks—for the most part—by hand. When the writing of these fake objects becomes cumbersome, I take a step back and re-analyze my design—which is typically where the problem lies.

This doesn't mean, though, that mocking frameworks are never useful, or are an anti-pattern. What I found, however, is that when I have an application with a handful of (generic) reusable abstractions, where abstractions are narrow (ISP), and designed around the SOLID principles in general, the need to auto-generate those Mock Objects is fairly small. Of course your mileage might vary and you might not be that lucky to be able to SOLIDly design an application from scratch. These are certainly cases where I still find mocking frameworks useful.

grumpyrodriguez commented 4 years ago

Thanks for the clarification @dotnetjunkie, that's helpful. I do agree, when the dependency abstractions are small in number and scope, the need for mocking frameworks mostly disappear.

It appears that the software community is strongly divided regarding the use of mocks (as it divided about everything all the time :) ). I see a lot of objections to use of mocks with the purpose of verifying the interactions between the system under test and its dependencies. One side claims using mocks to verify these interactions make tests brittle and extends test scope to implementation details, the other side claims the interactions count as part of the behaviour of the system under test and are worth including in unit tests.

My understanding from your response (given you use mocks and spies) is you're not necessarily against use of mocks (with calls to mocks verified) but you don't assume mocking frameworks are necessary to follow this practice, which I'd agree.

Did I get it right?

dotnetjunkie commented 4 years ago

My understanding from your response (given you use mocks and spies) is you're not necessarily against use of mocks (with calls to mocks verified) but you don't assume mocking frameworks are necessary to follow this practice

Correct.

grumpyrodriguez commented 4 years ago

Thanks, much appreciated. Looking forward to reading more of your blog posts.

BrunoJuchli commented 2 years ago

I tried ACM out but got a bitten by https://github.com/dotnet/runtime/issues/47802 As soon as one uses IAsyncEnumerables ones losing AsyncLocal scope/context :-(

Anyway: thank you Steven! For all the insights you provided over the years. I remember reading your stack overflow posts, then your blog posts, and I could see that your reasoning is great, but still I couldn't follow your experience - mine was lacking. I was a convinced user of Ninject (and all it's features) and I could follow your argument for poor man's DI but not the valuation of the pro's and con's. But 1,2 years later I got it. I expect it'll be the same with CCM vs ACM :D

dotnetjunkie commented 1 year ago

It is becoming apparent that Microsoft has no intentions in fixing the problems with AsyncLocal caused by the introduction of IAsyncEnumerable. This is problematic because, as time goes by, more developers will start iterating over IAsyncEnumerable collections explicitly and implicitly start depending on external libraries or framework components that will silently async yield over IAsyncEnumerable collections, causing the problem to only grow over time. This makes the use of AsyncLocal unreliable.

And even when -theoretically- Microsoft fixes this in the future, it requires "both compiler and runtime changes" (as stephentoub mentions in his response to https://github.com/dotnet/runtime/issues/47802). This means that libraries need to get recompiled and re-released. Libraries that don't get updated will keep having this 'bug,' which means the use of AsyncLocal will stay unreliable long after Microsoft fixed this.

This basically means that .NET is now becoming an environment that has "environment limitations" that prevents it from (effectively) storing ambient data.

To me this seems like we're taking a big step back and an unfortunate decision from Microsoft.

I'm considering updating my series to add a warning about the use of ACM in the context of .NET.