ploeh blog https://blog.ploeh.dk danish software design en-us Mark Seemann Tue, 26 Oct 2021 12:24:39 UTC Tue, 26 Oct 2021 12:24:39 UTC Functor variance compared to C#'s notion of variance https://blog.ploeh.dk/2021/10/25/functor-variance-compared-to-cs-notion-of-variance/ Mon, 25 Oct 2021 05:53:00 UTC <div id="post"> <p> <em>A note on C# co- and contravariance, and how it relates to functors.</em> </p> <p> This article is an instalment in <a href="/2021/09/02/contravariant-functors">an article series about contravariant functors</a>. It assumes that you've read the introduction, and a few of the examples. </p> <p> If you know your way around C# you may know that the language has its own notion of co- and contravariance. Perhaps you're wondering how it fits with contravariant functors. </p> <p> Quite well, fortunately. </p> <h3 id="1469d9fdd00f4a68b4c30a1bf81b7295"> Assignment compatibility <a href="#1469d9fdd00f4a68b4c30a1bf81b7295" title="permalink">#</a> </h3> <p> For the C# perspective on co- and contravariance, <a href="https://docs.microsoft.com/dotnet/csharp/programming-guide/concepts/covariance-contravariance">the official documentation</a> is already quite good. It starts with this example of <em>assignment compatibility</em>: </p> <blockquote> <p> <pre><span style="color:green;">//&nbsp;Assignment&nbsp;compatibility.</span> <span style="color:blue;">string</span>&nbsp;<span style="color:#1f377f;">str</span>&nbsp;=&nbsp;<span style="color:#a31515;">&quot;test&quot;</span>; <span style="color:green;">//&nbsp;An&nbsp;object&nbsp;of&nbsp;a&nbsp;more&nbsp;derived&nbsp;type&nbsp;is&nbsp;assigned&nbsp;to&nbsp;an&nbsp;object&nbsp;of&nbsp;a&nbsp;less&nbsp;derived&nbsp;type.</span> <span style="color:blue;">object</span>&nbsp;<span style="color:#1f377f;">obj</span>&nbsp;=&nbsp;str;</pre> </p> </blockquote> <p> This kind of assignment is always possible, because a <code>string</code> <em>is also already</em> an <code>object</code>. An upcast within the inheritance hierarchy is <em>always</em> possible, so C# automatically allows it. </p> <p> <a href="https://fsharp.org">F#</a>, on the other hand, doesn't. If you try to do something similar in F#, it doesn't compile: </p> <p> <pre><span style="color:blue;">let</span>&nbsp;str&nbsp;=&nbsp;<span style="color:#a31515;">&quot;test&quot;</span> <span style="color:blue;">let</span>&nbsp;obj&nbsp;:&nbsp;obj&nbsp;=&nbsp;str&nbsp;<span style="color:green;">//&nbsp;Doesn&#39;t&nbsp;compile</span></pre> </p> <p> The compiler error is: </p> <blockquote> This expression was expected to have type 'obj' but here has type 'string' </blockquote> <p> You have to explicitly use the upcast operator: </p> <p> <pre><span style="color:blue;">let</span>&nbsp;str&nbsp;=&nbsp;<span style="color:#a31515;">&quot;test&quot;</span> <span style="color:blue;">let</span>&nbsp;obj&nbsp;=&nbsp;str&nbsp;:&gt;&nbsp;obj</pre> </p> <p> When you do that, the explicit type declaration of the value is redundant, so I removed it. </p> <p> In this example, you can think of <code>:&gt;</code> as a function from <code>string</code> to <code>obj</code>: <code>string -&gt; obj</code>. In C#, the equivalent function would be <code>Func&lt;string, object&gt;</code>. </p> <p> These functions always exist for types that are properly related to each other, upcast-wise. You can think of it as a generic function <code>'a -&gt; 'b</code> (or <code>Func&lt;A, B&gt;</code>), with the proviso that <code>A</code> must be 'upcastable' to <code>B</code>: </p> <p> <img src="/content/binary/a-as-a-subtype-of-b.png" alt="Two boxes labeled 'A' and 'B with an arrow pointing from A to B."> </p> <p> In my head, I'd usually think about this as <em>A being a subtype of B</em>, but unless I explain what I mean by <em>subtyping</em>, it usually confuses people. I consider anything that can 'act as' something else a subtype. So <code>string</code> is a subtype of <code>object</code>, but I also consider <code>TimeSpan</code> a subtype of <code>IComparable</code>, because that cast is also always possible: </p> <p> <pre>TimeSpan&nbsp;<span style="color:#1f377f;">twoMinutes</span>&nbsp;=&nbsp;TimeSpan.FromMinutes(2); IComparable&nbsp;<span style="color:#1f377f;">comp</span>&nbsp;=&nbsp;twoMinutes;</pre> </p> <p> Once again, F# is only happy if you explicitly use the <code>:&gt;</code> operator: </p> <p> <pre><span style="color:blue;">let</span>&nbsp;twoMinutes&nbsp;=&nbsp;TimeSpan.FromMinutes&nbsp;2. <span style="color:blue;">let</span>&nbsp;comp&nbsp;=&nbsp;twoMinutes&nbsp;:&gt;&nbsp;IComparable</pre> </p> <p> All this is surely old hat to any .NET developer with a few months of programming under his or her belt. All the same, I want to drive home one last point (that you already know): Automatic upcast conversions are <a href="https://en.wikipedia.org/wiki/Transitive_relation">transitive</a>. Consider a class like <a href="https://docs.microsoft.com/dotnet/api/system.httpstyleuriparser">HttpStyleUriParser</a>, which is part of a small inheritance hierarchy: <code>object -&gt; UriParser -&gt; HttpStyleUriParser</code> (sic, that's how the documentation denotes the inheritance hierarchy; be careful about the arrow direction!). You can upcast an <code>HttpStyleUriParser</code> to both <code>UriParser </code> and <code>object</code>: </p> <p> <pre>HttpStyleUriParser&nbsp;<span style="color:#1f377f;">httParser</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;HttpStyleUriParser(); UriParser&nbsp;<span style="color:#1f377f;">parser</span>&nbsp;=&nbsp;httParser; <span style="color:blue;">object</span>&nbsp;<span style="color:#1f377f;">op</span>&nbsp;=&nbsp;httParser;</pre> </p> <p> Again, the same is true in F#, but you have to explicitly use the <code>:&gt;</code> operator. </p> <p> To recapitulate: C# has a built-in <em>automatic</em> conversion that upcasts. It's also built into F#, but here as an operator that you explicitly have to use. It's like an automatic function from subtype to supertype. </p> <h3 id="7d69802639da4e13aef41faf2a740c19"> Covariance <a href="#7d69802639da4e13aef41faf2a740c19" title="permalink">#</a> </h3> <p> The C# documentation continues with an example of covariance: </p> <blockquote> <p> <pre><span style="color:green;">//&nbsp;Covariance.</span> IEnumerable&lt;<span style="color:blue;">string</span>&gt;&nbsp;<span style="color:#1f377f;">strings</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;List&lt;<span style="color:blue;">string</span>&gt;(); <span style="color:green;">//&nbsp;An&nbsp;object&nbsp;that&nbsp;is&nbsp;instantiated&nbsp;with&nbsp;a&nbsp;more&nbsp;derived&nbsp;type&nbsp;argument</span> <span style="color:green;">//&nbsp;is&nbsp;assigned&nbsp;to&nbsp;an&nbsp;object&nbsp;instantiated&nbsp;with&nbsp;a&nbsp;less&nbsp;derived&nbsp;type&nbsp;argument.</span> <span style="color:green;">//&nbsp;Assignment&nbsp;compatibility&nbsp;is&nbsp;preserved.</span> IEnumerable&lt;<span style="color:blue;">object</span>&gt;&nbsp;<span style="color:#1f377f;">objects</span>&nbsp;=&nbsp;strings;</pre> </p> </blockquote> <p> Since <code>IEnumerable&lt;T&gt;</code> forms a <a href="/2018/03/22/functors">(covariant) functor</a> you can lift a function <code>Func&lt;A, B&gt;</code> to a function from <code>IEnumerable&lt;A&gt;</code> to <code>IEnumerable&lt;B&gt;</code>. Consider the above example that goes from <code>IEnumerable&lt;string&gt;</code> to <code>IEnumerable&lt;object&gt;</code>. Let's modify the diagram from the functor article: </p> <p> <img src="/content/binary/functor-diagram-for-ienumerable.png" alt="Functor diagram."> </p> <p> Since the C# compiler already knows that an automatic function (<code>:&gt;</code>) exists that converts <code>string</code> to <code>object</code>, it can <em>automatically</em> convert <code>IEnumerable&lt;string&gt;</code> to <code>IEnumerable&lt;object&gt;</code>. You don't have to call <code>Select</code> to do this. The compiler does it for you. </p> <p> How does it do that? </p> <p> It looks for a little annotation on the generic type argument. For covariant types, <a href="https://docs.microsoft.com/dotnet/csharp/programming-guide/concepts/covariance-contravariance/creating-variant-generic-interfaces">the relevant keyword</a> is <code>out</code>. And, as expected, the <code>T</code> in <a href="https://docs.microsoft.com/dotnet/api/system.collections.generic.ienumerable-1">IEnumerable&lt;T&gt;</a> is annotated with <code>out</code>: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">interface</span>&nbsp;<span style="color:#2b91af;">IEnumerable</span>&lt;<span style="color:blue;">out</span>&nbsp;<span style="color:#2b91af;">T</span>&gt;</pre> </p> <p> The same is true for <a href="https://docs.microsoft.com/dotnet/api/system.func-2">Func&lt;T, TResult&gt;</a>, which <a href="/2021/08/30/the-reader-functor">is both covariant</a> and <a href="/2021/10/04/reader-as-a-contravariant-functor">contravariant</a>: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">delegate</span>&nbsp;TResult&nbsp;<span style="color:#2b91af;">Func</span>&lt;<span style="color:blue;">in</span>&nbsp;<span style="color:#2b91af;">T</span>,&nbsp;<span style="color:blue;">out</span>&nbsp;<span style="color:#2b91af;">TResult</span>&gt;(T&nbsp;<span style="color:#1f377f;">arg</span>);</pre> </p> <p> The <code>in</code> keyword denotes contravariance, but we'll get to that shortly. </p> <p> The reason that covariance is annotated with the <code>out</code> keyword is that covariant type arguments usually sit in the return-type position. The rule is actually a little more nuanced than that, but I'll again refer you to <a href="https://reasonablypolymorphic.com">Sandy Maguire</a>'s <a href="https://www.goodreads.com/review/show/3406773267">excellent</a> book <a href="https://thinkingwithtypes.com">Thinking with Types</a> if you're interested in the details. </p> <h3 id="e409b7a8a3964385bcdffb1fb72e4251"> Contravariance <a href="#e409b7a8a3964385bcdffb1fb72e4251" title="permalink">#</a> </h3> <p> So far, so good. What about contravariance? The C# documentation continues its example: </p> <blockquote> <p> <pre><span style="color:green;">//&nbsp;Contravariance.</span> <span style="color:green;">//&nbsp;Assume&nbsp;that&nbsp;the&nbsp;following&nbsp;method&nbsp;is&nbsp;in&nbsp;the&nbsp;class:</span> <span style="color:green;">//&nbsp;static&nbsp;void&nbsp;SetObject(object&nbsp;o)&nbsp;{&nbsp;}</span> Action&lt;<span style="color:blue;">object</span>&gt;&nbsp;<span style="color:#1f377f;">actObject</span>&nbsp;=&nbsp;SetObject; <span style="color:green;">//&nbsp;An&nbsp;object&nbsp;that&nbsp;is&nbsp;instantiated&nbsp;with&nbsp;a&nbsp;less&nbsp;derived&nbsp;type&nbsp;argument</span> <span style="color:green;">//&nbsp;is&nbsp;assigned&nbsp;to&nbsp;an&nbsp;object&nbsp;instantiated&nbsp;with&nbsp;a&nbsp;more&nbsp;derived&nbsp;type&nbsp;argument.</span> <span style="color:green;">//&nbsp;Assignment&nbsp;compatibility&nbsp;is&nbsp;reversed.</span> Action&lt;<span style="color:blue;">string</span>&gt;&nbsp;<span style="color:#1f377f;">actString</span>&nbsp;=&nbsp;actObject;</pre> </p> </blockquote> <p> The <a href="https://docs.microsoft.com/dotnet/api/system.action-1">Action&lt;T&gt;</a> delegate <a href="/2021/09/06/the-command-handler-contravariant-functor">gives rise to a contravariant functor</a>. The <code>T</code> is also annotated with the <code>in</code> keyword, since the type argument sits in the input position: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">delegate</span>&nbsp;<span style="color:blue;">void</span>&nbsp;<span style="color:#2b91af;">Action</span>&lt;<span style="color:blue;">in</span>&nbsp;<span style="color:#2b91af;">T</span>&gt;(T&nbsp;<span style="color:#1f377f;">obj</span>)</pre> </p> <p> Again, let's modify the diagram from <a href="/2021/09/02/contravariant-functors">the article about contravariant functors</a>: </p> <p> <img src="/content/binary/contravariant-functor-diagram-for-action.png" alt="Contravariant functor diagram."> </p> <p> Again, since the C# compiler already knows that an automatic function exists that converts <code>string</code> to <code>object</code>, it can <em>automatically</em> convert <code>Action&lt;object&gt;</code> to <code>Action&lt;string&gt;</code>. You don't have to call <code>Contramap</code> to do this. The compiler does it for you. </p> <p> It knows that <code>Action&lt;T&gt;</code> is contravariant because it's annotated with the <code>in</code> keyword. Thus, it allows contravariant assignment. </p> <p> It all checks out. </p> <h3 id="660eb0eaa995410d891e07ec4b978ba6"> Conclusion <a href="#660eb0eaa995410d891e07ec4b978ba6" title="permalink">#</a> </h3> <p> The C# compiler understands co- and contravariance, but while it automatically supports it, it only deals with automatic conversion from subtype to supertype. Thus, for those kinds of conversions, you don't need a <code>Select</code> or <code>ContraMap</code> method. </p> <p> The functor notion of co- and contravariance is a generalisation of how the C# compiler works. Instead of relying on automatic conversions, the <code>Select</code> and <code>ContraMap</code> methods enable you to supply arbitrary conversion functions. </p> <p> <strong>Next:</strong> <a href="/2018/01/08/software-design-isomorphisms">Software design isomorphisms</a>. </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/2021/10/25/functor-variance-compared-to-cs-notion-of-variance Readability verification https://blog.ploeh.dk/2021/10/18/readability-verification/ Mon, 18 Oct 2021 07:37:00 UTC <div id="post"> <p> <em>How do you know whether the code you wrote is readable?</em> </p> <p> In a recent Twitter thread about pair and mob programming, <a href="https://dannorth.net">Dan North</a> observes: </p> <blockquote> <p> "That’s the tricky problem I was referring to. If you think you can write code that other humans can understand, without collaborating or calibrating with other humans, assuming that an after-the-fact check will always be affirmative, then you are a better programmer than me." </p> <footer><cite><a href="https://twitter.com/tastapod/status/1448184718122487811">Dan North</a></cite></footer> </blockquote> <p> I neither think that I'm a better programmer than Dan nor that, without collaboration, I can write code that other humans can understand. That's why I'd like someone else to <em>review</em> my code. Not write it together with me, but <em>read it</em> after I've written it. </p> <h3 id="b9a6a0093d0c4c2193c4e39d519ef582"> Advantages of pair and ensemble programming <a href="#b9a6a0093d0c4c2193c4e39d519ef582" title="permalink">#</a> </h3> <p> Pair programming and ensemble (AKA <em>mob</em>) programming is an efficient way to develop software. It works for lots of people. I'm not insisting otherwise. </p> <p> By working together, you can pool skills. Imagine working on a feature for a typical web application. This involves user interface, business logic, data access, and possibly other things as well. Few people are experts in all those areas. Personally, I'm comfortable around business logic and data access, but know little about web front-end development. It's great to have someone else's expertise to draw on. </p> <p> By working together in real time, you avoid hand-offs. If I had to help implementing a feature in an asynchronous manner, I'd typically implement domain logic and data access in a REST API, then tell a front-end expert that the API is ready. This way of working <a href="/2020/03/16/conways-law-latency-versus-throughput">introduces wait times into the process</a>, and may also cause rework if it turns out that the way I designed the API doesn't meet the requirements of the front end. </p> <p> Real-time collaboration addresses some of these concerns. It also improves code ownership. In <a href="/code-that-fits-in-your-head">Code That Fits in Your Head</a>, I quote <a href="https://twitter.com/birgitta410">Birgitta Böckeler</a> and <a href="https://sssggr.net">Nina Siessegger</a>: </p> <blockquote> <p> "Consistent pairing makes sure that every line of code was touched or seen by at least 2 people. This increases the chances that anyone on the team feels comfortable changing the code almost anywhere. It also makes the codebase more consistent than it would be with single coders only. </p> <p> "Pair programming alone does not guarantee you achieve collective code ownership. You need to make sure that you also rotate people through different pairs and areas of the code, to prevent knowledge silos." </p> <footer><cite>Birgitta Böckeler and Nina Siessegger, <a href="https://martinfowler.com/articles/on-pair-programming.html">On Pair Programming</a></cite></footer> </blockquote> <p> With mob programming, you take many of these advantages to the next level. If you include a domain expert in the group, you can learn about what the organisation actually needs as you're developing a feature. If you include specialised testers, they may see edge cases or error modes you didn't think of. If you include UX experts, you'll have a chance to develop software that users can actually figure out how to use. </p> <p> There are lots of benefits to be had from pair and ensemble programming. In <a href="/code-that-fits-in-your-head">Code That Fits in Your Head</a> I recommend that you try it. I've recommended it to my customers. I've had good experiences with it myself: </p> <blockquote> <p> "I’ve used [mob programming] with great success as a programming coach. In one engagement, I spent two to three days a week with a few other programmers, helping them apply test-driven development practices to their production code bases. After a few months of that, I went on vacation. Meanwhile those programmers kept going with test-driven development. Mob programming is great for knowledge transfer." </p> <footer><cite><a href="/code-that-fits-in-your-head">Code That Fits in Your Head</a></cite></footer> </blockquote> <p> <a href="/2021/10/11/serendipity-driven-development">I don't, however, think that it's a one-size-fits-all solution</a>. </p> <h3 id="c57bfb2342d2437596ff90a13fb29c44"> The curse of knowledge <a href="#c57bfb2342d2437596ff90a13fb29c44" title="permalink">#</a> </h3> <p> While outlining the advantages of pair and ensemble programming, I didn't mention readability. I don't see how those ways of working address the problem of writing readable code. </p> <p> I've reviewed code written by pairs, and it was neither more nor less readable than code written by a single programmer. I think that there's an easy-to-understand reason for this. It relates to the <em>curse of knowledge:</em> </p> <blockquote> <p> "In 1990, Elizabeth Newton earned a Ph.D. in psychology at Stanford by studying a simple game in which she assigned people to one of two roles: “tappers” or “listeners.” Tappers received a list of twenty-five well-known songs, such as “Happy Birthday to You” and “The Star-Spangled Banner.” Each tapper was asked to pick a song and tap out the rhythm to a listener (by knocking on a table). The listener’s job was to guess the song, based on the rhythm being tapped. (By the way, this experiment is fun to try at home if there’s a good “listener” candidate nearby.) </p> <p> "The listener’s job in this game is quite difficult. Over the course of Newton’s experiment, 120 songs were tapped out. Listeners guessed only 2.5 percent of the songs: 3 out of 120. </p> <p> "But here’s what made the result worthy of a dissertation in psychology. Before the listeners guessed the name of the song, Newton asked the tappers to predict the odds that the listeners would guess correctly. They predicted that the odds were 50 percent. </p> <p> "The tappers got their message across 1 time in 40, but they thought they were getting their message across 1 time in 2. Why? </p> <p> "When a tapper taps, she is <em>hearing the song in her head</em>. Go ahead and try it for yourself—tap out “The Star-Spangled Banner.” It’s impossible to avoid hearing the tune in your head. Meanwhile, the listeners can’t hear that tune—all they can hear is a bunch of disconnected taps, like a kind of bizarre Morse Code. </p> <p> "In the experiment, tappers are flabbergasted at how hard the listeners seem to be working to pick up the tune. <em>Isn’t the song obvious?</em> The tappers’ expressions, when a listener guesses “Happy Birthday to You” for “The Star-Spangled Banner,” are priceless: <em>How could you be so stupid?</em> </p> <p> "It’s hard to be a tapper. The problem is that tappers have been given knowledge (the song title) that makes it impossible for them to imagine what it’s like to <em>lack</em> that knowledge. When they’re tapping, they can’t imagine what it’s like for the listeners to hear isolated taps rather than a song. This is the Curse of Knowledge. Once we know something, we find it hard to imagine what it was like not to know it. Our knowledge has “cursed” us. And it becomes difficult for us to share our knowledge with others, because we can’t readily re-create our listeners’ state of mind. </p> <p> "The tapper/listener experiment is reenacted every day across the world. The tappers and listeners are CEOs and frontline employees, teachers and students, politicians and voters, marketers and customers, writers and readers. All of these groups rely on ongoing communication, but, like the tappers and listeners, they suffer from enormous information imbalances. When a CEO discusses “unlocking shareholder value,” there is a tune playing in her head that the employees can’t hear." </p> <footer><cite>Chip Heath and Dan Heath, <a href="https://amzn.to/3viu26j">Made to Stick</a></cite></footer> </blockquote> <p> When you're writing code, you're a <em>tapper</em>. As you're writing the code, you know <em>why</em> you are writing it the way you do, you know what you've already tried that didn't work, the informal requirements that someone told you about over the water cooler, etc. </p> <p> Why should pair or ensemble programming change that? </p> <blockquote> <p> "One of the roles of a PR is to verify that someone who didn't write the new code can understand it. </p> <p> "The constant communication of pair programming can result in code only that pair understands. Does a book with two authors not need an editor?" </p> <footer><cite><a href="https://twitter.com/laurence/status/1448485971289260039">Laurence Gonsalves</a></cite></footer> </blockquote> <p> So, how do you verify that code is readable? </p> <h3 id="77efc0b4e41a4f5597ff6e072187698f"> Readability <a href="#77efc0b4e41a4f5597ff6e072187698f" title="permalink">#</a> </h3> <p> I often forget to remind the reader that discussions like this one, about software productivity, mostly rely on <a href="https://martinfowler.com/bliki/AnecdotalEvidence.html">anecdotal evidence</a>. There's <a href="/2020/05/25/wheres-the-science">little scientific evidence about these topics</a>. The ensuing discussions <a href="/2020/10/12/subjectivity">tend to rely on subjectivity</a>, and so, ultimately, does this one. </p> <p> In <a href="/code-that-fits-in-your-head">Code That Fits in Your Head</a>, I suggest heuristics for writing readable code, but ultimately, the only reliable test of readability that I can think of is simple: </p> <p> Ask someone else to <em>read</em> the code. </p> <p> That's what a code review ought to do. Anyone who took part in writing the code is a <em>tapper</em>. After I've written code, I'm a <em>tapper</em>. I'm in no position to evaluate whether the code I just wrote is readable. </p> <p> You need a <em>listener</em> (or, here: a <em>reader</em>) to evaluate whether or not sufficient information came across. </p> <p> I agree with Dan North that I need other humans to collaborate and calibrate. I just disagree that people who write code are in a position to evaluate whether the code is readable (and thereby can sustain the business in the long run). </p> <h3 id="8655f1951b6a414f82d38435aa317e5c"> Rejection <a href="#8655f1951b6a414f82d38435aa317e5c" title="permalink">#</a> </h3> <p> What happens, then, if I submit a pull request that the reviewer finds unreadable? </p> <p> The reviewer should either suggest improvements or decline the pull request. </p> <p> I can tell from Dan's tweet that he's harbouring a common misconception about the pull request review process: </p> <blockquote> <p> "assuming that an after-the-fact check will always be affirmative" </p> <footer><cite><a href="https://twitter.com/tastapod/status/1448184718122487811">Dan North</a></cite></footer> </blockquote> <p> No, I don't assume that my pull requests always pass muster. That's also the reason that <a href="/2015/01/15/10-tips-for-better-pull-requests">pull requests should be small</a>. They should be small enough that you can afford to have them rejected. </p> <p> I'm currently helping one of my clients with some code. I add some code and send an <a href="/2021/06/21/agile-pull-requests">agile pull request</a>. </p> <p> Several times in the last month, my pull requests have remained unmerged. In none of the cases, actually, have the reviewer outright rejected the pull request. He just started asking questions, then we had a short debate over GitHub, and then I came to the conclusion that I should close the pull request myself. </p> <p> No drama, just feedback. </p> <h3 id="ad0609e523b8401fbab92dc0e90c44d5"> Conclusion <a href="#ad0609e523b8401fbab92dc0e90c44d5" title="permalink">#</a> </h3> <p> How do you verify that code is readable? </p> <p> I can't think of anything better than asking someone else to read the code. </p> <p> Obviously, we shouldn't ask random strangers about readability. We should ask team members to review code. One implication of collective code ownership is that when a team member accepts a pull request, he or she is also taking on the shared responsibility of maintaining that code. As I write in <a href="/code-that-fits-in-your-head">Code That Fits in Your Head</a>, a fundamental criterion for evaluating a pull request is: <em>Will I be okay maintaining this?</em> </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/2021/10/18/readability-verification Serendipity-driven development https://blog.ploeh.dk/2021/10/11/serendipity-driven-development/ Mon, 11 Oct 2021 05:54:00 UTC <div id="post"> <p> <em>How much does providence drive thought leadership?</em> </p> <p> I regularly listen to podcasts. Many podcast episodes are structured around an interview with a guest. A common interview technique (and icebreaker, I suppose) is to ask the guest how he or she became a voice in the field that's the topic for the episode. Surprisingly often, the answer is that it's basically a happy coincidence. He or she was young, had no specific plans, but tried a few things until eventually becoming enamoured with a particular topic. </p> <p> That's not just technology podcasts. I also listen to interviews with scientists and artists on a variety of topics. </p> <p> A <em>few</em> people are driven from an early age to study something specific. Most, it seems, are not. I'm no exception. I had a false start as an economist, but was so extremely fortunate that the 1990's were such a boom decade of IT that you could get a job in the field if you could spell HTML. </p> <p> It seems to me that it's a common (Western) experience for a young person to start adult life without much of a plan, but an unrealised responsiveness to certain stimuli. As a young person, you may have a general notion of your own inclinations, so you seek out certain activities and avoid others. Still, you may not really know yourself. </p> <p> I didn't know myself at 18. After <a href="https://en.wikipedia.org/wiki/Gymnasium_(school)">gymnasium</a> (~ high school) in 1989 my best friend started at computer science at the University of Copenhagen. I had no experience with computers and thought it sounded incredibly dry. I wanted to be a rock star or a comic book artist in the French-Belgian style. </p> <p> In order to get an education, though, I started at economics at the University of Copenhagen. Talk about a dry subject. </p> <p> Well, at least I learned game theory, n-dimensional topology, optimal control theory, chaos theory, and some other branches of mathematics, so perhaps the years weren't entirely wasted... </p> <p> Computers weren't on my radar, but I soon realised that it'd be practical to buy a PC in order to write my thesis. </p> <p> So, I bought one and soon found the computer much more interesting than economics. </p> <p> You may not realise that you'll love something until you try it. </p> <h3 id="1909691de650477189ee7d41a49cf22e"> Thought leadership <a href="#1909691de650477189ee7d41a49cf22e" title="permalink">#</a> </h3> <p> I recently wrote <a href="/2021/08/09/am-i-stuck-in-a-local-maximum">an article about the cognitive dissonance I felt</a> when interacting with many of my heroes. The <a href="https://twitter.com/ploeh/status/1424624134030602241">ensuing Twitter discussion</a> was enlightening. </p> <p> Many of my heroes balk at being called heroes or thought leaders, but I agree with <a href="https://hillelwayne.com/">Hillel Wayne</a>: </p> <blockquote> <p> "That's why, incidentally, "thought leaders" have so much weight in our industry. We like to make fun of them, but fact of the matter is that the Thought Leaders are the ones actually trying to communicate their techniques. </p> <p> "(That's why I want to unironically be a Thought Leader)" </p> <footer><cite><a href="https://twitter.com/hillelogram/status/1445435617047990273">Hillel Wayne</a></cite></footer> </blockquote> <p> I've been called a <em>though leader</em> a few times already, and like Hillel Wayne, I gratefully accept the label. </p> <p> There's <a href="/2020/05/25/wheres-the-science">little scientific evidence about what works in software development</a>, and most innovation happens behind closed doors. Thought leaders are those that observe and share the innovation with the rest of the world. </p> <p> I follow though leaders on Twitter, listen to podcasts on which they are guests, and <a href="https://www.goodreads.com/author/show/4383188.Mark_Seemann">read books</a>. </p> <p> I learned a lot from the discussion related to <a href="/2021/08/09/am-i-stuck-in-a-local-maximum">my article about feeling stuck</a>. I feel that I better understand why opposing views exist. Much has to do with context and nuance, two important factors easily lost on Twitter. </p> <p> I also think that personal experience plays a big role. Thought leaders share <a href="https://martinfowler.com/bliki/AnecdotalEvidence.html">anecdotal evidence</a>. As is also the case in science and business, we tend to share our successes. </p> <p> What feels like a success is what resonates with us. </p> <p> It's like the serendipity when you're young and finally encounter something that feels compatible with you. Should we call it serendipity-driven development? </p> <p> A couple of examples may be in order. </p> <h3 id="d4fb5cf60f584d7e8de3e0fcbcb902a7"> Pair programming <a href="#d4fb5cf60f584d7e8de3e0fcbcb902a7" title="permalink">#</a> </h3> <p> While I now have an increased awareness of what motivates other thought leaders, I still often disagree. It wouldn't be unnatural if our personal experiences with particular practices influence our positions. </p> <p> <img src="/content/binary/pair-programming.jpg" alt="Pair programming."> </p> <p> One such example is pair programming. In an interview (sorry, can't remember which) Robert C. Martin told how he found test-driven development dumb until either Kent Beck or Ward Cunningham paired with him to show him the light. Recently, <a href="http://www.exampler.com/">Brian Marick</a> shared a similar experience: </p> <blockquote> <p> "When I first heard of XP, I thought pair programming was the *second* stupidest idea I'd ever heard. The stupidest was everyone working in the same team room (*not* an "open office"). But..." </p> <footer><a href="https://twitter.com/marick/status/1446618423312715779">Brian Marick</a></footer> </blockquote> <p> This seems to be a common experience with pair programming. Most people dislike it until they have actually tried it. </p> <p> Well, I've tried both pair programming and ensemble (AKA mob) programming, and I don't <em>like</em> it. </p> <p> That's all: It's my <em>preference</em> - not any sort of objective truth. What little scientific evidence we can find in our field does seem to indicate that pair programming is efficient. In my book <a href="/code-that-fits-in-your-head">Code That Fits in Your Head</a> I've put aside my dislike to instead endorse pair and ensemble programming as something you should consider. </p> <p> There's enough evidence (anecdotal and otherwise) that it works well for many people, so give it a try. </p> <p> I also use it myself. While I find it exhausting, I find ensemble programming incredibly well-suited to knowledge transfer. I've used it to great success when teaching development organisations new ways of doing things. </p> <p> Even with the nicest people in the room, however, the process drains me. One reason is probably that I've a strong introvert side to my personality. </p> <p> Another perspective to consider is the role you assume. </p> <p> A common theme when people share stories of how they saw the light of pair programming is that they learned it from luminaries. If Kent Beck or Ward Cunningham personally tutors you, it's easy to see how it could feel like a revelation. </p> <p> On the other hand, <a href="https://en.wikipedia.org/wiki/Survivorship_bias">survivorship bias</a> could be at work. Perhaps Kent Beck showed pair programming and test-driven development to many people who never caught the bug, and thus never discussed it in public. </p> <p> In my own experience, I mostly taught myself test-driven development long before I tried pair programming, and I'd heard about pair programming long before I tried it. When I did try it, I wasn't the person being taught. I was in the role of the teacher. </p> <p> Teaching is both a satisfying and exhausting activity. I do consider myself a teacher of sorts, but I prefer to write. Whenever I've taught a workshop, given a lecture, or consulted, I'm always left happy but exhausted. It's really hard work. </p> <p> So is pair programming, in my experience. Efficient, most likely, but hard work. I can't muster much enthusiasm about it. </p> <h3 id="4b17192456614ca28a4e69cb5f86e23b"> REST <a href="#4b17192456614ca28a4e69cb5f86e23b" title="permalink">#</a> </h3> <p> Another topic about which I regularly disagree with others is <a href="https://en.wikipedia.org/wiki/Representational_state_transfer">REST</a>. Just try to find some of my articles <a href="/tags/#REST-ref">tagged REST</a> and read the comments. </p> <p> For the record, the crowd who disagrees with me is a completely different set of people than those with whom I disagree about pair programming and other agile practices. </p> <p> The people who disagree with me about REST may be right, and I could be wrong. My views on REST are strongly influenced by early experience. Do be aware of the pattern. </p> <p> In early 2012 a client asked for my help designing a stable API. The customer didn't ask me to design a REST API - in fact, I think he had a <a href="https://en.wikipedia.org/wiki/SOAP">SOAP</a> API in mind, but he was open to other options. One requirement was clear, though: The API had to be exceptionally stable and backwards compatible. There was a reason for this. </p> <p> My customer's business was to provide a consumer-grade online service. They were currently talking to a hardware producer who'd include support for the service in consumer hardware. Imagine thousands (perhaps millions) of devices sitting in people's homes, using the online service via the API we were about to design. </p> <p> Even if the hardware producer were to enable firmware upgrades of the devices, there'd be no way we could roll out new versions of client software in a controlled way. This meant that backwards compatibility was a top priority. </p> <p> I'd recently learned enough about REST to see the opportunity, so I suggested it as a principle for designing APIs that could evolve without breaking backwards compatibility. </p> <p> The resulting REST API was a success, and I worked with that client for many years on other projects. </p> <p> This experience clearly shaped my view on REST. To me, the major benefit of REST is the ability to design evolvable APIs without breaking changes. It does work best, however, if you design <a href="https://martinfowler.com/articles/richardsonMaturityModel.html">level 3 REST APIs</a>. </p> <p> People use HTTP APIs for all sorts of other reasons. Perhaps the driving factor isn't evolvability, but rather interoperability. Perhaps they're developing <a href="https://samnewman.io/patterns/architectural/bff/">backends for frontends</a> or APIs strictly for internal use in an organisation. In some scenarios you can easier schedule updates of clients to coincide with updates to the API, in which case backwards compatibility is less of a concern. </p> <p> Another concern about API design is <a href="https://thoughtbot.com/blog/who-is-empowered-by-your-design">who's empowered by your design</a>. It seems fair to say that a level 2 REST API is an easier sell. To many client developers, that's all they've ever encountered - they've never seen a level 3 REST API. </p> <p> I readily admit that a level 3 REST API puts an additional up-front burden on client developers. Such a design is a long game. If the API is active for many years, such investments are likely to pay off, while it may not be worthwhile in the short term. It could even hurt initial adoption, so it's not a one-size-fits-all architectural choice. </p> <p> In the context of thought leadership, however, my point is that I acknowledge that my view on REST, too, is flavoured by initial personal success. </p> <h3 id="f6e7da07a61340ef9f1617cb5fb19071"> Conclusion <a href="#f6e7da07a61340ef9f1617cb5fb19071" title="permalink">#</a> </h3> <p> I think it's natural to latch on to certain practices via serendipity, You go through life without being aware of a thing that turns out to be highly compatible with your preferences in a given context. Until you one day <em>do</em> encounter it, and it changes your life. </p> <p> I consider this only human. It's certainly happened to me multiple times, and I'd be surprised if it doesn't happen to others. </p> <p> Perhaps the people extolling the virtues of pair programming had great initial experiences that they've managed to carry forward. For me, the experience has been another. </p> <p> Likewise, I had an initial positive experience with REST that surely influenced my position on its virtues. Other people could have had a negative experience, and naturally protest against my ideas. There's nothing wrong with that. </p> <blockquote> <p> "Only a crisis - actual or perceived - produces real change. When that crisis occurs, the actions that are taken depend on the ideas that are lying around. That, I believe, is our basic function: to develop alternatives to existing policies, to keep them alive and available until the politically impossible becomes the politically inevitable" </p> <footer><a href="https://amzn.to/3BsIqLG">Milton Friedman</a></footer> </blockquote> <p> Thought leadership strikes me as similar to Friedman's ideas on policy alternatives. I don't see my role as an <em>enforcer</em> of ideas. I write in order to keep certain ideas alive, in the hope that one day, someone picks them up and uses them. </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/2021/10/11/serendipity-driven-development Reader as a contravariant functor https://blog.ploeh.dk/2021/10/04/reader-as-a-contravariant-functor/ Mon, 04 Oct 2021 05:47:00 UTC <div id="post"> <p> <em>Any function gives rise to a contravariant functor. An article for object-oriented programmers.</em> </p> <p> This article is an instalment in <a href="/2021/09/02/contravariant-functors">an article series about contravariant functors</a>. It assumes that you've read the introduction. In the <a href="/2021/09/06/the-command-handler-contravariant-functor">first example article</a>, you saw how the Command Handler pattern gives rise to a contravariant functor. <a href="/2021/09/09/the-specification-contravariant-functor">The next article</a> gave another example based on predicates. </p> <p> In the <a href="/2021/09/02/contravariant-functors">overview article</a> I also mentioned that equivalence and comparison form contravariant functors. Each can be described with an interface, or just function syntax. Let's put them in a table to compare them: </p> <p> <table border="1"> <thead> <tr> <th><em>Name</em></th> <th><em>C# method signature</em></th> <th><em>C# delegate(s)</em></th> <th><em>Haskell type(s)</em></th> </tr> </thead> <tbody> <tr> <td>Command Handler</td> <td><code><span style="color:blue;">void</span>&nbsp;<span style="color:#74531f;">Execute</span>(TCommand&nbsp;<span style="color:#1f377f;">command</span>);</code></td> <td><code>Action&lt;TCommand&gt;</code></td> <td><code>a -&gt; ()</code><br/><code>a -&gt; IO ()</code></td> </tr> <tr> <td>Specification</td> <td><code><span style="color:blue;">bool</span>&nbsp;<span style="color:#74531f;">IsSatisfiedBy</span>(T&nbsp;<span style="color:#1f377f;">candidate</span>);</code></td> <td><code>Predicate&lt;T&gt;</code><br/><code>Func&lt;T, bool&gt;</code></td> <td><code>a -&gt; Bool</code></td> </tr> <tr> <td>Equivalence</td> <td><code><span style="color:blue;">bool</span>&nbsp;<span style="color:#74531f;">Equals</span>(T&nbsp;<span style="color:#1f377f;">x</span>,&nbsp;T&nbsp;<span style="color:#1f377f;">y</span>);</code></td> <td><code>Func&lt;T, T, bool&gt;</code></td> <td><code>a -&gt; a -&gt; Bool</code></td> </tr> <tr> <td>Comparison</td> <td><code><span style="color:blue;">int</span>&nbsp;<span style="color:#74531f;">Compare</span>(T&nbsp;<span style="color:#1f377f;">x</span>,&nbsp;T&nbsp;<span style="color:#1f377f;">y</span>);</code></td> <td><code>Func&lt;T, T, int&gt;</code></td> <td><code>a -&gt; a -&gt; Ordering</code></td> </tr> </tbody> </table> </p> <p> In some cases, there's more than one possible representation. For example, in C# <a href="https://docs.microsoft.com/dotnet/api/system.predicate-1">Predicate</a> is isomorphic to <code>Func&lt;T, bool&gt;</code>. When it comes to the <a href="https://www.haskell.org">Haskell</a> representation of a Command Handler, the 'direct' translation of <code>Action&lt;T&gt;</code> is <code>a -&gt; ()</code>. In (Safe) Haskell, however, a function with that type is always a no-op. More realistically, a 'handler' function would have the type <code>a -&gt; IO ()</code> in order to allow side effects to happen. </p> <p> Do you notice a pattern? </p> <h3 id="920ac139cb1449789dac402d3e05c368"> Input variance <a href="#920ac139cb1449789dac402d3e05c368" title="permalink">#</a> </h3> <p> There's a pattern emerging from the above table. Notice that in all the examples, the function types are generic (AKA <em>parametrically polymorphic</em>) in their <em>input</em> types. </p> <p> This turns out to be part of a general rule. The actual rule is a little more complicated than that. I'll recommend <a href="https://reasonablypolymorphic.com">Sandy Maguire</a>'s <a href="https://www.goodreads.com/review/show/3406773267">excellent</a> book <a href="https://thinkingwithtypes.com">Thinking with Types</a> if you're interested in the details. </p> <p> For first-order functions, you can pick and fix <em>any</em> type as the return type and let the input type(s) vary: that function will give rise to a contravariant functor. </p> <p> In the above table, various handlers fix <code>void</code> (which is <a href="/2018/01/15/unit-isomorphisms">isomorphic to <em>unit</em></a> (<code>()</code>) as the output type and let the input type vary. Both Specification and Equivalence fix <code>bool</code> as the output type, and Comparison fix <code>int</code> (or, in Haskell, the more sane type <code>Ordering</code>), and allow the input type to vary. </p> <p> You can pick any other type. If you fix it as <em>the</em> output type for a function and let the input vary, you have the basis for a contravariant functor. </p> <h3 id="11651dbe49d04a6989c45fc52744ebf8"> Reader <a href="#11651dbe49d04a6989c45fc52744ebf8" title="permalink">#</a> </h3> <p> Consider this <code>IReader</code> interface: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">interface</span>&nbsp;<span style="color:#2b91af;">IReader</span>&lt;<span style="color:#2b91af;">R</span>,&nbsp;<span style="color:#2b91af;">A</span>&gt; { &nbsp;&nbsp;&nbsp;&nbsp;A&nbsp;<span style="color:#74531f;">Run</span>(R&nbsp;<span style="color:#1f377f;">environment</span>); }</pre> </p> <p> If you fix the environment type <code>R</code> and let the output type <code>A</code> vary, <a href="/2021/08/30/the-reader-functor">you have a (covariant) functor</a>. If, on the other hand, you fix the <em>output</em> type <code>A</code> and allow the input type <code>R</code> to vary, you can have yourself a contravariant functor: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">static</span>&nbsp;IReader&lt;R1,&nbsp;A&gt;&nbsp;<span style="color:#74531f;">ContraMap</span>&lt;<span style="color:#2b91af;">R</span>,&nbsp;<span style="color:#2b91af;">R1</span>,&nbsp;<span style="color:#2b91af;">A</span>&gt;( &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">this</span>&nbsp;IReader&lt;R,&nbsp;A&gt;&nbsp;<span style="color:#1f377f;">reader</span>, &nbsp;&nbsp;&nbsp;&nbsp;Func&lt;R1,&nbsp;R&gt;&nbsp;<span style="color:#1f377f;">selector</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;<span style="color:blue;">new</span>&nbsp;FuncReader&lt;R1,&nbsp;A&gt;(<span style="color:#1f377f;">r</span>&nbsp;=&gt;&nbsp;reader.Run(selector(r))); }</pre> </p> <p> As an example, you may have this (rather unwarranted) interface implementation: </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;">MinutesReader</span>&nbsp;:&nbsp;IReader&lt;<span style="color:blue;">int</span>,&nbsp;TimeSpan&gt; { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;TimeSpan&nbsp;<span style="color:#74531f;">Run</span>(<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">environment</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;TimeSpan.FromMinutes(environment); &nbsp;&nbsp;&nbsp;&nbsp;} }</pre> </p> <p> You can fix the output type to <code>TimeSpan</code> and let the input type vary using the <code>ContraMap</code> functions: </p> <p> <pre>[Fact] <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">void</span>&nbsp;<span style="color:#74531f;">WrappedContravariantExample</span>() { &nbsp;&nbsp;&nbsp;&nbsp;IReader&lt;<span style="color:blue;">int</span>,&nbsp;TimeSpan&gt;&nbsp;<span style="color:#1f377f;">r</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;MinutesReader(); &nbsp;&nbsp;&nbsp;&nbsp;IReader&lt;<span style="color:blue;">string</span>,&nbsp;TimeSpan&gt;&nbsp;<span style="color:#1f377f;">projected</span>&nbsp;=&nbsp;r.ContraMap((<span style="color:blue;">string</span>&nbsp;<span style="color:#1f377f;">s</span>)&nbsp;=&gt;&nbsp;<span style="color:blue;">int</span>.Parse(s)); &nbsp;&nbsp;&nbsp;&nbsp;Assert.Equal(<span style="color:blue;">new</span>&nbsp;TimeSpan(0,&nbsp;21,&nbsp;0),&nbsp;projected.Run(<span style="color:#a31515;">&quot;21&quot;</span>)); }</pre> </p> <p> When you <code>Run</code> the <code>projected</code> reader with the input string <code>"21"</code>, the <code>ContraMap</code> function first calls the <code>selector</code>, which (in this case) parses <code>"21"</code> to the integer <code>21</code>. It then calls <code>Run</code> on the 'original' <code>reader</code> with the value <code>21</code>. Since the 'original' <code>reader</code> is a <code>MinutesReader</code>, the output is a <code>TimeSpan</code> value that represents 21 minutes. </p> <h3 id="d147d424c6de412d9ad83cf659812ef6"> Raw functions <a href="#d147d424c6de412d9ad83cf659812ef6" title="permalink">#</a> </h3> <p> As was also the case when I introduced the Reader (covariant) functor, the <code>IReader</code> interface is just a teaching device. You don't need the interface in order to turn first-order functions into contravariant functors. It works on raw functions too: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">static</span>&nbsp;Func&lt;R1,&nbsp;A&gt;&nbsp;<span style="color:#74531f;">ContraMap</span>&lt;<span style="color:#2b91af;">R</span>,&nbsp;<span style="color:#2b91af;">R1</span>,&nbsp;<span style="color:#2b91af;">A</span>&gt;(<span style="color:blue;">this</span>&nbsp;Func&lt;R,&nbsp;A&gt;&nbsp;<span style="color:#1f377f;">func</span>,&nbsp;Func&lt;R1,&nbsp;R&gt;&nbsp;<span style="color:#1f377f;">selector</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;<span style="color:#1f377f;">r</span>&nbsp;=&gt;&nbsp;func(selector(r)); }</pre> </p> <p> In the following I'm going to dispense with the <code>IReader</code> interface and instead work with raw functions. </p> <h3 id="ad09f6dd9b3542b4ba8c01a01baa6afa"> Identity law <a href="#ad09f6dd9b3542b4ba8c01a01baa6afa" title="permalink">#</a> </h3> <p> A <code>ContraMap</code> method with the right signature isn't enough to be a contravariant functor. It must also obey the contravariant functor laws. As usual, it's proper computer-science work to actually prove this, but you can write some tests to demonstrate the identity law for functions. In this article, you'll see parametrised tests written with <a href="https://xunit.net">xUnit.net</a>. First, the identity law: </p> <p> <pre>[Theory] [InlineData(42)] [InlineData(1337)] [InlineData(2112)] [InlineData(90125)] <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">void</span>&nbsp;<span style="color:#74531f;">ContravariantIdentityLaw</span>(<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">input</span>) { &nbsp;&nbsp;&nbsp;&nbsp;Func&lt;<span style="color:blue;">int</span>,&nbsp;<span style="color:blue;">string</span>&gt;&nbsp;<span style="color:#1f377f;">f</span>&nbsp;=&nbsp;<span style="color:#1f377f;">i</span>&nbsp;=&gt;&nbsp;i.ToString(); &nbsp;&nbsp;&nbsp;&nbsp;Func&lt;<span style="color:blue;">int</span>,&nbsp;<span style="color:blue;">string</span>&gt;&nbsp;<span style="color:#1f377f;">actual</span>&nbsp;=&nbsp;f.ContraMap((<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">i</span>)&nbsp;=&gt;&nbsp;i); &nbsp;&nbsp;&nbsp;&nbsp;Assert.Equal(f(input),&nbsp;actual(input)); }</pre> </p> <p> Here I'm using the <code>(int i) =&gt; i</code> lambda expression as the identity function. As usual, you can't easily compare functions for equality, so you'll have to call them to verify that they produce the same output, which they do. </p> <h3 id="2e1d05c3d61c4773820dbbaec5967565"> Composition law <a href="#2e1d05c3d61c4773820dbbaec5967565" title="permalink">#</a> </h3> <p> Like the above example, you can also write a parametrised test that demonstrates that <code>ContraMap</code> obeys the composition law for contravariant functors: </p> <p> <pre>[Theory] [InlineData(4.2)] [InlineData(13.37)] [InlineData(21.12)] [InlineData(901.25)] <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">void</span>&nbsp;<span style="color:#74531f;">ContravariantCompositionLaw</span>(<span style="color:blue;">double</span>&nbsp;<span style="color:#1f377f;">input</span>) { &nbsp;&nbsp;&nbsp;&nbsp;Func&lt;<span style="color:blue;">string</span>,&nbsp;<span style="color:blue;">int</span>&gt;&nbsp;<span style="color:#1f377f;">h</span>&nbsp;=&nbsp;<span style="color:#1f377f;">s</span>&nbsp;=&gt;&nbsp;s.Length; &nbsp;&nbsp;&nbsp;&nbsp;Func&lt;<span style="color:blue;">double</span>,&nbsp;TimeSpan&gt;&nbsp;<span style="color:#1f377f;">f</span>&nbsp;=&nbsp;<span style="color:#1f377f;">i</span>&nbsp;=&gt;&nbsp;TimeSpan.FromSeconds(i); &nbsp;&nbsp;&nbsp;&nbsp;Func&lt;TimeSpan,&nbsp;<span style="color:blue;">string</span>&gt;&nbsp;<span style="color:#1f377f;">g</span>&nbsp;=&nbsp;<span style="color:#1f377f;">ts</span>&nbsp;=&gt;&nbsp;ts.ToString(); &nbsp;&nbsp;&nbsp;&nbsp;Assert.Equal( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;h.ContraMap((<span style="color:blue;">double</span>&nbsp;<span style="color:#1f377f;">d</span>)&nbsp;=&gt;&nbsp;g(f(d)))(input), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;h.ContraMap(g).ContraMap(f)(input)); }</pre> </p> <p> This test defines two local functions, <code>f</code> and <code>g</code>. Once more, you can't directly compare methods for equality, so instead you have to invoke both compositions to verify that they return the same <code>int</code> value. </p> <p> They do. </p> <h3 id="392a90e5e3204d459dae673d23be92e1"> Isomorphisms <a href="#392a90e5e3204d459dae673d23be92e1" title="permalink">#</a> </h3> <p> Now that we understand that any first-order function is contravariant, we can see that the previous examples of predicates, handlers, comparisons, and equivalences are really just special cases of the Reader contravariant functor. </p> <p> For example, <code>Predicate&lt;T&gt;</code> is trivially isomorphic to <code>Func&lt;T, bool&gt;</code>. Still, it might be worthwhile to flesh out how other translations might work: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">static</span>&nbsp;ISpecification&lt;T&gt;&nbsp;<span style="color:#74531f;">AsSpecification</span>&lt;<span style="color:#2b91af;">T</span>&gt;(<span style="color:blue;">this</span>&nbsp;Predicate&lt;T&gt;&nbsp;<span style="color:#1f377f;">predicate</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;<span style="color:blue;">new</span>&nbsp;DelegateSpecificationAdapter&lt;T&gt;(predicate); } <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">static</span>&nbsp;ISpecification&lt;T&gt;&nbsp;<span style="color:#74531f;">AsSpecification</span>&lt;<span style="color:#2b91af;">T</span>&gt;(<span style="color:blue;">this</span>&nbsp;Func&lt;T,&nbsp;<span style="color:blue;">bool</span>&gt;&nbsp;<span style="color:#1f377f;">predicate</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;<span style="color:blue;">new</span>&nbsp;DelegateSpecificationAdapter&lt;T&gt;(predicate); } <span style="color:blue;">private</span>&nbsp;<span style="color:blue;">class</span>&nbsp;<span style="color:#2b91af;">DelegateSpecificationAdapter</span>&lt;<span style="color:#2b91af;">T</span>&gt;&nbsp;:&nbsp;ISpecification&lt;T&gt; { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">private</span>&nbsp;<span style="color:blue;">readonly</span>&nbsp;Predicate&lt;T&gt;&nbsp;predicate; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">DelegateSpecificationAdapter</span>(Predicate&lt;T&gt;&nbsp;<span style="color:#1f377f;">predicate</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">this</span>.predicate&nbsp;=&nbsp;predicate; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">DelegateSpecificationAdapter</span>(Func&lt;T,&nbsp;<span style="color:blue;">bool</span>&gt;&nbsp;<span style="color:#1f377f;">predicate</span>)&nbsp;: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">this</span>((Predicate&lt;T&gt;)(<span style="color:#1f377f;">x</span>&nbsp;=&gt;&nbsp;predicate(x))) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:blue;">bool</span>&nbsp;<span style="color:#74531f;">IsSatisfiedBy</span>(T&nbsp;<span style="color:#1f377f;">candidate</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;predicate(candidate); &nbsp;&nbsp;&nbsp;&nbsp;} } <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">static</span>&nbsp;Predicate&lt;T&gt;&nbsp;<span style="color:#74531f;">AsPredicate</span>&lt;<span style="color:#2b91af;">T</span>&gt;(<span style="color:blue;">this</span>&nbsp;ISpecification&lt;T&gt;&nbsp;<span style="color:#1f377f;">specification</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;<span style="color:#1f377f;">candidate</span>&nbsp;=&gt;&nbsp;specification.IsSatisfiedBy(candidate); } <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">static</span>&nbsp;Func&lt;T, bool&gt;&nbsp;<span style="color:#74531f;">AsFunc</span>&lt;<span style="color:#2b91af;">T</span>&gt;(<span style="color:blue;">this</span>&nbsp;ISpecification&lt;T&gt;&nbsp;<span style="color:#1f377f;">specification</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;<span style="color:#1f377f;">candidate</span>&nbsp;=&gt;&nbsp;specification.IsSatisfiedBy(candidate); }</pre> </p> <p> Above are conversions between <code>ISpecification&lt;T&gt;</code> on the one hand, and <code>Predicate&lt;T&gt;</code> and <code>Func&lt;T, bool&gt;</code> on the other. Not shown are the conversions between <code>Predicate&lt;T&gt;</code> and <code>Func&lt;T, bool&gt;</code>, since they are already built into C#. </p> <p> Most saliently in this context is that it's possible to convert both <code>ISpecification&lt;T&gt;</code> and <code>Predicate&lt;T&gt;</code> to <code>Func&lt;T, bool&gt;</code>, and <code>Func&lt;T, bool&gt;</code> to <code>ISpecification&lt;T&gt;</code> or <code>Predicate&lt;T&gt;</code> without any loss of information. Specifications and predicates are isomorphic to an open constructed <code>Func</code> - that is, a Reader. </p> <p> I'll leave the other isomorphisms as exercises, with the following hints: </p> <ul> <li>You can only convert an <code>ICommandHandler&lt;T&gt;</code> to a <code>Func</code> if you introduce a <code>Unit</code> value, but you could also try to use <code>Action&lt;T&gt;</code>.</li> <li>For Equivalence, you'll need to translate the two input arguments to a single object or value.</li> <li>The same goes for Comparison.</li> </ul> <p> All the contravariant functor examples shown so far in this article series are isomorphic to the Reader contravariant functor. </p> <p> Particularly, this also explains why <a href="/2021/09/27/the-equivalence-contravariant-functor">it was possible to make <code>IEqualityComparer.GetHashCode</code> contravariant</a>. </p> <h3 id="fa845ae308634182bf6e82298205c9a8"> Haskell <a href="#fa845ae308634182bf6e82298205c9a8" title="permalink">#</a> </h3> <p> The Haskell <em>base</em> package comes with a <a href="https://hackage.haskell.org/package/base/docs/Data-Functor-Contravariant.html">Contravariant type class</a> and various instances. </p> <p> In order to replicate the above <code>MinutesReader</code> example, we can start by implementing a function with equivalent behaviour: </p> <p> <pre>Prelude Data.Functor.Contravariant Data.Time&gt; minutes m = secondsToDiffTime (60 * m) Prelude Data.Functor.Contravariant Data.Time&gt; :t minutes minutes :: Integer -&gt; DiffTime</pre> </p> <p> As GHCi reports, the <code>minutes</code> function has the type <code>Integer -&gt; DiffTime</code> (<code>DiffTime</code> corresponds to .NET's <code>TimeSpan</code>). </p> <p> The above C# example contramaps a <code>MinutesReader</code> with a function that parses a <code>string</code> to an <code>int</code>. In Haskell, we can use the built-in <code>read</code> function to equivalent effect. </p> <p> Here's where Haskell gets a little odd. In order to fit the <code>Contravariant</code> type class, we need to flip the type arguments of a function. A normal function is usually written as having the type <code>a -&gt; b</code>, but we can also write it as the type <code>(-&gt;) a b</code>. With this notation, <code>minutes</code> has the type <code>(-&gt;) Integer DiffTime</code>. </p> <p> In order to make <code>minutes</code> a contravariant instance, we need to fix <code>DiffTime</code> and let the input vary. What we'd like to have is something like this: <code>(-&gt;) a DiffTime</code>. Alas, that's not how you define a legal type class instance in Haskell. We have to flip the types around so that we can partially apply the type. The built-in <code>newtype Op</code> does that: </p> <p> <pre>Prelude Data.Functor.Contravariant Data.Time&gt; :t Op minutes Op minutes :: Op DiffTime Integer</pre> </p> <p> Since the general, partially applied type <code>Op a</code> is a <code>Contravariant</code> instance, it follows that the specific type <code>Op DiffTime</code> is. This means that we can <code>contramap</code> <code>Op minutes</code> with <code>read</code>: </p> <p> <pre>Prelude Data.Functor.Contravariant Data.Time&gt; :t contramap read (Op minutes) contramap read (Op minutes) :: Op DiffTime String</pre> </p> <p> Notice that this maps an <code>Op DiffTime Integer</code> to an <code>Op DiffTime String</code>. </p> <p> How do you use it? </p> <p> You can retrieve the function wrapped in <code>Op</code> with the <code>getOp</code> function: </p> <p> <pre>Prelude Data.Functor.Contravariant Data.Time&gt; :t getOp (contramap read (Op minutes)) getOp (contramap read (Op minutes)) :: String -&gt; DiffTime</pre> </p> <p> As you can tell, this expression indicates a <code>String -&gt; DiffTime</code> function. This means that if you call it with a string representation of an integer, you should get a <code>DiffTime</code> value back: </p> <p> <pre>Prelude Data.Functor.Contravariant Data.Time&gt; getOp (contramap read (Op minutes)) "21" 1260s</pre> </p> <p> As usual, this is way too complicated to be immediately useful, but it once again demonstrates that contravariant functors are ubiquitous. </p> <h3 id="c5952616e8b24528900fcdc9b2b75535"> Conclusion <a href="#c5952616e8b24528900fcdc9b2b75535" title="permalink">#</a> </h3> <p> Normal first-order functions give rise to contravariant functors. With sufficiently tinted glasses, <a href="/2018/01/08/software-design-isomorphisms">most programming constructs look like functions</a>. To me, at least, this indicates that a contravariant functor is a fundamental abstraction in programming. </p> <p> This result looks quite abstract, but future articles will build on it to arrive at a (to me) fascinating conclusion. Until then, though... </p> <p> <strong>Next:</strong> <a href="/2021/10/25/functor-variance-compared-to-cs-notion-of-variance">Functor variance compared to C#'s notion of variance</a>. </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/2021/10/04/reader-as-a-contravariant-functor The Equivalence contravariant functor https://blog.ploeh.dk/2021/09/27/the-equivalence-contravariant-functor/ Mon, 27 Sep 2021 06:08:00 UTC <div id="post"> <p> <em>An introduction to the Equivalence contravariant functor for object-oriented programmers.</em> </p> <p> This article is an instalment in <a href="/2021/09/02/contravariant-functors">an article series about contravariant functors</a>. It assumes that you've read the introduction. In previous articles, you saw examples of <a href="/2021/09/06/the-command-handler-contravariant-functor">the Command Handler</a> and <a href="/2021/09/09/the-specification-contravariant-functor">Specification</a> contravariant functors. This article presents another example. </p> <p> In <a href="/2021/09/20/keep-ids-internal-with-rest">a recent article</a> I described how I experimented with removing the <code>id</code> property from a JSON representation in a REST API. I also mentioned that doing that made one test fail. In this article you'll see the failing test and how the Equivalence contravariant functor can improve the situation. </p> <h3 id="be01e1b437a94b2689f5fdd3a68ae33f"> Baseline <a href="#be01e1b437a94b2689f5fdd3a68ae33f" title="permalink">#</a> </h3> <p> Before I made the change, the test in question looked like this: </p> <p> <pre>[Theory] [InlineData(1049,&nbsp;19,&nbsp;00,&nbsp;<span style="color:#a31515;">&quot;juliad@example.net&quot;</span>,&nbsp;<span style="color:#a31515;">&quot;Julia&nbsp;Domna&quot;</span>,&nbsp;5)] [InlineData(1130,&nbsp;18,&nbsp;15,&nbsp;<span style="color:#a31515;">&quot;x@example.com&quot;</span>,&nbsp;<span style="color:#a31515;">&quot;Xenia&nbsp;Ng&quot;</span>,&nbsp;9)] [InlineData(&nbsp;956,&nbsp;16,&nbsp;55,&nbsp;<span style="color:#a31515;">&quot;kite@example.edu&quot;</span>,&nbsp;<span style="color:blue;">null</span>,&nbsp;2)] [InlineData(&nbsp;433,&nbsp;17,&nbsp;30,&nbsp;<span style="color:#a31515;">&quot;shli@example.org&quot;</span>,&nbsp;<span style="color:#a31515;">&quot;Shanghai&nbsp;Li&quot;</span>,&nbsp;5)] <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">async</span>&nbsp;Task&nbsp;<span style="color:#74531f;">PostValidReservationWhenDatabaseIsEmpty</span>( &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">days</span>, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">hours</span>, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">minutes</span>, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">string</span>&nbsp;<span style="color:#1f377f;">email</span>, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">string</span>&nbsp;<span style="color:#1f377f;">name</span>, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">quantity</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">at</span>&nbsp;=&nbsp;DateTime.Now.Date&nbsp;+&nbsp;<span style="color:blue;">new</span>&nbsp;TimeSpan(days,&nbsp;hours,&nbsp;minutes,&nbsp;0); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">db</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;FakeDatabase(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">sut</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;ReservationsController( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">new</span>&nbsp;SystemClock(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">new</span>&nbsp;InMemoryRestaurantDatabase(Grandfather.Restaurant), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;db); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">dto</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;ReservationDto &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Id&nbsp;=&nbsp;<span style="color:#a31515;">&quot;B50DF5B1-F484-4D99-88F9-1915087AF568&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;At&nbsp;=&nbsp;at.ToString(<span style="color:#a31515;">&quot;O&quot;</span>), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Email&nbsp;=&nbsp;email, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name&nbsp;=&nbsp;name, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Quantity&nbsp;=&nbsp;quantity &nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">await</span>&nbsp;sut.Post(dto); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">expected</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;Reservation( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Guid.Parse(dto.Id), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">new</span>&nbsp;Email(email), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">new</span>&nbsp;Name(name&nbsp;??&nbsp;<span style="color:#a31515;">&quot;&quot;</span>), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;quantity); &nbsp;&nbsp;&nbsp;&nbsp;Assert.Contains(expected,&nbsp;db.Grandfather); }</pre> </p> <p> You can find this test in the code base that accompanies my book <a href="/code-that-fits-in-your-head">Code That Fits in Your Head</a>, although I've slightly simplified the initialisation of <code>expected</code> since I froze the code for the manuscript. I've already discussed this particular test in the articles <a href="/2020/12/07/branching-tests">Branching tests</a>, <a href="/2021/01/11/waiting-to-happen">Waiting to happen</a>, and <a href="/2021/01/18/parametrised-test-primitive-obsession-code-smell">Parametrised test primitive obsession code smell</a>. It's the gift that keeps giving. </p> <p> It's a <a href="/2019/04/01/an-example-of-state-based-testing-in-c">state-based integration test</a> that verifies the state of the <code>FakeDatabase</code> after 'posting' a reservation to 'the REST API'. I'm using quotes because the test doesn't really perform an HTTP POST request (it's not <a href="/2021/01/25/self-hosted-integration-tests-in-aspnet">a self-hosted integration test</a>). Rather, it directly calls the <code>Post</code> method on the <code>sut</code>. In the assertion phase, it uses Back Door Manipulation (as <a href="http://bit.ly/xunitpatterns">xUnit Test Patterns</a> terms it) to verify the state of the <a href="http://xunitpatterns.com/Fake%20Object.html">Fake</a> <code>db</code>. </p> <p> If you're wondering about the <code>Grandfather</code> property, <a href="/2020/11/16/redirect-legacy-urls">it represents the original restaurant that was grandfathered in</a> when I expanded the REST API to a multi-tenant service. </p> <p> Notice, particularly, the use of <code>dto.Id</code> when defining the <code>expected</code> reservation. </p> <h3 id="be8ae690e33a4e7fb3b5d5f15d6ddce9"> Brittle assertion <a href="#be8ae690e33a4e7fb3b5d5f15d6ddce9" title="permalink">#</a> </h3> <p> When I <a href="/2021/09/20/keep-ids-internal-with-rest">made the <code>Id</code> property <code>internal</code></a>, this test no longer compiled. I had to delete the assignment of <code>Id</code>, which also meant that I couldn't use a deterministic <code>Guid</code> to define the <code>expected</code> value. While I could create an arbitrary <code>Guid</code>, that would never pass the test, since the <code>Post</code> method also generates a new <code>Guid</code>. </p> <p> In order to <a href="/2019/10/21/a-red-green-refactor-checklist">get to green</a> as quickly as possible, I rewrote the assertion: </p> <p> <pre>Assert.Contains( &nbsp;&nbsp;&nbsp;&nbsp;db.Grandfather, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#1f377f;">r</span>&nbsp;=&gt;&nbsp;&nbsp;&nbsp;DateTime.Parse(dto.At,&nbsp;CultureInfo.InvariantCulture)&nbsp;==&nbsp;r.At &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp;&nbsp;<span style="color:blue;">new</span>&nbsp;Email(dto.Email)&nbsp;==&nbsp;r.Email &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp;&nbsp;<span style="color:blue;">new</span>&nbsp;Name(dto.Name&nbsp;??&nbsp;<span style="color:#a31515;">&quot;&quot;</span>)&nbsp;==&nbsp;r.Name &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp;&nbsp;dto.Quantity&nbsp;==&nbsp;r.Quantity);</pre> </p> <p> This passed the test so that I could move on. It may even be the simplest thing that could possibly work, but it's brittle and noisy. </p> <p> It's brittle because it explicitly considers the four properties <code>At</code>, <code>Email</code>, <code>Name</code>, and <code>Quantity</code> of the <code>Reservation</code> class. What happens if you add a new property to <code>Reservation</code>? What happens if you have similar assertions scattered over the code base? </p> <p> This is one reason that <a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself">DRY</a> also applies to unit tests. You want to have as few places as possible that you have to edit when making changes. Otherwise, the risk increases that you forget one or more. </p> <p> Not only is the assertion brittle - it's also noisy, because it's hard to read. There's parsing, null coalescing and object initialisation going on in those four lines of Boolean operations. Perhaps it'd be better to extract a well-named helper method, but while I'm often in favour of doing that, I'm also a little concerned that too many ad-hoc helper methods obscure something essential. After all: </p> <blockquote> <p> "Abstraction is the elimination of the irrelevant and the amplification of the essential" </p> <footer><cite>Robert C. Martin, <a href="http://amzn.to/19W4JHk">APPP</a></cite></footer> </blockquote> <p> The hardest part of abstraction is striking the right balance. Does a well-named helper method effectively communicate the essentials while eliminating <em>only</em> the irrelevant. While I favour good names over bad names, I'm also aware that <a href="/2020/11/23/good-names-are-skin-deep">good names are skin-deep</a>. If I can draw on a universal abstraction rather than coming up with an ad-hoc name, I prefer doing that. </p> <p> Which universal abstraction might be useful in this situation? </p> <h3 id="724d8609add4401cae58a14c259c5698"> Relaxed comparison <a href="#724d8609add4401cae58a14c259c5698" title="permalink">#</a> </h3> <p> The baseline version of the test relied on the structural equality of the <code>Reservation</code> class: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">override</span>&nbsp;<span style="color:blue;">bool</span>&nbsp;<span style="color:#74531f;">Equals</span>(<span style="color:blue;">object</span>?&nbsp;<span style="color:#1f377f;">obj</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;obj&nbsp;<span style="color:blue;">is</span>&nbsp;Reservation&nbsp;<span style="color:#1f377f;">reservation</span>&nbsp;&amp;&amp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Id.Equals(reservation.Id)&nbsp;&amp;&amp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;At&nbsp;==&nbsp;reservation.At&nbsp;&amp;&amp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EqualityComparer&lt;Email&gt;.Default.Equals(Email,&nbsp;reservation.Email)&nbsp;&amp;&amp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EqualityComparer&lt;Name&gt;.Default.Equals(Name,&nbsp;reservation.Name)&nbsp;&amp;&amp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Quantity&nbsp;==&nbsp;reservation.Quantity; }</pre> </p> <p> This implementation was auto-generated by a Visual Studio <em>Quick Action</em>. From C# 9, I could also have made <code>Reservation</code> a <a href="https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/record">record</a>, in which case the compiler would be taking care of implementing <code>Equals</code>. </p> <p> The <code>Reservation</code> class already defines the canonical way to compare two reservations for equality. Why can't we use that? </p> <p> The <code>PostValidReservationWhenDatabaseIsEmpty</code> test can no longer use the <code>Reservation</code> class' structural equality because it doesn't know what the <code>Id</code> is going to be. </p> <p> One way to address this problem is to inject a hypothetical <code>IGuidGenerator</code> dependency into <code>ReservationsController</code>. I consider this a valid alternative, since the Controller already takes an <code>IClock</code> dependency. I might be inclined towards such a course of action <a href="/2020/03/23/repeatable-execution">for other reasons</a>, but here I wanted to explore other options. </p> <p> Can we somehow reuse the <code>Equals</code> implementation of <code>Reservation</code>, but relax its behaviour so that it doesn't consider the <code>Id</code>? </p> <p> This would be <a href="https://docs.microsoft.com/archive/msdn-magazine/2010/october/msdn-magazine-the-working-programmer-multiparadigmatic-net-part-2">what Ted Neward called <em>negative variability</em></a> - the ability to subtract from an existing feature. As he implied in 2010, normal programming languages don't have that capability. That strikes me as true in 2021 as well. </p> <p> The best we can hope for, then, is to put the required custom comparison somewhere central, so that at least it's not scattered across the entire code base. Since the test uses <a href="https://xunit.net">xUnit.net</a>, a class that implements <code>IEqualityComparer&lt;Reservation&gt;</code> sounds like just the right solution. </p> <p> This is definitely doable, but it's odd having to define a custom equality comparer for a class that already has structural equality. In the context of the <code>PostValidReservationWhenDatabaseIsEmpty</code> test, we understand the reason, but for a future team member who may encounter the class out of context, it might be confusing. </p> <p> Are there other options? </p> <h3 id="df0297c4c0274368843e9e0f5bb98cba"> Reuse <a href="#df0297c4c0274368843e9e0f5bb98cba" title="permalink">#</a> </h3> <p> It turns out that, by lucky accident, the code base already contains an equality comparer that almost fits: </p> <p> <pre><span style="color:blue;">internal</span>&nbsp;<span style="color:blue;">sealed</span>&nbsp;<span style="color:blue;">class</span>&nbsp;<span style="color:#2b91af;">ReservationDtoComparer</span>&nbsp;:&nbsp;IEqualityComparer&lt;ReservationDto&gt; { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:blue;">bool</span>&nbsp;<span style="color:#74531f;">Equals</span>(ReservationDto?&nbsp;<span style="color:#1f377f;">x</span>,&nbsp;ReservationDto?&nbsp;<span style="color:#1f377f;">y</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">datesAreEqual</span>&nbsp;=&nbsp;Equals(x?.At,&nbsp;y?.At); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">if</span>&nbsp;(!datesAreEqual&nbsp;&amp;&amp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DateTime.TryParse(x?.At,&nbsp;<span style="color:blue;">out</span>&nbsp;var&nbsp;<span style="color:#1f377f;">xDate</span>)&nbsp;&amp;&amp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DateTime.TryParse(y?.At,&nbsp;<span style="color:blue;">out</span>&nbsp;var&nbsp;<span style="color:#1f377f;">yDate</span>)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;datesAreEqual&nbsp;=&nbsp;Equals(xDate,&nbsp;yDate); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;datesAreEqual &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp;&nbsp;Equals(x?.Email,&nbsp;y?.Email) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp;&nbsp;Equals(x?.Name,&nbsp;y?.Name) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp;&nbsp;Equals(x?.Quantity,&nbsp;y?.Quantity); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:blue;">int</span>&nbsp;<span style="color:#74531f;">GetHashCode</span>(ReservationDto&nbsp;<span style="color:#1f377f;">obj</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">dateHash</span>&nbsp;=&nbsp;obj.At?.GetHashCode(StringComparison.InvariantCulture); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">if</span>&nbsp;(DateTime.TryParse(obj.At,&nbsp;<span style="color:blue;">out</span>&nbsp;var&nbsp;<span style="color:#1f377f;">dt</span>)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dateHash&nbsp;=&nbsp;dt.GetHashCode(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;HashCode.Combine(dateHash,&nbsp;obj.Email,&nbsp;obj.Name,&nbsp;obj.Quantity); &nbsp;&nbsp;&nbsp;&nbsp;} }</pre> </p> <p> This class already compares two reservations' dates, emails, names, and quantities, while ignoring any IDs. Just what we need? </p> <p> There's only one problem. <code>ReservationDtoComparer</code> compares <code>ReservationDto</code> objects - not <code>Reservation</code> objects. </p> <p> Would it be possible to somehow, on the spot, without writing a new class, transform <code>ReservationDtoComparer</code> to an <code>IEqualityComparer&lt;Reservation&gt;</code>? </p> <p> Well, yes it is. </p> <h3 id="affeb3f683624666a9c1bb3b0bae342a"> Contravariant functor <a href="#affeb3f683624666a9c1bb3b0bae342a" title="permalink">#</a> </h3> <p> We can contramap an <code>IEqualityComparer&lt;ReservationDto&gt;</code> to a <code>IEqualityComparer&lt;Reservation&gt;</code> because <em>equivalence</em> gives rise to a contravariant functor. </p> <p> In order to enable contravariant mapping, you must add a <code>ContraMap</code> method: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">static</span>&nbsp;<span style="color:blue;">class</span>&nbsp;<span style="color:#2b91af;">Equivalance</span> { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:blue;">static</span>&nbsp;IEqualityComparer&lt;T1&gt;&nbsp;<span style="color:#74531f;">ContraMap</span>&lt;<span style="color:#2b91af;">T</span>,&nbsp;<span style="color:#2b91af;">T1</span>&gt;( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">this</span>&nbsp;IEqualityComparer&lt;T&gt;&nbsp;<span style="color:#1f377f;">source</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Func&lt;T1,&nbsp;T&gt;&nbsp;<span style="color:#1f377f;">selector</span>)&nbsp;<span style="color:blue;">where</span>&nbsp;T&nbsp;:&nbsp;<span style="color:blue;">notnull</span> &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;<span style="color:blue;">new</span>&nbsp;ContraMapComparer&lt;T,&nbsp;T1&gt;(source,&nbsp;selector); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">private</span>&nbsp;<span style="color:blue;">sealed</span>&nbsp;<span style="color:blue;">class</span>&nbsp;<span style="color:#2b91af;">ContraMapComparer</span>&lt;<span style="color:#2b91af;">T</span>,&nbsp;<span style="color:#2b91af;">T1</span>&gt;&nbsp;:&nbsp;IEqualityComparer&lt;T1&gt;&nbsp;<span style="color:blue;">where</span>&nbsp;T&nbsp;:&nbsp;<span style="color:blue;">notnull</span> &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">private</span>&nbsp;<span style="color:blue;">readonly</span>&nbsp;IEqualityComparer&lt;T&gt;&nbsp;source; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">private</span>&nbsp;<span style="color:blue;">readonly</span>&nbsp;Func&lt;T1,&nbsp;T&gt;&nbsp;selector; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">ContraMapComparer</span>(IEqualityComparer&lt;T&gt;&nbsp;<span style="color:#1f377f;">source</span>,&nbsp;Func&lt;T1,&nbsp;T&gt;&nbsp;<span style="color:#1f377f;">selector</span>) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">this</span>.source&nbsp;=&nbsp;source; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">this</span>.selector&nbsp;=&nbsp;selector; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:blue;">bool</span>&nbsp;<span style="color:#74531f;">Equals</span>([AllowNull]&nbsp;T1&nbsp;<span style="color:#1f377f;">x</span>,&nbsp;[AllowNull]&nbsp;T1&nbsp;<span style="color:#1f377f;">y</span>) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">if</span>&nbsp;(x&nbsp;<span style="color:blue;">is</span>&nbsp;<span style="color:blue;">null</span>&nbsp;&amp;&amp;&nbsp;y&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;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;<span style="color:blue;">true</span>; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">if</span>&nbsp;(x&nbsp;<span style="color:blue;">is</span>&nbsp;<span style="color:blue;">null</span>&nbsp;||&nbsp;y&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;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;<span style="color:blue;">false</span>; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;source.Equals(selector(x),&nbsp;selector(y)); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:blue;">int</span>&nbsp;<span style="color:#74531f;">GetHashCode</span>(T1&nbsp;<span style="color:#1f377f;">obj</span>) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;source.GetHashCode(selector(obj)); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} }</pre> </p> <p> Since the <code>IEqualityComparer&lt;T&gt;</code> interface defines <em>two</em> methods, the <code>selector</code> must contramap the behaviour of both <code>Equals</code> and <code>GetHashCode</code>. Fortunately, that's possible. </p> <p> Notice that, as explained in the overview article, in order to map from an <code>IEqualityComparer&lt;T&gt;</code> to an <code>IEqualityComparer&lt;T1&gt;</code>, the <code>selector</code> has to go the other way: from <code>T1</code> to <code>T</code>. How this is possible will become more apparent with an example, which will follow later in the article. </p> <h3 id="911357268ea14f09ac03bac6a781333e"> Identity law <a href="#911357268ea14f09ac03bac6a781333e" title="permalink">#</a> </h3> <p> A <code>ContraMap</code> method with the right signature isn't enough to be a contravariant functor. It must also obey the contravariant functor laws. As usual, it's proper computer-science work to actually prove this, but you can write some tests to demonstrate the identity law for the <code>IEqualityComparer&lt;T&gt;</code> interface. In this article, you'll see parametrised tests written with xUnit.net. First, the identity law: </p> <p> <pre>[Theory] [InlineData(<span style="color:#a31515;">&quot;18:30&quot;</span>,&nbsp;1,&nbsp;<span style="color:#a31515;">&quot;18:30&quot;</span>,&nbsp;1)] [InlineData(<span style="color:#a31515;">&quot;18:30&quot;</span>,&nbsp;2,&nbsp;<span style="color:#a31515;">&quot;18:30&quot;</span>,&nbsp;2)] [InlineData(<span style="color:#a31515;">&quot;19:00&quot;</span>,&nbsp;1,&nbsp;<span style="color:#a31515;">&quot;19:00&quot;</span>,&nbsp;1)] [InlineData(<span style="color:#a31515;">&quot;18:30&quot;</span>,&nbsp;1,&nbsp;<span style="color:#a31515;">&quot;19:00&quot;</span>,&nbsp;1)] [InlineData(<span style="color:#a31515;">&quot;18:30&quot;</span>,&nbsp;2,&nbsp;<span style="color:#a31515;">&quot;18:30&quot;</span>,&nbsp;1)] <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">void</span>&nbsp;<span style="color:#74531f;">IdentityLaw</span>(<span style="color:blue;">string</span>&nbsp;<span style="color:#1f377f;">time1</span>,&nbsp;<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">size1</span>,&nbsp;<span style="color:blue;">string</span>&nbsp;<span style="color:#1f377f;">time2</span>,&nbsp;<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">size2</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">sut</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;TimeDtoComparer(); &nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;<span style="color:#74531f;">id</span>&lt;<span style="color:#2b91af;">T</span>&gt;(T&nbsp;<span style="color:#1f377f;">x</span>)&nbsp;=&gt;&nbsp;x; &nbsp;&nbsp;&nbsp;&nbsp;IEqualityComparer&lt;TimeDto&gt;?&nbsp;<span style="color:#1f377f;">actual</span>&nbsp;=&nbsp;sut.ContraMap&lt;TimeDto,&nbsp;TimeDto&gt;(id); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">dto1</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;TimeDto&nbsp;{&nbsp;Time&nbsp;=&nbsp;time1,&nbsp;MaximumPartySize&nbsp;=&nbsp;size1&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">dto2</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;TimeDto&nbsp;{&nbsp;Time&nbsp;=&nbsp;time2,&nbsp;MaximumPartySize&nbsp;=&nbsp;size2&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;Assert.Equal(sut.Equals(dto1,&nbsp;dto2),&nbsp;actual.Equals(dto1,&nbsp;dto2)); &nbsp;&nbsp;&nbsp;&nbsp;Assert.Equal(sut.GetHashCode(dto1),&nbsp;actual.GetHashCode(dto1)); }</pre> </p> <p> In order to observe that the two comparers have identical behaviours, the test must invoke both the <code>Equals</code> and the <code>GetHashCode</code> methods on both <code>sut</code> and <code>actual</code> to assert that the two different objects produce the same output. </p> <p> All test cases pass. </p> <h3 id="c2228ba4c0044dc8b90ad92354850a22"> Composition law <a href="#c2228ba4c0044dc8b90ad92354850a22" title="permalink">#</a> </h3> <p> Like the above example, you can also write a parametrised test that demonstrates that <code>ContraMap</code> obeys the composition law for contravariant functors: </p> <p> <pre>[Theory] [InlineData(<span style="color:#a31515;">&quot;&nbsp;7:45&quot;</span>,&nbsp;<span style="color:#a31515;">&quot;18:13&quot;</span>)] [InlineData(<span style="color:#a31515;">&quot;18:13&quot;</span>,&nbsp;<span style="color:#a31515;">&quot;18:13&quot;</span>)] [InlineData(<span style="color:#a31515;">&quot;22&quot;</span>&nbsp;&nbsp;&nbsp;,&nbsp;<span style="color:#a31515;">&quot;22&quot;</span>&nbsp;&nbsp;&nbsp;)] [InlineData(<span style="color:#a31515;">&quot;22:32&quot;</span>,&nbsp;<span style="color:#a31515;">&quot;22&quot;</span>&nbsp;&nbsp;&nbsp;)] [InlineData(&nbsp;<span style="color:#a31515;">&quot;9&quot;</span>&nbsp;&nbsp;&nbsp;,&nbsp;&nbsp;<span style="color:#a31515;">&quot;9&quot;</span>&nbsp;&nbsp;&nbsp;)] [InlineData(&nbsp;<span style="color:#a31515;">&quot;9&quot;</span>&nbsp;&nbsp;&nbsp;,&nbsp;&nbsp;<span style="color:#a31515;">&quot;8&quot;</span>&nbsp;&nbsp;&nbsp;)] <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">void</span>&nbsp;<span style="color:#74531f;">CompositionLaw</span>(<span style="color:blue;">string</span>&nbsp;<span style="color:#1f377f;">time1</span>,&nbsp;<span style="color:blue;">string</span>&nbsp;<span style="color:#1f377f;">time2</span>) { &nbsp;&nbsp;&nbsp;&nbsp;IEqualityComparer&lt;TimeDto&gt;&nbsp;<span style="color:#1f377f;">sut</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;TimeDtoComparer(); &nbsp;&nbsp;&nbsp;&nbsp;Func&lt;<span style="color:blue;">string</span>,&nbsp;(<span style="color:blue;">string</span>,&nbsp;<span style="color:blue;">int</span>)&gt;&nbsp;<span style="color:#1f377f;">f</span>&nbsp;=&nbsp;<span style="color:#1f377f;">s</span>&nbsp;=&gt;&nbsp;(s,&nbsp;s.Length); &nbsp;&nbsp;&nbsp;&nbsp;Func&lt;(<span style="color:blue;">string</span>&nbsp;s,&nbsp;<span style="color:blue;">int</span>&nbsp;i),&nbsp;TimeDto&gt;&nbsp;<span style="color:#1f377f;">g</span>&nbsp;=&nbsp;<span style="color:#1f377f;">t</span>&nbsp;=&gt;&nbsp;<span style="color:blue;">new</span>&nbsp;TimeDto&nbsp;{&nbsp;Time&nbsp;=&nbsp;t.s,&nbsp;MaximumPartySize&nbsp;=&nbsp;t.i&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;IEqualityComparer&lt;<span style="color:blue;">string</span>&gt;?&nbsp;<span style="color:#1f377f;">projection1</span>&nbsp;=&nbsp;sut.ContraMap((<span style="color:blue;">string</span>&nbsp;<span style="color:#1f377f;">s</span>)&nbsp;=&gt;&nbsp;g(f(s))); &nbsp;&nbsp;&nbsp;&nbsp;IEqualityComparer&lt;<span style="color:blue;">string</span>&gt;?&nbsp;<span style="color:#1f377f;">projection2</span>&nbsp;=&nbsp;sut.ContraMap(g).ContraMap(f); &nbsp;&nbsp;&nbsp;&nbsp;Assert.Equal( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;projection1.Equals(time1,&nbsp;time2), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;projection2.Equals(time1,&nbsp;time2)); &nbsp;&nbsp;&nbsp;&nbsp;Assert.Equal( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;projection1.GetHashCode(time1), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;projection2.GetHashCode(time1)); }</pre> </p> <p> This test defines two local functions, <code>f</code> and <code>g</code>. Once more, you can't directly compare methods for equality, so instead you have to call both <code>Equals</code> and <code>GetHashCode</code> on <code>projection1</code> and <code>projection2</code> to verify that they return the same values. </p> <p> They do. </p> <h3 id="857e86fbf0944fe4b985cae73a9edb4b"> Relaxed assertion <a href="#857e86fbf0944fe4b985cae73a9edb4b" title="permalink">#</a> </h3> <p> The code base already contains a function that converts <code>Reservation</code> values to <code>ReservationDto</code> objects: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">static</span>&nbsp;ReservationDto&nbsp;<span style="color:#74531f;">ToDto</span>(<span style="color:blue;">this</span>&nbsp;Reservation&nbsp;<span style="color:#1f377f;">reservation</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">if</span>&nbsp;(reservation&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:#8f08c4;">throw</span>&nbsp;<span style="color:blue;">new</span>&nbsp;ArgumentNullException(nameof(reservation)); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;<span style="color:blue;">new</span>&nbsp;ReservationDto &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Id&nbsp;=&nbsp;reservation.Id.ToString(<span style="color:#a31515;">&quot;N&quot;</span>), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;At&nbsp;=&nbsp;reservation.At.ToIso8601DateTimeString(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Email&nbsp;=&nbsp;reservation.Email.ToString(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name&nbsp;=&nbsp;reservation.Name.ToString(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Quantity&nbsp;=&nbsp;reservation.Quantity &nbsp;&nbsp;&nbsp;&nbsp;}; }</pre> </p> <p> Given that it's possible to map from <code>Reservation</code> to <code>ReservationDto</code>, it's also possible to map equality comparers in the contrary direction: from <code>IEqualityComparer&lt;ReservationDto&gt;</code> to <code>IEqualityComparer&lt;Reservation&gt;</code>. That's just what the <code>PostValidReservationWhenDatabaseIsEmpty</code> test needs! </p> <p> Most of the test stays the same, but you can now write the assertion as: </p> <p> <pre><span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">expected</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;Reservation( &nbsp;&nbsp;&nbsp;&nbsp;Guid.NewGuid(), &nbsp;&nbsp;&nbsp;&nbsp;at, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">new</span>&nbsp;Email(email), &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">new</span>&nbsp;Name(name&nbsp;??&nbsp;<span style="color:#a31515;">&quot;&quot;</span>), &nbsp;&nbsp;&nbsp;&nbsp;quantity); Assert.Contains( &nbsp;&nbsp;&nbsp;&nbsp;expected, &nbsp;&nbsp;&nbsp;&nbsp;db.Grandfather, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">new</span>&nbsp;ReservationDtoComparer().ContraMap((Reservation&nbsp;<span style="color:#1f377f;">r</span>)&nbsp;=&gt;&nbsp;r.ToDto()));</pre> </p> <p> Instead of using the too-strict equality comparison of <code>Reservation</code>, the assertion now takes advantage of the relaxed, test-specific comparison of <code>ReservationDto</code> objects. </p> <p> What's not to like? </p> <p> To be truthful, this probably isn't a trick I'll perform often. I think it's fair to consider contravariant functors an advanced programming concept. On a team, I'd be concerned that colleagues wouldn't understand what's going on here. </p> <p> The purpose of this article series isn't to advocate for this style of programming. It's to show some realistic examples of contravariant functors. </p> <p> Even in <a href="https://www.haskell.org">Haskell</a>, where contravariant functors are en explicit part of <a href="https://hackage.haskell.org/package/base/docs/index.html">the <em>base</em> package</a>, I can't recall having availed myself of this functionality. </p> <h3 id="50a1d26e56054e8f896af110d176e3a5"> Equivalence in Haskell <a href="#50a1d26e56054e8f896af110d176e3a5" title="permalink">#</a> </h3> <p> The <a href="https://hackage.haskell.org/package/base/docs/Data-Functor-Contravariant.html">Haskell <em>Data.Functor.Contravariant</em> module</a> defines a <code>Contravariant</code> type class and some instances to go with it. One of these is a <code>newtype</code> called <code>Equivalence</code>, which is just a wrapper around <code>a -&gt; a -&gt; Bool</code>. </p> <p> In Haskell, equality is normally defined by the <code>Eq</code> type class. You can trivially 'promote' any <code>Eq</code> instance to an <code>Equivalence</code> instance using the <code>defaultEquivalence</code> value. </p> <p> To illustrate how this works in Haskell, you can reproduce the two reservation types: </p> <p> <pre><span style="color:blue;">data</span>&nbsp;Reservation&nbsp;=&nbsp;Reservation&nbsp;{ &nbsp;&nbsp;<span style="color:#2b91af;">reservationID</span>&nbsp;::&nbsp;<span style="color:blue;">UUID</span>, &nbsp;&nbsp;<span style="color:#2b91af;">reservationAt</span>&nbsp;::&nbsp;<span style="color:blue;">LocalTime</span>, &nbsp;&nbsp;<span style="color:#2b91af;">reservationEmail</span>&nbsp;::&nbsp;<span style="color:#2b91af;">String</span>, &nbsp;&nbsp;<span style="color:#2b91af;">reservationName</span>&nbsp;::&nbsp;<span style="color:#2b91af;">String</span>, &nbsp;&nbsp;<span style="color:#2b91af;">reservationQuantity</span>&nbsp;::&nbsp;<span style="color:#2b91af;">Int</span>&nbsp;} &nbsp;&nbsp;<span style="color:blue;">deriving</span>&nbsp;(<span style="color:#2b91af;">Eq</span>,&nbsp;<span style="color:#2b91af;">Show</span>) <span style="color:blue;">data</span>&nbsp;ReservationJson&nbsp;=&nbsp;ReservationJson&nbsp;{ &nbsp;&nbsp;<span style="color:#2b91af;">jsonAt</span>&nbsp;::&nbsp;<span style="color:#2b91af;">String</span>, &nbsp;&nbsp;<span style="color:#2b91af;">jsonEmail</span>&nbsp;::&nbsp;<span style="color:#2b91af;">String</span>, &nbsp;&nbsp;<span style="color:#2b91af;">jsonName</span>&nbsp;::&nbsp;<span style="color:#2b91af;">String</span>, &nbsp;&nbsp;<span style="color:#2b91af;">jsonQuantity</span>&nbsp;::&nbsp;<span style="color:#2b91af;">Double</span>&nbsp;} &nbsp;&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;">Generic</span>)</pre> </p> <p> The <code>ReservationJson</code> type doesn't have an ID, whereas <code>Reservation</code> does. Still, you can easily convert from <code>Reservation</code> to <code>ReservationJson</code>: </p> <p> <pre><span style="color:#2b91af;">reservationToJson</span>&nbsp;::&nbsp;<span style="color:blue;">Reservation</span>&nbsp;<span style="color:blue;">-&gt;</span>&nbsp;<span style="color:blue;">ReservationJson</span> reservationToJson&nbsp;(Reservation&nbsp;_&nbsp;at&nbsp;email&nbsp;name&nbsp;q)&nbsp;= &nbsp;&nbsp;ReservationJson&nbsp;(<span style="color:blue;">show</span>&nbsp;at)&nbsp;email&nbsp;name&nbsp;(<span style="color:blue;">fromIntegral</span>&nbsp;q)</pre> </p> <p> Now imagine that you have two reservations that differ only on <code>reservationID</code>: </p> <p> <pre><span style="color:#2b91af;">reservation1</span>&nbsp;::&nbsp;<span style="color:blue;">Reservation</span> reservation1&nbsp;= &nbsp;&nbsp;Reservation &nbsp;&nbsp;&nbsp;&nbsp;(fromWords&nbsp;3822151499&nbsp;288494060&nbsp;2147588346&nbsp;2611157519) &nbsp;&nbsp;&nbsp;&nbsp;(LocalTime&nbsp;(fromGregorian&nbsp;2021&nbsp;11&nbsp;11)&nbsp;(TimeOfDay&nbsp;12&nbsp;30&nbsp;0)) &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#a31515;">&quot;just.inhale@example.net&quot;</span> &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#a31515;">&quot;Justin&nbsp;Hale&quot;</span> &nbsp;&nbsp;&nbsp;&nbsp;2 <span style="color:#2b91af;">reservation2</span>&nbsp;::&nbsp;<span style="color:blue;">Reservation</span> reservation2&nbsp;= &nbsp;&nbsp;Reservation &nbsp;&nbsp;&nbsp;&nbsp;(fromWords&nbsp;1263859666&nbsp;288625132&nbsp;2147588346&nbsp;2611157519) &nbsp;&nbsp;&nbsp;&nbsp;(LocalTime&nbsp;(fromGregorian&nbsp;2021&nbsp;11&nbsp;11)&nbsp;(TimeOfDay&nbsp;12&nbsp;30&nbsp;0)) &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#a31515;">&quot;just.inhale@example.net&quot;</span> &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#a31515;">&quot;Justin&nbsp;Hale&quot;</span> &nbsp;&nbsp;&nbsp;&nbsp;2</pre> </p> <p> If you compare these two values using the standard equality operator, they're (not surprisingly) not the same: </p> <p> <pre>&gt; reservation1 == reservation2 False</pre> </p> <p> Attempting to compare them using the default <code>Equivalence</code> value doesn't help, either: </p> <p> <pre>&gt; (getEquivalence $ defaultEquivalence) reservation1 reservation2 False</pre> </p> <p> But if you promote the comparison to <code>Equivalence</code> and then <code>contramap</code> it with <code>reservationToJson</code>, they do look the same: </p> <p> <pre>&gt; (getEquivalence $ contramap reservationToJson $ defaultEquivalence) reservation1 reservation2 True</pre> </p> <p> This Haskell example is equivalent in spirit to the above C# assertion. </p> <p> Notice that <code>Equivalence</code> is only a wrapper around any function of the type <code>a -&gt; a -&gt; Bool</code>. This corresponds to the <code>IEqualityComparer</code> interface's <code>Equals</code> method. On the other hand, <code>Equivalence</code> has no counterpart to <code>GetHashCode</code> - that's a .NETism. </p> <p> When using Haskell as inspiration for identifying universal abstractions, it's not entirely clear how <code>Equivalence</code> is similar to <code>IEqualityComparer&lt;T&gt;</code>. While <code>a -&gt; a -&gt; Bool</code> is isomorphic to its <code>Equals</code> method, and thus gives rise to a contravariant functor, what about the <code>GetHashCode</code> method? </p> <p> As this article has demonstrated, it turned out that it's possible to also contramap the <code>GetHashCode</code> method, but was that just a fortunate accident, or is there something more fundamental going on? </p> <h3 id="d51dbd1743e14420ab8c38b25bc02369"> Conclusion <a href="#d51dbd1743e14420ab8c38b25bc02369" title="permalink">#</a> </h3> <p> Equivalence relations give rise to a contravariant functor. In this article, you saw how this property can be used to relax assertions in unit tests. </p> <p> Strictly speaking, an equivalence relation is exclusively a function that compares two values to return a Boolean value. No <code>GetHashCode</code> method is required. That's a .NET-specific implementation detail that, unfortunately, has been allowed to leak into the <code>object</code> base class. It's not part of the concept of an equivalence relation, but still, it's possible to form a contravariant functor from <code>IEqualityComparer&lt;T&gt;</code>. Is this just a happy coincidence, or could there be something more fundamental going on? </p> <p> Read on. </p> <p> <strong>Next:</strong> <a href="/2021/10/04/reader-as-a-contravariant-functor">Reader as a contravariant functor</a>. </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/2021/09/27/the-equivalence-contravariant-functor Keep IDs internal with REST https://blog.ploeh.dk/2021/09/20/keep-ids-internal-with-rest/ Mon, 20 Sep 2021 06:21:00 UTC <div id="post"> <p> <em>Instead of relying on entity IDs, use hypermedia to identify resources.</em> </p> <p> Whenever I've helped teams design HTTP APIs, sooner or later one request comes up - typically from client developers: <em>Please add the entity ID to the representation.</em> </p> <p> In this article I'll show an alternative, but first: the normal state of affairs. </p> <h3 id="24703d08faec4fe6a650599e54e8dbf8"> Business as usual <a href="#24703d08faec4fe6a650599e54e8dbf8" title="permalink">#</a> </h3> <p> It's such a common requirement that, despite admonitions not to expose IDs, I did it myself in the code base that accompanies my book <a href="/code-that-fits-in-your-head">Code That Fits in Your Head</a>. This code base is a <a href="https://martinfowler.com/articles/richardsonMaturityModel.html">level 3 REST API</a>, and still, I'd included the ID in the JSON representation of a reservation: </p> <p> <pre>{ &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;id&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;bf4e84130dac451b9c94049da8ea8c17&quot;</span>, &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;at&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;2021-12-08T20:30:00.0000000&quot;</span>, &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;email&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;snomob@example.com&quot;</span>, &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;name&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;Snow&nbsp;Moe&nbsp;Beal&quot;</span>, &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;quantity&quot;</span>:&nbsp;1 }</pre> </p> <p> At least the ID is a <a href="https://en.wikipedia.org/wiki/Universally_unique_identifier">GUID</a>, so I'm <a href="/2014/08/11/cqs-versus-server-generated-ids">not exposing internal database IDs</a>. </p> <p> After having written the book, the <code>id</code> property kept nagging me, and I wondered if it'd be possible to get rid of it. After all, in a true REST API, clients aren't supposed to construct URLs from templates. They're supposed to follow links. So why do you need the ID? </p> <h3 id="e480deb4e2b3470a847fc2995bdf406d"> Following links <a href="#e480deb4e2b3470a847fc2995bdf406d" title="permalink">#</a> </h3> <p> Early on in the system's lifetime, I began <a href="/2020/10/26/fit-urls">signing all URLs</a> to prevent clients from <a href="/2013/05/01/rest-lesson-learned-avoid-hackable-urls">retro-engineering URLs</a>. This also meant that most of my <a href="/2021/01/25/self-hosted-integration-tests-in-aspnet">self-hosted integration tests</a> were already following links: </p> <p> <pre>[Theory] [InlineData(867,&nbsp;19,&nbsp;10,&nbsp;<span style="color:#a31515;">&quot;adur@example.net&quot;</span>,&nbsp;<span style="color:#a31515;">&quot;Adrienne&nbsp;Ursa&quot;</span>,&nbsp;2)] [InlineData(901,&nbsp;18,&nbsp;55,&nbsp;<span style="color:#a31515;">&quot;emol@example.gov&quot;</span>,&nbsp;<span style="color:#a31515;">&quot;Emma&nbsp;Olsen&quot;</span>,&nbsp;5)] <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">async</span>&nbsp;Task&nbsp;<span style="color:#74531f;">ReadSuccessfulReservation</span>( &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">days</span>, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">hours</span>, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">minutes</span>, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">string</span>&nbsp;<span style="color:#1f377f;">email</span>, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">string</span>&nbsp;<span style="color:#1f377f;">name</span>, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">quantity</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">using</span>&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">api</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;LegacyApi(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">at</span>&nbsp;=&nbsp;DateTime.Today.AddDays(days).At(hours,&nbsp;minutes) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.ToIso8601DateTimeString(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">expected</span>&nbsp;=&nbsp;Create.ReservationDto(at,&nbsp;email,&nbsp;name,&nbsp;quantity); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">postResp</span>&nbsp;=&nbsp;<span style="color:blue;">await</span>&nbsp;api.PostReservation(expected); &nbsp;&nbsp;&nbsp;&nbsp;Uri&nbsp;<span style="color:#1f377f;">address</span>&nbsp;=&nbsp;FindReservationAddress(postResp); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">getResp</span>&nbsp;=&nbsp;<span style="color:blue;">await</span>&nbsp;api.CreateClient().GetAsync(address); &nbsp;&nbsp;&nbsp;&nbsp;getResp.EnsureSuccessStatusCode(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">actual</span>&nbsp;=&nbsp;<span style="color:blue;">await</span>&nbsp;getResp.ParseJsonContent&lt;ReservationDto&gt;(); &nbsp;&nbsp;&nbsp;&nbsp;Assert.Equal(expected,&nbsp;actual,&nbsp;<span style="color:blue;">new</span>&nbsp;ReservationDtoComparer()); &nbsp;&nbsp;&nbsp;&nbsp;AssertUrlFormatIsIdiomatic(address); }</pre> </p> <p> This parametrised test uses <a href="https://xunit.net">xUnit.net</a> 2.4.1 to first post a new reservation to the system, and then following the link provided in the response's <code>Location</code> header to verify that this resource contains a representation compatible with the reservation that was posted. </p> <p> A corresponding plaintext HTTP session would start like this: </p> <p> <pre>POST /restaurants/90125/reservations?sig=aco7VV%2Bh5sA3RBtrN8zI8Y9kLKGC60Gm3SioZGosXVE%3D HTTP/1.1 Content-Type: application/json { &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;at&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;2021-12-08&nbsp;20:30&quot;</span>, &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;email&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;snomob@example.com&quot;</span>, &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;name&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;Snow&nbsp;Moe&nbsp;Beal&quot;</span>, &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;quantity&quot;</span>:&nbsp;1 } HTTP/1.1 201 Created Content-Type: application/json; charset=utf-8 Location: example.com/restaurants/90125/reservations/bf4e84130dac451b9c94049da8ea8c17?sig=ZVM%2[...] { &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;id&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;bf4e84130dac451b9c94049da8ea8c17&quot;</span>, &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;at&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;2021-12-08T20:30:00.0000000&quot;</span>, &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;email&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;snomob@example.com&quot;</span>, &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;name&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;Snow&nbsp;Moe&nbsp;Beal&quot;</span>, &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;quantity&quot;</span>:&nbsp;1 }</pre> </p> <p> That's the first request and response. Clients can now examine the response's headers to find the <code>Location</code> header. That URL is the actual, external ID of the resource, not the <code>id</code> property in the JSON representation. </p> <p> The client can save that URL and request it whenever it needs the reservation: </p> <p> <pre>GET /restaurants/90125/reservations/bf4e84130dac451b9c94049da8ea8c17?sig=ZVM%2[...] HTTP/1.1 HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 { &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;id&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;bf4e84130dac451b9c94049da8ea8c17&quot;</span>, &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;at&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;2021-12-08T20:30:00.0000000&quot;</span>, &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;email&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;snomob@example.com&quot;</span>, &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;name&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;Snow&nbsp;Moe&nbsp;Beal&quot;</span>, &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;quantity&quot;</span>:&nbsp;1 }</pre> </p> <p> The actual, intended use of the API doesn't rely on the <code>id</code> property, neither do the tests. </p> <p> Based on this consistent design principle, I had reason to hope that I'd be able to remove the <code>id</code> property. </p> <h3 id="f4fc880aa8434cc2ac1675fcdf68bc18"> Breaking change <a href="#f4fc880aa8434cc2ac1675fcdf68bc18" title="permalink">#</a> </h3> <p> My motivation for making this change was to educate myself. I wanted to see if it would be possible to design a REST API that doesn't expose IDs in their JSON (or XML) representations. Usually I'm having trouble doing this in practice because when I'm consulting, I'm typically present to help the organisation with test-driven development and how to organise their code. It's always hard to learn new ways of doing things, and I don't wish to overwhelm my clients with too many changes all at once. </p> <p> So I usually let them do <a href="https://martinfowler.com/articles/richardsonMaturityModel.html">level 2 APIs</a> because that's what they're comfortable with. With that style of HTTP API design, it's hard to avoid <code>id</code> fields. </p> <p> This wasn't a constraint for the book's code, so I'd gone full REST on that API, and I'm happy that I did. By habit, though, I'd exposed the <code>id</code> property in JSON, and I now wanted to perform an experiment: Could I remove the field? </p> <p> A word of warning: You can't just remove a JSON property from a production API. That would constitute a breaking change, and even though clients aren't supposed to use the <code>id</code>, <a href="https://www.hyrumslaw.com">Hyrum's law</a> says that someone somewhere probably already is. </p> <p> This is just an experiment that I carried out on a separate Git branch, for my own edification. </p> <h3 id="3cf78b876e2a4f91b3e49b91f89bde02"> Leaning on the compiler <a href="#3cf78b876e2a4f91b3e49b91f89bde02" title="permalink">#</a> </h3> <p> As outlined, I had relatively strong faith in my test suite, so I decided to modify the <a href="https://en.wikipedia.org/wiki/Data_transfer_object">Data Transfer Object</a> (DTO) in question. Before the change, it looked like this: </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;">ReservationDto</span> { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;LinkDto[]?&nbsp;Links&nbsp;{&nbsp;<span style="color:blue;">get</span>;&nbsp;<span style="color:blue;">set</span>;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:blue;">string</span>?&nbsp;Id&nbsp;{&nbsp;<span style="color:blue;">get</span>;&nbsp;<span style="color:blue;">set</span>;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:blue;">string</span>?&nbsp;At&nbsp;{&nbsp;<span style="color:blue;">get</span>;&nbsp;<span style="color:blue;">set</span>;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:blue;">string</span>?&nbsp;Email&nbsp;{&nbsp;<span style="color:blue;">get</span>;&nbsp;<span style="color:blue;">set</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;<span style="color:blue;">set</span>;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:blue;">int</span>&nbsp;Quantity&nbsp;{&nbsp;<span style="color:blue;">get</span>;&nbsp;<span style="color:blue;">set</span>;&nbsp;} }</pre> </p> <p> At first, I simply tried to delete the <code>Id</code> property, but while it turned out to be not too bad in general, it did break one feature: The ability of <a href="/2020/08/24/adding-rest-links-as-a-cross-cutting-concern">the LinksFilter</a> to generate links to reservations. Instead, I changed the <code>Id</code> property to be internal: </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;">ReservationDto</span> { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;LinkDto[]?&nbsp;Links&nbsp;{&nbsp;<span style="color:blue;">get</span>;&nbsp;<span style="color:blue;">set</span>;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">internal</span>&nbsp;<span style="color:blue;">string</span>?&nbsp;Id&nbsp;{&nbsp;<span style="color:blue;">get</span>;&nbsp;<span style="color:blue;">set</span>;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:blue;">string</span>?&nbsp;At&nbsp;{&nbsp;<span style="color:blue;">get</span>;&nbsp;<span style="color:blue;">set</span>;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:blue;">string</span>?&nbsp;Email&nbsp;{&nbsp;<span style="color:blue;">get</span>;&nbsp;<span style="color:blue;">set</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;<span style="color:blue;">set</span>;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:blue;">int</span>&nbsp;Quantity&nbsp;{&nbsp;<span style="color:blue;">get</span>;&nbsp;<span style="color:blue;">set</span>;&nbsp;} }</pre> </p> <p> This enables the <code>LinksFilter</code> and other internal code to still access the <code>Id</code> property, while the unit tests no longer could. As expected, this change caused some compiler errors. That was expected, and my plan was to <em>lean on the compiler</em>, as <a href="https://michaelfeathers.silvrback.com">Michael Feathers</a> describes in <a href="http://bit.ly/working-effectively-with-legacy-code">Working Effectively with Legacy Code</a>. </p> <p> As I had hoped, relatively few things broke, and they were fixed in 5-10 minutes. Once everything compiled, I ran the tests. Only a single test failed, and this was a unit test that used some Back Door Manipulation, as <a href="http://bit.ly/xunitpatterns">xUnit Test Patterns</a> terms it. I'll return to that test in <a href="/2021/09/27/the-equivalence-contravariant-functor">a future article</a>. </p> <p> None of my self-hosted integration tests failed. </p> <h3 id="d65ef3b7816c4f73b1060af4532fe1dc"> ID-free interaction <a href="#d65ef3b7816c4f73b1060af4532fe1dc" title="permalink">#</a> </h3> <p> Since clients are supposed to follow links, they can still do so. For example, a <a href="https://en.wikipedia.org/wiki/Maître_d%27hôtel">maître d'hôtel</a> might request the day's schedule: </p> <p> <pre>GET /restaurants/90125/schedule/2021/12/8?sig=82fosBYsE9zSKkA4Biy5t%2BFMxl71XiLlFKaI2E[...] HTTP/1.1 Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZXN0YXVyYW50IjpbIjEiLCIyMTEyIiwi[...] HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 { &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;name&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;The&nbsp;Vatican&nbsp;Cellar&quot;</span>, &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;year&quot;</span>:&nbsp;2021, &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;month&quot;</span>:&nbsp;12, &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;day&quot;</span>:&nbsp;8, &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;date&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;2021-12-08&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;20:30:00&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;reservations&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;&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;&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:reservation&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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://example.com/restaurants/90125/reservations/bf4e84130dac4[...]&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;&nbsp;&nbsp;&nbsp;&nbsp;], &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;at&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;2021-12-08T20:30:00.0000000&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;email&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;snomob@example.com&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;name&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;Snow&nbsp;Moe&nbsp;Beal&quot;</span>, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2e75b6;">&quot;quantity&quot;</span>:&nbsp;1 &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;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;] &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;] }</pre> </p> <p> I've edited the response quite heavily by removing other links, and so on. </p> <p> Clients that wish to navigate to Snow Moe Beal's reservation must locate its <code>urn:reservation</code> link and use the corresponding <code>href</code> value. This is an opaque URL that clients can use to make requests: </p> <p> <pre>GET /restaurants/90125/reservations/bf4e84130dac451b9c94049da8ea8c17?sig=vxkBT1g1GHRmx[...] HTTP/1.1 HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 { &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;at&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;2021-12-08T20:30:00.0000000&quot;</span>, &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;email&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;snomob@example.com&quot;</span>, &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;name&quot;</span>:&nbsp;<span style="color:#a31515;">&quot;Snow&nbsp;Moe&nbsp;Beal&quot;</span>, &nbsp;&nbsp;<span style="color:#2e75b6;">&quot;quantity&quot;</span>:&nbsp;1 }</pre> </p> <p> In none of these interactions do clients rely on the <code>id</code> property - which is also gone now. It's gone because the <code>Id</code> property on the C# DTO is <code>internal</code>, which means that it's not being rendered. </p> <p> Mission accomplished. </p> <h3 id="849eb1540d7145c78415976e8c662597"> Conclusion <a href="#849eb1540d7145c78415976e8c662597" title="permalink">#</a> </h3> <p> It always grates on me when I have to add an <code>id</code> property to a representation in an HTTP API. It's often necessary when working with a level 2 API, but with a proper hypermedia-driven REST API, it may not be necessary. </p> <p> At least, the experiment I performed with the code base from my book <a href="/code-that-fits-in-your-head">Code That Fits in Your Head</a> indicates that this may be so. </p> </div> <div id="comments"> <hr> <h2 id="comments-header">Comments</h2> <div class="comment" id="cd972bab11b74bf382c5796f5b0bec7a"> <div class="comment-author"><a href="https://www.relativisticramblings.com/">Christer van der Meeren</a></div> <div class="comment-content"> <p>It seems to me that this approach will cause problems if 3rd parties need to integrate with your API in a way where they themselves need to store references to entities in your system. For example, they may expose your entities to their users with additional data in their systems/integrations. Sure, it is <em>possible</em> for them to use the URI as a primary key (<em>if</em> you guarantee a sensible max URI length; another can of worms), but if you internally use INT or UNIQUEIDENTIFIER as your primary key, I would not want to force them to use VARCHAR(whatever) as primary key.</p> <p>Therefore, in all our APIs, we document in the API specification that the IDs, though required by <a target="_blank" href="https://jsonapi.org/">JSON:API</a> (which we follow) to be passed as string values for consistency, can be safely assumed to be integers (or GUIDs, if relevant). We even document that they are <em>32-bit</em> ints, so any clients know they can safely use INT fields instead of BIGINT.</p> <p>JSON:API requires all entities to have a single ID. For obvious reasons, IDs should be stable. Therefore, for entities that represent an association between two other entities and do not have a separate, persisted ID, we have a need to have API IDs that contain information about the associated entities. To combat Hyrum's law, we typically concatenate the associated IDs using a known delimiter and encode the resulting string using a non-standard, URL-friendly encoding (i.e., not Base64, which may contain non-URL-friendly characters and is often obvious). This way, the IDs appear opaque to API clients. Of course, the format of these IDs are not documented in our API specifications, as they are not intended to be stored. Instead, the actual association is documented and the related entities retrievable (of course, since this information inherent to the entity's very nature), and the associated IDs may be used by clients in a multi-column primary key, just like we do.</p> <p>All of the above assumes that the integrating clients use a SQL database or similar. Let's face it; many do. If you have (or may hve in the future) a single client that do this, you have to take the above into account.</p> </div> <div class="comment-date">2021-09-20 9:07 UTC</div> </div> <div class="comment" id="2fa9b78a83b64b33ae16182ed7db450c"> <div class="comment-author"><a href="/">Mark Seemann</a></div> <div class="comment-content"> <p> Christer, thank you for writing. I think that one of the problems with discussions about REST APIs, or just HTTP APIs in general, is that people use them for all sorts of things. At one extreme, you have <a href="https://samnewman.io/patterns/architectural/bff/">Backends For Frontends</a>, where, if you aren't writing the API with the single client in mind, you're doing something wrong. At the other extreme, you have APIs that may have uncountable and unknown clients. When I write about REST, I mostly have the latter kind in mind. </p> <p> When designing APIs for many unknown clients, it makes little sense to take 'special needs' into account. Different clients may present mutually exclusive requirements. </p> <p> Clients that need to 'bookmark' REST resources in a database can do that by defining two columns: one an ordinary primary key column on which the table defines its clustered index, and another column for the link value itself, with a <code>UNIQUE</code> constraint. Something like this (in T-SQL dialect): </p> <p> <pre><span style="color:blue;">CREATE</span>&nbsp;<span style="color:blue;">TABLE</span>&nbsp;[dbo]<span style="color:gray;">.</span>[Foo]<span style="color:blue;">&nbsp;</span><span style="color:gray;">(</span> &nbsp;&nbsp;&nbsp;&nbsp;[Id]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">INT</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:gray;">NOT</span>&nbsp;<span style="color:gray;">NULL</span>&nbsp;<span style="color:blue;">IDENTITY</span>&nbsp;<span style="color:blue;">PRIMARY</span>&nbsp;<span style="color:blue;">KEY</span>&nbsp;<span style="color:blue;">CLUSTERED</span><span style="color:gray;">,</span> &nbsp;&nbsp;&nbsp;&nbsp;[Address]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">NVARCHAR&nbsp;</span><span style="color:gray;">(</span>850<span style="color:gray;">)</span>&nbsp;&nbsp;&nbsp;<span style="color:gray;">NOT</span>&nbsp;<span style="color:gray;">NULL</span>&nbsp;<span style="color:blue;">UNIQUE</span>&nbsp;<span style="color:blue;">NONCLUSTERED</span><span style="color:gray;">,</span> &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:green;">--&nbsp;Other&nbsp;columns&nbsp;go&nbsp;here...</span> <span style="color:gray;">);</span></pre> </p> <p> Client code can look up an API resource on internal key, or on address, as required. </p> </div> <div class="comment-date">2021-09-21 16:27 UTC</div> </div> <div class="comment" id="6a7b06cf97e9453bafe5ddafa5156093"> <div class="comment-author"><a href="https://www.relativisticramblings.com/">Christer van der Meeren</a></div> <div class="comment-content"> <p>Your URLs include a signature, which changes if you need to switch signing keys. Furthermore, the base URL for your API may change. The entities are still the same; the restaurant previously at old.domain/restaurants/1?sig=abc is the same as the restaurant now at new.domain/restaurants/1?sig=123. With your proposed bookmark-based solution, the API clients would effectively lose the associations in their system.</p> <p>Also, indexing a very long varchar column probably works fine for tables that are fairly small and not overly busy. But for large and/or busy tables containing entities that are created every second of every day (say, passages through gates at hundreds of large construction sites, which is one of the domains I work with), I think that the performance would suffer unreasonably. (Admittedly, I have of course not measured this; this is just speculation, and anyway not my main point.)</p> <p>You say you write APIs with arbitrary clients in mind. I do, too. That is one of the reasons I design my APIs at REST level 2 instead of 3. (JSON:API does offer some possibility of just "following links" if the client wishes to do that, though it is does not allow for APIs that are fully level 3/HATEOAS.) Having stable IDs with well-known formats and being able to construct URLs seems pragmatically like a good solution that keeps client developers happy. I do not have decades of experience, but I have never encountered clients who have been unhappy with my decision to go for level 2 instead of level 3. (I imagine I would have encountered some resistance in the opposite case, though that is pure speculation on my part.) Furthermore, I have never encountered the need for breaking changes that would be non-breaking by level 3 standards.</p> <p>You say it makes little sense to take "special needs" into account. Idealistically, I agree. Pragmatically, 1) SQL databases are so ubiquitous and have been for such a long time that making life better for those developers by including an ID with a guaranteed format seems like a fair decision, and 2) our APIs (and many others, I assume) are created not just for 3rd party integration but also for one or more 1st party front-ends, which naturally tends to receive some preferential treatment (e.g. features and designs that probably aren't useful to other clients).</p> </div> <div class="comment-date">2021-09-21 20:56 UTC</div> </div> <div class="comment" id="e1a154854b014ab8ad218b076579db4c"> <div class="comment-author"><a href="/">Mark Seemann</a></div> <div class="comment-content"> <p> Christer, thank you for writing. It's possible that I'm going about this the wrong way. I only report on what's been working for me, but that said, while I <em>do</em> have decades of general programming experience, I don't have decades of REST experience. I designed my first REST API in 2012. </p> <p> Additionally, just because one style of API design works well, that doesn't rule out that other types of design also work. </p> <p> Finally, this particular article is an experiment. I've never done something like this in the wild, so it's possible that it does have unforeseen issues. </p> <p> A couple of answers to your various points, though: </p> <p> I don't foresee having to change signing keys, but if that happens, it'd be a breaking change to remove support for old keys. One might have to, instead, retire old signing keys in the same way one can <a href="/2020/06/01/retiring-old-service-versions">retire old service versions</a>. Even if a key gets 'compromised', it's not an immediate issue. It only means that any client that possesses the leaked key <em>can</em> construct URLs directly by <a href="/2013/05/01/rest-lesson-learned-avoid-hackable-urls">retro-engineering implied URL templates</a>. This would still be undocumented and unsupported use of the API, which means that ultimately, it'd be against the client developers' own self-interest in doing that. </p> <p> <a href="/2020/10/26/fit-urls">Signing the URLs isn't a security measure</a>; it's more like a <a href="https://en.wikipedia.org/wiki/Nudge_theory">nudge</a>. </p> <blockquote> <p> "our APIs (and many others, I assume) are created not just for 3rd party integration but also for one or more 1st party front-ends, which naturally tends to receive some preferential treatment" </p> </blockquote> <p> I've written APIs like that as well, and if there's one thing I've learned from doing that is that if I'm ever again put in charge of such an API, I'll strongly resist giving preferential treatment to any clients. If a particular client needs a particular feature, the client team can develop and maintain a Backend for Frontend, which bases its own implementation on the general-purpose API. </p> <p> My experience with supporting particular clients is that client needs evolve much faster than APIs. This makes sense. Someone wants to do <a href="https://en.wikipedia.org/wiki/A/B_testing">A/B testing</a> on the client's user interface. Depending on the outcome of such a test, at least one of the supporting features will now be obsolete. I'm not much inclined having to support such features in an API where backwards compatibility is critical. </p> <p> But again, these things are never clear-cut. Much depends on the overall goals of the organisation - and these may also change over time. I'm not claiming that my way is <em>best</em> - only that it's possible. </p> </div> <div class="comment-date">2021-09-23 8:07 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/2021/09/20/keep-ids-internal-with-rest Unit testing private helper methods https://blog.ploeh.dk/2021/09/13/unit-testing-private-helper-methods/ Mon, 13 Sep 2021 05:25:00 UTC <div id="post"> <p> <em>Evolving a private helper method, guided by tests.</em> </p> <p> A frequently asked question about unit testing and test-driven development (TDD) is how to test private helper methods. I've <a href="/2015/09/22/unit-testing-internals">already attempted to answer that question: <em>through the public API</em></a>, but a recent comment to <a href="https://stackoverflow.com/a/69141655/126014">a Stack Overflow question</a> made me realise that I've failed to supply a code example. </p> <p> Show, don't tell. </p> <p> In this article I'll show a code example that outlines how a private helper method can evolve under TDD. </p> <h3 id="03e1e533e1514945812c557b006883c3"> Threshold <a href="#03e1e533e1514945812c557b006883c3" title="permalink">#</a> </h3> <p> The code example in this article comes from my book <a href="/code-that-fits-in-your-head">Code That Fits in Your Head</a>. When you buy the book, you get not only the finished code examples, but the entire Git repository, with detailed commit messages. </p> <p> A central part of the code base is a method that decides whether or not to accept a reservation attempt. It's essentially a solution to <a href="/2020/01/27/the-maitre-d-kata/">the Maître d' kata</a>. I wrote most of the book's code with TDD, and after commit <code>fa12fd69c158168178f3a75bcd900e5caa7e7dec</code> I decided that I ought to refactor the implementation. As I wrote in the commit message: </p> <p> <pre>Filter later reservations based on date The line count of the willAccept method has now risen to 28. Cyclomatic complexity is still at 7. It's ripe for refactoring.</pre> </p> <p> I think, by the way, that I made a small mistake. As far as I can tell, the <code>WillAccept</code> line count in this commit is <em>26</em> - not <em>28:</em> </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">bool</span>&nbsp;<span style="color:#74531f;">WillAccept</span>( &nbsp;&nbsp;&nbsp;&nbsp;IEnumerable&lt;Reservation&gt;&nbsp;<span style="color:#1f377f;">existingReservations</span>, &nbsp;&nbsp;&nbsp;&nbsp;Reservation&nbsp;<span style="color:#1f377f;">candidate</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">if</span>&nbsp;(existingReservations&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:#8f08c4;">throw</span>&nbsp;<span style="color:blue;">new</span>&nbsp;ArgumentNullException(nameof(existingReservations)); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">if</span>&nbsp;(candidate&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:#8f08c4;">throw</span>&nbsp;<span style="color:blue;">new</span>&nbsp;ArgumentNullException(nameof(candidate)); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">relevantReservations</span>&nbsp;=&nbsp;existingReservations &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.Where(<span style="color:#1f377f;">r</span>&nbsp;=&gt;&nbsp;candidate.At.Date&nbsp;==&nbsp;r.At.Date); &nbsp;&nbsp;&nbsp;&nbsp;List&lt;Table&gt;&nbsp;<span style="color:#1f377f;">availableTables</span>&nbsp;=&nbsp;Tables.ToList(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">foreach</span>&nbsp;(var&nbsp;<span style="color:#1f377f;">r</span>&nbsp;<span style="color:#8f08c4;">in</span>&nbsp;relevantReservations) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">table</span>&nbsp;=&nbsp;availableTables.Find(<span style="color:#1f377f;">t</span>&nbsp;=&gt;&nbsp;r.Quantity&nbsp;&lt;=&nbsp;t.Seats); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">if</span>&nbsp;(table&nbsp;<span style="color:blue;">is</span>&nbsp;{&nbsp;}) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;availableTables.Remove(table); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">if</span>&nbsp;(table.IsCommunal) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;availableTables.Add(table.Reserve(r.Quantity)); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;availableTables.Any(<span style="color:#1f377f;">t</span>&nbsp;=&gt;&nbsp;candidate.Quantity&nbsp;&lt;=&nbsp;t.Seats); }</pre> </p> <p> Still, I knew that it wasn't done - that I'd be adding more tests that would increase both the size and complexity of the method. It was brushing against more than one <a href="/2020/04/13/curb-code-rot-with-thresholds">threshold</a>. I decided that it was time for a prophylactic refactoring. </p> <p> Notice that the <a href="/2019/10/21/a-red-green-refactor-checklist">red-green-refactor checklist</a> explicitly states that refactoring is part of the process. It doesn't, however, mandate that refactoring must be done in the same commit as the green phase. Here, I did <em>red-green-commit-refactor-commit</em>. </p> <p> While I decided to refactor, I also knew that I still had some way to go before <code>WillAccept</code> would be complete. With the code still in flux, I didn't want to couple tests to a new method, so I chose to extract a <code>private</code> helper method. </p> <h3 id="8db39405ecce4ee9b647866eed0e1383"> Helper method <a href="#8db39405ecce4ee9b647866eed0e1383" title="permalink">#</a> </h3> <p> After the refactoring, the code looked like this: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">bool</span>&nbsp;<span style="color:#74531f;">WillAccept</span>( &nbsp;&nbsp;&nbsp;&nbsp;IEnumerable&lt;Reservation&gt;&nbsp;<span style="color:#1f377f;">existingReservations</span>, &nbsp;&nbsp;&nbsp;&nbsp;Reservation&nbsp;<span style="color:#1f377f;">candidate</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">if</span>&nbsp;(existingReservations&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:#8f08c4;">throw</span>&nbsp;<span style="color:blue;">new</span>&nbsp;ArgumentNullException(nameof(existingReservations)); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">if</span>&nbsp;(candidate&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:#8f08c4;">throw</span>&nbsp;<span style="color:blue;">new</span>&nbsp;ArgumentNullException(nameof(candidate)); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">relevantReservations</span>&nbsp;=&nbsp;existingReservations &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.Where(<span style="color:#1f377f;">r</span>&nbsp;=&gt;&nbsp;candidate.At.Date&nbsp;==&nbsp;r.At.Date); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">availableTables</span>&nbsp;=&nbsp;Allocate(relevantReservations); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;availableTables.Any(<span style="color:#1f377f;">t</span>&nbsp;=&gt;&nbsp;candidate.Quantity&nbsp;&lt;=&nbsp;t.Seats); } <span style="color:blue;">private</span>&nbsp;IEnumerable&lt;Table&gt;&nbsp;<span style="color:#74531f;">Allocate</span>( &nbsp;&nbsp;&nbsp;&nbsp;IEnumerable&lt;Reservation&gt;&nbsp;<span style="color:#1f377f;">reservations</span>) { &nbsp;&nbsp;&nbsp;&nbsp;List&lt;Table&gt;&nbsp;<span style="color:#1f377f;">availableTables</span>&nbsp;=&nbsp;Tables.ToList(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">foreach</span>&nbsp;(var&nbsp;<span style="color:#1f377f;">r</span>&nbsp;<span style="color:#8f08c4;">in</span>&nbsp;reservations) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">table</span>&nbsp;=&nbsp;availableTables.Find(<span style="color:#1f377f;">t</span>&nbsp;=&gt;&nbsp;r.Quantity&nbsp;&lt;=&nbsp;t.Seats); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">if</span>&nbsp;(table&nbsp;<span style="color:blue;">is</span>&nbsp;{&nbsp;}) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;availableTables.Remove(table); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">if</span>&nbsp;(table.IsCommunal) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;availableTables.Add(table.Reserve(r.Quantity)); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;availableTables; }</pre> </p> <p> I committed the change, and wrote in the commit message: </p> <p> <pre>Extract helper method from WillAccept This quite improves the complexity of the method, which is now 4, and at 18 lines of code. The new helper method also has a cyclomatic complexity of 4, and 17 lines of code. A remaining issue with the WillAccept method is that the code operates on different levels of abstraction. The call to Allocate represents an abstraction, while the filter on date is as low-level as it can get.</pre> </p> <p> As you can tell, I was well aware that there were remaining issues with the code. </p> <p> Since the new <code>Allocate</code> helper method is <code>private</code>, unit tests can't reach it directly. It's still <em>covered</em> by tests, though, just as that code block was before I extracted it. </p> <h3 id="b8928ae201444a78b7ca1715e486fb92"> More tests <a href="#b8928ae201444a78b7ca1715e486fb92" title="permalink">#</a> </h3> <p> I wasn't done with the <code>WillAccept</code> method, and after a bout of other refactorings, I added more test cases covering it. </p> <p> While the method ultimately grew to exhibit moderately complex behaviour, I had only two test methods covering it: one (not shown) for the rejection case, and another for the accept (<code>true</code>) case: </p> <p> <pre>[Theory,&nbsp;ClassData(<span style="color:blue;">typeof</span>(AcceptTestCases))] <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">void</span>&nbsp;<span style="color:#74531f;">Accept</span>( &nbsp;&nbsp;&nbsp;&nbsp;TimeSpan&nbsp;<span style="color:#1f377f;">seatingDuration</span>, &nbsp;&nbsp;&nbsp;&nbsp;IEnumerable&lt;Table&gt;&nbsp;<span style="color:#1f377f;">tables</span>, &nbsp;&nbsp;&nbsp;&nbsp;IEnumerable&lt;Reservation&gt;&nbsp;<span style="color:#1f377f;">reservations</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">sut</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;MaitreD(seatingDuration,&nbsp;tables); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">r</span>&nbsp;=&nbsp;Some.Reservation.WithQuantity(11); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">actual</span>&nbsp;=&nbsp;sut.WillAccept(reservations,&nbsp;r); &nbsp;&nbsp;&nbsp;&nbsp;Assert.True(actual); }</pre> </p> <p> I based the example code on the <a href="/2020/03/02/impureim-sandwich">impureim sandwich architecture</a>, which meant that domain logic (including the <code>WillAccept</code> method) is all <a href="https://en.wikipedia.org/wiki/Pure_function">pure functions</a>. The nice thing about pure functions is that <a href="/2015/05/07/functional-design-is-intrinsically-testable">they're easy to unit test</a>. </p> <p> The <code>Accept</code> test method uses an object data source (see the article <a href="/2021/01/18/parametrised-test-primitive-obsession-code-smell">Parametrised test primitive obsession code smell</a> for another example of the motivation behind using objects for test parametrisation), so adding more test cases were simply a matter of adding them to the data source: </p> <p> <pre><span style="color:silver;">Add(TimeSpan.FromHours(6), &nbsp;&nbsp;&nbsp;&nbsp;new[]&nbsp;{&nbsp;Table.Communal(11)&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;new[]&nbsp;{&nbsp;Some.Reservation.WithQuantity(11).TheDayAfter()&nbsp;});</span> Add(TimeSpan.FromHours(2.5), &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">new</span>[]&nbsp;{&nbsp;Table.Standard(12)&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">new</span>[]&nbsp;{&nbsp;Some.Reservation.WithQuantity(11).AddDate( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TimeSpan.FromHours(-2.5))&nbsp;}); Add(TimeSpan.FromHours(1), &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">new</span>[]&nbsp;{&nbsp;Table.Standard(14)&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">new</span>[]&nbsp;{&nbsp;Some.Reservation.WithQuantity(9).AddDate( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TimeSpan.FromHours(1))&nbsp;});</pre> </p> <p> The bottom two test cases are new additions. In that way, by adding new test cases, I could keep evolving <code>WillAccept</code> and its various private helper methods (of which I added more). While no tests directly exercise the private helper methods, the unit tests still <a href="https://en.wikipedia.org/wiki/Transitive_relation">transitively</a> exercise the private parts of the code base. </p> <p> Since I followed TDD, no private helper methods sprang into existence untested. I didn't have to jump through hoops in order to be able to unit test private helper methods. Rather, the private helper methods were a natural by-product of the red-green-refactor process - particularly, the <em>refactor</em> phase. </p> <h3 id="6c5f4e12a3cb4318a3331cf4f2485028"> Conclusion <a href="#6c5f4e12a3cb4318a3331cf4f2485028" title="permalink">#</a> </h3> <p> Following TDD doesn't preclude the creation of private helper methods. In fact, private helper methods can (and should?) emerge during the refactoring phase of the red-green-refactoring cycle. </p> <p> For long-time practitioners of TDD, there's nothing new in this, but people new to TDD are still learning. This question keeps coming up, so I hope that this example is useful. </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/2021/09/13/unit-testing-private-helper-methods The Specification contravariant functor https://blog.ploeh.dk/2021/09/09/the-specification-contravariant-functor/ Thu, 09 Sep 2021 09:12:00 UTC <div id="post"> <p> <em>An introduction for object-oriented programmers to the Specification contravariant functor.</em> </p> <p> This article is an instalment in <a href="/2021/09/02/contravariant-functors">an article series about contravariant functors</a>. It assumes that you've read the introduction. In the <a href="/2021/09/06/the-command-handler-contravariant-functor">previous article</a>, you saw an example of a contravariant functor based on the Command Handler pattern. This article gives another example. </p> <p> <a href="http://amzn.to/WBCwx7">Domain-Driven Design</a> discusses the benefits of the <a href="https://en.wikipedia.org/wiki/Specification_pattern">Specification pattern</a>. In its generic incarnation this pattern gives rise to a contravariant functor. </p> <h3 id="2d6538ee35d84c47808f6b162f61eeb3"> Interface <a href="#2d6538ee35d84c47808f6b162f61eeb3" title="permalink">#</a> </h3> <p> <a href="http://amzn.to/WBCwx7">DDD</a> introduces the pattern with a non-generic <code>InvoiceSpecification</code> interface. The book also shows other examples, and it quickly becomes clear that with generics, you can generalise the pattern to this interface: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">interface</span>&nbsp;<span style="color:#2b91af;">ISpecification</span>&lt;<span style="color:#2b91af;">T</span>&gt; { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">bool</span>&nbsp;<span style="color:#74531f;">IsSatisfiedBy</span>(T&nbsp;<span style="color:#1f377f;">candidate</span>); }</pre> </p> <p> Given such an interface, you can implement standard reusable Boolean logic such as <em>and</em>, <em>or</em>, and <em>not</em>. (Exercise: consider how implementations of <em>and</em> and <em>or</em> correspond to well-known <a href="/2017/10/06/monoids">monoids</a>. Do the implementations look like <a href="https://en.wikipedia.org/wiki/Composite_pattern">Composites</a>? <a href="/2018/03/12/composite-as-a-monoid">Is that a coincidence?</a>) </p> <p> The <code>ISpecification&lt;T&gt;</code> interface is really just a glorified predicate. These days the Specification pattern may seem somewhat exotic in languages with first-class functions. C#, for example, defines both a <a href="https://docs.microsoft.com/dotnet/api/system.predicate-1">specialised Predicate delegate</a>, as well as the more general <code>Func&lt;T, bool&gt;</code> delegate. Since you can pass those around as objects, that's often good enough, and you don't need an <code>ISpecification</code> interface. </p> <p> Still, for the sake of argument, in this article I'll start with the Specification pattern and demonstrate how that gives rise to a contravariant functor. </p> <h3 id="a13ce5becb564762847a6876f87aa16f"> Natural number specification <a href="#a13ce5becb564762847a6876f87aa16f" title="permalink">#</a> </h3> <p> Consider the <code>AdjustInventoryService</code> class from <a href="/2021/09/06/the-command-handler-contravariant-functor">the previous article</a>. I'll repeat the 'original' <code>Execute</code> method here: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">void</span>&nbsp;<span style="color:#74531f;">Execute</span>(AdjustInventory&nbsp;<span style="color:#1f377f;">command</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">productInventory</span>&nbsp;=&nbsp;<span style="color:blue;">this</span>.repository.GetByIdOrNull(command.ProductId) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;??&nbsp;<span style="color:blue;">new</span>&nbsp;ProductInventory(command.ProductId); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">quantityAdjustment</span>&nbsp;=&nbsp;command.Quantity&nbsp;*&nbsp;(command.Decrease&nbsp;?&nbsp;-1&nbsp;:&nbsp;1); &nbsp;&nbsp;&nbsp;&nbsp;productInventory&nbsp;=&nbsp;productInventory.AdjustQuantity(quantityAdjustment); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">if</span>&nbsp;(productInventory.Quantity&nbsp;&lt;&nbsp;0) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">throw</span>&nbsp;<span style="color:blue;">new</span>&nbsp;InvalidOperationException(<span style="color:#a31515;">&quot;Can&#39;t&nbsp;decrease&nbsp;below&nbsp;0.&quot;</span>); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">this</span>.repository.Save(productInventory); }</pre> </p> <p> Notice the Guard Clause: </p> <p> <pre><span style="color:#8f08c4;">if</span>&nbsp;(productInventory.Quantity&nbsp;&lt;&nbsp;0)</pre> </p> <p> Image that we'd like to introduce some flexibility here. It's admittedly a silly example, but just come along for the edification. Imagine that we'd like to use an injected <code>ISpecification&lt;ProductInventory&gt;</code> instead: </p> <p> <pre><span style="color:#8f08c4;">if</span>&nbsp;(!specification.IsSatisfiedBy(productInventory))</pre> </p> <p> That doesn't sound too difficult, but what if you only have an <code>ISpecification</code> implementation like the following? </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;">NaturalNumber</span>&nbsp;:&nbsp;ISpecification&lt;<span style="color:blue;">int</span>&gt; { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:blue;">readonly</span>&nbsp;<span style="color:blue;">static</span>&nbsp;ISpecification&lt;<span style="color:blue;">int</span>&gt;&nbsp;Specification&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">new</span>&nbsp;NaturalNumber(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">private</span>&nbsp;<span style="color:#2b91af;">NaturalNumber</span>() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:blue;">bool</span>&nbsp;<span style="color:#74531f;">IsSatisfiedBy</span>(<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">candidate</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;0&nbsp;&lt;=&nbsp;candidate; &nbsp;&nbsp;&nbsp;&nbsp;} }</pre> </p> <p> That's essentially what you need, but alas, it only implements <code>ISpecification&lt;int&gt;</code>, not <code>ISpecification&lt;ProductInventory&gt;</code>. Do you <em>really</em> have to write a new <a href="https://en.wikipedia.org/wiki/Adapter_pattern">Adapter</a> just to implement the right interface? </p> <p> No, you don't. </p> <h3 id="069f9ff7ee4d41dab4cf9243804dc873"> Contravariant functor <a href="#069f9ff7ee4d41dab4cf9243804dc873" title="permalink">#</a> </h3> <p> Fortunately, an interface like <code>ISpecification&lt;T&gt;</code> gives rise to a contravariant functor. This will enable you to compose an <code>ISpecification&lt;ProductInventory&gt;</code> object from the <code>NaturalNumber</code> specification. </p> <p> In order to enable contravariant mapping, you must add a <code>ContraMap</code> method: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">static</span>&nbsp;ISpecification&lt;T1&gt;&nbsp;<span style="color:#74531f;">ContraMap</span>&lt;<span style="color:#2b91af;">T</span>,&nbsp;<span style="color:#2b91af;">T1</span>&gt;( &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">this</span>&nbsp;ISpecification&lt;T&gt;&nbsp;<span style="color:#1f377f;">source</span>, &nbsp;&nbsp;&nbsp;&nbsp;Func&lt;T1,&nbsp;T&gt;&nbsp;<span style="color:#1f377f;">selector</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;<span style="color:blue;">new</span>&nbsp;ContraSpecification&lt;T,&nbsp;T1&gt;(source,&nbsp;selector); } <span style="color:blue;">private</span>&nbsp;<span style="color:blue;">class</span>&nbsp;<span style="color:#2b91af;">ContraSpecification</span>&lt;<span style="color:#2b91af;">T</span>,&nbsp;<span style="color:#2b91af;">T1</span>&gt;&nbsp;:&nbsp;ISpecification&lt;T1&gt; { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">private</span>&nbsp;<span style="color:blue;">readonly</span>&nbsp;ISpecification&lt;T&gt;&nbsp;source; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">private</span>&nbsp;<span style="color:blue;">readonly</span>&nbsp;Func&lt;T1,&nbsp;T&gt;&nbsp;selector; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">ContraSpecification</span>(ISpecification&lt;T&gt;&nbsp;<span style="color:#1f377f;">source</span>,&nbsp;Func&lt;T1,&nbsp;T&gt;&nbsp;<span style="color:#1f377f;">selector</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">this</span>.source&nbsp;=&nbsp;source; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">this</span>.selector&nbsp;=&nbsp;selector; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:blue;">bool</span>&nbsp;<span style="color:#74531f;">IsSatisfiedBy</span>(T1&nbsp;<span style="color:#1f377f;">candidate</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;source.IsSatisfiedBy(selector(candidate)); &nbsp;&nbsp;&nbsp;&nbsp;} }</pre> </p> <p> Notice that, as explained in the overview article, in order to map from an <code>ISpecification&lt;T&gt;</code> to an <code>ISpecification&lt;T1&gt;</code>, the <code>selector</code> has to go the other way: from <code>T1</code> to <code>T</code>. How this is possible will become more apparent with an example, which will follow later in the article. </p> <h3 id="f3211a80973c4d85b63a564704e67028"> Identity law <a href="#f3211a80973c4d85b63a564704e67028" title="permalink">#</a> </h3> <p> A <code>ContraMap</code> method with the right signature isn't enough to be a contravariant functor. It must also obey the contravariant functor laws. As usual, it's proper computer-science work to actually prove this, but you can write some tests to demonstrate the identity law for the <code>ISpecification&lt;T&gt;</code> interface. In this article, you'll see parametrised tests written with <a href="https://xunit.net">xUnit.net</a>. First, the identity law: </p> <p> <pre>[Theory] [InlineData(-102)] [InlineData(&nbsp;&nbsp;-3)] [InlineData(&nbsp;&nbsp;-1)] [InlineData(&nbsp;&nbsp;&nbsp;0)] [InlineData(&nbsp;&nbsp;&nbsp;1)] [InlineData(&nbsp;&nbsp;32)] [InlineData(&nbsp;283)] <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">void</span>&nbsp;<span style="color:#74531f;">IdentityLaw</span>(<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">input</span>) { &nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;<span style="color:#74531f;">id</span>&lt;<span style="color:#2b91af;">T</span>&gt;(T&nbsp;<span style="color:#1f377f;">x</span>)&nbsp;=&gt;&nbsp;x; &nbsp;&nbsp;&nbsp;&nbsp;ISpecification&lt;<span style="color:blue;">int</span>&gt;&nbsp;<span style="color:#1f377f;">projection</span>&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NaturalNumber.Specification.ContraMap&lt;<span style="color:blue;">int</span>,&nbsp;<span style="color:blue;">int</span>&gt;(id); &nbsp;&nbsp;&nbsp;&nbsp;Assert.Equal( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NaturalNumber.Specification.IsSatisfiedBy(input), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;projection.IsSatisfiedBy(input)); }</pre> </p> <p> In order to observe that the two Specifications have identical behaviours, the test has to invoke <code>IsSatisfiedBy</code> on both of them to verify that the return values are the same. </p> <p> All test cases pass. </p> <h3 id="84d4761adecd427fbd9e463a05e8cc67"> Composition law <a href="#84d4761adecd427fbd9e463a05e8cc67" title="permalink">#</a> </h3> <p> Like the above example, you can also write a parametrised test that demonstrates that <code>ContraMap</code> obeys the composition law for contravariant functors: </p> <p> <pre>[Theory] [InlineData(&nbsp;&nbsp;&nbsp;<span style="color:#a31515;">&quot;0:05&quot;</span>)] [InlineData(&nbsp;&nbsp;&nbsp;<span style="color:#a31515;">&quot;1:20&quot;</span>)] [InlineData(&nbsp;&nbsp;&nbsp;<span style="color:#a31515;">&quot;0:12:10&quot;</span>)] [InlineData(&nbsp;&nbsp;&nbsp;<span style="color:#a31515;">&quot;1:00:12&quot;</span>)] [InlineData(<span style="color:#a31515;">&quot;1.13:14:34&quot;</span>)] <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">void</span>&nbsp;<span style="color:#74531f;">CompositionLaw</span>(<span style="color:blue;">string</span>&nbsp;<span style="color:#1f377f;">input</span>) { &nbsp;&nbsp;&nbsp;&nbsp;Func&lt;<span style="color:blue;">string</span>,&nbsp;TimeSpan&gt;&nbsp;<span style="color:#1f377f;">f</span>&nbsp;=&nbsp;TimeSpan.Parse; &nbsp;&nbsp;&nbsp;&nbsp;Func&lt;TimeSpan,&nbsp;<span style="color:blue;">int</span>&gt;&nbsp;<span style="color:#1f377f;">g</span>&nbsp;=&nbsp;<span style="color:#1f377f;">ts</span>&nbsp;=&gt;&nbsp;(<span style="color:blue;">int</span>)ts.TotalMinutes; &nbsp;&nbsp;&nbsp;&nbsp;Assert.Equal( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NaturalNumber.Specification.ContraMap((<span style="color:blue;">string</span>&nbsp;<span style="color:#1f377f;">s</span>)&nbsp;=&gt;&nbsp;g(f(s))).IsSatisfiedBy(input), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NaturalNumber.Specification.ContraMap(g).ContraMap(f).IsSatisfiedBy(input)); }</pre> </p> <p> This test defines two local functions, <code>f</code> and <code>g</code>. Once more, you can't directly compare methods for equality, so instead you have to call <code>IsSatisfiedBy</code> on both compositions to verify that they return the same Boolean value. </p> <p> They do. </p> <h3 id="94ecc00ea3064f86b48c45d0e9627cc8"> Product inventory specification <a href="#94ecc00ea3064f86b48c45d0e9627cc8" title="permalink">#</a> </h3> <p> You can now produce the desired <code>ISpecification&lt;ProductInventory&gt;</code> from the <code>NaturalNumber</code> Specification without having to add a new class: </p> <p> <pre>ISpecification&lt;ProductInventory&gt;&nbsp;<span style="color:#1f377f;">specification</span>&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;NaturalNumber.Specification.ContraMap((ProductInventory&nbsp;<span style="color:#1f377f;">inv</span>)&nbsp;=&gt;&nbsp;inv.Quantity);</pre> </p> <p> Granted, it is, once more, a silly example, but the purpose of this article isn't to convince you that this is better (it probably isn't). The purpose of the article is to show an example of a contravariant functor, and how it can be used. </p> <h3 id="376573ff36c64561b5fc231589f6922f"> Predicates <a href="#376573ff36c64561b5fc231589f6922f" title="permalink">#</a> </h3> <p> For good measure, any predicate forms a contravariant functor. You don't need the <code>ISpecification</code> interface. Here are <code>ContraMap</code> overloads for <code>Predicate&lt;T&gt;</code> and <code>Func&lt;T, bool&gt;</code>: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">static</span>&nbsp;Predicate&lt;T1&gt;&nbsp;<span style="color:#74531f;">ContraMap</span>&lt;<span style="color:#2b91af;">T</span>,&nbsp;<span style="color:#2b91af;">T1</span>&gt;(<span style="color:blue;">this</span>&nbsp;Predicate&lt;T&gt;&nbsp;<span style="color:#1f377f;">predicate</span>,&nbsp;Func&lt;T1,&nbsp;T&gt;&nbsp;<span style="color:#1f377f;">selector</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;<span style="color:#1f377f;">x</span>&nbsp;=&gt;&nbsp;predicate(selector(x)); } <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">static</span>&nbsp;Func&lt;T1,&nbsp;<span style="color:blue;">bool</span>&gt;&nbsp;<span style="color:#74531f;">ContraMap</span>&lt;<span style="color:#2b91af;">T</span>,&nbsp;<span style="color:#2b91af;">T1</span>&gt;(<span style="color:blue;">this</span>&nbsp;Func&lt;T,&nbsp;<span style="color:blue;">bool</span>&gt;&nbsp;<span style="color:#1f377f;">predicate</span>,&nbsp;Func&lt;T1,&nbsp;T&gt;&nbsp;<span style="color:#1f377f;">selector</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;<span style="color:#1f377f;">x</span>&nbsp;=&gt;&nbsp;predicate(selector(x)); }</pre> </p> <p> Notice that the lambda expressions are identical in both implementations. </p> <h3 id="4c2e7471713547d5a24a20dacce49806"> Conclusion <a href="#4c2e7471713547d5a24a20dacce49806" title="permalink">#</a> </h3> <p> Like Command Handlers and Event Handlers, generic predicates give rise to a contravariant functor. This includes both the Specification pattern, <code>Predicate&lt;T&gt;</code>, and <code>Func&lt;T, bool&gt;</code>. </p> <p> Are you noticing a pattern? </p> <p> <strong>Next:</strong> <a href="/2021/09/27/the-equivalence-contravariant-functor">The Equivalence contravariant functor</a>. </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/2021/09/09/the-specification-contravariant-functor The Command Handler contravariant functor https://blog.ploeh.dk/2021/09/06/the-command-handler-contravariant-functor/ Mon, 06 Sep 2021 05:46:00 UTC <div id="post"> <p> <em>An introduction to the Command Handler contravariant functor for object-oriented programmers.</em> </p> <p> This article is an instalment in <a href="/2021/09/02/contravariant-functors">an article series about contravariant functors</a>. It assumes that you've read the introduction. </p> <p> Asynchronous software architectures, such as those described in <a href="http://bit.ly/eipatterns">Enterprise Integration Patterns</a>, often make good use of a pattern where <em>Commands</em> are (preferably immutable) <a href="https://en.wikipedia.org/wiki/Data_transfer_object">Data Transfer Objects</a> (DTOs) that are often placed on a persistent queue and later handled by a background process. </p> <p> Even if you don't use asynchronous processing, separating command data from command handling can be beneficial for your software's granular architecture. In perhaps his most remarkable contribution to <a href="/dippp">our book</a>, <a href="https://blogs.cuttingedge.it/steven">Steven van Deursen</a> describes how this pattern can greatly simplify how you deal with cross-cutting concerns. </p> <h3 id="3d338bea6fa74d149b239067a283967c"> Interface <a href="#3d338bea6fa74d149b239067a283967c" title="permalink">#</a> </h3> <p> In <a href="/dippp">DIPPP</a> the interface is called <code>ICommandService</code>, but in this article I'll instead call it <code>ICommandHandler</code>. It's a generic interface with a single method: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">interface</span>&nbsp;<span style="color:#2b91af;">ICommandHandler</span>&lt;<span style="color:#2b91af;">TCommand</span>&gt; { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">void</span>&nbsp;<span style="color:#74531f;">Execute</span>(TCommand&nbsp;<span style="color:#1f377f;">command</span>); }</pre> </p> <p> The book explains how this interface enables you to gracefully handle cross-cutting concerns without any reflection magic. You can also peruse <a href="https://github.com/DependencyInjection-2nd-edition/codesamples">its example code base on GitHub</a>. In this article, however, I'm using <a href="https://github.com/ploeh/codesamples">a fork of that code</a> because I wanted to make the properties of contravariant functors stand out more clearly. </p> <p> In the sample code base, an ASP.NET Controller delegates work to an injected <code>ICommandHandler&lt;AdjustInventory&gt;</code> called <code>inventoryAdjuster</code>. </p> <p> <pre>[Route(<span style="color:#a31515;">&quot;inventory/adjustinventory&quot;</span>)] <span style="color:blue;">public</span>&nbsp;ActionResult&nbsp;<span style="color:#74531f;">AdjustInventory</span>(AdjustInventoryViewModel&nbsp;<span style="color:#1f377f;">viewModel</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">if</span>&nbsp;(!<span style="color:blue;">this</span>.ModelState.IsValid) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;<span style="color:blue;">this</span>.View(nameof(Index),&nbsp;<span style="color:blue;">this</span>.Populate(viewModel)); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;AdjustInventory&nbsp;<span style="color:#1f377f;">command</span>&nbsp;=&nbsp;viewModel.Command; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">this</span>.inventoryAdjuster.Execute(command); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">this</span>.TempData[<span style="color:#a31515;">&quot;SuccessMessage&quot;</span>]&nbsp;=&nbsp;<span style="color:#a31515;">&quot;Inventory&nbsp;successfully&nbsp;adjusted.&quot;</span>; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;<span style="color:blue;">this</span>.RedirectToAction(nameof(HomeController.Index),&nbsp;<span style="color:#a31515;">&quot;Home&quot;</span>); }</pre> </p> <p> There's a single implementation of <code>ICommandHandler&lt;AdjustInventory&gt;</code>, which is a class called <code>AdjustInventoryService</code>: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">class</span>&nbsp;<span style="color:#2b91af;">AdjustInventoryService</span>&nbsp;:&nbsp;ICommandHandler&lt;AdjustInventory&gt; { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">private</span>&nbsp;<span style="color:blue;">readonly</span>&nbsp;IInventoryRepository&nbsp;repository; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">AdjustInventoryService</span>(IInventoryRepository&nbsp;<span style="color:#1f377f;">repository</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">if</span>&nbsp;(repository&nbsp;==&nbsp;<span style="color:blue;">null</span>) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">throw</span>&nbsp;<span style="color:blue;">new</span>&nbsp;ArgumentNullException(nameof(repository)); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">this</span>.repository&nbsp;=&nbsp;repository; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:blue;">void</span>&nbsp;<span style="color:#74531f;">Execute</span>(AdjustInventory&nbsp;<span style="color:#1f377f;">command</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">productInventory</span>&nbsp;=&nbsp;<span style="color:blue;">this</span>.repository.GetByIdOrNull(command.ProductId) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;??&nbsp;<span style="color:blue;">new</span>&nbsp;ProductInventory(command.ProductId); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">quantityAdjustment</span>&nbsp;=&nbsp;command.Quantity&nbsp;*&nbsp;(command.Decrease&nbsp;?&nbsp;-1&nbsp;:&nbsp;1); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;productInventory&nbsp;=&nbsp;productInventory.AdjustQuantity(quantityAdjustment); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">if</span>&nbsp;(productInventory.Quantity&nbsp;&lt;&nbsp;0) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">throw</span>&nbsp;<span style="color:blue;">new</span>&nbsp;InvalidOperationException(<span style="color:#a31515;">&quot;Can&#39;t&nbsp;decrease&nbsp;below&nbsp;0.&quot;</span>); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">this</span>.repository.Save(productInventory); &nbsp;&nbsp;&nbsp;&nbsp;} }</pre> </p> <p> The <code>Execute</code> method first loads the inventory data from the database, calculates how to adjust it, and saves it. This is all fine and good object-oriented design, and my intent with the present article isn't to point fingers at it. My intent is only to demonstrate how the <code>ICommandHandler</code> interface gives rise to a contravariant functor. </p> <p> I'm using this particular code base because it provides a good setting for a realistic example. </p> <h3 id="24bc8cde80ca4234b4eea11c7617a784"> Towards Domain-Driven Design <a href="#24bc8cde80ca4234b4eea11c7617a784" title="permalink">#</a> </h3> <p> Consider these two lines of code from <code>AdjustInventoryService</code>: </p> <p> <pre><span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">quantityAdjustment</span>&nbsp;=&nbsp;command.Quantity&nbsp;*&nbsp;(command.Decrease&nbsp;?&nbsp;-1&nbsp;:&nbsp;1); productInventory&nbsp;=&nbsp;productInventory.AdjustQuantity(quantityAdjustment);</pre> </p> <p> Doesn't that look like a case of <a href="https://wiki.c2.com/?FeatureEnvySmell">Feature Envy</a>? Doesn't this calculation belong better on another class? Which one? The <code>AdjustInventory</code> Command? That's one option, but in this style of architecture Commands are supposed to be dumb DTOs, so that may not be the best fit. <code>ProductInventory</code>? That may be more promising. </p> <p> Before making that change, however, let's consider the current state of the class. </p> <p> One of the changes I made in my fork of the code was to turn the <code>ProductInventory</code> class into an immutable <a href="https://martinfowler.com/bliki/ValueObject.html">Value Object</a>, as recommended in <a href="http://amzn.to/WBCwx7">DDD</a>: </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;">ProductInventory</span> { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">ProductInventory</span>(Guid&nbsp;<span style="color:#1f377f;">id</span>)&nbsp;:&nbsp;<span style="color:blue;">this</span>(id,&nbsp;0) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">ProductInventory</span>(Guid&nbsp;<span style="color:#1f377f;">id</span>,&nbsp;<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">quantity</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Id&nbsp;=&nbsp;id; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Quantity&nbsp;=&nbsp;quantity; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;Guid&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;">int</span>&nbsp;Quantity&nbsp;{&nbsp;<span style="color:blue;">get</span>;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;ProductInventory&nbsp;<span style="color:#74531f;">WithQuantity</span>(<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">newQuantity</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;<span style="color:blue;">new</span>&nbsp;ProductInventory(Id,&nbsp;newQuantity); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;ProductInventory&nbsp;<span style="color:#74531f;">AdjustQuantity</span>(<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">adjustment</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;WithQuantity(Quantity&nbsp;+&nbsp;adjustment); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:blue;">override</span>&nbsp;<span style="color:blue;">bool</span>&nbsp;<span style="color:#74531f;">Equals</span>(<span style="color:blue;">object</span>&nbsp;<span style="color:#1f377f;">obj</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;obj&nbsp;<span style="color:blue;">is</span>&nbsp;ProductInventory&nbsp;<span style="color:#1f377f;">inventory</span>&nbsp;&amp;&amp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Id.Equals(inventory.Id)&nbsp;&amp;&amp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Quantity&nbsp;==&nbsp;inventory.Quantity; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:blue;">override</span>&nbsp;<span style="color:blue;">int</span>&nbsp;<span style="color:#74531f;">GetHashCode</span>() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;HashCode.Combine(Id,&nbsp;Quantity); &nbsp;&nbsp;&nbsp;&nbsp;} }</pre> </p> <p> That looks like a lot of code, but keep in mind that <a href="/2018/09/17/typing-is-not-a-programming-bottleneck">typing isn't the bottleneck</a> - and besides, most of that code was written by various Visual Studio <em>Quick Actions</em>. </p> <p> Let's try to add a <code>Handle</code> method to <code>ProductInventory</code>: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;ProductInventory&nbsp;<span style="color:#74531f;">Handle</span>(AdjustInventory&nbsp;<span style="color:#1f377f;">command</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">adjustment</span>&nbsp;=&nbsp;command.Quantity&nbsp;*&nbsp;(command.Decrease&nbsp;?&nbsp;-1&nbsp;:&nbsp;1); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;AdjustQuantity(adjustment); }</pre> </p> <p> While <code>AdjustInventoryService</code> isn't too difficult to unit test, it still does require setting up and configuring some <a href="https://martinfowler.com/bliki/TestDouble.html">Test Doubles</a>. The new method, on the other hand, is actually a <a href="https://en.wikipedia.org/wiki/Pure_function">pure function</a>, which means that <a href="/2015/05/07/functional-design-is-intrinsically-testable">it's trivial to unit test</a>: </p> <p> <pre>[Theory] [InlineData(0,&nbsp;<span style="color:blue;">false</span>,&nbsp;0,&nbsp;0)] [InlineData(0,&nbsp;&nbsp;<span style="color:blue;">true</span>,&nbsp;0,&nbsp;0)] [InlineData(0,&nbsp;<span style="color:blue;">false</span>,&nbsp;1,&nbsp;1)] [InlineData(0,&nbsp;<span style="color:blue;">false</span>,&nbsp;2,&nbsp;2)] [InlineData(1,&nbsp;<span style="color:blue;">false</span>,&nbsp;1,&nbsp;2)] [InlineData(2,&nbsp;<span style="color:blue;">false</span>,&nbsp;3,&nbsp;5)] [InlineData(5,&nbsp;&nbsp;<span style="color:blue;">true</span>,&nbsp;2,&nbsp;3)] [InlineData(5,&nbsp;&nbsp;<span style="color:blue;">true</span>,&nbsp;5,&nbsp;0)] <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">void</span>&nbsp;<span style="color:#74531f;">Handle</span>( &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">initial</span>, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">bool</span>&nbsp;<span style="color:#1f377f;">decrease</span>, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">adjustment</span>, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">expected</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">sut</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;ProductInventory(Guid.NewGuid(),&nbsp;initial); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">command</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;AdjustInventory &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ProductId&nbsp;=&nbsp;sut.Id, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Decrease&nbsp;=&nbsp;decrease, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Quantity&nbsp;=&nbsp;adjustment &nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">actual</span>&nbsp;=&nbsp;sut.Handle(command); &nbsp;&nbsp;&nbsp;&nbsp;Assert.Equal(sut.WithQuantity(expected),&nbsp;actual); }</pre> </p> <p> Now that the new function is available on <code>ProductInventory</code>, you can use it in <code>AdjustInventoryService</code>: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">void</span>&nbsp;<span style="color:#74531f;">Execute</span>(AdjustInventory&nbsp;<span style="color:#1f377f;">command</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">productInventory</span>&nbsp;=&nbsp;<span style="color:blue;">this</span>.repository.GetByIdOrNull(command.ProductId) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;??&nbsp;<span style="color:blue;">new</span>&nbsp;ProductInventory(command.ProductId); &nbsp;&nbsp;&nbsp;&nbsp;productInventory&nbsp;=&nbsp;productInventory.Handle(command); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">if</span>&nbsp;(productInventory.Quantity&nbsp;&lt;&nbsp;0) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">throw</span>&nbsp;<span style="color:blue;">new</span>&nbsp;InvalidOperationException(<span style="color:#a31515;">&quot;Can&#39;t&nbsp;decrease&nbsp;below&nbsp;0.&quot;</span>); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">this</span>.repository.Save(productInventory); }</pre> </p> <p> The <code>Execute</code> method now delegates its central logic to <code>ProductInventory.Handle</code>. </p> <h3 id="ee1b47388e1340a9ac8ced8eb3d7a181"> Encapsulation <a href="#ee1b47388e1340a9ac8ced8eb3d7a181" title="permalink">#</a> </h3> <p> If you consider the <code>Execute</code> method in its current incarnation, you may wonder why it checks whether the <code>Quantity</code> is negative. Shouldn't that be the responsibility of <code>ProductInventory</code>? Why do we even allow <code>ProductInventory</code> to enter an invalid state? </p> <p> This breaks encapsulation. Encapsulation is one of the most misunderstood concepts in programming, but as <a href="/encapsulation-and-solid">I explain in my PluralSight course</a>, as a minimum requirement, an object should not allow itself to be put into an invalid state. </p> <p> How to better encapsulate <code>ProductInventory</code>? Add a Guard Clause to the constructor: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">ProductInventory</span>(Guid&nbsp;<span style="color:#1f377f;">id</span>,&nbsp;<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">quantity</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">if</span>&nbsp;(quantity&nbsp;&lt;&nbsp;0) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">throw</span>&nbsp;<span style="color:blue;">new</span>&nbsp;ArgumentOutOfRangeException( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nameof(quantity), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#a31515;">&quot;Negative&nbsp;quantity&nbsp;not&nbsp;allowed.&quot;</span>); &nbsp;&nbsp;&nbsp;&nbsp;Id&nbsp;=&nbsp;id; &nbsp;&nbsp;&nbsp;&nbsp;Quantity&nbsp;=&nbsp;quantity; }</pre> </p> <p> Again, such behaviour is trivial to drive with a unit test: </p> <p> <pre>[Theory] [InlineData(&nbsp;-1)] [InlineData(&nbsp;-2)] [InlineData(-19)] <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">void</span>&nbsp;<span style="color:#74531f;">SetNegativeQuantity</span>(<span style="color:blue;">int</span>&nbsp;<span style="color:#1f377f;">negative</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">id</span>&nbsp;=&nbsp;Guid.NewGuid(); &nbsp;&nbsp;&nbsp;&nbsp;Action&nbsp;<span style="color:#1f377f;">action</span>&nbsp;=&nbsp;()&nbsp;=&gt;&nbsp;<span style="color:blue;">new</span>&nbsp;ProductInventory(id,&nbsp;negative); &nbsp;&nbsp;&nbsp;&nbsp;Assert.Throws&lt;ArgumentOutOfRangeException&gt;(action); }</pre> </p> <p> With those changes in place, <code>AdjustInventoryService</code> becomes even simpler: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">void</span>&nbsp;<span style="color:#74531f;">Execute</span>(AdjustInventory&nbsp;<span style="color:#1f377f;">command</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">productInventory</span>&nbsp;=&nbsp;<span style="color:blue;">this</span>.repository.GetByIdOrNull(command.ProductId) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;??&nbsp;<span style="color:blue;">new</span>&nbsp;ProductInventory(command.ProductId); &nbsp;&nbsp;&nbsp;&nbsp;productInventory&nbsp;=&nbsp;productInventory.Handle(command); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">this</span>.repository.Save(productInventory); }</pre> </p> <p> Perhaps even so simple that the class begins to seem unwarranted. </p> <h3 id="6f41a860c47741d7b2eb3b4b720d1d7f"> Sandwich <a href="#6f41a860c47741d7b2eb3b4b720d1d7f" title="permalink">#</a> </h3> <p> It's just a database Query, a single pure function call, and another database Command. In fact, it looks a lot like an <a href="/2020/03/02/impureim-sandwich">impureim sandwich</a>: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">void</span>&nbsp;<span style="color:#74531f;">Execute</span>(AdjustInventory&nbsp;<span style="color:#1f377f;">command</span>) { <span style="background-color: lightsalmon;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">productInventory</span>&nbsp;=&nbsp;<span style="color:blue;">this</span>.repository.GetByIdOrNull(command.ProductId)</span> <span style="background-color: palegreen;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;??&nbsp;<span style="color:blue;">new</span>&nbsp;ProductInventory(command.ProductId); &nbsp;&nbsp;&nbsp;&nbsp;productInventory&nbsp;=&nbsp;productInventory.Handle(command);</span> <span style="background-color: lightsalmon;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">this</span>.repository.Save(productInventory);</span> }</pre> </p> <p> In fact, it'd probably be more appropriate to move the null-handling closer to the other <a href="https://en.wikipedia.org/wiki/Referential_transparency">referentially transparent</a> code: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">void</span>&nbsp;<span style="color:#74531f;">Execute</span>(AdjustInventory&nbsp;<span style="color:#1f377f;">command</span>) { <span style="background-color: lightsalmon;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">productInventory</span>&nbsp;=&nbsp;<span style="color:blue;">this</span>.repository.GetByIdOrNull(command.ProductId);</span> <span style="background-color: palegreen;">&nbsp;&nbsp;&nbsp;&nbsp;productInventory&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(productInventory&nbsp;??&nbsp;<span style="color:blue;">new</span>&nbsp;ProductInventory(command.ProductId)).Handle(command);</span> <span style="background-color: lightsalmon;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">this</span>.repository.Save(productInventory);</span> }</pre> </p> <p> Why do we need the <code>AdjustInventoryService</code> class, again? </p> <p> Can't we move those three lines of code to the Controller? We could, but that might make testing the above <code>AdjustInventory</code> Controller action more difficult. After all, at the moment, the Controller has an injected <code>ICommandHandler&lt;AdjustInventory&gt;</code>, which is easy to replace with a Test Double. </p> <p> If only we could somehow <em>compose</em> an <code>ICommandHandler&lt;AdjustInventory&gt;</code> from the above sandwich <em>without having to define a class</em>... </p> <h3 id="535cefbfe8564f888f92fa4edd1fe7c8"> Contravariant functor <a href="#535cefbfe8564f888f92fa4edd1fe7c8" title="permalink">#</a> </h3> <p> Fortunately, an interface like <code>ICommandHandler&lt;T&gt;</code> gives rise to a contravariant functor. This will enable you to compose an <code>ICommandHandler&lt;AdjustInventory&gt;</code> object from the above constituent parts. </p> <p> In order to enable contravariant mapping, you must add a <code>ContraMap</code> method: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">static</span>&nbsp;ICommandHandler&lt;T1&gt;&nbsp;<span style="color:#74531f;">ContraMap</span>&lt;<span style="color:#2b91af;">T</span>,&nbsp;<span style="color:#2b91af;">T1</span>&gt;( &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">this</span>&nbsp;ICommandHandler&lt;T&gt;&nbsp;<span style="color:#1f377f;">source</span>, &nbsp;&nbsp;&nbsp;&nbsp;Func&lt;T1,&nbsp;T&gt;&nbsp;<span style="color:#1f377f;">selector</span>) { &nbsp;&nbsp;&nbsp;&nbsp;Action&lt;T1&gt;&nbsp;<span style="color:#1f377f;">action</span>&nbsp;=&nbsp;<span style="color:#1f377f;">x</span>&nbsp;=&gt;&nbsp;source.Execute(selector(x)); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;<span style="color:blue;">new</span>&nbsp;DelegatingCommandHandler&lt;T1&gt;(action); }</pre> </p> <p> Notice that, as explained in the overview article, in order to map from an <code>ICommandHandler&lt;T&gt;</code> to an <code>ICommandHandler&lt;T1&gt;</code>, the <code>selector</code> has to go the other way: from <code>T1</code> to <code>T</code>. How this is possible will become more apparent with an example, which will follow later in the article. </p> <p> The <code>ContraMap</code> method uses a <code>DelegatingCommandHandler</code> that wraps any <code>Action&lt;T&gt;</code>: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">class</span>&nbsp;<span style="color:#2b91af;">DelegatingCommandHandler</span>&lt;<span style="color:#2b91af;">T</span>&gt;&nbsp;:&nbsp;ICommandHandler&lt;T&gt; { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">private</span>&nbsp;<span style="color:blue;">readonly</span>&nbsp;Action&lt;T&gt;&nbsp;action; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">DelegatingCommandHandler</span>(Action&lt;T&gt;&nbsp;<span style="color:#1f377f;">action</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">this</span>.action&nbsp;=&nbsp;action; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:blue;">void</span>&nbsp;<span style="color:#74531f;">Execute</span>(T&nbsp;<span style="color:#1f377f;">command</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;action(command); &nbsp;&nbsp;&nbsp;&nbsp;} }</pre> </p> <p> If you're now wondering whether <code>Action&lt;T&gt;</code> itself gives rise to a contravariant functor, then yes it does. </p> <h3 id="cab26cece052462890c8e04363a907ec"> Identity law <a href="#cab26cece052462890c8e04363a907ec" title="permalink">#</a> </h3> <p> A <code>ContraMap</code> method with the right signature isn't enough to be a contravariant functor. It must also obey the contravariant functor laws. As usual, it's proper computer-science work to actually prove this, but you can write some tests to demonstrate the identity law for the <code>ICommandHandler&lt;T&gt;</code> interface. In this article, you'll see parametrised tests written with <a href="https://xunit.net">xUnit.net</a>. First, the identity law: </p> <p> <pre>[Theory] [InlineData(<span style="color:#a31515;">&quot;foo&quot;</span>)] [InlineData(<span style="color:#a31515;">&quot;bar&quot;</span>)] [InlineData(<span style="color:#a31515;">&quot;baz&quot;</span>)] [InlineData(<span style="color:#a31515;">&quot;qux&quot;</span>)] [InlineData(<span style="color:#a31515;">&quot;quux&quot;</span>)] [InlineData(<span style="color:#a31515;">&quot;quuz&quot;</span>)] [InlineData(<span style="color:#a31515;">&quot;corge&quot;</span>)] [InlineData(<span style="color:#a31515;">&quot;grault&quot;</span>)] [InlineData(<span style="color:#a31515;">&quot;garply&quot;</span>)] <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">void</span>&nbsp;<span style="color:#74531f;">IdentityLaw</span>(<span style="color:blue;">string</span>&nbsp;<span style="color:#1f377f;">input</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">observations</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;List&lt;<span style="color:blue;">string</span>&gt;(); &nbsp;&nbsp;&nbsp;&nbsp;ICommandHandler&lt;<span style="color:blue;">string</span>&gt;&nbsp;<span style="color:#1f377f;">sut</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;DelegatingCommandHandler&lt;<span style="color:blue;">string</span>&gt;(observations.Add); &nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;<span style="color:#74531f;">id</span>&lt;<span style="color:#2b91af;">T</span>&gt;(T&nbsp;<span style="color:#1f377f;">x</span>)&nbsp;=&gt;&nbsp;x; &nbsp;&nbsp;&nbsp;&nbsp;ICommandHandler&lt;<span style="color:blue;">string</span>&gt;&nbsp;<span style="color:#1f377f;">projection</span>&nbsp;=&nbsp;sut.ContraMap&lt;<span style="color:blue;">string</span>,&nbsp;<span style="color:blue;">string</span>&gt;(id); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:green;">//&nbsp;Run&nbsp;both&nbsp;handlers</span> &nbsp;&nbsp;&nbsp;&nbsp;sut.Execute(input); &nbsp;&nbsp;&nbsp;&nbsp;projection.Execute(input); &nbsp;&nbsp;&nbsp;&nbsp;Assert.Equal(2,&nbsp;observations.Count); &nbsp;&nbsp;&nbsp;&nbsp;Assert.Single(observations.Distinct()); }</pre> </p> <p> In order to observe that the two handlers have identical behaviours, the test has to <code>Execute</code> both of them to verify that both observations are the same. </p> <p> All test cases pass. </p> <h3 id="b4000e7978f949d8817590b0779d0afe"> Composition law <a href="#b4000e7978f949d8817590b0779d0afe" title="permalink">#</a> </h3> <p> Like the above example, you can also write a parametrised test that demonstrates that <code>ContraMap</code> obeys the composition law for contravariant functors: </p> <p> <pre>[Theory] [InlineData(<span style="color:#a31515;">&quot;foo&quot;</span>)] [InlineData(<span style="color:#a31515;">&quot;bar&quot;</span>)] [InlineData(<span style="color:#a31515;">&quot;baz&quot;</span>)] [InlineData(<span style="color:#a31515;">&quot;qux&quot;</span>)] [InlineData(<span style="color:#a31515;">&quot;quux&quot;</span>)] [InlineData(<span style="color:#a31515;">&quot;quuz&quot;</span>)] [InlineData(<span style="color:#a31515;">&quot;corge&quot;</span>)] [InlineData(<span style="color:#a31515;">&quot;grault&quot;</span>)] [InlineData(<span style="color:#a31515;">&quot;garply&quot;</span>)] <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">void</span>&nbsp;<span style="color:#74531f;">CompositionLaw</span>(<span style="color:blue;">string</span>&nbsp;<span style="color:#1f377f;">input</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">observations</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;List&lt;TimeSpan&gt;(); &nbsp;&nbsp;&nbsp;&nbsp;ICommandHandler&lt;TimeSpan&gt;&nbsp;<span style="color:#1f377f;">sut</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;DelegatingCommandHandler&lt;TimeSpan&gt;(observations.Add); &nbsp;&nbsp;&nbsp;&nbsp;Func&lt;<span style="color:blue;">string</span>,&nbsp;<span style="color:blue;">int</span>&gt;&nbsp;<span style="color:#1f377f;">f</span>&nbsp;=&nbsp;<span style="color:#1f377f;">s</span>&nbsp;=&gt;&nbsp;s.Length; &nbsp;&nbsp;&nbsp;&nbsp;Func&lt;<span style="color:blue;">int</span>,&nbsp;TimeSpan&gt;&nbsp;<span style="color:#1f377f;">g</span>&nbsp;=&nbsp;<span style="color:#1f377f;">i</span>&nbsp;=&gt;&nbsp;TimeSpan.FromDays(i); &nbsp;&nbsp;&nbsp;&nbsp;ICommandHandler&lt;<span style="color:blue;">string</span>&gt;&nbsp;<span style="color:#1f377f;">projection1</span>&nbsp;=&nbsp;sut.ContraMap((<span style="color:blue;">string</span>&nbsp;<span style="color:#1f377f;">s</span>)&nbsp;=&gt;&nbsp;g(f(s))); &nbsp;&nbsp;&nbsp;&nbsp;ICommandHandler&lt;<span style="color:blue;">string</span>&gt;&nbsp;<span style="color:#1f377f;">projection2</span>&nbsp;=&nbsp;sut.ContraMap(g).ContraMap(f); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:green;">//&nbsp;Run&nbsp;both&nbsp;handlers</span> &nbsp;&nbsp;&nbsp;&nbsp;projection1.Execute(input); &nbsp;&nbsp;&nbsp;&nbsp;projection2.Execute(input); &nbsp;&nbsp;&nbsp;&nbsp;Assert.Equal(2,&nbsp;observations.Count); &nbsp;&nbsp;&nbsp;&nbsp;Assert.Single(observations.Distinct()); }</pre> </p> <p> This test defines two local functions, <code>f</code> and <code>g</code>. Once more, you can't directly compare methods for equality, so instead you have to <code>Execute</code> them to verify that they produce the same observable effect. </p> <p> They do. </p> <h3 id="a068d2c54eda4315a4c592aa30b998f4"> Composed inventory adjustment handler <a href="#a068d2c54eda4315a4c592aa30b998f4" title="permalink">#</a> </h3> <p> We can now return to the inventory adjustment example. You may recall that the Controller would <code>Execute</code> a <code>command</code> on an injected <code>ICommandHandler&lt;AdjustInventory&gt;</code>: </p> <p> <pre><span style="color:blue;">this</span>.inventoryAdjuster.Execute(command);</pre> </p> <p> As a first step, we can attempt to compose <code>inventoryAdjuster</code> on the fly: </p> <p> <pre>ICommandHandler&lt;AdjustInventory&gt;&nbsp;<span style="color:#1f377f;">inventoryAdjuster</span>&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">new</span>&nbsp;DelegatingCommandHandler&lt;ProductInventory&gt;(repository.Save) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.ContraMap((ProductInventory&nbsp;<span style="color:#1f377f;">inv</span>)&nbsp;=&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(inv&nbsp;??&nbsp;<span style="color:blue;">new</span>&nbsp;ProductInventory(command.ProductId)).Handle(command)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.ContraMap((AdjustInventory&nbsp;<span style="color:#1f377f;">cmd</span>)&nbsp;=&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;repository.GetByIdOrNull(cmd.ProductId)); inventoryAdjuster.Execute(command);</pre> </p> <p> Contra-mapping is hard to get one's head around, and to make matters worse, you have to read it from the bottom towards the top to understand what it does. It really is contrarian. </p> <p> How do you arrive at something like this? </p> <p> You start by looking at what you have. The Controller may already have an injected <code>repository</code> with various methods. <code>repository.Save</code>, for example, has this signature: </p> <p> <pre><span style="color:blue;">void</span>&nbsp;<span style="color:#74531f;">Save</span>(ProductInventory&nbsp;<span style="color:#1f377f;">productInventory</span>);</pre> </p> <p> Since it has a <code>void</code> return type, you can treat <code>repository.Save</code> as an <code>Action&lt;ProductInventory&gt;</code>. Wrap it in a <code>DelegatingCommandHandler</code> and you have an <code>ICommandHandler&lt;ProductInventory&gt;</code>: </p> <p> <pre>ICommandHandler&lt;ProductInventory&gt;&nbsp;<span style="color:#1f377f;">inventoryAdjuster</span>&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">new</span>&nbsp;DelegatingCommandHandler&lt;ProductInventory&gt;(repository.Save);</pre> </p> <p> That's not what you need, though. You need an <code>ICommandHandler&lt;AdjustInventory&gt;</code>. How do you get closer to that? </p> <p> You already know from the <code>AdjustInventoryService</code> class that you can use a pure function as the core of the impureim sandwich. Try that and see what it gives you: </p> <p> <pre>ICommandHandler&lt;ProductInventory&gt;&nbsp;<span style="color:#1f377f;">inventoryAdjuster</span>&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">new</span>&nbsp;DelegatingCommandHandler&lt;ProductInventory&gt;(repository.Save) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.ContraMap((ProductInventory&nbsp;<span style="color:#1f377f;">inv</span>)&nbsp;=&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(inv&nbsp;??&nbsp;<span style="color:blue;">new</span>&nbsp;ProductInventory(command.ProductId)).Handle(command));</pre> </p> <p> That doesn't change the type of the handler, but implements the desired functionality. </p> <p> You have an <code>ICommandHandler&lt;ProductInventory&gt;</code> that you need to somehow map to an <code>ICommandHandler&lt;AdjustInventory&gt;</code>. How do you do that? </p> <p> By supplying a function that goes the other way: from <code>AdjustInventory</code> to <code>ProductInventory</code>. Does such a method exist? Yes, it does, on the repository: </p> <p> <pre>ProductInventory&nbsp;<span style="color:#74531f;">GetByIdOrNull</span>(Guid&nbsp;<span style="color:#1f377f;">id</span>);</pre> </p> <p> Or, close enough. While <code>AdjustInventory</code> is not a <code>Guid</code>, it <em>comes with</em> a <code>Guid</code>: </p> <p> <pre>ICommandHandler&lt;AdjustInventory&gt;&nbsp;<span style="color:#1f377f;">inventoryAdjuster</span>&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">new</span>&nbsp;DelegatingCommandHandler&lt;ProductInventory&gt;(repository.Save) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.ContraMap((ProductInventory&nbsp;<span style="color:#1f377f;">inv</span>)&nbsp;=&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(inv&nbsp;??&nbsp;<span style="color:blue;">new</span>&nbsp;ProductInventory(command.ProductId)).Handle(command)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.ContraMap((AdjustInventory&nbsp;<span style="color:#1f377f;">cmd</span>)&nbsp;=&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;repository.GetByIdOrNull(cmd.ProductId));</pre> </p> <p> That's cool, but unfortunately, this composition cheats. It closes over <code>command</code>, which is a run-time variable only available inside the <code>AdjustInventory</code> Controller action. </p> <p> If we're allowed to compose the Command Handler <em>inside</em> the <code>AdjustInventory</code> method, we might as well just have written: </p> <p> <pre><span style="color:blue;">var</span>&nbsp;<span style="color:#1f377f;">inv</span>&nbsp;=&nbsp;repository.GetByIdOrNull(command.ProductId); inv&nbsp;=&nbsp;(inv&nbsp;??&nbsp;<span style="color:blue;">new</span>&nbsp;ProductInventory(command.ProductId)).Handle(command); repository.Save(inv);</pre> </p> <p> This is clearly much simpler, so why don't we do that? </p> <p> In this particular example, that's probably a better idea overall, but I'm trying to explain what is possible with contravariant functors. The goal here is to decouple the caller (the Controller) from the handler. We want to be able to define the handler outside of the Controller action. </p> <p> That's what the <code>AdjustInventory</code> class does, but can we leverage the contravariant functor to compose an <code>ICommandHandler&lt;AdjustInventory&gt;</code> <em>without</em> adding a new class? </p> <h3 id="01c3971cdf1d43ca8fd5db6005477304"> Composition without closures <a href="#01c3971cdf1d43ca8fd5db6005477304" title="permalink">#</a> </h3> <p> The use of a closure in the above composition is what disqualifies it. Is it possible to compose an <code>ICommandHandler&lt;AdjustInventory&gt;</code> when the <code>command</code> object is unavailable to close over? </p> <p> Yes, but it isn't pretty: </p> <p> <pre>ICommandHandler&lt;AdjustInventory&gt;&nbsp;<span style="color:#1f377f;">inventoryAdjuster</span>&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">new</span>&nbsp;DelegatingCommandHandler&lt;ProductInventory&gt;(repository.Save) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.ContraMap((ValueTuple&lt;AdjustInventory,&nbsp;ProductInventory&gt;&nbsp;<span style="color:#1f377f;">t</span>)&nbsp;=&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(t.Item2&nbsp;??&nbsp;<span style="color:blue;">new</span>&nbsp;ProductInventory(t.Item1.ProductId)).Handle(t.Item1)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.ContraMap((AdjustInventory&nbsp;<span style="color:#1f377f;">cmd</span>)&nbsp;=&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(cmd,&nbsp;repository.GetByIdOrNull(cmd.ProductId)));</pre> </p> <p> You can let the composing function return a tuple of the original input value <em>and</em> the projected value. That's what the lowest <code>ContraMap</code> does. This means that the upper <code>ContraMap</code> receives this tuple to map. Not pretty, but possible. </p> <p> I never said that this was the <em>best</em> way to address some of the concerns I've hinted at in this article. The purpose of the article was mainly to give you a sense of what a contravariant functor can do. </p> <h3 id="0a960dd6e8f24121a5b9229b9cca1e7a"> Action as a contravariant functor <a href="#0a960dd6e8f24121a5b9229b9cca1e7a" title="permalink">#</a> </h3> <p> Wrapping an <code>Action&lt;T&gt;</code> in a <code>DelegatingCommandHandler</code> isn't necessary in order to form the contravariant functor. I only used the <code>ICommandHandler</code> interface as an object-oriented-friendly introduction to the example. In fact, any <code>Action&lt;T&gt;</code> gives rise to a contravariant functor with this <code>ContraMap</code> function: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">static</span>&nbsp;Action&lt;T1&gt;&nbsp;<span style="color:#74531f;">ContraMap</span>&lt;<span style="color:#2b91af;">T</span>,&nbsp;<span style="color:#2b91af;">T1</span>&gt;(<span style="color:blue;">this</span>&nbsp;Action&lt;T&gt;&nbsp;<span style="color:#1f377f;">source</span>,&nbsp;Func&lt;T1,&nbsp;T&gt;&nbsp;<span style="color:#1f377f;">selector</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#8f08c4;">return</span>&nbsp;<span style="color:#1f377f;">x</span>&nbsp;=&gt;&nbsp;source(selector(x)); }</pre> </p> <p> As you can tell, the function being returned is similar to the lambda expression used to implement <code>ContraMap</code> for <code>ICommandHandler&lt;T&gt;</code>. </p> <p> This turns out to make little difference in the context of the examples shown here, so I'm not going to tire you with more example code. </p> <h3 id="9c7dc6d88a164a0b8bd7ac06eea22dc4"> Conclusion <a href="#9c7dc6d88a164a0b8bd7ac06eea22dc4" title="permalink">#</a> </h3> <p> Any generic polymorphic interface or abstract method with a <code>void</code> return type gives rise to a contravariant functor. This includes the <code>ICommandHandler&lt;T&gt;</code> (originally <code>ICommandService&lt;T&gt;</code>) interface, but also another interface discussed in <a href="/dippp">DIPPP</a>: <code>IEventHandler&lt;TEvent&gt;</code>. </p> <p> The utility of this insight may not be immediately apparent. Contrary to its built-in support for functors, C# doesn't have any language features that light up if you implement a <code>ContraMap</code> function. Even in <a href="https://www.haskell.org">Haskell</a> where <a href="https://hackage.haskell.org/package/base/docs/Data-Functor-Contravariant.html">the Contravariant functor is available in the <em>base</em> library</a>, I can't recall having ever used it. </p> <p> Still, even if not a <em>practical</em> insight, the ubiquitous presence of contravariant functors in everyday programming 'building blocks' tells us something profound about the fabric of programming abstraction and polymorphism. </p> <p> <strong>Next:</strong> <a href="/2021/09/09/the-specification-contravariant-functor">The Specification contravariant functor</a>. </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/2021/09/06/the-command-handler-contravariant-functor Contravariant functors https://blog.ploeh.dk/2021/09/02/contravariant-functors/ Thu, 02 Sep 2021 06:49:00 UTC <div id="post"> <p> <em>A more exotic kind of universal abstraction.</em> </p> <p> This article series is part of <a href="/2018/03/19/functors-applicatives-and-friends">a larger series of articles about functors, applicatives, and other mappable containers</a>. </p> <p> So far in the article series, you've seen examples of mappable containers that map in the same direction of projections, so to speak. Let's unpack that. </p> <h3 id="272009219c12482cba296186e0e0a645"> Covariance recap <a href="#272009219c12482cba296186e0e0a645" title="permalink">#</a> </h3> <p> <a href="/2018/03/22/functors">Functors</a>, <a href="/2018/10/01/applicative-functors">applicative functors</a>, and <a href="/2018/12/24/bifunctors">bifunctors</a> all follow the direction of projections. Consider the illustration from <a href="/2018/03/22/functors">the article about functors</a>: </p> <p> <img src="/content/binary/functor-diagram.png" alt="Functor diagram."> </p> <p> The function <code>f</code> maps from <code>a</code> to <code>b</code>. You can think of <code>a</code> and <code>b</code> as two types, or two sets. For example, if <code>a</code> is the set of all strings, it might correspond to the type <code>String</code>. Likewise, if <code>b</code> is the set of all integers, then it corresponds to a type called <code>Int</code>. The function <code>f</code> would, in that case, have the type <code>String -&gt; Int</code>; that is: it maps strings to integers. The most natural such function seems to be one that counts the number of characters in a string: </p> <p> <pre>&gt; f = length &gt; f "foo" 3 &gt; f "ploeh" 5</pre> </p> <p> This little interactive session uses <a href="https://www.haskell.org">Haskell</a>, but even if you've never heard about Haskell before, you should still be able to understand what's going on. </p> <p> A functor is a <a href="https://bartoszmilewski.com/2014/01/14/functors-are-containers">container</a> of values, for example a collection, a <a href="/2018/03/26/the-maybe-functor">Maybe</a>, a <a href="/2018/09/10/the-lazy-functor">lazy computation</a>, or many other things. If <code>f</code> maps from <code>a</code> to <code>b</code>, then lifting it to the functor <code>F</code> retains the direction. That's what the above figure illustrates. Not only does the functor project <code>a</code> to <code>F a</code> and <code>b</code> to <code>F b</code>, it also maps <code>f</code> to <code>F f</code>, which is <code>F a -&gt; F b</code>. </p> <p> For lists it might look like this: </p> <p> <pre>&gt; fmap f ["bar", "fnaah", "Gauguin"] [3,5,7]</pre> </p> <p> Here <code>fmap</code> lifts the function <code>String -&gt; Int</code> to <code>[String] -&gt; [Int]</code>. Notice that the types 'go in the same direction' when you lift a function to the functor. The types vary <em>with</em> the function - they <em>co</em>-vary; hence <em>covariance</em>. </p> <p> While applicative functors and bifunctors are more complex, they are still covariant. Consult, for example, the diagrams in my <a href="/2018/12/24/bifunctors">bifunctor article</a> to get an intuitive sense that this still holds. </p> <h3 id="187c2160ddf94c119c341534189d3eab"> Contravariance <a href="#187c2160ddf94c119c341534189d3eab" title="permalink">#</a> </h3> <p> What happens if we change the direction of <em>only one</em> arrow? For example, we could change the direction of the <code>f</code> arrow, so that the function is now a function from <code>b</code> to <code>a</code>: <code>b -&gt; a</code>. The figure would look like this: </p> <p> <img src="/content/binary/contravariant-functor-diagram.png" alt="Contravariant functor diagram."> </p> <p> This looks <em>almost</em> like the first figure, with one crucial difference: The lower arrow now goes from right to left. Notice that the upper arrow still goes from left to right: <code>F a -&gt; F b</code>. In other words, the functor varies in the contrary direction than the projected function. It's <em>contravariant</em>. </p> <p> This seems really odd. Why would anyone do that? </p> <p> As is so often the case with universal abstractions, it's not so much a question of coming up with an odd concept and see what comes of it. It's actually an abstract description of some common programming constructs. In this series of articles, you'll see examples of some contravariant functors: </p> <ul> <li><a href="/2021/09/06/the-command-handler-contravariant-functor">The Command Handler contravariant functor</a></li> <li><a href="/2021/09/09/the-specification-contravariant-functor">The Specification contravariant functor</a></li> <li><a href="/2021/09/27/the-equivalence-contravariant-functor">The Equivalence contravariant functor</a></li> <li><a href="/2021/10/04/reader-as-a-contravariant-functor">Reader as a contravariant functor</a></li> <li><a href="/2021/10/25/functor-variance-compared-to-cs-notion-of-variance">Functor variance compared to C#'s notion of variance</a></li> </ul> <p> These aren't the only examples, but they should be enough to get the point across. Other examples include equivalence and comparison. </p> <h3 id="b7b1780cc7a74ffaace2a42f06301561"> Lifting <a href="#b7b1780cc7a74ffaace2a42f06301561" title="permalink">#</a> </h3> <p> How do you lift a function <code>f</code> to a contravariant functor? For covariant functors (normally just called <em>functors</em>), Haskell has the <code>fmap</code> function, while in C# you'd be writing a family of <code>Select</code> methods. Let's compare. In Haskell, <code>fmap</code> has this type: </p> <p> <pre>fmap :: Functor f =&gt; (a -&gt; b) -&gt; f a -&gt; f b</pre> </p> <p> You can read it like this: For any <code>Functor f</code>, <code>fmap</code> lifts a function of the type <code>a -&gt; b</code> to a function of the type <code>f a -&gt; f b</code>. Another way to read this is that given a function <code>a -&gt; b</code> and a container of type <code>f a</code>, you can produce a container of type <code>f b</code>. Due to <a href="https://en.wikipedia.org/wiki/Currying">currying</a>, these two interpretations are both correct. </p> <p> In C#, you'd be writing a <a href="/2018/03/22/functors">method on <code>Functor&lt;T&gt;</code> that looks like this</a>: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">Functor</span>&lt;<span style="color:#2b91af;">TResult</span>&gt;&nbsp;Select&lt;<span style="color:#2b91af;">TResult</span>&gt;(<span style="color:#2b91af;">Func</span>&lt;<span style="color:#2b91af;">T</span>,&nbsp;<span style="color:#2b91af;">TResult</span>&gt;&nbsp;selector)</pre> </p> <p> This fits the later interpretation of <code>fmap</code>: Given an instance of <code>Functor&lt;T&gt;</code>, you can call <code>Select</code> with a <code>Func&lt;T, TResult&gt;</code> to produce a <code>Functor&lt;TResult&gt;</code>. </p> <p> What does the equivalent function look like for contravariant functors? Haskell <a href="https://hackage.haskell.org/package/base/docs/Data-Functor-Contravariant.html">defines it</a> as: </p> <p> <pre>contramap :: Contravariant f =&gt; (b -&gt; a) -&gt; f a -&gt; f b</pre> </p> <p> You can read it like this: For any <code>Contravariant</code> functor <code>f</code>, <code>contramap</code> lifts a function <code>(b -&gt; a)</code> to a function from <code>f a</code> to <code>f b</code>. Or, in the alternative (but equally valid) interpretation that matches C# better, given a function <code>(b -&gt; a)</code> and an <code>f a</code>, you can produce an <code>f b</code>. </p> <p> In C#, you'd be writing a method on <code>Contravariant&lt;T&gt;</code> that looks like this: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;Contravariant&lt;T1&gt;&nbsp;<span style="color:#74531f;">ContraMap</span>&lt;<span style="color:#2b91af;">T1</span>&gt;(Func&lt;T1,&nbsp;T&gt;&nbsp;<span style="color:#1f377f;">selector</span>)</pre> </p> <p> The actual generic type (here exemplified by <code>Contravariant&lt;T&gt;</code>) will differ, but the shape of the method will be the same. In order to map from <code>Contravariant&lt;T&gt;</code> to <code>Contravariant&lt;T1&gt;</code>, you need a function that <em>goes the other way</em>: <code>Func&lt;T1, T&gt;</code> goes from <code>T1</code> to <code>T</code>. </p> <p> In C#, the function name doesn't have to be <code>ContraMap</code>, since C# doesn't have any built-in understanding of contravariant functors - as opposed to functors, where a method called <code>Select</code> will light up some language features. In this article series I'll stick with <code>ContraMap</code> since I couldn't think of a better name. </p> <h3 id="72905e6e48a343e1bf78deae36be0abf"> Laws <a href="#72905e6e48a343e1bf78deae36be0abf" title="permalink">#</a> </h3> <p> Like functors, applicative functors, <a href="/2017/10/06/monoids">monoids</a>, and other universal abstractions, contravariant functors are characterised by simple laws. The contravariant functor laws are equivalent to the (covariant) <a href="/2018/03/22/functors">functor laws</a>: <em>identity</em> and <em>composition</em>. </p> <p> In pseudo-Haskell, we can express the <em>identity</em> law as: </p> <p> <pre>contramap id = id</pre> </p> <p> and the <em>composition</em> law as: </p> <p> <pre>contramap (g . f) = contramap f . contramap g</pre> </p> <p> The <em>identity</em> law is equivalent to the first functor law. It states that mapping a contravariant functor with the identity function is equivalent to a no-op. The <em>identity function</em> is a function that returns all input unchanged. (It's called the <em>identity function</em> because it's the <em>identity</em> for the <a href="/2017/11/13/endomorphism-monoid">endomorphism monoid</a>.) In <a href="https://fsharp.org">F#</a> and Haskell, this is simply a built-in function called <code>id</code>. </p> <p> In C#, you can write a demonstration of the law as a unit test. Here's the essential part of such a test: </p> <p> <pre>Func&lt;<span style="color:blue;">string</span>,&nbsp;<span style="color:blue;">string</span>&gt;&nbsp;<span style="color:#1f377f;">id</span>&nbsp;=&nbsp;<span style="color:#1f377f;">x</span>&nbsp;=&gt;&nbsp;x; Contravariant&lt;<span style="color:blue;">string</span>&gt;&nbsp;<span style="color:#1f377f;">sut</span>&nbsp;=&nbsp;createContravariant(); Assert.Equal(sut,&nbsp;sut.ContraMap(id),&nbsp;comparer);</pre> </p> <p> The <code>ContraMap</code> method <em>does</em> return a new object, so a custom <code>comparer</code> is required to evaluate whether <code>sut</code> is equal to <code>sut.ContraMap(id)</code>. </p> <p> The <em>composition</em> law governs how composition works. Again, notice how lifting reverses the order of functions. In C#, the relevant unit test code might look like this: </p> <p> <pre>Func&lt;<span style="color:blue;">string</span>,&nbsp;<span style="color:blue;">int</span>&gt;&nbsp;<span style="color:#1f377f;">f</span>&nbsp;=&nbsp;<span style="color:#1f377f;">s</span>&nbsp;=&gt;&nbsp;s.Length; Func&lt;<span style="color:blue;">int</span>,&nbsp;TimeSpan&gt;&nbsp;<span style="color:#1f377f;">g</span>&nbsp;=&nbsp;<span style="color:#1f377f;">i</span>&nbsp;=&gt;&nbsp;TimeSpan.FromDays(i); Contravariant&lt;TimeSpan&gt;&nbsp;<span style="color:#1f377f;">sut</span>&nbsp;=&nbsp;createContravariant(); Assert.Equal( &nbsp;&nbsp;&nbsp;&nbsp;sut.ContraMap((<span style="color:blue;">string</span>&nbsp;<span style="color:#1f377f;">s</span>)&nbsp;=&gt;&nbsp;g(f(s))), &nbsp;&nbsp;&nbsp;&nbsp;sut.ContraMap(g).ContraMap(f), &nbsp;&nbsp;&nbsp;&nbsp;comparer);</pre> </p> <p> This may actually look less surprising in C# than it does in Haskell. Here the lifted composition doesn't look reversed, but that's because C# doesn't have a composition operator for raw functions, so I instead wrote it as a lambda expression: <code>(string&nbsp;s)&nbsp;=&gt;&nbsp;g(f(s))</code>. If you contrast this C# example with the equivalent assertion of the (covariant) second functor law, you can see that the function order is flipped: <code>f(g(i))</code>. </p> <p> <pre><span style="color:#2b91af;">Assert</span>.Equal(sut.Select(g).Select(f),&nbsp;sut.Select(i&nbsp;=&gt;&nbsp;f(g(i))));</pre> </p> <p> It can be difficult to get your head around the order of contravariant composition without some examples. I'll provide examples in the following articles, but I wanted to leave the definition of the two contravariant functor laws here for reference. </p> <h3 id="68b342bda0ff41f5aec6fb7c08b299d3"> Conclusion <a href="#68b342bda0ff41f5aec6fb7c08b299d3" title="permalink">#</a> </h3> <p> Contravariant functors are functors that map in the opposite direction of an underlying function. This seems counter-intuitive but describes the actual behaviour of quite normal functions. </p> <p> This is hardly illuminating without some examples, so without further ado, let's proceed to the first one. </p> <p> <strong>Next:</strong> <a href="/2021/09/06/the-command-handler-contravariant-functor">The Command Handler contravariant functor</a>. </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/2021/09/02/contravariant-functors