Skip to content
Cyrille DUPUYDAUBY edited this page Jan 2, 2020 · 3 revisions

Purpose

This page provides the rationale of (NFluent's) design decisions that are often challenged.

Being opinionated

We (NFluent's team) make clear that we are proponent of TDD and other test first practices. This impacts API design decision in more or less subtle ways. The following entries provide clarification on what this means.

Why does IsEqualTo accepts any type as an expected value ?

1. First reason: TDD!

IsEqualTo is the cornerstone of test first development, as the developer provides the results she/he expects (hopes?) the code will provide when run in specified conditions. On the other hand, TDD implies writing the test first, as in even before any production code is written. This means the object/value that will hold the result may not be decided yet.

When using NUnit's Assert.AreEqual, this implies you provide the expected value as the first parameter, and the outcome value/objects as the second one. A nice side effect of this, is that the IDE can guess the type of second parameter (same as the first parameter's) helping with autocompletion feature. Sadly, this design is also difficult to read and often to lead to inversion of values. That's why NFluent uses the reverse, more natural, ordering; i.e.: Check.That(sut).... Except that type resolution logic for object oriented languages relies on having an explicit type for the instance used when invoking a method. Or to put it more explicitly: when using Check.That(something).IsEqualTo(somevalue) the IDE cannot infer the type of something using the definition(s) of IsEqualTo. Alas, TDD implies the opposite: something type should derive from (and often match) the type of somevalue.

That's the first reason why we relaxed the syntax of IsEqualTo to accept object as a parameter.

2. Second reason: BCL design

Also IsEqualTo relies on the BCL (Net Base Class Library) which drives the design of classes and structs in C#. More specifically, the standard way to test for equality is to use the Equals method. And it normally accepts an object instance as a parameter, but it may also provides a signature accepting an instance of the 'same' type. For that matter, a developper if free to implement whatever signature overload he may need for Equals. As of C# 8.0, there is no mechanism that could support providing signatures of IsEqualTo that matches the signature of Equals for the sut types. This means that offering only 'typed' version of IsEqualTo was the cause of undue loss of functionality for properly defined types! This was not acceptable.

Clone this wiki locally