Stop throwing Exceptions! Start being Explicit

Stop throwing Exceptions.  Start being Explicit

If you’re writing a library for other developers to consume on NuGet or if you’re creating an API within your own project, stop throwing exceptions and start being explicit.

Exceptions are like landmines. Consuming callers have absolutely no idea what exceptions you might throw or how/when/why they will step on one. C# is dishonest when it comes to looking at method signatures.

YouTube

Check out my YouTube channel where I created a video that accompanies this blog post.

Honesty

I first heard of the concept of honesty in programming languages from a video of Erik Meijer discussing functional programming.

Take for example the following C# interface with a single method:

If you’re using this interface and call GetShippingAddress, what’s your expectation? You should expect to get back a string.

What’s not explicit is that you may also get back null or have an exception thrown which you need to catch. Which type of Exception? Who knows.

You could argue with C# 8 Nullable Reference Types that null is now explicit, so thankfully that’s a non-issue. However, GetShippingAddress throwing an exception is possible and as a consumer, you have no idea that you need to handle exceptions (or which types).

Pit of Failure

The argument I’ve received to this is to use XMLDocs to document your API so that developers/consumers know which exceptions you might throw and why.

That’s very nice of you and XMLDocs are great and should definitely be used. However, it does not force the developer/consumer to catch the relevant exceptions you might throw. This isn’t putting your consumer in the pit of success.

It’s putting a landmine in your API and hoping they know how to deal with it when they step on it.

Pit of Success

I’d always rather be pushed by a library, framework, or programming language into the pit of success.

Here’s an example of an interface and implementation.

If the quantity is less than 0, we’re throwing an exception. Otherwise we return an int, which is the quantity of the product we have in our basket.

The alternative to try/catch is to be explicit in signature by telling our consumer that we are either going to return them a string or a validation error, which is our exception.

To do this, we can create a new type called Either.

Either will contain only one value. Either one of the type parameters of TLeft or TRight.

The Match() method forces the consumer to handle both possible cases. This is the key. It forces the consumer down the path of handling multiple outcomes.

Now let’s remove the exception and instead return a Either<int, QuantityValidationError>

As mentioned the consumer is forced to handle both success and failure. The consumer is forced. It’s a not a choice.

What that looks like in a Razor page.

If we get the quantity back, we’re returning a redirect. If there is a validationError, we are returning a BadRequestResult, both of which are an IActionResult.

Stop Throwing Exceptions

Hopefully, you can see the value in having your APIs guide your consumers and have them be totally honest. There are no surprises that they need to be aware of. What the method signature is, is what they can expect.

If you’ve got any feedback about this approach, let me know in the comments or Twitter.

Related Links

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.

Thread Safety & Scoped Lifetime in Dependency Injection Containers

Thread Saftey & Scoped Lifetime in Dependency Injection Containers

If you’re using Scoped Lifetime in a Dependency Injection containers, beware! You may be run into race conditions due to a lack of thread safety.

I was doing a live stream on Domain Events over on my YouTube Channel where I was taking advantage of Scoped Lifetime. After the stream, I realized Scoped Lifetime and thread safety isn’t mentioned much and I’m not sure why? It could be because developers aren’t using multiple threads within the top-level request (HTTP request or service bus message invocation). Or it’s because developers are writing thread-safe code by default. I tend to think it’s the former.

Either way, I figured it would be worthwhile providing an example of using Scoped Lifetime and how you can run into issues if you aren’t writing thread-safe code.

YouTube

Check out my YouTube channel where I created a video that accompanies this blog post.

Thread-Safe

I’m going to first create ClassC which will have a method NotThreadSafe where it will take a string as a parameter, set that to a private member, then return the length of that private member.

The NotThreadSafe() method on ClassC is not thread-safe because setting the private member and returning its length are two different operations. If it’s called concurrently by two different threads, it could return the length of the last thread that set the _state member. Ultimately this is a race condition.

Demo

To demonstrate this I’m going to create a couple more classes that illustrate this race condition in a way this is more similar to what you’d actually have in a project with dependencies.

ClassB will take a dependency on ClassC, and I’ll create a top-level ClassA which will take a dependency on both ClassB and ClassC.

Scoped Lifetime in Dependency Injection Containers

The thing to notice here is that ClassA uses a Task.WhenAll. I’m not immediately awaiting the result of the Task. Instead, I’m going to fire off both calls asynchronously and then wait for all of them to finish. What this means is that multiple threads could be used. This is ultimately what can cause the race condition.

Running this code as-is is so simplistic that you won’t likely hit the race condition. In order to make it more likely to hit, I’m going to add a delay.

Now to prove the race condition, here’s a little xUnit test.

This test fails because ClassB sets the _state member second, but finishes first. ClassA finishes last and returns _state.length which is now blank because ClassB has already finished.

Scoped Lifetime in Dependency Injection Containers

If you’re using Scoped Lifetime in a DI container, do you run into thread safety issues? Do you think about thread-safety or are you not concerned as you do not typically use multiple threads within a top-level request such as an ASP.NET Core HTTP request. Let me know in the comments or on Twitter.

Related Links

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.

NuGet Package Alternatives when Migrating to .NET Core

NuGet Package Alternatives

Migrating from .NET Framework to .NET Core requires all of your NuGet Package dependencies to also be compliant with .NET Core. But what happens when you find a dependency that only targets .NET Framework? Here are a few NuGet package alternatives that I’ve run into during my own migration.

Migrating from .NET Framework to .NET Core

This post is in a blog series for migrating from .NET Framework to .NET Core. Here’ are some earlier post if you need to catch up:

Entity Framework

Probably the most common dependency most projects have is on Entity Framework. Luckily there are a few options in terms of support for .NET Core.

First, Entity Framework version 6.3 and higher target .NET Standard 2.1. Which means that you must migrate to .NET Core 3.0 or higher.

This is a bit of a problem if you want to migrate to .NET Core 2.1 as I’ve mentioned in my previous posts. This is more applicable if you’re migrating from ASP.NET on .NET Framework.

There is a second option which is to use Z.EntityFramework.Classic

Entity Framework Classic is an EF6 fork with performance enhancement, new features, and .NET Core support.

The community (free) version supports everything that’s in EF6 but targets .NET Standard 2.0. Which means you can run on .NET Core 2.1.

Machine Key

If you’re using System.Web.MachineKey and cannot for whatever reason move to the new ASP.NET Core Data Protection, you might want to look at AspNetCore.DataProtection.MachineKey

This package adds a new DataProtector that is configured using your existing Decryption & Validation Keys from your web.config. This allows you to Decrypt data that you might have already encrypted using MachineKey on .NET Framework. This package also supports .NET Standard 2.0

ImageProcessor

If you do any image processing on .NET Framework, you might be using the ImageProcessor library. Although not a direct replacement, the same author, James Jackson-South has created a new library ImageSharp that does work on .NET Core

These libraries are completely different. ImageSharp is not a drop in replacement for ImageProcessor but it’s by far the best image library that can run on .NET Core.

PDF

Another issue we ran into was PDF generation. For this I turned to IronPDF. This is a commercial product that requires a license. It does support .NET Standard 2.0 and works on Windows, MacOS, and Linux.

If you’re using PdfSharp, there is a  replacement package, PdfSharpCore.PdfSharp that targets .NET Standard.

NuGet Package Alternatives

Have you run into packages that don’t support .NET Core or .NET Standard?

If you have and/or have found any NuGet package alternatives, let me know in the comments or on Twitter. I’d like to keep this an evolving post with other recommendations.

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.