1
Vote

Unmaintained library, so now what?

description

Hey @dot_NET_Junkie

In this thread, you say you don't use this anymore. I'm surprised, because it's so good!

What do you use now? I assume it is even better that CuttingEdge.Conditions, and that is surprising!

comments

dot_NET_Junkie wrote Mar 7, 2015 at 12:37 PM

Hi,

CuttingEdge.Conditions specializes in getting the correct exceptions back for precondition checks (and doing that in a fluent way). Communicating the most specific exception message and exception type are especially important for reusable libraries, where the consumer of the library is unknown, and the consumer has no direct access to the source code (during debugging).

For line of business applications however, communicating the correct exception type and message are much less important, simply because there is complete access to the source code.

But this raises a conflict in the design of CuttingEdge.Conditions. The library is especially useful for library developers, but on the other hand, while developing a reusable library, you like to minimize the dependencies on external libraries. External dependencies cause risks for you, and the consumers of your library.

Because of this the developers for the MongoDb drivers for .NET copied the CuttingEdge.Conditions source code and made it internal to their own dll. They didn't want to have this second dll (while they still clearly loved the Conditions API).

For that reason I never used Conditions myself in the other reusable libraries I created (such as Simple Injector), while for the line of business applications that I helped writing, I never felt the need to add an extra dependency on a 3rd party tool (which adds some completity and risk), for something that I could easily do with a single internal class.

Instead, for both the the LOB projects and OSS projects I run, I define an internal class named Requires with methods like IsNotNull and IsNotNullOrEmpty. Those methods are really straightforward to write, so I add new methods only when I need them (YAGNI); but usually I won't get more than 4 or 5 methods in it.

Here's an example of that class:
internal static class Requires
{
    public static void IsNotNull(object instance, string paramName) {
        if (object.ReferenceEquals(null, instance)) {
            throw new ArgumentNullException(paramName);
        }
    }
}
Alternatively, if performance is really critical on a microscopic level (which is never the case in my LOB projects), I might optimize this further to the following:
internal static class Requires
{
    public static void IsNotNull(object instance, string paramName) {
        if (object.ReferenceEquals(null, instance)) {
            ThrowArgumentNullException(paramName);
        }
    }

    private static void ThrowArgumentNullException(string paramName) {
        throw new ArgumentNullException(paramName);
    }
}
By extracting the code that throws the exception into its own method, the IsNotNull method can be inlined by the JIT (note that methods that throw an exception will never be inlined by the JIT). But again, for LOB projects, such optimization is hardly ever useful.

thoqbk wrote Mar 10, 2015 at 10:48 AM

Very interesting. I didn't expect that answer.

I still use it because it makes my life easier. Your concern about referencing third-party DLLs is just a way of life now - we have dozens of referenced assemblies (easier than ever to manage them with nuget). Building a serious system, quickly, is almost impossible if you're gonna roll everything yourself. Yes, it means risk, but it means we can build stuff faster, and it's community supported libraries which are fixed quickly. I understand your point though - if I'm maintaining an existing large system, I'd probably swop-out external deps one by one over time.

I expected to hear you say that you moved to Microsoft's Code Contracts.

dot_NET_Junkie wrote Mar 10, 2015 at 12:16 PM

In the past I tried Code Contracts, but I never got it to work. I got weird exceptions at runtime, and no one on the internet I could find why this was. I was annoyed that this feature didn't work out-of-the-box and needed some weird configuration to get working. I therefore stopped trying and never looked back. Perhaps MS fixed this, but I already lost interest. I must say that I don't do precondition checks that often anymore in my code.

Since I'm using a DI container, I'm 100% sure that every constructor that my container auto-wires will never get a null reference injected, so that removes the need for doing null checks in constructors.

Since I'm using a message based architecture, I verify my messages (often using DataAnnotions instead of precondition checks).

My methods are often small enough to easily locate null references if they happen.

The use of Microsoft Code Contracts with compile time support sounds really cool, but usually data is coming from the outside (through a web request, etc) and compile-time supported code contracts don't help on such system boundary.

What's left is that I sometimes add my precondition checks in cases where it really helps development or makes the contract very explicit. In most cases however, I'm happy to leave most of the checks out (in my LOB applications that is).