Monday, January 7, 2019

More DI: Async Interfaces, Decorators, and .NET Standard

I've been helping developers get a handle on the basics of dependency injection (DI) since 2012. The next several articles cover some things that are important when using DI in the real world. These go along with code on GitHub: https://github.com/jeremybytes/di-decorators.

Articles

More DI: Async Interfaces
More DI: Adding Retry with the Decorator Pattern
More DI: Unit Testing Async Methods
More DI: Adding Exception Logging with the Decorator Pattern
More DI: Adding a Client-Side Cache with the Decorator Pattern
More DI: Stacking Decorators (coming soon)
More DI: Dealing with .NET Standard in .NET Framework (coming soon)
More DI: General Purpose Decorators (coming soon)

These articles all reference code on GitHub: https://github.com/jeremybytes/di-decorators

More DI: Async Interfaces
The first article deals with some updates to the sample application. The .NET world has changed quite a bit since I first started talking about dependency injection in 2012. Back then we were using SOAP services and mostly synchronous code. But things are different now. We're mainly using services that return JSON with asynchronous methods.

Previously, I asked about dealing with asynchronous code (Code Samples: Simple or Correct). I do not like the idea of including asynchronous code when introducing dependency injection because a lot of developers don't have a handle on using Task yet (one of my more popular presentations is on Task and Await). Where I landed (thanks to Stephen Cleary's comment) is to use synchronous code for the introduction.

The code samples in these articles use asynchronous code. So the first stop is to take a quick look at the async interfaces and how they change the application.

More DI: Decorators
The core reason for the code updates was to show some more things that we can do with the Decorator pattern. I've been showing a quick example using the decorator pattern to add a client-side cache to an application. There has been a lot of interest in this, so I wanted to show some other decorators.

These new decorators show how to add retry functionality and also how to log exceptions. In addition to seeing how decorators can add functionality to an existing interface implementation, we'll also see how we can stack decorators. This lets us add multiple functions which all run with one method call.

More DI: Unit Testing Async Methods
Since our interfaces our asynchronous, our unit tests need to be asynchronous as well. We'll look at easy ways to add asynchrony to our tests (even though our tests may only contain synchronous code). And we'll also look at different fake objects that we can use to test the functionality of the decorators.

More DI: General Purpose Decorators
The decorators shown above work with a specific-purpose interface (in this case, reading Person objects from a data store). There are some more interesting ways to put applications together using more general-purpose interfaces. This can give us the ability to write a single decorator (such as the retry decorator) that will work with a variety of different functions. The downside is that this can also make our code more difficult to read. We'll take a look at the benefits and the drawbacks.

More DI: Dealing with .NET Standard in .NET Framework
In the process of updating the code, I've also moved the libraries to .NET Standard. These project manage NuGet packages a bit differently, and referencing the libraries in a .NET Framework application (in this case, WPF) causes some problems with the package references.

Most of these can be resolved with a quick change to the project file itself. But there's still an outstanding issue that I have with SQLite. There are a couple of workarounds, and we'll see which one I picked and why.

Keep Exploring
I've been using Dependency Injection since 2012, and I keep coming across new ideas. I started by getting a handle on the basics (with constructor injection and some property injection). Once I was comfortable with these, I found myself using them automatically. The rest is code that is easier to unit test. On further exploration, I've added techniques that make my code more modular, and I can snap pieces together in different ways. Keep exploring, and finding new ways to make your code better for the environments you work in.

Happy Coding!

No comments:

Post a Comment