DEV Community

Scott Hannen
Scott Hannen

Posted on • Originally published at scotthannen.org on

Reflections and Corrections

If you’re reading this, perhaps you’ve found something on this blog interesting or helpful. Odds are that you’ve never read the About Me page. And why would you?

This post is about my other blog posts. Like the About Me page, I’m writing it only because to some extent my blog represents me. Over time, however, the individual posts may not. I feel compelled to address this somehow, even though it’s unlikely that anyone cares except me.

Some of this reflecton is a little bit funny. This blog contains bits and pieces of my learning journey, but it’s weird to read myself describing unit tests like I’ve just discovered fire. In other cases the information is obsolete. And sometimes I no longer feel the same way about what I wrote or I was just wrong.

With that in mind, here are some notes on a few older posts:

Abstract Factory Pattern

Alternatives To Abstract Factories Part I - Lifetime Management

I used abstract factories a lot in 2016. Since then it’s completely fallen off my radar. I didn’t use it in any domain modeling sense because I had no idea what that was.

In the example I created an IAddressValidatorFactory. Code that needed an IAddressValidator would pass it some argument (like an address). The implementation would decide what sort of IAddressValidator to create, create it, and return it.

In retrospect the way I used these factories made little sense. Even if it’s abstract, why would a consumer need to know that there’s a factory creating implementations of IAddressValidator?

There may be different address validation strategies. For example, the way we validate postal codes or provinces could vary depending on the country. But I’d encapsulate all of that within an implementation of IAddressValidator. Pass the address to it, and internally it decides which validation strategies to implement. Within that encapsulation there could still be a factory that returns a different IAddressValidator. But I wouldn’t expose any of that complexity to any consumer that just wants to validate an address.

Dependency (Constructor) Injection With Web API Action Filters

Once upon a time we needed this. Now we don’t. There are attributes like ServiceFilterAttribute and TypeFilterAttribute that simplify injecting dependencies into filters.

Define Types Instead of Using Primitives

This post could be replaced with

Google “value objects.” They’re great. Use them.

If we’re using C# records then we don’t need to implement equality checks.

# .NET Event Bus - Dependency Injection Friendly and Agnostic

This was fun to play with back in 2016. I think I used it once. In real life I think I used it once. I was picking up little pieces of domain modelling concepts but never got to use them. Eight years later I rarely get the opportunity to do anything that resembles domain modelling. Unfortunately the pull of anemic, database-centric code is very strong in many .NET environments.

Given the opportunity to use domain events I don’t know whether I’d bother with writing custom code when options like NServiceBus are available.

The Dependency Inversion Principle For Beginners

Dependency inversion is a valuable concept. These days it’s so baked into .NET applications that I’m not sure if the explanation helps. I don’t think about it when writing code. It’s just what we do. At the same time I didn’t understand the concept as well and my explanation was probably all over the place.

Depending on Functions Instead of Interfaces - Why and How

Depending on Functions Instead of Interfaces - The Navigation Problem

I still like the idea of it and I use it once in a while, but not as much as I hoped. It’s one more slightly different thing introduced into a code base and never catches on.

String Interpolation Functions vs. string.Format Constants

This is a solution without a problem.

The Interface Segregation Principle Applied in C#/.NET

I mostly stand by this. I argued that the principle is about dependencies and coupling, not about avoiding large interfaces. I suppose it’s about both, although we generally overlook the coupling issues and focus on the size of the interface. I’ll re-iterate that articles focusing on not throwing NotImplementedException completely miss the point. We shouldn’t throw that, but that’s not what the principle is about.

No, MediatR Didn’t Run Over My Dog

This is the one that haunts me. I was in an odd purist phase in which I ranted about MediatR left and right. Yes, it was misused in places. No, I still don’t see how it’s connected to the mediator design pattern. And yes, I still cringe when I see “CQRS with MediatR” articles because the two have nothing to do with each other.

That has nothing to do with the tool. I’ve used it many times since then. It’s familiar. It does something we need. My reasons why we shouldn’t use it didn’t make sense. I recant. (In this case I felt compelled to add comments to that effect all over the original post.)

An Experiment With Making Integration Tests Easier to Write - Part One

An Experiment With Making Integration Tests Easier to Write - Part Two

It was an experiment. It led me in the right direction but I wouldn’t do what I described here. It’s overcomplicated. Over time I’ve settled on something more like what I described in this post.

  • Cleanly separate dependency injection code so that I can re-use the production code in a test.
  • Create a TestServer or IHost and register dependencies with it using the same code as I use in production, including code that reads from configuration settings.
  • If neeeded, override some dependencies with mocks.
  • Either send HTTP requests using the HttpClient provided by TestServer, or resolve dependencies from the ServiceProvider and interact with them.

That’s it. I’m the only one who cares, but now I feel better.

Top comments (0)