ploeh blog https://blog.ploeh.dk danish software design en-us Mark Seemann Wed, 21 Oct 2020 16:22:28 UTC Wed, 21 Oct 2020 16:22:28 UTC Monomorphic functors https://blog.ploeh.dk/2020/10/19/monomorphic-functors/ Mon, 19 Oct 2020 07:36:00 UTC <div id="post"> <p> <em>Non-generic mappable containers, with a realistic example.</em> </p> <p> This article is an instalment in <a href="/2018/03/22/functors">an article series about functors</a>. Previous articles have covered <a href="/2018/03/26/the-maybe-functor">Maybe</a>, <a href="/2018/09/10/the-lazy-functor">Lazy</a>, and other functors. This article looks at what happens when you weaken one of the conditions that the article series so far has implied. </p> <p> In the <a href="/2018/03/22/functors">introductory article</a>, I wrote: <blockquote> As a rule of thumb, if you have a type with a generic type argument, it's a candidate to be a functor. </blockquote> That still holds, but then <a href="https://about.me/tysonwilliams">Tyson Williams</a> <a href="/2018/03/22/functors#dee7ec216a464248b6103ea0979948ab">asks if that's a required condition</a>. It turns out that it isn't. In this article, you'll learn about the implications of weakening this condition. </p> <p> As is my habit with many of the articles in this article series, I'll start by uncovering the structure of the concept, and only later show a more realistic example. </p> <h3 id="bea56fadde1e4e9da8389a6c31937216"> Mapping strings <a href="#bea56fadde1e4e9da8389a6c31937216" title="permalink">#</a> </h3> <p> So far in this article series, you've seen examples of <a href="https://bartoszmilewski.com/2014/01/14/functors-are-containers">containers</a> with a generic type argument: <code>Tree&lt;T&gt;</code>, <code>Task&lt;T&gt;</code>, and so on. Furthermore, you've seen how a functor is a container with a <em>structure-preserving map</em>. This function has various names in different languages: <code>Select</code>, <code>fmap</code>, <code>map</code>, etcetera. </p> <p> Until now, you've only seen examples where this mapping enables you to translate from one type argument to another. You can, for example, translate the characters in a string to Boolean values, like this: </p> <p> <pre>&gt; <span style="color:#a31515;">&quot;Safe&nbsp;From&nbsp;Harm&quot;</span>.<span style="color:#2b91af;">Select</span>(c&nbsp;=&gt;&nbsp;c.IsVowel()) Enumerable.WhereSelectEnumerableIterator&lt;char, bool&gt; &nbsp;&nbsp;{ false, true, false, true, false, false, false, true, false, false, false, true, false, false }</pre> </p> <p> This works because in C#, <a href="https://docs.microsoft.com/dotnet/api/system.string">the String class</a> implements various interfaces, among these <code>IEnumerable&lt;char&gt;</code>. By treating a <code>string</code> as an <code>IEnumerable&lt;char&gt;</code>, you can map each element. That's the standard IEnumerable functor (AKA <em>the list functor</em>). </p> <p> What if you'd like to map the characters in a string to other characters? Perhaps you'd like to map vowels to upper case, and all other characters to lower case. You could try this: </p> <p> <pre>&gt; <span style="color:#a31515;">&quot;Safe&nbsp;From&nbsp;Harm&quot;</span>.<span style="color:#2b91af;">Select</span>(c&nbsp;=&gt;&nbsp;c.IsVowel()&nbsp;?&nbsp;<span style="color:blue;">char</span>.ToUpper(c)&nbsp;:&nbsp;<span style="color:blue;">char</span>.ToLower(c)) Enumerable.WhereSelectEnumerableIterator&lt;char, char&gt; &nbsp;&nbsp;{ 's', 'A', 'f', 'E', ' ', 'f', 'r', 'O', 'm', ' ', 'h', 'A', 'r', 'm' }</pre> </p> <p> That sort of works, but as you can tell, the result isn't a <code>string</code>, it's an <code>IEnumerable&lt;char&gt;</code>. </p> <p> This isn't a big problem, because one of the <code>string</code> constructor overloads take a <code>char</code> array as input, so you can do this: </p> <p> <pre>&gt; <span style="color:blue;">new</span>&nbsp;<span style="color:blue;">string</span>&nbsp;(<span style="color:#a31515;">&quot;Safe&nbsp;From&nbsp;Harm&quot;</span>.<span style="color:#2b91af;">Select</span>(c&nbsp;=&gt;&nbsp;c.IsVowel()&nbsp;?&nbsp;<span style="color:blue;">char</span>.ToUpper(c)&nbsp;:&nbsp;<span style="color:blue;">char</span>.ToLower(c)).<span style="color:#2b91af;">ToArray</span>()) "sAfE frOm hArm"</pre> </p> <p> It isn't the prettiest, but it gets the job done. </p> <h3 id="fd3da7dcd560415d81ab82bfb772d94c"> Monomorphic functor in C# <a href="#fd3da7dcd560415d81ab82bfb772d94c" title="permalink">#</a> </h3> <p> If you contemplate the last example, you may arrive at the conclusion that you could package some of that boilerplate code in a reusable function. Since we're already talking about functors, why not call it <code>Select</code>? </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">static</span>&nbsp;<span style="color:blue;">string</span>&nbsp;Select(<span style="color:blue;">this</span>&nbsp;<span style="color:blue;">string</span>&nbsp;source,&nbsp;<span style="color:#2b91af;">Func</span>&lt;<span style="color:blue;">char</span>,&nbsp;<span style="color:blue;">char</span>&gt;&nbsp;selector) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">return</span>&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:blue;">string</span>(source.AsEnumerable().Select(selector).ToArray()); }</pre> </p> <p> It somewhat simplifies things: </p> <p> <pre>&gt; <span style="color:#a31515;">&quot;Safe&nbsp;From&nbsp;Harm&quot;</span>.Select(c&nbsp;=&gt;&nbsp;c.IsVowel()&nbsp;?&nbsp;<span style="color:blue;">char</span>.ToUpper(c)&nbsp;:&nbsp;<span style="color:blue;">char</span>.ToLower(c)) "sAfE frOm hArm"</pre> </p> <p> Since I deliberately wrote the <code>Select</code> method in the style of other <code>Select</code> methods (apart from the generics), you may wonder if C# query syntax also works? </p> <p> <pre>&gt; <span style="color:blue;">from</span>&nbsp;c&nbsp;<span style="color:blue;">in</span>&nbsp;<span style="color:#a31515;">&quot;Army&nbsp;of&nbsp;Me&quot;</span> . <span style="color:blue;">select</span>&nbsp;c.IsVowel()&nbsp;?&nbsp;<span style="color:blue;">char</span>.ToUpper(c)&nbsp;:&nbsp;<span style="color:blue;">char</span>.ToLower(c) "ArmY Of mE"</pre> </p> <p> It compiles and works! The C# compiler understands monomorphic containers! </p> <p> I admit that I was quite surprised when I first tried this out. </p> <h3 id="8ef3808c11a34d9aaa1c25b94539f843"> Monomorphic functor in Haskell <a href="#8ef3808c11a34d9aaa1c25b94539f843" title="permalink">#</a> </h3> <p> Surprisingly, in this particular instance, C# comes out looking more flexible than <a href="https://www.haskell.org">Haskell</a>. This is mainly because in C#, functors are implemented as a special compiler feature, whereas in Haskell, <code>Functor</code> is defined using the general-purpose <em>type class</em> language feature. </p> <p> There's <a href="https://hackage.haskell.org/package/mono-traversable">a package</a> that defines a <code>MonoFunctor</code> type class, as well as some instances. With it, you can write code like this: </p> <p> <pre><span style="color:#2b91af;">ftg</span>&nbsp;::&nbsp;<span style="color:blue;">Text</span> ftg&nbsp;=&nbsp;omap&nbsp;(\c&nbsp;-&gt;&nbsp;<span style="color:blue;">if</span>&nbsp;isVowel&nbsp;c&nbsp;<span style="color:blue;">then</span>&nbsp;toUpper&nbsp;c&nbsp;<span style="color:blue;">else</span>&nbsp;toLower&nbsp;c)&nbsp;<span style="color:#a31515;">&quot;Fade&nbsp;to&nbsp;Grey&quot;</span></pre> </p> <p> Even though <code>Text</code> isn't a <code>Functor</code> instance, it <em>is</em> a <code>MonoFunctor</code> instance. The value of <code>ftg</code> is <code>"fAdE tO grEY"</code>. </p> <p> All the normal functors (<code>[]</code>, <code>Maybe</code>, etc.) are also <code>MonoFunctor</code> instances, since the normal <code>Functor</code> instance is more capable than a <code>MonoFunctor</code>. </p> <h3 id="30dd605a3bb34d1985e1d277e1c9b0a5"> Restaurant example <a href="#30dd605a3bb34d1985e1d277e1c9b0a5" title="permalink">#</a> </h3> <p> While I've introduced the concept of a monomorphic functor with a trivial string example, I actually discovered the C# feature when I was working on some more realistic code. As I often do, I was working on a variation of an online restaurant reservation system. </p> <p> The code base contained a rather complex variation of an implementation of the <a href="/2020/01/27/the-maitre-d-kata">Maître d' kata</a>. The <code>MaitreD</code> constructor looked like this: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">MaitreD</span>( &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">TimeOfDay</span>&nbsp;opensAt, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">TimeOfDay</span>&nbsp;lastSeating, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">TimeSpan</span>&nbsp;seatingDuration, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">IEnumerable</span>&lt;<span style="color:#2b91af;">Table</span>&gt;&nbsp;tables)</pre> </p> <p> This had worked well when the system only dealt with a single restaurant, but I was now expanding it to a multi-tenant system and I needed to keep track of some more information about each restaurant, such as its name and ID. While I could have added such information to the <code>MaitreD</code> class, I didn't want to pollute that class with data it didn't need. While the restaurant's opening time and seating duration are necessary for the decision algorithm, the name isn't. </p> <p> So I introduced a wrapper class: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">sealed</span>&nbsp;<span style="color:blue;">class</span>&nbsp;<span style="color:#2b91af;">Restaurant</span> { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">Restaurant</span>(<span style="color:blue;">int</span>&nbsp;id,&nbsp;<span style="color:blue;">string</span>&nbsp;name,&nbsp;<span style="color:#2b91af;">MaitreD</span>&nbsp;maitreD) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Id&nbsp;=&nbsp;id; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name&nbsp;=&nbsp;name; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MaitreD&nbsp;=&nbsp;maitreD; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:blue;">int</span>&nbsp;Id&nbsp;{&nbsp;<span style="color:blue;">get</span>;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:blue;">string</span>&nbsp;Name&nbsp;{&nbsp;<span style="color:blue;">get</span>;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">MaitreD</span>&nbsp;MaitreD&nbsp;{&nbsp;<span style="color:blue;">get</span>;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:green;">//&nbsp;More&nbsp;code&nbsp;follows...</span></pre> </p> <p> I also added copy-and-update methods (AKA 'withers'): </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">Restaurant</span>&nbsp;WithId(<span style="color:blue;">int</span>&nbsp;newId) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">return</span>&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">Restaurant</span>(newId,&nbsp;Name,&nbsp;MaitreD); } <span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">Restaurant</span>&nbsp;WithName(<span style="color:blue;">string</span>&nbsp;newName) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">return</span>&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">Restaurant</span>(Id,&nbsp;newName,&nbsp;MaitreD); } <span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">Restaurant</span>&nbsp;WithMaitreD(<span style="color:#2b91af;">MaitreD</span>&nbsp;newMaitreD) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">return</span>&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">Restaurant</span>(Id,&nbsp;Name,&nbsp;newMaitreD); }</pre> </p> <p> Still, if you need to modify the <code>MaitreD</code> within a given <code>Restaurant</code> object, you first have to have a reference to the <code>Restaurant</code> so that you can read its <code>MaitreD</code> property, then you can edit the <code>MaitreD</code>, and finally call <code>WithMaitreD</code>. Doable, but awkward: </p> <p> <pre>restaurant.WithMaitreD(restaurant.MaitreD.WithSeatingDuration(<span style="color:#2b91af;">TimeSpan</span>.FromHours(.5)))</pre> </p> <p> So I got the idea that I might try to add a structure-preserving map to <code>Restaurant</code>, which I did: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">Restaurant</span>&nbsp;Select(<span style="color:#2b91af;">Func</span>&lt;<span style="color:#2b91af;">MaitreD</span>,&nbsp;<span style="color:#2b91af;">MaitreD</span>&gt;&nbsp;selector) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">if</span>&nbsp;(selector&nbsp;<span style="color:blue;">is</span>&nbsp;<span style="color:blue;">null</span>) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">throw</span>&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">ArgumentNullException</span>(<span style="color:blue;">nameof</span>(selector)); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">return</span>&nbsp;WithMaitreD(selector(MaitreD)); }</pre> </p> <p> The first time around, it enabled me to rewrite the above expression as: </p> <p> <pre>restaurant.Select(m&nbsp;=&gt;&nbsp;m.WithSeatingDuration(<span style="color:#2b91af;">TimeSpan</span>.FromHours(.5)))</pre> </p> <p> That's already a little nicer. It also handles the situation where you may not have a named <code>Restaurant</code> variable you can query; e.g. if you have a method that returns a <code>Restaurant</code> object, and you just want to continue calling into a <a href="https://martinfowler.com/bliki/FluentInterface.html">Fluent API</a>. </p> <p> Then I thought, <em>I wonder if query syntax works, too...</em> </p> <p> <pre><span style="color:blue;">from</span>&nbsp;m&nbsp;<span style="color:blue;">in</span>&nbsp;restaurant <span style="color:blue;">select</span>&nbsp;m.WithSeatingDuration(<span style="color:#2b91af;">TimeSpan</span>.FromHours(.5))</pre> </p> <p> And it <em>does</em> work! </p> <p> I know that a lot of people don't like query syntax, but I think it has certain advantages. In this case, it actually isn't shorter, but it's a nice alternative. I particularly find that if I try to <a href="/2019/11/04/the-80-24-rule">fit my code into a tight box</a>, query syntax sometimes gives me an opportunity to format code over multiple lines in a way that's more natural than with method-call syntax. </p> <h3 id="c386660f74424f33921f35265e61ecf0"> Conclusion <a href="#c386660f74424f33921f35265e61ecf0" title="permalink">#</a> </h3> <p> A monomorphic functor is still a functor, only it constrains the type of mapping you can perform. It can be useful to map monomorphic containers like strings, or immutable nested data structures like the above <code>Restaurant</code> class. </p> <p> <strong>Next:</strong> <a href="/2018/12/03/set-is-not-a-functor">Set is not a functor</a>. </p> </div> <div id="comments"> <hr> <h2 id="comments-header"> Comments </h2> <div class="comment" id="bb0bb9d1bf094c1897f9dd42fb49712c"> <div class="comment-author"><a href="https://about.me/tysonwilliams">Tyson Williams</a></div> <div class="comment-content"> <p> Excellent article! I was planning to eventually write a blog post on this topic, but now there is no need. </p> <blockquote> <p> I know that a lot of people don't like query syntax, but I think it has certain advantages. In this case, it actually isn't shorter, but it's a nice alternative. I particularly find that if I try to <a href="/2019/11/04/the-80-24-rule">fit my code into a tight box</a>, query syntax sometimes gives me an opportunity to format code over multiple lines in a way that's more natural than with method-call syntax. </p> </blockquote> <p> Said another way, one objective measure that is better in this case when using query syntax is that the maximum line width is smaller. It is objective primarily in the sense that maximum line width is objective and secondarily in the sense that we generally agree that code with a lower maximum line width is typically easier to understand. </p> <p> Another such objective measure of quality that I value is the maximum number of matching pairs of parentheses that are nested. This measure improves to two in your query syntax code from three in your previous code. The reason it was three before is because there are four levels of detail and your code decreases the level of detail three times: <code>Restaurant</code> to <code>MaitreD</code>, <code>MaitreD</code> to <code>TimeSpan</code>, and <code>TimeSpan</code> to <code>double</code>. Query syntax is one way to decrease the level of detail without having to introduce a pair of matching parentheses. </p> <p> I find more success minimizing this measure of quality when taking a bottom-up approach. Using the <a href="https://github.com/louthy/language-ext/blob/3df8c837961a502d7a03268b6cac636a57c49056/LanguageExt.Core/DataTypes/Cond/Cond.cs#L56-L70"><code>Apply</code> extension method from <code>language-ext</code></a>, which is like the <a href="https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/symbol-and-operator-reference/#table-of-symbols-and-operators:~:text=Passes%20the%20result%20of%20the%20left%20side%20to%20the%20function%20on%20the%20right%20side%20(forward%20pipe%20operator).">forward pipe operator in F#</a>, we can rewrite this code without any nested pairs of matching parentheses as </p> <p> <pre>.5.Apply(<span style="color:#2b91af;">TimeSpan</span>.FromHours).Apply(m&nbsp;=&gt;&nbsp;m.WithSeatingDuration).Apply(restaurant.Select)</pre> </p> <p> (I did not check if this code compiles. If it does not, it would be because the C# compiler is unsure how to implicitly convert some method group to its intended <code>Func&lt;,&gt;</code> delegate.) This code also has natural line-breaking points before each dot operator, which leads to a comfortable value for the maximum line width. </p> <p> Another advantage of this code that I value is that the execution happens in the same order in which I (as an English speaker) read it: left to right. Your code before using the query syntax executed from right to left as dictated by the matching parentheses. In fact, since the dot operator is left associative, the degree to which execution occurs from left to right is inversely correlated to the number of nested pairs of parentheses. (One confusing thing here is the myriad of different semantic meanings in C# to the syntactic use of a pair of parentheses.) </p> </div> <div class="comment-date">2020-10-19 14:05 UTC</div> </div> <div class="comment" id="8e6b870ce4aa44aa98a16a7969def6e9"> <div class="comment-author"><a href="/">Mark Seemann</a></div> <div class="comment-content"> <p> Tyson, thank you for writing. I've never thought about measuring complexity by nested parentheses, but I like it! It makes intuitive sense. </p> <p> I'm not sure it applies to LISP-like languages, but perhaps some reader comes by some day who can enlighten us. </p> </div> <div class="comment-date">2020-10-21 13:55 UTC</div> </div> </div><hr> This blog is totally free, but if you like it, please consider <a href="https://blog.ploeh.dk/support">supporting it</a>. Mark Seemann https://blog.ploeh.dk/2020/10/19/monomorphic-functors Subjectivity https://blog.ploeh.dk/2020/10/12/subjectivity/ Mon, 12 Oct 2020 07:40:00 UTC <div id="post"> <p> <em>A subjective experience can be sublime, but it isn't an argument.</em> </p> <p> I once wrote <a href="https://amzn.to/36xLycs">a book</a>. One of the most common adjectives people used about it was <em>opinionated</em>. That's okay. It is, I think, a ramification of <a href="/2020/04/13/curb-code-rot-with-thresholds#6c5e4b0817f742bf9ecc0a9050ecb7b5">the way I write</a>. I prioritise writing so that you understand what I mean, and why I mean it. You can call that opinionated if you like. </p> <p> This means that I frequently run into online arguments, mostly on Twitter. This particularly happens when I write something that readers don't like. </p> <h3 id="6a04cf26fdfc483db096de13451a7273"> The sublime <a href="#6a04cf26fdfc483db096de13451a7273" title="permalink">#</a> </h3> <p> Whether or not you <em>like</em> something is a subjective experience. I have nothing against subjective experiences. </p> <p> Subjective experiences fuel art. Before I became a programmer, I wanted to be an artist. I've loved <a href="https://en.wikipedia.org/wiki/Bande_dessin%C3%A9e">French-Belgian</a> comics for as long as I remember (my favourites have always been <a href="https://en.wikipedia.org/wiki/Hermann_Huppen">Hermann</a> and <a href="https://en.wikipedia.org/wiki/Jean_Giraud">Jean Giraud</a>), and until I gave up in my mid-twenties, I wanted to become a graphic novelist. </p> <p> <img src="/content/binary/graphic-novel-pages.jpg" alt="Spread of original pages of my graphic novel."> </p> <p> This interest in drawing also fuelled a similar interest in paintings and art in general. I've had many sublime experiences in front of a work of art in various museums around the world. These were all subjective experiences that were precious to me. </p> <p> For as long as I've been interested in graphic arts, I've also loved music. I've worn <a href="https://en.wikipedia.org/wiki/LP_record">LPs</a> thin in the 1970s and '80s. I've played guitar and wanted to be a rock star. I regularly get goosebumps from listing to outstanding music. These are all subjective experiences. </p> <p> Having an experience is part of the human condition. </p> <p> How you <em>feel</em> about something, however, isn't an argument. </p> <h3 id="c60fc277c32d4e67be30f81d7434da51"> Arguing about subjective experience <a href="#c60fc277c32d4e67be30f81d7434da51" title="permalink">#</a> </h3> <p> I rarely read music reviews. How you experience music is such a personal experience that I find it futile to argue about it. Maybe you share my feelings that <a href="https://en.wikipedia.org/wiki/Army_of_Me">Army of Me</a> is a sublime track, or maybe it leaves you cold. If you don't like that kind of music, I can't argue that you should. </p> <p> Such a discussion generally takes place at the kindergarten level: <em>"Army of Me is a great song!</em>, <em>"No it isn't,"</em> <em>"Yes it is,"</em> and so on. </p> <p> This doesn't mean that we can't talk about music (or, by extension, other subjective experiences). Talking about music can be exhilarating, particularly when you meet someone who shares your taste. Finding common ground, exploring and inspiring each other, learning about artists you didn't know about, is wonderful. It forges bonds between people. I suppose it's the same mechanism in which sports fans find common ground. </p> <p> Sharing subjective experience may not be entirely futile. You can't use your <em>feelings</em> as an argument, but explaining <em>why</em> you feel a certain way can be illuminating. This is the realm of much art criticism. A good, popular and easily digestible example is the <a href="https://strongsongspodcast.com">Strong Songs podcast</a>. The host, Kirk Hamilton, likes plenty of music that I don't. I must admit, though, that his <a href="https://strongsongspodcast.com/satisfied-from-hamilton">exigesis of <em>Satisfied</em> from Hamilton</a> left me with more appreciation for that song than I normally have for that genre. </p> <p> This is why, in a technical argument, when people say, <em>"I don't like it"</em>, I ask <em>why?</em> </p> <p> Your <em>preference</em> doesn't convince me to change my mind, but if you can explain your perspective, it may make me consider a point of which I wasn't aware. </p> <h3 id="8759a0fb5e2f496ebc7d264072906648"> It Depends™ <a href="#8759a0fb5e2f496ebc7d264072906648" title="permalink">#</a> </h3> <p> Among other roles, I consult. Consultants are infamous for saying <em>it depends</em>, and obviously, if that's all we say, it'd be useless. </p> <p> Most advice is given in a context. When a consultant starts a sentence with <em>it depends</em>, he or she must continue by explaining on what it depends. Done right, this can be tremendously valuable, because it gives the customer a framework they can use to make decisions. </p> <p> In the same family as <em>it depends</em>, I often run into arguments like <em>nothing is black or white</em>, <em>it's a trade-off</em>, or other platitudes. Okay, it probably <em>is</em> a trade-off, but between <em>what?</em> </p> <p> If it's a trade-off between my reasoned argument on the one hand, and someone's preference on the other hand, my reasoned argument wins. </p> <p> Why? Because I can always trump with <em>my</em> preference as well. </p> <h3 id="6dd1b6841a5d42c8b295432859c5187d"> Conclusion <a href="#6dd1b6841a5d42c8b295432859c5187d" title="permalink">#</a> </h3> <p> Our subjective experiences are important pieces of our lives. I hope that my detour around my love of art highlighted that I consider subjective experiences vital. </p> <p> When we discuss how to do things, however, a <em>preference</em> isn't an argument. You may prefer to do things in one way, and I another. Such assertions, alone, don't move the discussion anywhere. </p> <p> What we <em>can</em> do is to attempt to uncover the underlying causes for our preferences. There's no guarantee that we'll reach enlightenment, but it's certain that we'll get nowhere if we don't. </p> <p> That's the reason that, when someone states <em>"I prefer"</em>, I often ask <em>why?</em> </p> </div> <div id="comments"> <hr> <h2 id="comments-header"> Comments </h2> <div class="comment" id="f826ff3d591f4d6ebb1e7d93c00cea3a"> <div class="comment-author"><a href="https://about.me/tysonwilliams">Tyson Williams</a></div> <div class="comment-content"> <blockquote> <p> Consultants are infamous for saying <em>it depends</em>, and obviously, if that's all we say, it'd be useless. </p> <p> Most advice is given in a context. When a consultant starts a sentence with <em>it depends</em>, he or she must continue by explaining on what it depends. Done right, this can be tremendously valuable, because it gives the customer a framework they can use to make decisions. </p> </blockquote> <p> I have a vague memory of learning this through some smoothly worded saying. As I recall, it went something like this. </p> <blockquote> Anyone can say "It depends", but an expert can say on what it depends. </blockquote> <p> I don't think that is the exact phrase, because I don't think it sounds very smooth. Does anyone know of a succinct and smooth mnemonic phrase that captures this idea? </p> </div> <div class="comment-date">2020-10-12 13:54 UTC</div> </div> </div><hr> This blog is totally free, but if you like it, please consider <a href="https://blog.ploeh.dk/support">supporting it</a>. Mark Seemann https://blog.ploeh.dk/2020/10/12/subjectivity Fortunately, I don't squash my commits https://blog.ploeh.dk/2020/10/05/fortunately-i-dont-squash-my-commits/ Mon, 05 Oct 2020 06:00:00 UTC <div id="post"> <p> <em>The story of a bug, and how I addressed it.</em> </p> <p> Okay, I admit it: I could have given this article all sorts of alternative titles, each of which would have made as much sense as the one I chose. I didn't want to go with some of the other titles I had in mind, because they would give it all away up front. I didn't want to spoil the surprise. </p> <p> I recently ran into this bug, it took me hours to troubleshoot it, and I was appalled when I realised what the problem was. </p> <p> This is the story of that bug. </p> <p> There are several insights from this story, and I admit that I picked the most click-baity one for the title. </p> <h3 id="94bc204499df483897121bb0343f73f7"> Yak shaving <a href="#94bc204499df483897121bb0343f73f7" title="permalink">#</a> </h3> <p> I was working on the umpteenth variation of an online restaurant reservations system, and one of the features I'd added was a schedule only visible to the <a href="https://en.wikipedia.org/wiki/Ma%C3%AEtre_d%27h%C3%B4tel">maître d'</a>. The schedule includes a list of all reservations for a day, including guests' email addresses and so on. For that reason, I'd protected that resource by requiring a valid <a href="https://en.wikipedia.org/wiki/JSON_Web_Token">JSON Web Token</a> (JWT) with an appropriate role. </p> <p> I'd deployed a new version of the API and went for an ad-hoc test. To my surprise, that particular resource didn't work. When I tried to request it, I got a <code>403 Forbidden</code> response. </p> <p> "That's odd," I though, "it worked the last time I tried this." </p> <p> The system is set up with continuous deployment. I push <em>master</em> to a remote repository, and a build pipeline takes over from there. It only deploys the new version if all tests pass, so my first reaction was that I might have made a mistake with the JWT. </p> <p> I wasted significant time decoding the JWT and comparing its contents to what it was supposed to be. I couldn't find any problems. </p> <p> I also meticulously compared the encryption key I'd used to sign the JWT with the key on the server. They were identical. </p> <p> Incredulous, and running out of ideas, I tried running all tests on my development machine. Indeed, all 170 tests passed. </p> <p> Finally, I gave up and ran the API on my development machine. It takes all of a 30 seconds to configure the code to run in that environment, so you're excused if you wonder why I didn't already do that. What can I say? I've almost two decades of experience with automated test suites. Usually, if all tests pass, the problem is environmental: a network topology issue, a bad or missing connection string, a misconfigured encryption key, an invalid JWT, things like that. </p> <p> To my surprise, the problem also manifested on my machine. </p> <h3 id="b726532ae06844eb8aeaa2c27ca0d913"> Not my code <a href="#b726532ae06844eb8aeaa2c27ca0d913" title="permalink">#</a> </h3> <p> Okay, even with hundreds of tests, perhaps some edge case went unnoticed. The only problem with that hypothesis was that this was hardly an edge case. I was only making a <code>GET</code> request with a <code>Bearer</code> token. I wasn't going through some convoluted sequence of steps. </p> <p> <pre>GET /restaurants/1/schedule/2020/9/30 HTTP/1.1 Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5c[...]</pre> </p> <p> I expected a successful response containing some JSON, but the result was <code>403 Forbidden</code>. That was the same behaviour I saw in the production environment. </p> <p> Now, to be clear, this is indeed a protected resource. If you present an invalid JWT, <code>403 Forbidden</code> is the expected response. That's why I wasted a few hours looking for problems with the the JWT. </p> <p> I finally, hesitatingly, concluded that the problem might be somewhere else. The JWT looked okay. So, hours into my troubleshooting I reluctantly set a breakpoint in my code and started the debugger. It isn't rational, but I tend to see it as a small personal defeat if I have to use the debugger. Even so, if used judiciously, it can be an effective way to identify problems. </p> <p> The debugger never hit my breakpoint. </p> <p> To be clear, the beginning of my Controller method looked like this: </p> <p> <pre>[<span style="color:#2b91af;">Authorize</span>(Roles&nbsp;=&nbsp;<span style="color:#a31515;">&quot;MaitreD&quot;</span>)] [<span style="color:#2b91af;">HttpGet</span>(<span style="color:#a31515;">&quot;restaurants/{restaurantId}/schedule/{year}/{month}/{day}&quot;</span>)] <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">async</span>&nbsp;<span style="color:#2b91af;">Task</span>&lt;<span style="color:#2b91af;">ActionResult</span>&gt;&nbsp;Get( &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">int</span>&nbsp;restaurantId, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">int</span>&nbsp;year, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">int</span>&nbsp;month, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">int</span>&nbsp;day) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">if</span>&nbsp;(!AccessControlList.Authorize(restaurantId)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">return</span>&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">ForbidResult</span>();</pre> </p> <p> My breakpoint was on the first line (the <code>if</code> conditional), but the debugger didn't break into it. When I issued my <code>GET</code> request, I immediately got the <code>403 Forbidden</code> response. The breakpoint just sat there in the debugger, mocking me. </p> <p> When that happens, it's natural to conclude that the problem occurs somewhere in the framework; in this case, ASP.NET. To test that hypothesis, I commented out the <code>[Authorize]</code> attribute and reissued the <code>GET</code> request. My hypothesis was that I'd get a <code>200 OK</code> response, since the attribute is what tells ASP.NET to check authorisation. </p> <p> The hypothesis held. The response was <code>200 OK</code>. </p> <h3 id="fdff404f12644a898b6a3e695fb6533f"> Test interdependency <a href="#fdff404f12644a898b6a3e695fb6533f" title="permalink">#</a> </h3> <p> I hate when that happens. It's up there with fixing other people's printers. The problem is in the framework, not in my code. I didn't have any authorisation callbacks registered, so I was fairly certain that the problem wasn't in my code. </p> <p> I rarely jump to the conclusion that there's a bug in the framework. In my experience, <a href="https://blog.codinghorror.com/the-first-rule-of-programming-its-always-your-fault">select is rarely broken</a>. My new hypothesis had to be that I'd somehow managed to misconfigure the framework. </p> <p> But where? There were automated tests that verified that a client could request that resource with a valid JWT. There were other automated tests that verified what happened if you presented an invalid JWT, or none at all. And all tests were passing. </p> <p> While I was fiddling with the tests, I eventually ran a parametrised test by itself, instead of the entire test suite: </p> <p> <pre>[<span style="color:#2b91af;">Theory</span>] [<span style="color:#2b91af;">InlineData</span>(&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#a31515;">&quot;Hipgnosta&quot;</span>,&nbsp;2024,&nbsp;11,&nbsp;&nbsp;2)] [<span style="color:#2b91af;">InlineData</span>(&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#a31515;">&quot;Nono&quot;</span>,&nbsp;2018,&nbsp;&nbsp;9,&nbsp;&nbsp;9)] [<span style="color:#2b91af;">InlineData</span>(<span style="color:#a31515;">&quot;The&nbsp;Vatican&nbsp;Cellar&quot;</span>,&nbsp;2021,&nbsp;10,&nbsp;10)] <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">async</span>&nbsp;<span style="color:#2b91af;">Task</span>&nbsp;GetRestaurantScheduleWhileAuthorized( &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">string</span>&nbsp;name, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">int</span>&nbsp;year, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">int</span>&nbsp;month, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">int</span>&nbsp;day)</pre> </p> <p> This parametrised test has three test cases. When I ran just that test method, two of the test cases passed, but one failed: the <em>Nono</em> case, for some reason I haven't yet figured out. </p> <p> I didn't understand why that test case ought to fail while the others succeeded, but I had an inkling. I commented out the <em>Nono</em> test case and ran the test method again. </p> <p> One passed and one failing test. </p> <p> Now <em>The Vatican Cellar</em> test case was failing. I commented that out and ran the test method again. The remaining test case failed. </p> <p> This reeks of some sort of test interdependency. Apparently, <em>something</em> happens during the first test run that makes succeeding tests pass, but it happens too late for the first one. But what? </p> <h3 id="c95c3e707f46467abbf8ff02a9594c4c"> Bisect <a href="#c95c3e707f46467abbf8ff02a9594c4c" title="permalink">#</a> </h3> <p> Then something occurred to me that I should have thought of sooner. This feature used to work. Not only had the tests been passing, but I'd actually interacted with the deployed service, presenting a valid JWT and received a <code>200 OK</code> response. </p> <p> Once than dawned on me, I realised that it was just a manner of performing a binary search. Since, of course, I use version control, I had a version I knew worked, and a version that didn't work. The task, then, was to find the commit that introduced the defect. </p> <p> As I've already implied, the system in question is an example code base. While I have a cloud-based production environment, none but I use it. It had been four or five days since I'd actually interacted with the real service, and I'd been busy making changes, trusting exclusively in my test suite. I tend to make frequent, small commits instead of big, infrequent commits, so I had accumulated about a hundred and fifty commits since the 'last known good' deployment. </p> <p> Searching through hundreds of commits sounds overwhelming, but using binary search, it's actually not that bad. Pick the commit halfway between the 'last known good' commit and the most recent commit, and check it out. See if the defect is present there. If it is, you know that it was introduced somewhere between the commit you're looking at, and the 'last known good' commit. If it isn't present, it was introduced later. Regardless of the outcome, you know in which half to look. You now pick a new commit in the middle of that set and repeat the exercise. Even with, say, a hundred commits, the first bisection reduces the candidate set to 50, the next bisection to 25, then 13, then 7, 4, 2, and then you have it. If you do this systematically, you should find the exact commit in less than eight iterations. </p> <p> This is, as far as I understand it, the algorithm used by <em>Git bisect</em>. You don't have to use the <code>bisect</code> command - the algorithm is easy enough to do by hand - but let's see how it works. </p> <p> You start a <code>bisect</code> session with: </p> <p> <pre><span style="color: green">mark@Vindemiatrix</span> <span style="color: purple">MINGW64</span> <span style="color: orange">~/Documents/Redacted/Restaurant</span> <span style="color: darkturquoise">((93c6c35...))</span> $ git bisect start <span style="color: green">mark@Vindemiatrix</span> <span style="color: purple">MINGW64</span> <span style="color: orange">~/Documents/Redacted/Restaurant</span> <span style="color: darkturquoise">((93c6c35...)|BISECTING)</span></pre> </p> <p> This starts an interactive session, which you can tell from the Git integration in Git Bash (it says <code>BISECTING</code>). You now mark a commit as being bad: </p> <p> <pre>$ git bisect bad <span style="color: green">mark@Vindemiatrix</span> <span style="color: purple">MINGW64</span> <span style="color: orange">~/Documents/Redacted/Restaurant</span> <span style="color: darkturquoise">((93c6c35...)|BISECTING)</span></pre> </p> <p> If you don't provide a commit ID at that point, Git is going to assume that you meant that the current commit (in this case <code>93c6c35</code>) is bad. That's what I had in mind, so that's fine. </p> <p> You now tell it about a commit ID that you know is good: </p> <p> <pre>$ git bisect good 7dfdab2 Bisecting: 75 revisions left to test after this (roughly 6 steps) [1f78c9a90c2088423ab4fc145b7b2ec3859d6a9a] Use InMemoryRestaurantDatabase in a test <span style="color: green">mark@Vindemiatrix</span> <span style="color: purple">MINGW64</span> <span style="color: orange">~/Documents/Redacted/Restaurant</span> <span style="color: darkturquoise">((1f78c9a...)|BISECTING)</span></pre> </p> <p> Notice that Git is already telling us how many iterations we should expect. You can also see that it checked out a new commit (<code>1f78c9a</code>) for you. That's the half-way commit. </p> <p> At this point, I manually ran the test method with the three test cases. All three passed, so I marked that commit as good: </p> <p> <pre>$ git bisect good Bisecting: 37 revisions left to test after this (roughly 5 steps) [5abf65a72628efabbf05fccd1b79340bac4490bc] Delete Either API <span style="color: green">mark@Vindemiatrix</span> <span style="color: purple">MINGW64</span> <span style="color: orange">~/Documents/Redacted/Restaurant</span> <span style="color: darkturquoise">((5abf65a...)|BISECTING)</span></pre> </p> <p> Again, Git estimates how many more steps are left and checks out a new commit (<code>5abf65a</code>). </p> <p> I repeated the process for each step, marking the commit as either good or bad, depending on whether or not the test passed: </p> <p> <pre>$ git bisect bad Bisecting: 18 revisions left to test after this (roughly 4 steps) [fc48292b0d654f4f20522710c14d7726e6eefa70] Delete redundant Test Data Builders <span style="color: green">mark@Vindemiatrix</span> <span style="color: purple">MINGW64</span> <span style="color: orange">~/Documents/Redacted/Restaurant</span> <span style="color: darkturquoise">((fc48292...)|BISECTING)</span> $ git bisect good Bisecting: 9 revisions left to test after this (roughly 3 steps) [b0cb1f5c1e9e40b1dabe035c41bfb4babfbe4585] Extract WillAcceptUpdate helper method <span style="color: green">mark@Vindemiatrix</span> <span style="color: purple">MINGW64</span> <span style="color: orange">~/Documents/Redacted/Restaurant</span> <span style="color: darkturquoise">((b0cb1f5...)|BISECTING)</span> $ git bisect good Bisecting: 4 revisions left to test after this (roughly 2 steps) [d160c57288455377f8b0ad05985b029146228445] Extract ConfigureClock helper method <span style="color: green">mark@Vindemiatrix</span> <span style="color: purple">MINGW64</span> <span style="color: orange">~/Documents/Redacted/Restaurant</span> <span style="color: darkturquoise">((d160c57...)|BISECTING)</span> $ git bisect good Bisecting: 2 revisions left to test after this (roughly 1 step) [4cb73c219565d8377aa67d79024d6836f9000935] Compact code <span style="color: green">mark@Vindemiatrix</span> <span style="color: purple">MINGW64</span> <span style="color: orange">~/Documents/Redacted/Restaurant</span> <span style="color: darkturquoise">((4cb73c2...)|BISECTING)</span> $ git bisect good Bisecting: 0 revisions left to test after this (roughly 1 step) [34238c7d2606e9007b96b54b43e678589723520c] Extract CreateTokenValidationParameters method <span style="color: green">mark@Vindemiatrix</span> <span style="color: purple">MINGW64</span> <span style="color: orange">~/Documents/Redacted/Restaurant</span> <span style="color: darkturquoise">((34238c7...)|BISECTING)</span> $ git bisect bad Bisecting: 0 revisions left to test after this (roughly 0 steps) [7d6583a97ff45fbd85878cecb5af11d93213a25d] Move Configure method up <span style="color: green">mark@Vindemiatrix</span> <span style="color: purple">MINGW64</span> <span style="color: orange">~/Documents/Redacted/Restaurant</span> <span style="color: darkturquoise">((7d6583a...)|BISECTING)</span> $ git bisect good 34238c7d2606e9007b96b54b43e678589723520c is the first bad commit <span style="color: orange">commit 34238c7d2606e9007b96b54b43e678589723520c</span> Author: Mark Seemann &lt;mark@example.com&gt; Date: Wed Sep 16 07:15:12 2020 +0200 Extract CreateTokenValidationParameters method Restaurant.RestApi/Startup.cs | 32 <span style="color: green">+++++++++++++++++++</span><span style="color: red">-------------</span> 1 file changed, 19 insertions(+), 13 deletions(-) <span style="color: green">mark@Vindemiatrix</span> <span style="color: purple">MINGW64</span> <span style="color: orange">~/Documents/Redacted/Restaurant</span> <span style="color: darkturquoise">((7d6583a...)|BISECTING)</span></pre> </p> <p> Notice that the last step finds the culprit. It tells you which commit is the bad one, but surprisingly doesn't check it out for you. You can do that using a label Git has created for you: </p> <p> <pre>$ git checkout refs/bisect/bad Previous HEAD position was 7d6583a Move Configure method up HEAD is now at 34238c7 Extract CreateTokenValidationParameters method <span style="color: green">mark@Vindemiatrix</span> <span style="color: purple">MINGW64</span> <span style="color: orange">~/Documents/Redacted/Restaurant</span> <span style="color: darkturquoise">((34238c7...)|BISECTING)</span></pre> </p> <p> You've now found and checked out the offending commit. Hopefully, the changes in that commit should give you a clue about the problem. </p> <h3 id="2f3c813d0cbf47eabb52467cff0c7692"> The culprit <a href="#2f3c813d0cbf47eabb52467cff0c7692" title="permalink">#</a> </h3> <p> What's in that commit? Take a gander: </p> <p> <pre>$ git show <span style="color: orange">commit 34238c7d2606e9007b96b54b43e678589723520c (</span><span style="color: mediumturquoise">HEAD</span><span style="color: orange">,</span> refs/bisect/bad<span style="color: orange">)</span> Author: Mark Seemann &lt;mark@example.com&gt; Date: Wed Sep 16 07:15:12 2020 +0200 Extract CreateTokenValidationParameters method <strong>diff --git a/Restaurant.RestApi/Startup.cs b/Restaurant.RestApi/Startup.cs index 6c161b5..bcde861 100644 --- a/Restaurant.RestApi/Startup.cs +++ b/Restaurant.RestApi/Startup.cs</strong> <span style="color: darkturquoise">@@ -79,10 +79,6 @@</span> namespace Ploeh.Samples.Restaurants.RestApi private void ConfigureAuthorization(IServiceCollection services) { <span style="color: red">- JwtSecurityTokenHandler.DefaultMapInboundClaims = false; - - var secret = Configuration["JwtIssuerSigningKey"]; -</span> services.AddAuthentication(opts =&gt; { opts.DefaultAuthenticateScheme = <span style="color: darkturquoise">@@ -91,15 +87,8 @@</span> namespace Ploeh.Samples.Restaurants.RestApi JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer(opts =&gt; { <span style="color: red">- opts.TokenValidationParameters = new TokenValidationParameters - { - ValidateIssuerSigningKey = true, - IssuerSigningKey = new SymmetricSecurityKey( - Encoding.ASCII.GetBytes(secret)), - ValidateIssuer = false, - ValidateAudience = false, - RoleClaimType = "role" - };</span> <span style="color: green">+ opts.TokenValidationParameters = + CreateTokenValidationParameters();</span> opts.RequireHttpsMetadata = false; }); <span style="color: darkturquoise">@@ -108,6 +97,23 @@</span> namespace Ploeh.Samples.Restaurants.RestApi sp.GetService&lt;IHttpContextAccessor&gt;().HttpContext.User)); } <span style="color: green">+ private TokenValidationParameters CreateTokenValidationParameters() + { + JwtSecurityTokenHandler.DefaultMapInboundClaims = false; + + var secret = Configuration["JwtIssuerSigningKey"]; + + return new TokenValidationParameters + { + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey( + Encoding.ASCII.GetBytes(secret)), + ValidateIssuer = false, + ValidateAudience = false, + RoleClaimType = "role" + }; + } +</span> private void ConfigureRepository(IServiceCollection services) {</pre> </p> <p> Can you spot the problem? </p> <p> As soon as I saw that diff, the problem almost jumped out at me. I'm so happy that I make small commits. What you see here is, I promise, the entire diff of that commit. </p> <p> Clearly, you're not familiar with this code base, but even so, you might be able to intuit the problem from the above diff. You don't need domain-specific knowledge for it, or knowledge of the rest of the code base. </p> <p> I'll give you a hint: I moved a line of code into a lambda expression. </p> <h3 id="1cfcd1adb0b24b6098aa250c73f5cba2"> Deferred execution <a href="#1cfcd1adb0b24b6098aa250c73f5cba2" title="permalink">#</a> </h3> <p> In the above commit, I extracted a helper method that I called <code>CreateTokenValidationParameters</code>. As the name communicates, it creates JWT validation parameters. In other words, it supplies the configuration values that determine how ASP.NET figures out how to authorise an HTTP request. </p> <p> Among other things, it sets the <code>RoleClaimType</code> property to <code>"role"</code>. By default, the <code>[Authorize]</code> attribute is looking for a role claim with a rather complicated identifier. Setting the <code>RoleClaimType</code> enables you to change the identifier. By setting it to <code>"role"</code>, I'm telling the ASP.NET framework that it should look for claims named <code>role</code> in the JWT, and these should be translated to role claims. </p> <p> Except that it doesn't work. </p> <p> Ostensibly, this is for backwards compatibility reasons. You have to set <a href="https://docs.microsoft.com/dotnet/api/system.identitymodel.tokens.jwt.jwtsecuritytokenhandler.defaultmapinboundclaims">JwtSecurityTokenHandler.DefaultMapInboundClaims</a> to <code>false</code>. Notice that this is a global variable. </p> <p> I thought that the line of code that does that conceptually belongs together with the other code that configures the JWT validation parameters, so I moved it in there. I didn't think much about it, and all my tests were still passing. </p> <p> What happened, though, was that I moved mutation of a global variable into a helper method that was called from a lambda expression. Keep in mind that lambda expressions represent code that may run later; that execution is deferred. </p> <p> By moving that mutation statement into the helper method, I inadvertently deferred its execution. When the application's <code>Startup</code> code runs, it configures the service. All the code that runs inside of <code>AddJwtBearer</code>, however, doesn't run immediately; it runs when needed. </p> <p> This explains why all tests were passing. My test suite has plenty of self-hosted integration tests in the style of <a href="/outside-in-tdd">outside-in test-driven development</a>. When I ran all the tests, the deferred code block would run in some other test context, flipping that global bit as a side effect. When the test suite reaches the test that fails when run in isolation, the bit is already flipped, and then it works. </p> <p> It took me hours to figure out what the problem was, and it turned out that the root cause was a global variable. </p> <p> Global variables are evil. Who knew? </p> <h3 id="cbf70c019a264e8fa861e13536db688f"> Can't reproduce <a href="#cbf70c019a264e8fa861e13536db688f" title="permalink">#</a> </h3> <p> Once you figure out what the problem is, you should reproduce it with an automated test. </p> <p> Yes, and how do I do that here? I already had tests that verify that you can <code>GET</code> the desired resource if you present a valid JWT. And <em>that test passes!</em> </p> <p> The only way I can think of to reproduce the issue with an automated test is to create a completely new, independent test library with only one test. I considered doing that, weighed the advantages against the disadvantages and decided, given the context, that it wasn't worth the effort. </p> <p> That means, though, that I had to accept that within the confines of my existing testing strategy, I can't reproduce the defect. This doesn't happen to me often. In fact, I can't recall that it's ever happened to me before, like this. </p> <h3 id="2ae70aa4524e48bf9b0190aeaa158192"> Resolution <a href="#2ae70aa4524e48bf9b0190aeaa158192" title="permalink">#</a> </h3> <p> It took me hours to find the bug, and ten seconds to fix it. I just moved the mutation of <code>JwtSecurityTokenHandler.DefaultMapInboundClaims</code> back to the <code>ConfigureAuthorization</code> method: </p> <p> <pre><strong>diff --git a/Restaurant.RestApi/Startup.cs b/Restaurant.RestApi/Startup.cs index d4917f5..e40032f 100644 --- a/Restaurant.RestApi/Startup.cs +++ b/Restaurant.RestApi/Startup.cs</strong> <span style="color: darkturquoise">@@ -79,6 +79,7 @@</span> namespace Ploeh.Samples.Restaurants.RestApi private void ConfigureAuthorization(IServiceCollection services) { <span style="color: green">+ JwtSecurityTokenHandler.DefaultMapInboundClaims = false;</span> services.AddAuthentication(opts =&gt; { opts.DefaultAuthenticateScheme = <span style="color: darkturquoise">@@ -99,8 +100,6 @@</span> namespace Ploeh.Samples.Restaurants.RestApi private TokenValidationParameters CreateTokenValidationParameters() { <span style="color: red">- JwtSecurityTokenHandler.DefaultMapInboundClaims = false; -</span> var secret = Configuration["JwtIssuerSigningKey"]; return new TokenValidationParameters</pre> </p> <p> An ad-hoc smoke test verified that this solved the problem. </p> <h3 id="55a0017f1aab47b6b9049e63d51d79ff"> Conclusion <a href="#55a0017f1aab47b6b9049e63d51d79ff" title="permalink">#</a> </h3> <p> There are multiple insights to be had from this experience: <ul> <li>Global variables are evil</li> <li>Binary search, or bisection, is useful when troubleshooting</li> <li>Not all bugs can be reproduced by an automated test</li> <li>Small commits make it easy to detect problems</li> </ul> I've always disliked Git's <em>squash</em> feature, and here's one of the many reasons to dislike it. Had this happened in a code base with a 'nice history' (as the <em>squash</em> proponents like to present it), that small commit would have been bundled with various other commits. The problem wouldn't have jumped at me if buried in dozens of other changes. </p> </div> <hr> This blog is totally free, but if you like it, please consider <a href="https://blog.ploeh.dk/support">supporting it</a>. Mark Seemann https://blog.ploeh.dk/2020/10/05/fortunately-i-dont-squash-my-commits EnsureSuccessStatusCode as an assertion https://blog.ploeh.dk/2020/09/28/ensuresuccessstatuscode-as-an-assertion/ Mon, 28 Sep 2020 05:50:00 UTC <div id="post"> <p> <em>It finally dawned on me that EnsureSuccessStatusCode is a fine test assertion.</em> </p> <p> Okay, I admit that sometimes I can be too literal and rigid in my thinking. At least as far back as 2012 I've been doing <a href="/outside-in-tdd">outside-in TDD</a> against self-hosted HTTP APIs. When you do that, you'll regularly need to verify that an HTTP response is successful. </p> <h3 id="77cb250db1ab4278bad68cf7736ae62e"> Assert equality <a href="#77cb250db1ab4278bad68cf7736ae62e" title="permalink">#</a> </h3> <p> You can, of course, write an assertion like this: </p> <p> <pre><span style="color:#2b91af;">Assert</span>.Equal(<span style="color:#2b91af;">HttpStatusCode</span>.OK,&nbsp;response.StatusCode);</pre> </p> <p> If the assertion fails, it'll produce a comprehensible message like this: </p> <p> <pre>Assert.Equal() Failure Expected: OK Actual: BadRequest</pre> </p> <p> What's not to like? </p> <h3 id="2ba5bb17d1f8423184a50b2fa1fcb667"> Assert success <a href="#2ba5bb17d1f8423184a50b2fa1fcb667" title="permalink">#</a> </h3> <p> The problem with testing strict equality in this context is that it's often too narrow a definition of success. </p> <p> You may start by returning <code>200 OK</code> as response to a <code>POST</code> request, but then later evolve the API to return <code>201 Created</code> or <code>202 Accepted</code>. Those status codes still indicate success, and are typically accompanied by more information (e.g. a <code>Location</code> header). Thus, evolving a REST API from returning <code>200 OK</code> to <code>201 Created</code> or <code>202 Accepted</code> isn't a breaking change. </p> <p> It does, however, break the above assertion, which may now fail like this: </p> <p> <pre>Assert.Equal() Failure Expected: OK Actual: Created</pre> </p> <p> You could attempt to fix this issue by instead verifying <a href="https://docs.microsoft.com/dotnet/api/system.net.http.httpresponsemessage.issuccessstatuscode">IsSuccessStatusCode</a>: </p> <p> <pre><span style="color:#2b91af;">Assert</span>.True(response.IsSuccessStatusCode);</pre> </p> <p> That permits the API to evolve, but introduces another problem. </p> <h3 id="0389a3d633c64aec8068be619ddce54c"> Legibility <a href="#0389a3d633c64aec8068be619ddce54c" title="permalink">#</a> </h3> <p> What happens when an assertion against <code>IsSuccessStatusCode</code> fails? </p> <p> <pre>Assert.True() Failure Expected: True Actual: False</pre> </p> <p> That's not helpful. At least, you'd like to know which other status code was returned instead. You can address that concern by using an overload to <code>Assert.True</code> (most unit testing frameworks come with such an overload): </p> <p> <pre><span style="color:#2b91af;">Assert</span>.True( &nbsp;&nbsp;&nbsp;&nbsp;response.IsSuccessStatusCode, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#a31515;">$&quot;Actual&nbsp;status&nbsp;code:&nbsp;</span>{response.StatusCode}<span style="color:#a31515;">.&quot;</span>);</pre> </p> <p> This produces more helpful error messages: </p> <p> <pre>Actual status code: BadRequest. Expected: True Actual: False</pre> </p> <p> Granted, the <em>Expected: True, Actual: False</em> lines are redundant, but at least the information you care about is there; in this example, the status code was <code>400 Bad Request</code>. </p> <h3 id="9697ab68967948f89792b82d00028ccf"> Conciseness <a href="#9697ab68967948f89792b82d00028ccf" title="permalink">#</a> </h3> <p> That's not bad. You can use that <code>Assert.True</code> overload everywhere you want to assert success. You can even copy and paste the code, <a href="/2014/08/07/why-dry">because it's an idiom that doesn't change</a>. Still, since <a href="/2019/11/04/the-80-24-rule">I like to stay within 80 characters line width</a>, this little phrase takes up three lines of code. </p> <p> Surely, a helper method can address that problem: </p> <p> <pre><span style="color:blue;">internal</span>&nbsp;<span style="color:blue;">static</span>&nbsp;<span style="color:blue;">void</span>&nbsp;AssertSuccess(<span style="color:blue;">this</span>&nbsp;<span style="color:#2b91af;">HttpResponseMessage</span>&nbsp;response) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">Assert</span>.True( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response.IsSuccessStatusCode, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#a31515;">$&quot;Actual&nbsp;status&nbsp;code:&nbsp;</span>{response.StatusCode}<span style="color:#a31515;">.&quot;</span>); }</pre> </p> <p> I can now write a one-liner as an assertion: </p> <p> <pre>response.AssertSuccess();</pre> </p> <p> What's not to like? </p> <h3 id="6990f2fbc33f4beca15c122b5b4ccc22"> Carrying coals to Newcastle <a href="#6990f2fbc33f4beca15c122b5b4ccc22" title="permalink">#</a> </h3> <p> If you're already familiar with the <a href="https://docs.microsoft.com/dotnet/api/system.net.http.httpresponsemessage">HttpResponseMessage</a> class, you may have been reading this far with some frustration. It already comes with a method called <a href="https://docs.microsoft.com/dotnet/api/system.net.http.httpresponsemessage.ensuresuccessstatuscode">EnsureSuccessStatusCode</a>. Why not just use that instead? </p> <p> <pre>response.EnsureSuccessStatusCode();</pre> </p> <p> As long as the <code>response</code> status code is in the 200 range, this method call succeeds, but if not, it throws an exception: </p> <p> <pre>Response status code does not indicate success: 400 (Bad Request).</pre> </p> <p> That's exactly the information you need. </p> <p> I admit that I can sometimes be too rigid in my thinking. I've known about this method for years, but I never thought of it as a <em>unit testing assertion</em>. It's as if there's a category in my programming brain that's labelled <em>unit testing assertions</em>, and it only contains methods that originate from unit testing. </p> <p> I even knew about <a href="https://docs.microsoft.com/dotnet/api/system.diagnostics.debug.assert">Debug.Assert</a>, so I knew that assertions also exist outside of unit testing. That assertion isn't suitable for unit testing, however, so I never included it in my category of unit testing assertions. </p> <p> The <code>EnsureSuccessStatusCode</code> method doesn't have <em>assert</em> in its name, but it behaves just like a unit testing assertion: it throws an exception with a useful error message if a criterion is not fulfilled. I just never thought of it as useful for unit testing purposes because it's part of 'production code'. </p> <h3 id="5ff49213dd304440887719d6879ff7fb"> Conclusion <a href="#5ff49213dd304440887719d6879ff7fb" title="permalink">#</a> </h3> <p> The built-in <code>EnsureSuccessStatusCode</code> method is fine for unit testing purposes. Who knows, perhaps other class libraries contain similar assertion methods, although they may be hiding behind names that don't include <em>assert</em>. Perhaps your own production code contains such methods. If so, they can double as unit testing assertions. </p> <p> I've been doing test-driven development for close to two decades now, and one of many consistent experiences is this: <ul> <li>In the beginning of a project, the unit tests I write are verbose. This is natural, because I'm still getting to know the domain.</li> <li>After some time, I begin to notice patterns in my tests, so I refactor them. I introduce helper APIs in the test code.</li> <li>Finally, I realise that some of those unit testing APIs might actually be useful in the production code too, so I move them over there.</li> </ul> Test-driven development is process that gives you feedback about your production code's APIs. Listen to your tests. </p> </div> <div id="comments"> <hr> <h2 id="comments-header"> Comments </h2> <div class="comment" id="20484094920349b7a91eebcb9b15c628"> <div class="comment-author"><a href="https://github.com/YevgeniyShunevych">Yevgeniy Shunevych</a></div> <div class="comment-content"> <p> Unfortunately, I can't agree that it's fine to use <code>EnsureSuccessStatusCode</code> or other similar methods for assertions. An exception of a kind different from assertion (<code>XunitException</code> for XUnit, <code>AssertionException</code> for NUnit) is handled in a bit different way by the testing framework. <code>EnsureSuccessStatusCode</code> method throws <code>HttpRequestException</code>. Basically, a test that fails with such exception is considered as "Failed by error". </p> <p> For example, the test result message in case of 404 status produced by the <code>EnsureSuccessStatusCode</code> method is: </p> <p> <pre>System.Net.Http.HttpRequestException : Response status code does not indicate success: 404 (Not Found).</pre> </p> <p> Where "System.Net.Http.HttpRequestException :" text looks redundant, as we do assertion. This also may make other people think that the reason for this failure is not an assertion, but an unexpected exception. In case of regular assertion exception type, that text is missing. </p> <p> Other points are related to NUnit: <ul> <li> There are 2 different failure test outcome kinds in NUnit: <ul> <li>Failure: a test assertion failed. (Status=Failed, Label=empty)</li> <li>Error: an unexpected exception occurred. (Status=Failed, Label=Error)</li> </ul> See NUnit <a href="https://docs.nunit.org/articles/nunit/writing-tests/TestContext.html#common-outcomes">Common Outcomes</a>. Thus `EnsureSuccessStatusCode` produces "Error" status instead of desirable "Failure". </li> <li>You can't use methods like <code>EnsureSuccessStatusCode</code> as assertion inside multiple asserts.</li> <li>NUnit tracks the count of assertions for each test. <code>"assertions"</code> property gets into the test results XML file and might be useful. This property increments on assertion methods, <code>EnsureSuccessStatusCode</code> - obviously doesn't increment it.</li> </ul> </p> </div> <div class="comment-date">2020-09-30 15:25 UTC</div> </div> <div class="comment" id="16adadb969f1406c9c18605c8c85ef83"> <div class="comment-author"><a href="/">Mark Seemann</a></div> <div class="comment-content"> <p> Yevgeniy, thank you for writing. This shows, I think, that all advice is contextual. It's been more than a decade since I regularly used NUnit, but I vaguely recall that it gives special treatment to its own assertion exceptions. </p> <p> I also grant that the "System.Net.Http.HttpRequestException" part of the message is redundant. To make matters worse, even without that 'prologue' the information that we care about (the actual status code) is all the way to the right. It'll often require horizontal scrolling to see it. </p> <p> That doesn't much bother me, though. I think that one should optimise for the most frequent scenario. For example, I favour taking a bit of extra time to write readable code, because <a href="/2018/09/17/typing-is-not-a-programming-bottleneck">the bottleneck in programming isn't typing</a>. In the same vein, I find it a good trade-off being able to avoid adding more code against an occasional need to scroll horizontally. The cost of code isn't the time it takes to write it, but the maintenance burden it imposes, as well as the cognitive load it adds. </p> <p> The point here is that while horizontal scrolling is inconvenient, the <em>most frequent scenario</em> is that tests don't fail. The inconvenience only manifests in the rare circumstance that a test fails. </p> <p> I want to thank you, however, for pointing out the issues with NUnit. It reinforces the impression I already had of it, as a framework to stay away from. That design seems to me to impose a lock-in that prevents you from mixing NUnit with improved APIs. </p> <p> In contrast, the <a href="https://www.nuget.org/packages/xunit.core">xunit.core</a> library doesn't include <a href="https://www.nuget.org/packages/xunit.assert">xunit.assert</a>. I often take advantage of that when I write unit tests in F#. While the xUnit.net assertion library is adequate, <a href="https://github.com/SwensenSoftware/unquote">Unquote</a> is much better for F#. I appreciate that xUnit.net enables me to combine the tools that work best in a given situation. </p> </div> <div class="comment-date">2020-10-02 07:35 UTC</div> </div> <div class="comment" id="3dbfa056360b4df6a052be2776a6f930"> <div class="comment-author"><a href="https://github.com/YevgeniyShunevych">Yevgeniy Shunevych</a></div> <div class="comment-content"> <p> I see your point, Mark. Thanks for your reply. </p> <p> I would like to add a few words in defense of the NUnit. </p> <p> First of all, there is no problem to use an extra library for NUnit assertions too. For example, I like <a href="https://fluentassertions.com/">FluentAssertions</a> that works great for both XUnit and NUnit. </p> <p> NUnit 3 also has a set of useful features that are missing in XUnit like: <ul> <li> <a href="https://docs.nunit.org/articles/nunit/writing-tests/assertions/multiple-asserts.html">Multiple asserts</a> - quite useful for UI testing, for example. </li> <li> <a href="https://docs.nunit.org/articles/nunit/writing-tests/Warnings.html">Warnings</a>. </li> <li> <a href="https://docs.nunit.org/articles/nunit/writing-tests/TestContext.html">TestContext</a>. </li> <li> <a href="https://docs.nunit.org/articles/nunit/writing-tests/TestContext.html#addtestattachment-37">File attachments</a> - useful for UI tests or tests that verify files. For example, when the UI test fails, you can take a screenshot, save it and add to NUnit as an attachment. Or when you test PDF file, you can attach the file that doesn't pass the test. </li> </ul> </p> <p> I can recommend to reconsider the view of NUnit, as the library progressed well during its 3rd version. XUnit and NUnit seem interchangeable for unit testing. But NUnit, from my point of view, provides the features that are helpful in integration and UI testing. </p> </div> <div class="comment-date">2020-10-05 13:24 UTC</div> </div> <div class="comment" id="fded96f5f68a4d8ba1e782678dd854be"> <div class="comment-author"><a href="/">Mark Seemann</a></div> <div class="comment-content"> <p> Yevgeniy, I haven't done UI testing since sometime in 2005, I think, so I wasn't aware of that. It's good to know that NUnit may excel at that, and the other scenarios you point out. </p> <p> To be clear, while I still think I may prefer xUnit.net, I don't consider it perfect. </p> </div> <div class="comment-date">2020-10-05 14:10 UTC</div> </div> </div> <hr> This blog is totally free, but if you like it, please consider <a href="https://blog.ploeh.dk/support">supporting it</a>. Mark Seemann https://blog.ploeh.dk/2020/09/28/ensuresuccessstatuscode-as-an-assertion An XPath query for long methods https://blog.ploeh.dk/2020/09/21/an-xpath-query-for-long-methods/ Mon, 21 Sep 2020 05:28:00 UTC <div id="post"> <p> <em>A filter for Visual Studio code metrics.</em> </p> <p> I consider it a good idea to <a href="/2020/04/13/curb-code-rot-with-thresholds">limit</a> the size of code blocks. Small methods are <a href="/2019/11/18/small-methods-are-easy-to-troubleshoot">easier to troubleshoot</a> and in general fit better in your head. When it comes to vertical size, however, the editors I use don't come with visual indicators like <a href="https://marketplace.visualstudio.com/items?itemName=PaulHarrington.EditorGuidelines">they do for horizontal size</a>. </p> <p> When you're in the midst of developing a feature, you don't want to be <em>prevented</em> from doing so by a tool that refuses to compile your code if methods get too long. On the other hand, it might be a good idea to regularly run a tool over your code base to identify which methods are getting too long. </p> <p> With Visual Studio you can calculate code metrics, which include a measure of the number of lines of code for each method. One option produces an XML file, but if you have a large code base, those XML files are big. </p> <p> The XML files typically look like this: </p> <p> <pre><span style="color:blue;">&lt;?</span><span style="color:#a31515;">xml</span><span style="color:blue;">&nbsp;</span><span style="color:red;">version</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">1.0</span>&quot;<span style="color:blue;">&nbsp;</span><span style="color:red;">encoding</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">utf-8</span>&quot;<span style="color:blue;">?&gt;</span> <span style="color:blue;">&lt;</span><span style="color:#a31515;">CodeMetricsReport</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Version</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">1.0</span>&quot;<span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Targets</span><span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Target</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">Restaurant.RestApi.csproj</span>&quot;<span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Assembly</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">Ploeh.Samples.Restaurants.RestApi,&nbsp;...</span>&quot;<span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metrics</span><span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metric</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">MaintainabilityIndex</span>&quot;<span style="color:blue;">&nbsp;</span><span style="color:red;">Value</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">87</span>&quot;<span style="color:blue;">&nbsp;/&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metric</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">CyclomaticComplexity</span>&quot;<span style="color:blue;">&nbsp;</span><span style="color:red;">Value</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">537</span>&quot;<span style="color:blue;">&nbsp;/&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metric</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">ClassCoupling</span>&quot;<span style="color:blue;">&nbsp;</span><span style="color:red;">Value</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">208</span>&quot;<span style="color:blue;">&nbsp;/&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metric</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">DepthOfInheritance</span>&quot;<span style="color:blue;">&nbsp;</span><span style="color:red;">Value</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">1</span>&quot;<span style="color:blue;">&nbsp;/&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metric</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">SourceLines</span>&quot;<span style="color:blue;">&nbsp;</span><span style="color:red;">Value</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">3188</span>&quot;<span style="color:blue;">&nbsp;/&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metric</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">ExecutableLines</span>&quot;<span style="color:blue;">&nbsp;</span><span style="color:red;">Value</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">711</span>&quot;<span style="color:blue;">&nbsp;/&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color:#a31515;">Metrics</span><span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Namespaces</span><span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Namespace</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">Ploeh.Samples.Restaurants.RestApi</span>&quot;<span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metrics</span><span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metric</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">MaintainabilityIndex</span>&quot;<span style="color:blue;">&nbsp;</span><span style="color:red;">Value</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">87</span>&quot;<span style="color:blue;">&nbsp;/&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metric</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">CyclomaticComplexity</span>&quot;<span style="color:blue;">&nbsp;</span><span style="color:red;">Value</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">499</span>&quot;<span style="color:blue;">&nbsp;/&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metric</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">ClassCoupling</span>&quot;<span style="color:blue;">&nbsp;</span><span style="color:red;">Value</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">204</span>&quot;<span style="color:blue;">&nbsp;/&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metric</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">DepthOfInheritance</span>&quot;<span style="color:blue;">&nbsp;</span><span style="color:red;">Value</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">1</span>&quot;<span style="color:blue;">&nbsp;/&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metric</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">SourceLines</span>&quot;<span style="color:blue;">&nbsp;</span><span style="color:red;">Value</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">3100</span>&quot;<span style="color:blue;">&nbsp;/&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metric</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">ExecutableLines</span>&quot;<span style="color:blue;">&nbsp;</span><span style="color:red;">Value</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">701</span>&quot;<span style="color:blue;">&nbsp;/&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color:#a31515;">Metrics</span><span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Types</span><span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">NamedType</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">CalendarController</span>&quot;<span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metrics</span><span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metric</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">MaintainabilityIndex</span>&quot;<span style="color:blue;">&nbsp;</span><span style="color:red;">Value</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">73</span>&quot;<span style="color:blue;">&nbsp;/&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metric</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">CyclomaticComplexity</span>&quot;<span style="color:blue;">&nbsp;</span><span style="color:red;">Value</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">14</span>&quot;<span style="color:blue;">&nbsp;/&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metric</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">ClassCoupling</span>&quot;<span style="color:blue;">&nbsp;</span><span style="color:red;">Value</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">34</span>&quot;<span style="color:blue;">&nbsp;/&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metric</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">DepthOfInheritance</span>&quot;<span style="color:blue;">&nbsp;</span><span style="color:red;">Value</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">1</span>&quot;<span style="color:blue;">&nbsp;/&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metric</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">SourceLines</span>&quot;<span style="color:blue;">&nbsp;</span><span style="color:red;">Value</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">190</span>&quot;<span style="color:blue;">&nbsp;/&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metric</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">ExecutableLines</span>&quot;<span style="color:blue;">&nbsp;</span><span style="color:red;">Value</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">42</span>&quot;<span style="color:blue;">&nbsp;/&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color:#a31515;">Metrics</span><span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Members</span><span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Method</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">Task</span><span style="color:red;">&amp;lt;</span><span style="color:blue;">ActionResult</span><span style="color:red;">&amp;gt;</span><span style="color:blue;">&nbsp;CalendarController.Get(...</span>&quot;<span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metrics</span><span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metric</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">MaintainabilityIndex</span>&quot;<span style="color:blue;">&nbsp;</span><span style="color:red;">Value</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">64</span>&quot;<span style="color:blue;">&nbsp;/&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metric</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">CyclomaticComplexity</span>&quot;<span style="color:blue;">&nbsp;</span><span style="color:red;">Value</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">2</span>&quot;<span style="color:blue;">&nbsp;/&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metric</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">ClassCoupling</span>&quot;<span style="color:blue;">&nbsp;</span><span style="color:red;">Value</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">12</span>&quot;<span style="color:blue;">&nbsp;/&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metric</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">SourceLines</span>&quot;<span style="color:blue;">&nbsp;</span><span style="color:red;">Value</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">28</span>&quot;<span style="color:blue;">&nbsp;/&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span style="color:#a31515;">Metric</span><span style="color:blue;">&nbsp;</span><span style="color:red;">Name</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">ExecutableLines</span>&quot;<span style="color:blue;">&nbsp;</span><span style="color:red;">Value</span><span style="color:blue;">=</span>&quot;<span style="color:blue;">7</span>&quot;<span style="color:blue;">&nbsp;/&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color:#a31515;">Metrics</span><span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color:#a31515;">Method</span><span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--</span><span style="color:green;">Much&nbsp;more&nbsp;data&nbsp;goes&nbsp;here</span><span style="color:blue;">--&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color:#a31515;">Members</span><span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color:#a31515;">NamedType</span><span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color:#a31515;">Types</span><span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color:#a31515;">Namespace</span><span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color:#a31515;">Namespaces</span><span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color:#a31515;">Assembly</span><span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span style="color:#a31515;">Target</span><span style="color:blue;">&gt;</span> <span style="color:blue;">&nbsp;&nbsp;&lt;/</span><span style="color:#a31515;">Targets</span><span style="color:blue;">&gt;</span> <span style="color:blue;">&lt;/</span><span style="color:#a31515;">CodeMetricsReport</span><span style="color:blue;">&gt;</span></pre> </p> <p> How can you filter such a file to find only those methods that are too long? </p> <p> That sounds like a job for <a href="https://en.wikipedia.org/wiki/XPath">XPath</a>. I admit, though, that I use XPath only rarely. While the general idea of the syntax is easy to grasp, it has enough subtle pitfalls that it's not that easy to use, either. </p> <p> Partly for my own benefit, and partly for anyone else who might need it, here's an XPath query that looks for long methods: </p> <p> <pre>//Members/child::*[Metrics/Metric[@Value &gt; 24 and @Name = "SourceLines"]]</pre> </p> <p> This query looks for <a href="/2019/11/04/the-80-24-rule">methods longer that 24 lines of code</a>. If you don't agree with that <a href="/2020/04/13/curb-code-rot-with-thresholds">threshold</a> you can always change it to another value. You can also change <code>@Name</code> to look for <code>CyclomaticComplexity</code> or one of the other metrics. </p> <p> Given the above XML metrics report, the XPath filter would select (among other members) the <code>CalendarController.Get</code> method, because it has 28 lines of source code. It turns out, though, that the filter produces some false positives. The method in question is actually fine: </p> <p> <pre><span style="color:green;">/*&nbsp;This&nbsp;method&nbsp;loads&nbsp;a&nbsp;year&#39;s&nbsp;worth&nbsp;of&nbsp;reservations&nbsp;in&nbsp;order&nbsp;to&nbsp;segment &nbsp;*&nbsp;them&nbsp;all.&nbsp;In&nbsp;a&nbsp;realistic&nbsp;system,&nbsp;this&nbsp;could&nbsp;be&nbsp;quite&nbsp;stressful&nbsp;for &nbsp;*&nbsp;both&nbsp;the&nbsp;database&nbsp;and&nbsp;the&nbsp;web&nbsp;server.&nbsp;Some&nbsp;of&nbsp;that&nbsp;concern&nbsp;can&nbsp;be &nbsp;*&nbsp;addressed&nbsp;with&nbsp;an&nbsp;appropriate&nbsp;HTTP&nbsp;cache&nbsp;header&nbsp;and&nbsp;a&nbsp;reverse&nbsp;proxy, &nbsp;*&nbsp;but&nbsp;a&nbsp;better&nbsp;solution&nbsp;would&nbsp;be&nbsp;a&nbsp;CQRS-style&nbsp;architecture&nbsp;where&nbsp;the &nbsp;*&nbsp;calendars&nbsp;get&nbsp;re-rendered&nbsp;as&nbsp;materialised&nbsp;views&nbsp;in&nbsp;a&nbsp;background &nbsp;*&nbsp;process.&nbsp;That&#39;s&nbsp;beyond&nbsp;the&nbsp;scope&nbsp;of&nbsp;this&nbsp;example&nbsp;code&nbsp;base,&nbsp;though. &nbsp;*/</span> [<span style="color:#2b91af;">ResponseCache</span>(Duration&nbsp;=&nbsp;60)] [<span style="color:#2b91af;">HttpGet</span>(<span style="color:#a31515;">&quot;restaurants/{restaurantId}/calendar/{year}&quot;</span>)] <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">async</span>&nbsp;<span style="color:#2b91af;">Task</span>&lt;<span style="color:#2b91af;">ActionResult</span>&gt;&nbsp;Get(<span style="color:blue;">int</span>&nbsp;restaurantId,&nbsp;<span style="color:blue;">int</span>&nbsp;year) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;restaurant&nbsp;=&nbsp;<span style="color:blue;">await</span>&nbsp;RestaurantDatabase &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.GetRestaurant(restaurantId).ConfigureAwait(<span style="color:blue;">false</span>); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">if</span>&nbsp;(restaurant&nbsp;<span style="color:blue;">is</span>&nbsp;<span style="color:blue;">null</span>) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">return</span>&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">NotFoundResult</span>(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;period&nbsp;=&nbsp;<span style="color:#2b91af;">Period</span>.Year(year); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;days&nbsp;=&nbsp;<span style="color:blue;">await</span>&nbsp;MakeDays(restaurant,&nbsp;period) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.ConfigureAwait(<span style="color:blue;">false</span>); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">return</span>&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">OkObjectResult</span>( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">CalendarDto</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name&nbsp;=&nbsp;restaurant.Name, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Year&nbsp;=&nbsp;year, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Days&nbsp;=&nbsp;days &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}); }</pre> </p> <p> That method only has 18 lines of actual source code, from the beginning of the method declaration to the closing bracket. Visual Studio's metrics calculator, however, also counts the attributes and the comments. </p> <p> In general, I only add comments when I want to communicate something that I can't express as a type or a method name, so in this particular code base, it's not much of an issue. If you consistently adorn every method with doc comments, on the other hand, you may need to perform some pre-processing on the source code before you calculate the metrics. </p> </div><hr> This blog is totally free, but if you like it, please consider <a href="https://blog.ploeh.dk/support">supporting it</a>. Mark Seemann https://blog.ploeh.dk/2020/09/21/an-xpath-query-for-long-methods We need young programmers; we need old programmers https://blog.ploeh.dk/2020/09/14/we-need-young-programmers-we-need-old-programmers/ Mon, 14 Sep 2020 05:46:00 UTC <div id="post"> <p> <em>The software industry loves young people, but old-timers serve an important purpose, too.</em> </p> <p> Our culture idolises youth. There's several reasons for this, I believe. Youth seems synonymous with vigour, strength, beauty, and many other desirable qualities. The cynical perspective is that young people, while rebellious, also tend to be easy to manipulate, if you know which buttons to push. A middle-aged man like me isn't susceptible to the argument that I should buy a particular pair of Nike shoes because they're named after Michael Jordan, but for a while, one pair wasn't enough for my teenage daughter. </p> <p> In intellectual pursuits (like software development), youth is often extolled as the source of innovation. You're often confronted with examples like that of <a href="https://en.wikipedia.org/wiki/%C3%89variste_Galois">Évariste Galois</a>, who made all his discoveries before turning 21. <a href="https://en.wikipedia.org/wiki/Ada_Lovelace">Ada Lovelace</a> was around 28 years when she produced what is considered the 'first computer program'. <a href="https://en.wikipedia.org/wiki/Alan_Turing">Alan Turing</a> was 24 when he wrote <a href="https://en.wikipedia.org/wiki/Turing%27s_proof">On Computable Numbers, with an Application to the Entscheidungsproblem</a>. </p> <p> Clearly, young age is no detriment to making ground-breaking contributions. It has even become folklore that everyone past the age of 35 is a has-been whose only chance at academic influence is to write a textbook. </p> <h3 id="800321a74c054ea0b75815c86f4ce18d"> The story of the five monkeys <a href="#800321a74c054ea0b75815c86f4ce18d" title="permalink">#</a> </h3> <p> You may have seen a story called <em>the five monkeys experiment</em>. It's most likely a fabrication, but it goes like this: </p> <p> A group of scientists placed five monkeys in a cage, and in the middle, a ladder with bananas on the top. Every time a monkey went up the ladder, the scientists soaked the rest of the monkeys with cold water. After a while, every time a monkey went up the ladder, the others would beat it up. </p> <p> After some time, none of the monkeys dared go up the ladder regardless of the temptation. The scientists then substituted one of the monkeys with a new one, who'd immediately go for the bananas, only to be beaten up by the others. After several beatings, the new member learned not to climb the ladder even though it never knew why. </p> <p> A second monkey was substituted and the same occurred. The first monkey participated in beating the second. A third monkey was exchanged and the story repeated. The fourth was substituted and the beating was repeated. Finally the fifth monkey was replaced. </p> <p> Left was a group of five monkeys who, even though they never received a cold shower, continued to beat up any monkey who attempted to climb the ladder. If it was possible to ask the monkeys why they would beat up all who attempted to go up the ladder, the answer would probably be: </p> <p> "That's how we do things here." </p> <p> While the story is probably just that: a story, it tells us something about the drag induced by age and experience. If you've been in the business for decades, you've seen numerous failed attempts at something you yourself tried when you were young. You know that it can't be done. </p> <p> Young people don't know that a thing can't be done. If they can avoid the monkey-beating, they'll attempt the impossible. </p> <h3 id="4add8a9af0424d7e889d3125837ed611"> Changing circumstances <a href="#4add8a9af0424d7e889d3125837ed611" title="permalink">#</a> </h3> <p> Is attempting the impossible a good idea? </p> <p> In general, no, because it's... impossible. There's a reason older people tell young people that a thing can't be done. It's not just because they're stodgy conservatives who abhor change. It's because they see the effort as wasteful. Perhaps they're even trying to be kind, guiding young people off a path where only toil and disappointment is to be found. </p> <p> What old people don't realise is that sometimes, circumstances change. </p> <p> What was impossible twenty years ago may not be impossible today. We see this happening in many fields. Producing a commercially viable electric car was impossible for decades, until, with the advances made in battery technology, it became possible. </p> <p> Technology changes rapidly in software development. People trying something previously impossible may find that it's possible today. Once, if you had lots of data, you had to store it in fully normalised form, because storage was expensive. For a decade, relational databases were the only game in town. Then circumstances changed. Storage became cheaper, and a new movement of NoSQL storage emerged. What was before impossible became possible. </p> <p> Older people often don't see the new opportunities, because they 'know' that some things are impossible. Young people push the envelope driven by a combination of zest and ignorance. Most fail, but a few succeed. </p> <h3 id="4272a069588e47f796646bd282b9de02"> Lottery of the impossible <a href="#4272a069588e47f796646bd282b9de02" title="permalink">#</a> </h3> <p> I think of this process as a lottery. Imagine that every impossible thing is a red ball in an urn. Every young person who tries the impossible draws a random ball from the urn. </p> <p> The urn contains millions of red balls, but every now and then, one of them turns green. You don't know which one, but if you draw it, it represents something that was previously impossible which has now become possible. </p> <p> This process produces growth, because once discovered, the new and better way of doing things can improve society in general. Occasionally, the young discoverer may even gain some fame and fortune. </p> <p> It seems wasteful, though. Most people who attempt the impossible will reach the predictable conclusion. What was deemed impossible was, indeed, impossible. </p> <p> When I'm in a cynical mood, I don't think that it's youth in itself that is the source of progress. It's just the <a href="https://en.wikipedia.org/wiki/Law_of_large_numbers">law of large numbers</a> applied. If there's a one in million chance that something will succeed, but ten million people attempt it, it's only a matter of time before one succeeds. </p> <p> Society at large can benefit from the success of the few, but ten million people still wasted their efforts. </p> <h3 id="016744f0ea77495c958a7914f08187db"> We need the old, too <a href="#016744f0ea77495c958a7914f08187db" title="permalink">#</a> </h3> <p> If you accept the argument that young people are more likely to try the impossible, we need the young people. Do we need the old people? </p> <p> I'm turning fifty in 2020. You may consider that old, but I expect to work for many more years. I don't know if the software industry needs fifty-year-olds, but that's not the kind of old I have in mind. I'm thinking of people who have retired, or are close to retirement. </p> <p> In our youth-glorifying culture, we tend to dismiss the opinion and experiences of old people. <em>Oh, well, it's just a codgy old man</em> (or woman), we'll say. </p> <p> We ignore the experience of the old, because we believe that they haven't been keeping up with times. Their experiences don't apply to us, because we live under new circumstance. Well, see above. </p> <p> I'm not advocating that we turn into a gerontocracy that venerates our elders solely because of their age. Again, according to the law of large numbers, some people live to old age. There need not be any correlation between survivors and wisdom. </p> <p> We need the old to tell us the truth, because they have little to lose. </p> <h3 id="8b5c613ba6c44bb4b4e6dbba7ae7d19a"> Nothing to lose <a href="#8b5c613ba6c44bb4b4e6dbba7ae7d19a" title="permalink">#</a> </h3> <p> In the last couple of years, I've noticed a trend. A book comes out, exposing the sad state of affairs in some organisation. This has happened regularly in Denmark, where I live. One book may expose the deplorable conditions of the Danish tax authorities, one may describe the situation in the ministry of defence, one criticises the groupthink associated with the climate crisis, and so on. </p> <p> Invariably, it turns out that the book is written by a professor emeritus or a retired department head. </p> <p> I don't think that these people, all of a sudden, had an epiphany after they retired. They knew all about the rot in the system they were part of, while they were part of it, but they've had too much to lose. You could argue that they should have said something before they retired, but that requires a moral backbone we can't expect most people to have. </p> <p> When people retire, the threat of getting fired disappears. Old people can speak freely to a degree most other people can't. </p> <p> Granted, many may simply use that freedom to spew bile or shout <em>Get off my lawn!</em>, but many are in the unique position to reveal truths no-one else dare speak. Many are, perhaps, just bitter, but some may possess knowledge that they are in a unique position to reveal. </p> <p> When that grumpy old guy on Twitter writes something that makes you uncomfortable, consider this: he may still be right. </p> <h3 id="2d64bd2c7ccb4b7ca2418802ed82689e"> Being unreasonable <a href="#2d64bd2c7ccb4b7ca2418802ed82689e" title="permalink">#</a> </h3> <p> In a way, you could say that we need young and old people for the same fundamental reason. Not all of them, but enough of them, are in a position to be unreasonable. <blockquote> <p> "The reasonable man adapts himself to the world: the unreasonable one persists in trying to adapt the world to himself. Therefore all progress depends on the unreasonable man." </p> <footer><cite>George Bernard Shaw</cite></footer> </blockquote> Young people and old people are unreasonable in each their own way, and we need both. </p> <h3 id="df88f595ec814e2bafcbd018ff5f5ad2"> Conclusion <a href="#df88f595ec814e2bafcbd018ff5f5ad2" title="permalink">#</a> </h3> <p> We need young people in the software development industry. Because of their vigour and inexperience, they'll push the envelope. Most will fail to do the impossible, but a few succeed. </p> <p> This may seem like a cynical view, but we've all been young, and most of us have been through such a phase. It's like a rite of passage, and even if you fail to make your mark on the world, you're still likely to have learned a lot. </p> <p> We need old people because they're in a position to speak truth to the world. Notice that I didn't make my argument about the <em>experience</em> of old-timers. Actually, I find that valuable as well, but that's the ordinary argument: <em>Listen to old people, because they have experience and wisdom.</em> </p> <p> Some of them do, at least. </p> <p> I didn't make much out of that argument, because you already know it. There'd be no reason to write this essay if that was all I had to say. Old people have less on the line, so they can speak more freely. If someone you used to admire retires and all of a sudden starts saying or writing unpleasant and surprising things, there might be a good explanation, and it might be a good idea to pay attention. </p> <p> Or maybe he or she is just bitter or going senile... </p> </div><hr> This blog is totally free, but if you like it, please consider <a href="https://blog.ploeh.dk/support">supporting it</a>. Mark Seemann https://blog.ploeh.dk/2020/09/14/we-need-young-programmers-we-need-old-programmers Add null check without brackets in Visual Studio https://blog.ploeh.dk/2020/09/07/add-null-check-without-brackets-in-visual-studio/ Mon, 07 Sep 2020 06:47:00 UTC <div id="post"> <p> <em>A Visual Studio tweak.</em> </p> <p> The most recent versions of Visual Studio have included many new <em>Quick Actions</em>, accessible with <kbd>Ctrl</kbd> + <kbd>.</kbd> or <kbd>Alt</kbd> + <kbd>Enter</kbd>. The overall feature has been around for some years, but the product group has been adding features at a good pace recently, it seems to me. </p> <p> One feature has been around for at least a year: <em>Add null check</em>. In a default installation of Visual Studio, it looks like this: </p> <p> <img src="/content/binary/add-null-check-with-brackets.png" alt="Screen shot of the 'Add null check' Quick Action. By default it'll add brackets around the throw statement."> </p> <p> As the screen shot shows, it'll auto-generate a Guard Clause like this: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">bool</span>&nbsp;Overlaps(<span style="color:#2b91af;">Reservation</span>&nbsp;other) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">if</span>&nbsp;(other&nbsp;<span style="color:blue;">is</span>&nbsp;<span style="color:blue;">null</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">throw</span>&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">ArgumentNullException</span>(<span style="color:blue;">nameof</span>(other)); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;otherSeating&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">Seating</span>(SeatingDuration,&nbsp;other.Date); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">return</span>&nbsp;Overlaps(otherSeating); }</pre> </p> <p> Part of my personal coding style is that I don't use brackets for one-liners. This is partially motivated by the desire to save vertical space, since I try to <a href="/2019/11/04/the-80-24-rule">keep methods as small as possible</a>. Some people worry that not using brackets for one-liners makes the code more vulnerable to defects, but I typically have automated regressions tests to keep an eye on correctness. </p> <p> The above default behaviour of the <em>Add null check</em> Quick Action annoyed me because I had to manually remove the brackets. It's one of those things that annoy you a little, but not enough that you throw aside what you're doing to figure out if you can change the situation. </p> <p> Until it annoyed me enough to investigate whether there was something I <em>could</em> do about it. It turns out to be easy to tweak the behaviour. </p> <p> In Visual Studio 2019, go to <em>Tools</em>, <em>Options</em>, <em>Text Editor</em>, <em>C#</em>, <em>Code Style</em>, <em>General</em> and change the <em>Prefer braces</em> option to <em>No</em>: </p> <p> <img src="/content/binary/visual-studio-prefer-braces-option.png" alt="Screen shot of Visual Studio Options dialog box."> </p> <p> This changes the behaviour of the <em>Add null check</em> Quick Action: </p> <p> <img src="/content/binary/add-null-check-without-brackets.png" alt="Screen shot of the 'Add null check' Quick Action after the behaviour change. It no longer adds brackets around the throw statement."> </p> <p> After applying the Quick Action, my code now looks like this: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">bool</span>&nbsp;Overlaps(<span style="color:#2b91af;">Reservation</span>&nbsp;other) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">if</span>&nbsp;(other&nbsp;<span style="color:blue;">is</span>&nbsp;<span style="color:blue;">null</span>) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">throw</span>&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">ArgumentNullException</span>(<span style="color:blue;">nameof</span>(other)); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;otherSeating&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">Seating</span>(SeatingDuration,&nbsp;other.Date); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">return</span>&nbsp;Overlaps(otherSeating); }</pre> </p> <p> This better fits my preference. </p> </div> <div id="comments"> <hr> <h2 id="comments-header"> Comments </h2> <div class="comment" id="bbe35bc429dc4d759fab30cfc90c9bdd"> <div class="comment-author">Daniel</div> <div class="comment-content"> <p> The same should go for if's, switch's, try/catch and perhaps a few other things. While we are at it, spacing is also a good source for changing layout in code, e.g: decimal.Round( amount * 1.0000m, provider.Getdecimals( currency ) ) ). </p> </div> <div class="comment-date">2020-09-07 7:14 UTC</div> </div> <div class="comment" id="ec5cf23c648e4277b851685bc55e258a"> <div class="comment-author">James World</div> <div class="comment-content"> <p> When assigning parameters to fields, I like this one-line option for a null check: </p> <p> <pre>_thing = thing ?? throw new ArgumentNullException(nameof(thing));</pre>. </p> <p> How do you feel about it? You could even use a disard in your example: <pre>_ = thing ?? throw new ArgumentNullException(nameof(thing));</pre> </p> </div> <div class="comment-date">2020-09-07 13:14 UTC</div> </div> <div class="comment" id="e456bf65fe3e426f97639b8855622a7b"> <div class="comment-author"><a href="/">Mark Seemann</a></div> <div class="comment-content"> <p> James, thank you for writing. I'm aware of that option, but rarely use it in my examples. I try to write my example code in a way that they may also be helpful to Java developers, or programmers that use other C-based languages. Obviously, that concern doesn't apply if I discuss something specific to C#, but when I try to explain design patterns or low-level architecture, I try to stay away from language features exclusive to C#. </p> <p> In other contexts, I might or might not use that language feature, but I admit that it jars me. I find that it's a 'clever' solution to something that's not much of a problem. The <code>??</code> operator is intended as a short-circuiting operator one can use to simplify variable assignment. Throwing on the right-hand side never assigns a value. </p> <p> It's as though you would use the <a href="/2018/04/09/coalescing-composite-as-a-monoid">coalescing monoid</a> to pick the left-hand side, but let the program fail on the right-hand side. In Haskell it would look like this: </p> <p> <pre>x = thing &lt;&gt; undefined</pre> </p> <p> The compiler infers that <code>x</code> has the same type as <code>thing</code>, e.g. <code>Semigroup a =&gt; Maybe a</code>. If <code>thing</code>, however, is <code>Nothing</code>, the expression crashes when evaluated. </p> <p> While this compiles in Haskell, I consider it unidiomatic. It too blatantly advertises the existence of the so-called <a href="https://en.wikipedia.org/wiki/Bottom_type">bottom value</a> (⊥). We know it's there, but we prefer to pretend that it's not. </p> <p> That line of reasoning is subjective, and if I find myself in a code base that uses <code>??</code> like you've shown, I'd try to fit in with that style. It doesn't annoy me that much, after all. </p> <p> It's also shorter, I must admit that. </p> </div> <div class="comment-date">2020-09-08 05:57 UTC</div> </div> <div class="comment" id="5c16a687f8b4421fa826ef7c66656767"> <div class="comment-author"><a href="https://about.me/tysonwilliams">Tyson Williams</a></div> <div class="comment-content"> <blockquote> <p> The above default behaviour of the <em>Add null check</em> Quick Action annoyed me because I had to manually remove the brackets. It's one of those things that annoy you a little, but not enough that you throw aside what you're doing to figure out if you can change the situation. </p> <p> Until it annoyed me enough to investigate whether there was something I <em>could</em> do about it. It turns out to be easy to tweak the behaviour. </p> <p> In Visual Studio 2019, go to <em>Tools</em>, <em>Options</em>, <em>Text Editor</em>, <em>C#</em>, <em>Code Style</em>, <em>General</em> and change the <em>Prefer braces</em> option to <em>No</em>: </p> </blockquote> <p> You can do more than that. As suggested by Visual Studio in your second screenshot, you can (after making the change to not prefer braces) generate an <code>.editorconfig</code> file containing your coding style settings. Visual Studio will prompt you to save the file alongside your solution. If you do so, then any developer that opens these files with Visual Studio with also have your setting to not prefer braces. I wrote a <a href="https://tysonwilliams.coding.blog/2020-09-12_editorconfig">short post about EditorConfig</a> that contains more information. </p> </div> <div class="comment-date">2020-09-13 01:53 UTC</div> </div> </div> <hr> This blog is totally free, but if you like it, please consider <a href="https://blog.ploeh.dk/support">supporting it</a>. Mark Seemann https://blog.ploeh.dk/2020/09/07/add-null-check-without-brackets-in-visual-studio Properties for all https://blog.ploeh.dk/2020/08/31/properties-for-all/ Mon, 31 Aug 2020 08:39:00 UTC <div id="post"> <p> <em>Writing test cases for all possible input values.</em> </p> <p> I've noticed that programmers new to automated testing struggle with a fundamental task: how to come up with good test input? </p> <p> There's plenty of design patterns that address that issue, including <a href="http://www.natpryce.com/articles/000714.html">Test Data Builders</a>. Still, test-driven development, when done right, gives you good feedback on the design of your API. I don't consider having to resort to Test Data Builder as much of a compromise, but still, it's even better if you can model the API in question so that it requires no redundant data. </p> <p> Most business processes can be modelled as finite state machines. Once you've understood the problem well enough to enumerate the possible states, you can reverse-engineer an <a href="https://en.wikipedia.org/wiki/Algebraic_data_type">algebraic data type</a> from that enumeration. </p> <p> While the data carried around in the state machine may be unconstrained, the number of state and state transitions is usually limited. Model the states as enumerable values, and you can cover all input values with simple combinatorics. </p> <h3 id="44553eea5abb4ab58c73ce173a12ddde"> Tennis states <a href="#44553eea5abb4ab58c73ce173a12ddde" title="permalink">#</a> </h3> <p> The <a href="https://codingdojo.org/kata/Tennis">Tennis kata</a> is one of my favourite exercises. Just like a business process, it turns out that you can model the rules as a finite state machine. There's a state where both players have <em>love</em>, 15, 30, or 40 points (although both can't have 40 points; that state is called <em>deuce</em>); there's a state where a player has the <em>advantage</em>; and so on. </p> <p> I've <a href="https://blog.ploeh.dk/2016/02/10/types-properties-software-designing-with-types">previously written about how to design the states of the Tennis kata with types</a>, so here, I'll just limit myself to the few types that turn out to matter as test input: players and points. </p> <p> Here are both types defined as <a href="https://www.haskell.org">Haskell</a> <a href="https://en.wikipedia.org/wiki/Tagged_union">sum types</a>: </p> <p> <pre><span style="color:blue;">data</span>&nbsp;Player&nbsp;=&nbsp;PlayerOne&nbsp;|&nbsp;PlayerTwo&nbsp;<span style="color:blue;">deriving</span>&nbsp;(<span style="color:#2b91af;">Eq</span>,&nbsp;<span style="color:#2b91af;">Show</span>,&nbsp;<span style="color:#2b91af;">Read</span>,&nbsp;<span style="color:#2b91af;">Enum</span>,&nbsp;<span style="color:#2b91af;">Bounded</span>) <span style="color:blue;">data</span>&nbsp;Point&nbsp;=&nbsp;Love&nbsp;|&nbsp;Fifteen&nbsp;|&nbsp;Thirty&nbsp;<span style="color:blue;">deriving</span>&nbsp;(<span style="color:#2b91af;">Eq</span>,&nbsp;<span style="color:#2b91af;">Show</span>,&nbsp;<span style="color:#2b91af;">Read</span>,&nbsp;<span style="color:#2b91af;">Enum</span>,&nbsp;<span style="color:#2b91af;">Bounded</span>)</pre> </p> <p> Notice that both are instances of the <code>Enum</code> and <code>Bounded</code> type classes. This means that it's possible to enumerate all values that inhabit each type. You can use that to your advantage when writing unit tests. </p> <h3 id="5a6d5d80394b4486bb17adc4cd8cf727"> Properties for every value <a href="#5a6d5d80394b4486bb17adc4cd8cf727" title="permalink">#</a> </h3> <p> Most people think of <a href="/property-based-testing-intro">property-based testing</a> as something that involves a special framework such as <a href="https://hackage.haskell.org/package/QuickCheck">QuickCheck</a>, <a href="https://github.com/hedgehogqa">Hedgehog</a>, or <a href="https://fscheck.github.io/FsCheck/index.html">FsCheck</a>. I often use such frameworks, but as I've <a href="/2015/02/23/property-based-testing-without-a-property-based-testing-framework">written about before</a>, sometimes enumerating all possible input values is simpler and faster than relying on randomly generated values. There's no reason to generate 100 random values of a type inhabited by only three values. </p> <p> Instead, write properties for the entire <a href="https://en.wikipedia.org/wiki/Domain_of_a_function">domain</a> of the function in question. </p> <p> In Haskell, you can define a generic enumeration like this: </p> <p> <pre><span style="color:#2b91af;">every</span>&nbsp;::&nbsp;(<span style="color:blue;">Enum</span>&nbsp;a,&nbsp;<span style="color:blue;">Bounded</span>&nbsp;a)&nbsp;<span style="color:blue;">=&gt;</span>&nbsp;[a] every&nbsp;=&nbsp;[<span style="color:blue;">minBound</span>&nbsp;..&nbsp;<span style="color:blue;">maxBound</span>] </pre> </p> <p> I don't know why this function doesn't already exist in the standard library, but I suppose that most people just rely on the list comprehension syntax <code>[minBound .. maxBound]</code>... </p> <p> With it you can write simple properties of the Tennis game. For example: </p> <p> <pre><span style="color:#a31515;">&quot;Given&nbsp;deuce,&nbsp;when&nbsp;player&nbsp;wins,&nbsp;then&nbsp;that&nbsp;player&nbsp;has&nbsp;advantage&quot;</span>&nbsp;~:&nbsp;<span style="color:blue;">do</span> &nbsp;&nbsp;player&nbsp;&lt;-&nbsp;every &nbsp;&nbsp;<span style="color:blue;">let</span>&nbsp;actual&nbsp;=&nbsp;score&nbsp;Deuce&nbsp;player &nbsp;&nbsp;<span style="color:blue;">return</span>&nbsp;$&nbsp;Advantage&nbsp;player&nbsp;~=?&nbsp;actual </pre> </p> <p> Here I'm using <a href="/2018/05/07/inlined-hunit-test-lists">inlined HUnit test lists</a>. With the Tennis kata, it's easiest to start with the <em>deuce</em> case, because regardless of player, the new state is that the winning player has advantage. That's what that property asserts. Because of the <code>do</code> notation, the property produces a list of test cases, one for <code>every</code> player. There's only two <code>Player</code> values, so it's only two test cases. </p> <p> The beauty of <code>do</code> notation (or the list monad in general) is that you can combine enumerations, for example like this: </p> <p> <pre><span style="color:#a31515;">&quot;Given&nbsp;forty,&nbsp;when&nbsp;player&nbsp;wins&nbsp;ball,&nbsp;then&nbsp;that&nbsp;player&nbsp;wins&nbsp;the&nbsp;game&quot;</span>&nbsp;~:&nbsp;<span style="color:blue;">do</span> &nbsp;&nbsp;player&nbsp;&lt;-&nbsp;every &nbsp;&nbsp;opp&nbsp;&lt;-&nbsp;every &nbsp;&nbsp;<span style="color:blue;">let</span>&nbsp;actual&nbsp;=&nbsp;score&nbsp;(Forty&nbsp;$&nbsp;FortyData&nbsp;player&nbsp;opp)&nbsp;player &nbsp;&nbsp;<span style="color:blue;">return</span>&nbsp;$&nbsp;Game&nbsp;player&nbsp;~=?&nbsp;actual </pre> </p> <p> While <code>player</code> is a <code>Player</code> value, <code>opp</code> (<em>Other Player's Point</em>) is a <code>Point</code> value. Since there's two possible <code>Player</code> values and three possible <code>Point</code> values, the combination yields six test cases. </p> <p> I've been doing the Tennis kata a couple of times using this approach. I've also done it in C# with <a href="https://xunit.net">xUnit.net</a>, where the first test of the <em>deuce</em> state looks like this: </p> <p> <pre>[<span style="color:#2b91af;">Theory</span>,&nbsp;<span style="color:#2b91af;">MemberData</span>(<span style="color:blue;">nameof</span>(Player))] <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">void</span>&nbsp;TransitionFromDeuce(<span style="color:#2b91af;">IPlayer</span>&nbsp;player) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;sut&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">Deuce</span>(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;actual&nbsp;=&nbsp;sut.BallTo(player); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;expected&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">Advantage</span>(player); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">Assert</span>.Equal(expected,&nbsp;actual); }</pre> </p> <p> <a href="/2019/12/16/zone-of-ceremony">C# takes more ceremony than Haskell</a>, but the idea is the same. The <code>Player</code> data source for the <code>[Theory]</code> is defined as an enumeration of the possible values: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">static</span>&nbsp;<span style="color:#2b91af;">IEnumerable</span>&lt;<span style="color:blue;">object</span>[]&gt;&nbsp;Player { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">get</span> &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">yield</span>&nbsp;<span style="color:blue;">return</span>&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:blue;">object</span>[]&nbsp;{&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">PlayerOne</span>()&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">yield</span>&nbsp;<span style="color:blue;">return</span>&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:blue;">object</span>[]&nbsp;{&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">PlayerTwo</span>()&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;} }</pre> </p> <p> All the times I've done the Tennis kata by fully exhausting the domain of the transition functions in question, I've arrived at 40 test cases. I wonder if that's the number of possible state transitions of the game, or if it's just an artefact of the way I've modelled it. I suspect the latter... </p> <h3 id="21ccf5bd3c3f48859bbb8c766b0a0610"> Conclusion <a href="#21ccf5bd3c3f48859bbb8c766b0a0610" title="permalink">#</a> </h3> <p> You can sometimes enumerate all possible inputs to an API. Even if a function takes a Boolean value and a byte as input, the enumeration of all possible combinations is only 2 * 256 = 512 values. You computer will tear through all of those combinations faster than you can say <em>random selection</em>. Consider writing APIs that take algebraic data types as input, and writing properties that exhaust the domain of the functions in question. </p> </div><hr> This blog is totally free, but if you like it, please consider <a href="https://blog.ploeh.dk/support">supporting it</a>. Mark Seemann https://blog.ploeh.dk/2020/08/31/properties-for-all Adding REST links as a cross-cutting concern https://blog.ploeh.dk/2020/08/24/adding-rest-links-as-a-cross-cutting-concern/ Mon, 24 Aug 2020 06:47:00 UTC <div id="post"> <p> <em>Use a piece of middleware to enrich a Data Transfer Object. An ASP.NET Core example.</em> </p> <p> When developing true REST APIs, you should <a href="https://martinfowler.com/articles/richardsonMaturityModel.html">use hypermedia controls</a> (i.e. <em>links</em>) to guide clients to the resources they need. I've always felt that the code that generates these links tends to make otherwise readable Controller methods unreadable. </p> <p> I'm currently experimenting with generating links as a cross-cutting concern. So far, I like it very much. </p> <h3 id="57785b860f604552b099e42b296f6fb6"> Links from home <a href="#57785b860f604552b099e42b296f6fb6" title="permalink">#</a> </h3> <p> Consider an online restaurant reservation system. When you make a <code>GET</code> request against the home resource (which is the only published URL for the API), you should receive a representation like this: </p> <p> <pre>{ &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;links&quot;</span>:&nbsp;[ &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;rel&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;urn:reservations&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;href&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;http://localhost:53568/reservations&quot;</span> &nbsp;&nbsp;&nbsp;&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;rel&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;urn:year&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;href&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;http://localhost:53568/calendar/2020&quot;</span> &nbsp;&nbsp;&nbsp;&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;rel&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;urn:month&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;href&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;http://localhost:53568/calendar/2020/8&quot;</span> &nbsp;&nbsp;&nbsp;&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;rel&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;urn:day&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;href&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;http://localhost:53568/calendar/2020/8/13&quot;</span> &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;] }</pre> </p> <p> As you can tell, my example just runs on my local development machine, but I'm sure that you can see past that. There's three calendar links that clients can use to <code>GET</code> the restaurant's calendar for the current day, month, or year. Clients can use these resources to present a user with a date picker or a similar user interface so that it's possible to pick a date for a reservation. </p> <p> When a client wants to make a reservation, it can use the URL identified by the <code>rel</code> (<em>relationship type</em>) <code>"urn:reservations"</code> to make a <code>POST</code> request. </p> <h3 id="724d54b2bb4a4071b0f965105541c792"> Link generation as a Controller responsibility <a href="#724d54b2bb4a4071b0f965105541c792" title="permalink">#</a> </h3> <p> I first wrote the code that generates these links directly in the Controller class that serves the home resource. It looked like this: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">IActionResult</span>&nbsp;Get() { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;links&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">List</span>&lt;<span style="color:#2b91af;">LinkDto</span>&gt;(); &nbsp;&nbsp;&nbsp;&nbsp;links.Add(Url.LinkToReservations()); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">if</span>&nbsp;(enableCalendar) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;now&nbsp;=&nbsp;<span style="color:#2b91af;">DateTime</span>.Now; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;links.Add(Url.LinkToYear(now.Year)); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;links.Add(Url.LinkToMonth(now.Year,&nbsp;now.Month)); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;links.Add(Url.LinkToDay(now.Year,&nbsp;now.Month,&nbsp;now.Day)); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">return</span>&nbsp;Ok(<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">HomeDto</span>&nbsp;{&nbsp;Links&nbsp;=&nbsp;links.ToArray()&nbsp;}); }</pre> </p> <p> That doesn't look too bad, but 90% of the code is exclusively concerned with generating links. (<code>enableCalendar</code>, by the way, is a <a href="https://en.wikipedia.org/wiki/Feature_toggle">feature flag</a>.) That seems acceptable in this special case, because there's really nothing else the home resource has to do. For other resources, the Controller code might contain some composition code as well, and then all the link code starts to look like noise that makes it harder to understand the actual purpose of the Controller method. You'll see an example of a non-trivial Controller method later in this article. </p> <p> It seemed to me that enriching a Data Transfer Object (DTO) with links ought to be a cross-cutting concern. </p> <h3 id="1973741c11414414bcd0ca2748bf0f0d"> LinksFilter <a href="#1973741c11414414bcd0ca2748bf0f0d" title="permalink">#</a> </h3> <p> In ASP.NET Core, you can implement cross-cutting concerns with a type of middleware called <a href="https://docs.microsoft.com/dotnet/api/microsoft.aspnetcore.mvc.filters.iasyncactionfilter">IAsyncActionFilter</a>. I added one called <code>LinksFilter</code>: </p> <p> <pre><span style="color:blue;">internal</span>&nbsp;<span style="color:blue;">class</span>&nbsp;<span style="color:#2b91af;">LinksFilter</span>&nbsp;:&nbsp;<span style="color:#2b91af;">IAsyncActionFilter</span> { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">private</span>&nbsp;<span style="color:blue;">readonly</span>&nbsp;<span style="color:blue;">bool</span>&nbsp;enableCalendar; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">IUrlHelperFactory</span>&nbsp;UrlHelperFactory&nbsp;{&nbsp;<span style="color:blue;">get</span>;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">LinksFilter</span>( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">IUrlHelperFactory</span>&nbsp;urlHelperFactory, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">CalendarFlag</span>&nbsp;calendarFlag) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UrlHelperFactory&nbsp;=&nbsp;urlHelperFactory; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;enableCalendar&nbsp;=&nbsp;calendarFlag.Enabled; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:blue;">async</span>&nbsp;<span style="color:#2b91af;">Task</span>&nbsp;OnActionExecutionAsync( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">ActionExecutingContext</span>&nbsp;context, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">ActionExecutionDelegate</span>&nbsp;next) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;ctxAfter&nbsp;=&nbsp;<span style="color:blue;">await</span>&nbsp;next().ConfigureAwait(<span style="color:blue;">false</span>); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">if</span>&nbsp;(!(ctxAfter.Result&nbsp;<span style="color:blue;">is</span>&nbsp;<span style="color:#2b91af;">OkObjectResult</span>&nbsp;ok)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">return</span>; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;url&nbsp;=&nbsp;UrlHelperFactory.GetUrlHelper(ctxAfter); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">switch</span>&nbsp;(ok.Value) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">case</span>&nbsp;<span style="color:#2b91af;">HomeDto</span>&nbsp;homeDto: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddLinks(homeDto,&nbsp;url); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">break</span>; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">case</span>&nbsp;<span style="color:#2b91af;">CalendarDto</span>&nbsp;calendarDto: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddLinks(calendarDto,&nbsp;url); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">break</span>; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">default</span>: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">break</span>; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:green;">//&nbsp;...</span></pre> </p> <p> There's only one method to implement. If you want to run some code <em>after</em> the Controllers have had their chance, you invoke the <code>next</code> delegate to get the resulting context. It should contain the response to be returned. If <code>Result</code> isn't an <code>OkObjectResult</code> there's no content to enrich with links, so the method just returns. </p> <p> Otherwise, it switches on the type of the <code>ok.Value</code> and passes the DTO to an appropriate helper method. Here's the <code>AddLinks</code> overload for <code>HomeDto</code>: </p> <p> <pre><span style="color:blue;">private</span>&nbsp;<span style="color:blue;">void</span>&nbsp;AddLinks(<span style="color:#2b91af;">HomeDto</span>&nbsp;dto,&nbsp;<span style="color:#2b91af;">IUrlHelper</span>&nbsp;url) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">if</span>&nbsp;(enableCalendar) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;now&nbsp;=&nbsp;<span style="color:#2b91af;">DateTime</span>.Now; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dto.Links&nbsp;=&nbsp;<span style="color:blue;">new</span>[] &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;url.LinkToReservations(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;url.LinkToYear(now.Year), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;url.LinkToMonth(now.Year,&nbsp;now.Month), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;url.LinkToDay(now.Year,&nbsp;now.Month,&nbsp;now.Day) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">else</span> &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dto.Links&nbsp;=&nbsp;<span style="color:blue;">new</span>[]&nbsp;{&nbsp;url.LinkToReservations()&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;} }</pre> </p> <p> You can probably recognise the implemented behaviour from before, where it was implemented in the <code>Get</code> method. That method now looks like this: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">ActionResult</span>&nbsp;Get() { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">return</span>&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">OkObjectResult</span>(<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">HomeDto</span>()); }</pre> </p> <p> That's clearly much simpler, but you probably think that little has been achieved. After all, doesn't this just move some code from one place to another? </p> <p> Yes, that's the case in this particular example, but I wanted to start with an example that was so simple that it highlights how to move the code to a filter. Consider, then, the following example. </p> <h3 id="9156b0b69f4d485fa373a8c4b06547d5"> A calendar resource <a href="#9156b0b69f4d485fa373a8c4b06547d5" title="permalink">#</a> </h3> <p> The online reservation system enables clients to navigate its calendar to look up dates and time slots. A representation might look like this: </p> <p> <pre>{ &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;links&quot;</span>:&nbsp;[ &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;rel&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;previous&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;href&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;http://localhost:53568/calendar/2020/8/12&quot;</span> &nbsp;&nbsp;&nbsp;&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;rel&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;next&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;href&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;http://localhost:53568/calendar/2020/8/14&quot;</span> &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;], &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;year&quot;</span>:&nbsp;2020, &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;month&quot;</span>:&nbsp;8, &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;day&quot;</span>:&nbsp;13, &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;days&quot;</span>:&nbsp;[ &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;links&quot;</span>:&nbsp;[ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;rel&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;urn:year&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;href&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;http://localhost:53568/calendar/2020&quot;</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;rel&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;urn:month&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;href&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;http://localhost:53568/calendar/2020/8&quot;</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;rel&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;urn:day&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;href&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;http://localhost:53568/calendar/2020/8/13&quot;</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;], &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;date&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;2020-08-13&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;entries&quot;</span>:&nbsp;[ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;time&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;18:00:00&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;maximumPartySize&quot;</span>:&nbsp;10 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;time&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;18:15:00&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;maximumPartySize&quot;</span>:&nbsp;10 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;time&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;18:30:00&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;maximumPartySize&quot;</span>:&nbsp;10 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;time&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;18:45:00&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;maximumPartySize&quot;</span>:&nbsp;10 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;time&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;19:00:00&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;maximumPartySize&quot;</span>:&nbsp;10 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;time&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;19:15:00&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;maximumPartySize&quot;</span>:&nbsp;10 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;time&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;19:30:00&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;maximumPartySize&quot;</span>:&nbsp;10 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;time&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;19:45:00&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;maximumPartySize&quot;</span>:&nbsp;10 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;time&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;20:00:00&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;maximumPartySize&quot;</span>:&nbsp;10 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;time&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;20:15:00&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;maximumPartySize&quot;</span>:&nbsp;10 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;time&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;20:30:00&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;maximumPartySize&quot;</span>:&nbsp;10 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;time&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;20:45:00&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;maximumPartySize&quot;</span>:&nbsp;10 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;time&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;21:00:00&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;maximumPartySize&quot;</span>:&nbsp;10 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;] &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;] }</pre> </p> <p> This is a JSON representation of the calendar for August 13, 2020. The data it contains is the identification of the date, as well as a series of <code>entries</code> that lists the largest reservation the restaurant can accept for each time slot. </p> <p> Apart from the data, the representation also contains links. There's a general collection of links that currently holds only <code>next</code> and <code>previous</code>. In addition to that, each day has its own array of links. In the above example, only a single day is represented, so the <code>days</code> array contains only a single object. For a month calendar (navigatable via the <code>urn:month</code> link), there'd be between 28 and 31 <code>days</code>, each with its own <code>links</code> array. </p> <p> Generating all these links is a complex undertaking all by itself, so separation of concerns is a boon. </p> <h3 id="8f85a3a882164352aa57d600a21628be"> Calendar links <a href="#8f85a3a882164352aa57d600a21628be" title="permalink">#</a> </h3> <p> As you can see in the above <code>LinksFilter</code>, it branches on the type of value wrapped in an <code>OkObjectResult</code>. If the type is <code>CalendarDto</code>, it calls the appropriate <code>AddLinks</code> overload: </p> <p> <pre><span style="color:blue;">private</span>&nbsp;<span style="color:blue;">static</span>&nbsp;<span style="color:blue;">void</span>&nbsp;AddLinks(<span style="color:#2b91af;">CalendarDto</span>&nbsp;dto,&nbsp;<span style="color:#2b91af;">IUrlHelper</span>&nbsp;url) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;period&nbsp;=&nbsp;dto.ToPeriod(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;previous&nbsp;=&nbsp;period.Accept(<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">PreviousPeriodVisitor</span>()); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;next&nbsp;=&nbsp;period.Accept(<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">NextPeriodVisitor</span>()); &nbsp;&nbsp;&nbsp;&nbsp;dto.Links&nbsp;=&nbsp;<span style="color:blue;">new</span>[] &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;url.LinkToPeriod(previous,&nbsp;<span style="color:#a31515;">&quot;previous&quot;</span>), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;url.LinkToPeriod(next,&nbsp;<span style="color:#a31515;">&quot;next&quot;</span>) &nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">if</span>&nbsp;(dto.Days&nbsp;<span style="color:blue;">is</span>&nbsp;{&nbsp;}) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">foreach</span>&nbsp;(<span style="color:blue;">var</span>&nbsp;day&nbsp;<span style="color:blue;">in</span>&nbsp;dto.Days) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddLinks(day,&nbsp;url); }</pre> </p> <p> It both generates the <code>previous</code> and <code>next</code> links on the <code>dto</code>, as well as the links for each day. While I'm not going to bore you with more of that code, you can tell, I hope, that the <code>AddLinks</code> method calls other helper methods and classes. The point is that link generation involves more than just a few lines of code. </p> <p> You already saw that in the first example (related to <code>HomeDto</code>). The question is whether there's still some significant code left in the Controller class? </p> <h3 id="ab37807dfce0431b8308f86ec18a44aa"> Calendar resource <a href="#ab37807dfce0431b8308f86ec18a44aa" title="permalink">#</a> </h3> <p> The <code>CalendarController</code> class defines three overloads of <code>Get</code> - one for a single day, one for a month, and one for an entire year. Each of them looks like this: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">async</span>&nbsp;<span style="color:#2b91af;">Task</span>&lt;<span style="color:#2b91af;">ActionResult</span>&gt;&nbsp;Get(<span style="color:blue;">int</span>&nbsp;year,&nbsp;<span style="color:blue;">int</span>&nbsp;month) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;period&nbsp;=&nbsp;<span style="color:#2b91af;">Period</span>.Month(year,&nbsp;month); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;days&nbsp;=&nbsp;<span style="color:blue;">await</span>&nbsp;MakeDays(period).ConfigureAwait(<span style="color:blue;">false</span>); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">return</span>&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">OkObjectResult</span>( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">CalendarDto</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Year&nbsp;=&nbsp;year, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Month&nbsp;=&nbsp;month, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Days&nbsp;=&nbsp;days &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}); }</pre> </p> <p> It doesn't look as though much is going on, but at least you can see that it returns a <code>CalendarDto</code> object. </p> <p> While the method looks simple, it's not. Significant work happens in the <code>MakeDays</code> helper method: </p> <p> <pre><span style="color:blue;">private</span>&nbsp;<span style="color:blue;">async</span>&nbsp;<span style="color:#2b91af;">Task</span>&lt;<span style="color:#2b91af;">DayDto</span>[]&gt;&nbsp;MakeDays(<span style="color:#2b91af;">IPeriod</span>&nbsp;period) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;firstTick&nbsp;=&nbsp;period.Accept(<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">FirstTickVisitor</span>()); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;lastTick&nbsp;=&nbsp;period.Accept(<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">LastTickVisitor</span>()); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;reservations&nbsp;=&nbsp;<span style="color:blue;">await</span>&nbsp;Repository &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.ReadReservations(firstTick,&nbsp;lastTick).ConfigureAwait(<span style="color:blue;">false</span>); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;days&nbsp;=&nbsp;period.Accept(<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">DaysVisitor</span>()) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.Select(d&nbsp;=&gt;&nbsp;MakeDay(d,&nbsp;reservations)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.ToArray(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">return</span>&nbsp;days; }</pre> </p> <p> After having read relevant <code>reservations</code> from the database, it applies complex business logic to allocate them and thereby being able to report on remaining capacity for each time slot. </p> <p> Not having to worry about link generation while doing all that work seems like a benefit. </p> <h3 id="87b164914be0450fbd523735946cf146"> Filter registration <a href="#87b164914be0450fbd523735946cf146" title="permalink">#</a> </h3> <p> You must tell the ASP.NET Core framework about any filters that you add. You can do that in the <code>Startup</code> class' <code>ConfigureServices</code> method: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">void</span>&nbsp;ConfigureServices(<span style="color:#2b91af;">IServiceCollection</span>&nbsp;services) { &nbsp;&nbsp;&nbsp;&nbsp;services.AddControllers(opts&nbsp;=&gt;&nbsp;opts.Filters.Add&lt;<span style="color:#2b91af;">LinksFilter</span>&gt;()); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:green;">//&nbsp;...</span></pre> </p> <p> When registered, the filter executes for each HTTP request. When the object represents a <code>200 OK</code> result, the filter populates the DTOs with links. </p> <h3 id="ced9fd76d526420aa1a847da4398e904"> Conclusion <a href="#ced9fd76d526420aa1a847da4398e904" title="permalink">#</a> </h3> <p> By treating RESTful link generation as a cross-cutting concern, you can separate if from the logic of generating the data structure that represents the resource. That's not the only way to do it. You could also write a simple function that populates DTOs, and call it directly from each Controller action. </p> <p> What I like about using a filter is that I don't have to remember to do that. Once the filter is registered, it'll populate all the DTOs it knows about, regardless of which Controller generated them. </p> </div> <div id="comments"> <hr> <h2 id="comments-header"> Comments </h2> <div class="comment" id="fff391e80e27427e8fc93959deef3768"> <div class="comment-author"><a href="https://twitter.com/MehdiFalamarzi?s=08">Mehdi Falamarzi</a></div> <div class="comment-content"> <p> Thanks for your good and insightful posts. </p> <p> Separation of REST concerns from MVC controller's concerns is a great idea, But in my opinion this solution has two problems: </p> <h3 id="52608f57b49942aaaafdab7aae22c85"> Distance between related REST implementations <a href="#52608f57b49942aaaafdab7aae22c85" title="permalink">#</a> </h3> <p> When implementing REST by MVC pattern often REST archetypes are the reasons for a MVC Controller class to be created. As long as the MVC Controller class describes the archetype, And links of a resource is a part of the response when implementing hypermedia controls, having the archetype and its related links in the place where the resource described is a big advantage in easiness and readability of the design. pulling out link implementations and putting them in separate classes causes higher readability and uniformity of the code abstranction levels in the action method at the expense of making a distance between related REST implementation. </p> <h3 id="fa1203384d3746bfadd276aae6ac860f"> Implementation scalability <a href="#fa1203384d3746bfadd276aae6ac860f" title="permalink">#</a> </h3> <p> There is a switch statement on the ActionExecutingContext's result in the LinksFilter to decide what links must be represented to the client in the response.The DTOs thre are the results of the clients's requests for URIs. If this solution generalised for every resources the API must represent there will be several cases for the switch statement to handle. Beside that every resources may have different implemetations for generating their links. Putting all this in one place leads the LinksFilter to be coupled with too many helper classes and this coupling process never stops. </p> <h3 id="4dd0703da482480abffbaffabdb27741"> Solution <a href="#4dd0703da482480abffbaffabdb27741" title="permalink">#</a> </h3> <p> LinkDescriptor and LinkSubscriber for resources links definition </p> <div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"> <pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">public</span> <span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">LinkDescriptor</span> { <span style="color: #008800; font-weight: bold">public</span> <span style="color: #333399; font-weight: bold">string</span> Rel { <span style="color: #008800; font-weight: bold">get</span>; <span style="color: #008800; font-weight: bold">set</span>; } <span style="color: #008800; font-weight: bold">public</span> <span style="color: #333399; font-weight: bold">string</span> Href { <span style="color: #008800; font-weight: bold">get</span>; <span style="color: #008800; font-weight: bold">set</span>; } <span style="color: #008800; font-weight: bold">public</span> <span style="color: #333399; font-weight: bold">string</span> Resource { <span style="color: #008800; font-weight: bold">get</span>; <span style="color: #008800; font-weight: bold">set</span>; } } </pre> </div> <p> Letting the MVC controller classes have their resource's links definitions but not in action methods. </p> <div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"> <pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">public</span> ActionResult <span style="color: #0066BB; font-weight: bold">Get</span>() { <span style="color: #008800; font-weight: bold">return</span> <span style="color: #008800; font-weight: bold">new</span> <span style="color: #0066BB; font-weight: bold">OkObjectResult</span>(<span style="color: #008800; font-weight: bold">new</span> HomeDto()); } <span style="color: #008800; font-weight: bold">public</span> <span style="color: #008800; font-weight: bold">static</span> <span style="color: #008800; font-weight: bold">void</span> <span style="color: #0066BB; font-weight: bold">RegisterLinks</span>(LinkSubscriber subscriber) { subscriber .Add( resource: <span style="background-color: #fff0f0">&quot;/Home&quot;</span>, rel: <span style="background-color: #fff0f0">&quot;urn:reservations&quot;</span>, href: <span style="background-color: #fff0f0">&quot;/reservations&quot;</span>) .Add( resource: <span style="background-color: #fff0f0">&quot;/Home&quot;</span>, rel: <span style="background-color: #fff0f0">&quot;urn:year&quot;</span>, href: <span style="background-color: #fff0f0">&quot;/calendar/2020&quot;</span>) .Add( resource: <span style="background-color: #fff0f0">&quot;/Home&quot;</span>, rel: <span style="background-color: #fff0f0">&quot;urn:month&quot;</span>, href: <span style="background-color: #fff0f0">&quot;/calendar/2020/8&quot;</span>) .Add( resource: <span style="background-color: #fff0f0">&quot;/Home&quot;</span>, rel: <span style="background-color: #fff0f0">&quot;urn:day&quot;</span>, href: <span style="background-color: #fff0f0">&quot;/calendar/2020/8/13&quot;</span>); } </pre> </div> <p> Registering resources links by convention </p> <div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"> <pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">public</span> <span style="color: #008800; font-weight: bold">static</span> <span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">MvcBuilderExtensions</span> { <span style="color: #008800; font-weight: bold">public</span> <span style="color: #008800; font-weight: bold">static</span> IMvcBuilder <span style="color: #0066BB; font-weight: bold">AddRestLinks</span>(<span style="color: #008800; font-weight: bold">this</span> IMvcBuilder mvcBuilder) { <span style="color: #333399; font-weight: bold">var</span> subscriber = <span style="color: #008800; font-weight: bold">new</span> LinkSubscriber(); <span style="color: #333399; font-weight: bold">var</span> linkRegistrationMethods = GetLinkRegistrationMethods(mvcBuilder.Services); PopulateLinks(subscriber, linkRegistrationMethods); mvcBuilder.Services.AddSingleton&lt;IEnumerable&lt;LinkDescriptor&gt;&gt;(subscriber.LinkDescriptors); <span style="color: #008800; font-weight: bold">return</span> mvcBuilder; } <span style="color: #008800; font-weight: bold">private</span> <span style="color: #008800; font-weight: bold">static</span> List&lt;MethodInfo&gt; GetLinkRegistrationMethods(IServiceCollection services) { <span style="color: #008800; font-weight: bold">return</span> <span style="color: #0066BB; font-weight: bold">typeof</span>(MvcBuilderExtensions).Assembly.ExportedTypes .Where(tp =&gt; <span style="color: #008800; font-weight: bold">typeof</span>(ControllerBase).IsAssignableFrom(tp)) .Select(tp =&gt; tp.GetMethod(<span style="background-color: #fff0f0">&quot;RegisterLinks&quot;</span>, <span style="color: #008800; font-weight: bold">new</span>[] { <span style="color: #008800; font-weight: bold">typeof</span>(LinkSubscriber) })) .Where(mi =&gt; mi != <span style="color: #008800; font-weight: bold">null</span>) .ToList(); } <span style="color: #008800; font-weight: bold">private</span> <span style="color: #008800; font-weight: bold">static</span> <span style="color: #008800; font-weight: bold">void</span> <span style="color: #0066BB; font-weight: bold">PopulateLinks</span>(LinkSubscriber subscriber, List&lt;MethodInfo&gt; linkRegistrationMethods) { <span style="color: #008800; font-weight: bold">foreach</span> (<span style="color: #333399; font-weight: bold">var</span> method <span style="color: #008800; font-weight: bold">in</span> linkRegistrationMethods) { method.Invoke(<span style="color: #008800; font-weight: bold">null</span>, <span style="color: #008800; font-weight: bold">new</span>[] { subscriber }); } } } </pre> </div> <p> Add dependencies and execute procedures for adding links to responses </p> <div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"> <pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">public</span> <span style="color: #008800; font-weight: bold">void</span> <span style="color: #0066BB; font-weight: bold">ConfigureServices</span>(IServiceCollection services) { services.AddControllers(conf =&gt; conf.Filters.Add&lt;LinksFilter&gt;()) .AddRestLinks(); } </pre> </div> <p> And Last letting the LinksFilter to dynamicaly add resources links by utilizing ExpandoObject </p> <div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"> <pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">public</span> <span style="color: #008800; font-weight: bold">class</span> <span style="color: #BB0066; font-weight: bold">LinksFilter</span> : IAsyncActionFilter { <span style="color: #008800; font-weight: bold">private</span> <span style="color: #008800; font-weight: bold">readonly</span> IEnumerable&lt;LinkDescriptor&gt; links; <span style="color: #008800; font-weight: bold">public</span> <span style="color: #0066BB; font-weight: bold">LinksFilter</span>(IEnumerable&lt;LinkDescriptor&gt; links) { <span style="color: #008800; font-weight: bold">this</span>.links = links; } <span style="color: #008800; font-weight: bold">public</span> <span style="color: #008800; font-weight: bold">async</span> Task <span style="color: #0066BB; font-weight: bold">OnActionExecutionAsync</span>(ActionExecutingContext context, ActionExecutionDelegate next) { <span style="color: #333399; font-weight: bold">var</span> relatedLinks = links .Where(lk =&gt; context.HttpContext.Request.Path.Value.ToLower() == lk.Resource); <span style="color: #008800; font-weight: bold">if</span> (relatedLinks.Any()) <span style="color: #008800; font-weight: bold">await</span> <span style="color: #0066BB; font-weight: bold">ManipulateResponseAsync</span>(context, next, relatedLinks); } <span style="color: #008800; font-weight: bold">private</span> <span style="color: #008800; font-weight: bold">async</span> Task <span style="color: #0066BB; font-weight: bold">ManipulateResponseAsync</span>(ActionExecutingContext context, ActionExecutionDelegate next, IEnumerable&lt;LinkDescriptor&gt; relatedLinks) { <span style="color: #333399; font-weight: bold">var</span> ctxAfter = <span style="color: #008800; font-weight: bold">await</span> next().ConfigureAwait(<span style="color: #008800; font-weight: bold">false</span>); <span style="color: #008800; font-weight: bold">if</span> (!(ctxAfter.Result <span style="color: #008800; font-weight: bold">is</span> ObjectResult objRes)) <span style="color: #008800; font-weight: bold">return</span>; <span style="color: #333399; font-weight: bold">var</span> expandoResult = <span style="color: #008800; font-weight: bold">new</span> ExpandoObject(); FillExpandoWithResultProperties(expandoResult, objRes.Value); FillExpandoWithLinks(expandoResult, relatedLinks); objRes.Value = expandoResult; } <span style="color: #008800; font-weight: bold">private</span> <span style="color: #008800; font-weight: bold">void</span> <span style="color: #0066BB; font-weight: bold">FillExpandoWithResultProperties</span>(ExpandoObject resultExpando, <span style="color: #333399; font-weight: bold">object</span> <span style="color: #008800; font-weight: bold">value</span>) { <span style="color: #333399; font-weight: bold">var</span> properties = <span style="color: #008800; font-weight: bold">value</span>.GetType().GetProperties(); <span style="color: #008800; font-weight: bold">foreach</span> (<span style="color: #333399; font-weight: bold">var</span> property <span style="color: #008800; font-weight: bold">in</span> properties) { resultExpando.TryAdd(property.Name, property.GetValue(<span style="color: #008800; font-weight: bold">value</span>)); } } <span style="color: #008800; font-weight: bold">private</span> <span style="color: #008800; font-weight: bold">void</span> <span style="color: #0066BB; font-weight: bold">FillExpandoWithLinks</span>(ExpandoObject resultExpando, IEnumerable&lt;LinkDescriptor&gt; relatedLinks) { <span style="color: #333399; font-weight: bold">var</span> linksToAdd = relatedLinks.Select(lk =&gt; <span style="color: #008800; font-weight: bold">new</span> { Rel = lk.Rel, Href = lk.Href }); resultExpando.TryAdd(<span style="background-color: #fff0f0">&quot;Links&quot;</span>, linksToAdd); } } </pre> </div> <p> If absoulute URI in href field is prefered, IUriHelper can be injected in LinksFilter to create URI paths. </p> </div> <div class="comment-date">2020-08-24 23:39 UTC</div> </div> <div class="comment" id="127d2750e83811ea8dd900155d8065e1"> <div class="comment-author"><a href="https://github.com/JesHansen">Jes Hansen</a></div> <div class="comment-content"> <p> Mark, thanks for figuring out the tricky parts so we don't have to. :-) </p> <p> I did not see a link to a repo with the completed code from this article, and a cursory look around your Github profile didn't give away any obvious clues. Is the example code in the article part of a repo we can clone? If so, could you please provide a link? </p> </div> <div class="comment-date">2020-08-27 07:45 UTC</div> </div> <div class="comment" id="13197699aaff4a90901910a1975c4de0"> <div class="comment-author"><a href="/">Mark Seemann</a></div> <div class="comment-content"> <p> Jes, it's part of a larger project that I'm currently working on. Eventually, I hope to publish it, but it's not yet in a state where I wish to do that. </p> <p> Did I leave out essential details that makes it hard to reproduce the idea? </p> </div> <div class="comment-date">2020-08-27 08:07 UTC</div> </div> <div class="comment" id="0e3477f6e84311eaadc700155d8065e1"> <div class="comment-author"><a href="https://github.com/JesHansen">Jes Hansen</a></div> <div class="comment-content"> <p> No, your presentation was fine. Looking forward to see the completed project! </p> </div> <div class="comment-date">2020-08-27 08:57 UTC</div> </div> <div class="comment" id="a5f42d7c00e947a885506abdd2a16628"> <div class="comment-author"><a href="/">Mark Seemann</a></div> <div class="comment-content"> <p> Mehdi, thank you for writing. It's true that the <code>LinksFilter</code> implementation code contains a <code>switch</code> statement, and that this is one of multiple possible designs. I do believe that this is a trade-off rather than a problem per se. </p> <p> That <code>switch</code> statement is an implementation detail of the filter, and something I might decide to change in the future. I did choose that implementation, though, because I it was the simplest design that came to my mind. As presented, the <code>switch</code> statement just calls some private helper methods (all called <code>AddLinks</code>), but if one wanted that code close to the rest of the Controller code, one could just move those helper methods to the relevant Controller classes. </p> <p> While you wouldn't need to resort to Reflection to do that, it's true that this would leave that <code>switch</code> statement as a central place where developers would have to go if they add a new resource. It's true that your proposed solution addresses that problem, but doesn't it just shift the burden somewhere else? Now, developers will have to know that they ought to add a <code>RegisterLinks</code> method with a specific signature to their Controller classes. This replaces a design with compile-time checking with something that may fail at run time. How is that an improvement? </p> <p> I think that I understand your other point about the distance of code, but it assumes a particular notion of REST that I find parochial. Most (.NET) developers I've met design REST APIs in a code-centric (if not a database-centric) way. They tend to conflate <em>representations</em> with <em>resources</em> and translate both to Controller classes. </p> <p> The idea behind <em>Representational State Transfer</em>, however, is to decouple state from representation. Resources have state, but can have multiple representations. Vice versa, many resources may share the same representation. In the code base I used for this article, not only do I have three overloaded <code>Get</code> methods on <code>CalendarController</code> that produce <code>CalendarDto</code> representations, I also have a <code>ScheduleController</code> class that does the same. </p> <p> Granted, not all REST API code bases are designed like this. I admit that what actually motivated me to do things like this was to avoid having to inherit from <code>ControllerBase</code>. Moving all the code that relies heavily on the ASP.NET infrastructure keeps the Controller classes lighter, and thus easier to test. I should probably write an article about that... </p> </div> <div class="comment-date">2020-09-01 07:56 UTC</div> </div> </div><hr> This blog is totally free, but if you like it, please consider <a href="https://blog.ploeh.dk/support">supporting it</a>. Mark Seemann https://blog.ploeh.dk/2020/08/24/adding-rest-links-as-a-cross-cutting-concern Unit testing is fine https://blog.ploeh.dk/2020/08/17/unit-testing-is-fine/ Mon, 17 Aug 2020 05:29:00 UTC <div id="post"> <p> <em>Unit testing considered harmful? I think not.</em> </p> <p> Once in a while, some article, video, or podcast makes the rounds on social media, arguing that unit testing is bad, overrated, harmful, or the like. I'm not going to link to any specific resources, because this post isn't an attack on any particular piece of work. Many of these are sophisticated, thoughtful, and make good points, but still arrive at the wrong conclusion. </p> <p> The line of reasoning tends to be to show examples of bad unit tests and conclude that, based on the examples, unit tests are bad. </p> <p> The power of examples is great, but clearly, this is a logical fallacy. </p> <h3 id="5dbc2a18fc7f439b9db0282f0613b2a5"> Symbolisation <a href="#5dbc2a18fc7f439b9db0282f0613b2a5" title="permalink">#</a> </h3> <p> In case it isn't clear that the argument is invalid, I'll demonstrate it using the techniques I've learned from <a href="https://bit.ly/predicate-logic-intro">Howard Pospesel's introduction to predicate logic</a>. </p> <p> We can begin by symbolising the natural-language arguments into well-formed formulas. I'll keep this as simple as possible: </p> <p> <pre>∃xBx ⊢ ∀xBx (Domain: unit tests; Bx = x is bad)</pre> </p> <p> Basically, <code>Bx</code> states that <code>x</code> is bad, where <code>x</code> is a unit test. <code>∃xBx</code> is a statement that there exists a unit test <code>x</code> for which <code>x</code> is bad; i.e. <em>bad unit tests exist</em>. The statement <code>∀xBx</code> claims that for all unit tests <code>x</code>, <code>x</code> is bad; i.e. <em>all unit tests are bad</em>. The turnstile symbol <code>⊢</code> in the middle indicates that the antecedent on the left proves the consequent to the right. </p> <p> Translated back to natural language, the claim is this: <em>Because bad unit tests exist, all unit tests are bad.</em> </p> <p> You can trivially prove this <a href="https://en.wikipedia.org/wiki/Sequent">sequent</a> invalid. </p> <h3 id="a5f5e5c8e1f94696b8ffb86a119170b4"> Logical fallacy <a href="#a5f5e5c8e1f94696b8ffb86a119170b4" title="permalink">#</a> </h3> <p> One way to prove the sequent invalid is to use a truth tree: </p> <p> <img src="/content/binary/truth-tree-open-all-unit-tests-bad.png" alt="Truth tree that disproves the sequent about all unit tests being bad."> </p> <p> Briefly, the way this works is that the statements on the left-hand side represent truth, while the ones to the right are false. By placing the antecedent on the left, but the consequent on the right, you're basically assuming the sequent to be wrong. This is is also the way you <em>prove</em> correct sequents true; if the conclusion is assumed false, a logical truth should lead to a contradiction. If it doesn't, the sequent is invalid. That's what happens here. </p> <p> The tree remains <em>open</em>, which means that the original sequent is invalid. It's a logical fallacy. </p> <h3 id="c19e880f945d4a44a40ca1ccb9b96f74"> Counter examples <a href="#c19e880f945d4a44a40ca1ccb9b96f74" title="permalink">#</a> </h3> <p> You probably already knew that. All it takes to counter a universal assertion such as <em>all unit tests are bad</em> is to produce a counter example. One is sufficient, because if just a single good unit test exists, it can't be true that <em>all</em> are bad. </p> <p> Most of the think pieces that argue that unit testing is bad do so by showing examples of bad unit tests. These tests typically involve lots of mocks and stubs; they tend to test the interaction between internal components instead of the components themselves, or the system as a whole. I agree that this often leads to <a href="http://xunitpatterns.com/Fragile%20Test.html">fragile tests</a>. </p> <p> While I still spend my testing energy according to the <a href="https://martinfowler.com/bliki/TestPyramid.html">Test Pyramid</a>, I don't write unit tests like that. I rarely use dynamic mock libraries. Instead, I <a href="/2020/03/02/impureim-sandwich">push impure actions to the boundary of the system</a> and write most of the application code as <a href="https://en.wikipedia.org/wiki/Pure_function">pure functions</a>, which are <a href="/2015/05/07/functional-design-is-intrinsically-testable">intrinsically testable</a>. No test-induced damage there. </p> <p> I follow up with <a href="/outside-in-tdd">boundary tests</a> that demonstrate that the <a href="/2015/12/21/integration-testing-composed-functions">functions are integrated into a working system</a>. That's just another layer in the Test Pyramid, but smaller. You don't need that many integration tests when you have a foundation of good unit tests. </p> <p> While I'm currently working on a larger body of work that showcases this approach, this blog <a href="/2019/04/01/an-example-of-state-based-testing-in-c">already has examples of this</a>. </p> <h3 id="414e235a672042a6a07e572027250df0"> Conclusion <a href="#414e235a672042a6a07e572027250df0" title="permalink">#</a> </h3> <p> You often hear or see the claim that unit tests are bad. The supporting argument is that a particular (popular, I admit) style of unit testing is bad. </p> <p> If the person making this claim only knows of that single style of unit testing, it's natural to jump to the conclusion that all unit testing must be bad. </p> <p> That's not the case. I write most of my unit tests in a style dissimilar from the interaction-heavy, mocks-and-stubs-based style that most people use. These test have a low maintenance burden and don't cause test-induced damage. </p> <p> Unit testing is fine. </p> </div><hr> This blog is totally free, but if you like it, please consider <a href="https://blog.ploeh.dk/support">supporting it</a>. Mark Seemann https://blog.ploeh.dk/2020/08/17/unit-testing-is-fine