ploeh blog2023-05-30T12:26:05+00:00Mark Seemanndanish software designhttps://blog.ploeh.dkFavour flat code file foldershttps://blog.ploeh.dk/2023/05/29/favour-flat-code-file-folders2023-05-29T19:20:00+00:00Mark Seemann
<div id="post">
<p>
<em>How code files are organised is hardly related to sustainability of code bases.</em>
</p>
<p>
My recent article <a href="/2023/05/15/folders-versus-namespaces">Folders versus namespaces</a> prompted some reactions. A few kind people <a href="https://twitter.com/Savlambda/status/1658453377489960960">shared how they organise code bases</a>, both on Twitter and in the comments. Most reactions, however, carry the (subliminal?) subtext that organising code in file folders is how things are done.
</p>
<p>
I'd like to challenge that notion.
</p>
<p>
As is usually my habit, I mostly do this to make you think. I don't insist that I'm universally right in all contexts, and that everyone else are wrong. I only write to suggest that alternatives exist.
</p>
<p>
The <a href="/2023/05/15/folders-versus-namespaces">previous article</a> wasn't a recommendation; it's was only an exploration of an idea. As I describe in <a href="/2021/06/14/new-book-code-that-fits-in-your-head">Code That Fits in Your Head</a>, I recommend flat folder structures. Put most code files in the same directory.
</p>
<h3 id="58c997618e794a26bc366859b216e226">
Finding files <a href="#58c997618e794a26bc366859b216e226">#</a>
</h3>
<p>
People usually dislike that advice. <em>How can I find anything?!</em>
</p>
<p>
Let's start with a counter-question: How can you find anything if you have a deep file hierarchy? Usually, if you've organised code files in subfolders of subfolders of folders, you typically start with a collapsed view of the tree.
</p>
<p>
<img src="/content/binary/mostly-collapsed-solution-explorer-tree.png" alt="Mostly-collapsed Solution Explorer tree.">
</p>
<p>
Those of my readers who know a little about search algorithms will point out that a <a href="https://en.wikipedia.org/wiki/Search_tree">search tree</a> is an efficient data structure for locating content. The assumption, however, is that you already know (or can easily construct) the <em>path</em> you should follow.
</p>
<p>
In a view like the above, <em>most</em> files are hidden in one of the collapsed folders. If you want to find, say, the <code>Iso8601.cs</code> file, where do you look for it? Which path through the tree do you take?
</p>
<p>
<em>Unfair!</em>, you protest. You don't know what the <code>Iso8601.cs</code> file does. Let me enlighten you: That file contains functions that render dates and times in <a href="https://en.wikipedia.org/wiki/ISO_8601">ISO 8601</a> formats. These are used to transmit dates and times between systems in a platform-neutral way.
</p>
<p>
So where do you look for it?
</p>
<p>
It's probably not in the <code>Controllers</code> or <code>DataAccess</code> directories. Could it be in the <code>Dtos</code> folder? <code>Rest</code>? <code>Models</code>?
</p>
<p>
Unless your first guess is correct, you'll have to open more than one folder before you find what you're looking for. If each of these folders have subfolders of their own, that only exacerbates the problem.
</p>
<p>
If you're curious, some programmer (me) decided to put the <code>Iso8601.cs</code> file in the <code>Dtos</code> directory, and perhaps you already guessed that. That's not the point, though. The point is this: 'Organising' code files in folders is only efficient if you can unerringly predict the correct path through the tree. You'll have to get it right the first time, every time. If you don't, it's not the most efficient way.
</p>
<p>
Most modern code editors come with features that help you locate files. In <a href="https://visualstudio.microsoft.com/">Visual Studio</a>, for example, you just hit <kbd>Ctrl</kbd>+<kbd>,</kbd> and type a bit of the file name: <em>iso</em>:
</p>
<p>
<img src="/content/binary/visual-studio-go-to-all.png" alt="Visual Studio Go To All dialog.">
</p>
<p>
Then hit <kbd>Enter</kbd> to open the file. In <a href="https://code.visualstudio.com/">Visual Studio Code</a>, the corresponding keyboard shortcut is <kbd>Ctrl</kbd>+<kbd>p</kbd>, and I'd be highly surprised if other editors didn't have a similar feature.
</p>
<p>
To conclude, so far: Organising files in a folder hierarchy is <em>at best</em> on par with your editor's built-in search feature, but is likely to be less productive.
</p>
<h3 id="f3dffaf6e73e42a6a10e1f403b8bf37b">
Navigating a code base <a href="#f3dffaf6e73e42a6a10e1f403b8bf37b">#</a>
</h3>
<p>
What if you don't quite know the name of the file you're looking for? In such cases, the file system is even less helpful.
</p>
<p>
I've seen people work like this:
</p>
<ol>
<li>Look at some code. Identify another code item they'd like to view. (Examples may include: Looking at a unit test and wanting to see the <a href="https://en.wikipedia.org/wiki/System_under_test">SUT</a>, or looking at a class and wanting to see the base class.)</li>
<li>Move focus to the editor's folder view (in Visual Studio called the <em>Solution Explorer</em>).</li>
<li>Scroll to find the file in question.</li>
<li>Double-click said file.</li>
</ol>
<p>
Regardless of how the files are organised, you could, instead, <em>go to definition</em> (<kbd>F12</kbd> with my Visual Studio keyboard layout) in a single action. Granted, how well this works varies with editor and language. Still, even when editor support is less optimal (e.g. a code base with a mix of <a href="https://fsharp.org/">F#</a> and C#, or a <a href="https://www.haskell.org/">Haskell</a> code base), I can often find things faster with a search (<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>f</kbd>) than via the file system.
</p>
<p>
A modern editor has efficient tools that can help you find what you're looking for. Looking through the file system is often the least efficient way to find the code you're looking for.
</p>
<h3 id="b050833e38ab4ee7a1ed3429979d8405">
Large code bases <a href="#b050833e38ab4ee7a1ed3429979d8405">#</a>
</h3>
<p>
Do I recommend that you dump thousands of code files in a single directory, then?
</p>
<p>
Hardly, but a question like that presupposes that code bases have thousands of code files. Or more, even. And I've seen such code bases.
</p>
<p>
Likewise, it's a common complaint that Visual Studio is slow when opening solutions with hundreds of projects. And the day Microsoft fixes that problem, people are going to complain that it's slow when opening a solution with thousands of projects.
</p>
<p>
Again, there's an underlying assumption: That a 'real' code base <em>must</em> be so big.
</p>
<p>
Consider alternatives: Could you decompose the code base into multiple smaller code bases? Could you extract subsystems of the code base and package them as reusable packages? Yes, you can do all those things.
</p>
<p>
Usually, I'd pull code bases apart long before they hit a thousand files. Extract modules, libraries, utilities, etc. and put them in separate code bases. Use existing package managers to distribute these smaller pieces of code. Keep the code bases small, and you don't need to organise the files.
</p>
<h3 id="64b5d272a18d41778a021540cd710fd1">
Maintenance <a href="#64b5d272a18d41778a021540cd710fd1">#</a>
</h3>
<p>
<em>But, if all files are mixed together in a single folder, how do we keep the code maintainable?</em>
</p>
<p>
Once more, implicit (but false) assumptions underlie such questions. The assumption is that 'neatly' organising files in hierarchies somehow makes the code easier to maintain. Really, though, it's more akin to a teenager who 'cleans' his room by sweeping everything off the floor only to throw it into his cupboard. It does enable hoovering the floor, but it doesn't make it easier to find anything. The benefit is mostly superficial.
</p>
<p>
Still, consider a tree.
</p>
<p>
<img src="/content/binary/file-tree.png" alt="A tree of folders with files.">
</p>
<p>
This may not be the way you're used to see files and folders rendered, but this diagram emphases the tree structure and makes what happens next starker.
</p>
<p>
The way that most languages work, putting code files in folders makes little difference to the compiler. If the classes in my <code>Controllers</code> folder need some classes from the <code>Dtos</code> folder, you just use them. You may need to import the corresponding namespace, but modern editors make that a breeze.
</p>
<p>
<img src="/content/binary/two-files-coupled-across-tree-branches.png" alt="A tree of folders with files. Two files connect across the tree's branches.">
</p>
<p>
In the above tree, the two files who now communicate are coloured orange. Notice that they span across two main branches of the tree.
</p>
<p>
Thus, even though the files are organised in a tree, it has no impact on the maintainability of the code base. Code can reference other code in other parts of the tree. You can <a href="http://evelinag.com/blog/2014/06-09-comparing-dependency-networks/">easily create cycles in a language like C#</a>, and organising files in trees makes no difference.
</p>
<p>
Most languages, however, enforce that library dependencies form a <a href="https://en.wikipedia.org/wiki/Directed_acyclic_graph">directed acyclic graph</a> (i.e. <a href="/2013/12/03/layers-onions-ports-adapters-its-all-the-same">if the data access library references the domain model, the domain model can't reference the data access library</a>). The C# (and most other languages) compiler enforces what <a href="/ref/appp">Robert C. Martin calls the Acyclic Dependencies Principle</a>. Preventing cycles prevents <a href="https://en.wikipedia.org/wiki/Spaghetti_code">spaghetti code</a>, which is <a href="/2022/11/21/decouple-to-delete">key to a maintainable code base</a>.
</p>
<p>
(Ironically, <a href="/2015/04/15/c-will-eventually-get-all-f-features-right">one of the more controversial features of F# is actually one of its greatest strengths: It doesn't allow cycles</a>.)
</p>
<h3 id="ffe0131017254522acd40d2445929f24">
Tidiness <a href="#ffe0131017254522acd40d2445929f24">#</a>
</h3>
<p>
Even so, I do understand the lure of organising code files in an elaborate hierarchy. It looks so <em>neat</em>.
</p>
<p>
Previously, I've <a href="/2021/05/17/against-consistency">touched on the related topic of consistency</a>, and while I'm a bit of a neat freak myself, I have to realise that tidiness seems to be largely unrelated to the sustainability of a code base.
</p>
<p>
As another example in this category, I've seen more than one code base with consistently beautiful documentation. Every method was adorned with formal <a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/xmldoc/">XML documentation</a> with every input parameter as well as output described.
</p>
<p>
Every new phase in a method was delineated with another neat comment, nicely adorned with a 'comment frame' and aligned with other comments.
</p>
<p>
It was glorious.
</p>
<p>
Alas, that documentation sat on top of 750-line methods with a cyclomatic complexity above 50. The methods were so long that <a href="/2019/12/23/the-case-of-the-mysterious-curly-bracket">developers had to introduce artificial variable scopes to avoid naming collisions</a>.
</p>
<p>
The reason I was invited to look at that code in the first place was that the organisation had trouble with maintainability, and they asked me to help.
</p>
<p>
It was neat, yet unmaintainable.
</p>
<p>
This discussion about tidiness may seem like a digression, but I think it's important to make the implicit explicit. If I'm not much mistaken, preference for order is a major reason that so many developers want to organise code files into hierarchies.
</p>
<h3 id="47227afb0a674330bb1b3556f751799d">
Organising principles <a href="#47227afb0a674330bb1b3556f751799d">#</a>
</h3>
<p>
What other motivations for file hierarchies could there be? How about the directory structure as an organising principle?
</p>
<p>
The two most common organising principles are <a href="/2023/05/15/folders-versus-namespaces">those that I experimented with in the previous article</a>:
</p>
<ol>
<li>By technical role (Controller, View Model, DTO, etc.)</li>
<li>By feature</li>
</ol>
<p>
A technical leader might hope that, by presenting a directory structure to team members, it imparts an organising principle on the code to be.
</p>
<p>
It may even do so, but is that actually a benefit?
</p>
<p>
It might subtly discourage developers from introducing code that doesn't fit into the predefined structure. If you organise code by technical role, developers might put most code in Controllers, producing mostly procedural <a href="https://martinfowler.com/eaaCatalog/transactionScript.html">Transaction Scripts</a>. If you organise by feature, this might encourage duplication because developers don't have a natural place to put general-purpose code.
</p>
<p>
<em>You can put truly shared code in the root folder,</em> the counter-argument might be. This is true, but:
</p>
<ol>
<li>This seems to be implicitly discouraged by the folder structure. After all, the hierarchy is there for a reason, right? Thus, any file you place in the root seems to suggest a failure of organisation.</li>
<li>On the other hand, if you flaunt that not-so-subtle hint and put many code files in the root, what advantage does the hierarchy furnish?</li>
</ol>
<p>
In <em>Information Distribution Aspects of Design Methodology</em> <a href="https://en.wikipedia.org/wiki/David_Parnas">David Parnas</a> writes about documentation standards:
</p>
<blockquote>
<p>
"standards tend to force system structure into a standard mold. A standard [..] makes some assumptions about the system. [...] If those assumptions are violated, the [...] organization fits poorly and the vocabulary must be stretched or misused."
</p>
<footer><cite><a href="https://en.wikipedia.org/wiki/David_Parnas">David Parnas</a>, <em>Information Distribution Aspects of Design Methodology</em></cite></footer>
</blockquote>
<p>
(The above quote is on the surface about documentation standards, and I've deliberately butchered it a bit (clearly marked) to make it easier to spot the more general mechanism.)
</p>
<p>
In the same paper, Parnas describes the danger of making hard-to-change decisions too early. Applied to directory structure, the lesson is that you should postpone designing a file hierarchy until you know more about the problem. Start with a flat directory structure and add folders later, if at all.
</p>
<h3 id="426c5128ef804c6abfe6005d267cb624">
Beyond files? <a href="#426c5128ef804c6abfe6005d267cb624">#</a>
</h3>
<p>
My claim is that you don't need <em>much</em> in way of directory hierarchy. From this doesn't follow, however, that we may never leverage such options. Even though I left most of the example code for <a href="/2021/06/14/new-book-code-that-fits-in-your-head">Code That Fits in Your Head</a> in a single folder, I did add a specialised folder as an <a href="/ref/ddd">anti-corruption layer</a>. Folders do have their uses.
</p>
<blockquote>
<p>
"Why not take it to the extreme and place most code in a single file? If we navigate by "namespace view" and search, do we need all those files?"
</p>
<footer><cite><a href="https://twitter.com/ronnieholm/status/1662219232652963840">Ronnie Holm</a></cite></footer>
</blockquote>
<p>
Following a thought to its extreme end can shed light on a topic. Why not, indeed, put all code in a single file?
</p>
<p>
Curious thought, but possibly not new. I've never programmed in <a href="https://en.wikipedia.org/wiki/Smalltalk">SmallTalk</a>, but as I understand it, the language came with tooling that was both <a href="https://en.wikipedia.org/wiki/Integrated_development_environment">IDE</a> and execution environment. Programmers would write source code in the editor, but although the code was persisted to disk, it may not have been as text files.
</p>
<p>
Even if I completely misunderstand how SmallTalk worked, it's not inconceivable that you could have a development environment based directly on a database. Not that I think that this sounds like a good idea, but it sounds technically possible.
</p>
<p>
Whether we do it one way or another seems mostly to be a question of tooling. What problems would you have if you wrote an entire C# (Java, Python, F#, or similar) code base as a single file? It becomes more difficult to look at two or more parts of the code base at the same time. Still, Visual Studio can actually give you split windows of the same file, but I don't know how it scales if you need multiple views over the same huge file.
</p>
<h3 id="fd3145a641ad4de18dbab9616e2ed4b7">
Conclusion <a href="#fd3145a641ad4de18dbab9616e2ed4b7">#</a>
</h3>
<p>
I recommend flat directory structures for code files. Put most code files in the root of a library or app. Of course, if your system is composed from multiple libraries (dependencies), each library has its own directory.
</p>
<p>
Subfolders aren't <em>prohibited</em>, only generally discouraged. Legitimate reasons to create subfolders may emerge as the code base evolves.
</p>
<p>
My misgivings about code file directory hierarchies mostly stem from the impact they have on developers' minds. This may manifest as <a href="https://en.wikipedia.org/wiki/Magical_thinking">magical thinking</a> or <a href="https://en.wikipedia.org/wiki/Cargo_cult">cargo-cult programming</a>: Erect elaborate directory structures to keep out the evil spirits of spaghetti code.
</p>
<p>
It doesn't work that way.
</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>.Visual Studio Code snippet to make URLs relativehttps://blog.ploeh.dk/2023/05/23/visual-studio-code-snippet-to-make-urls-relative2023-05-23T19:23:00+00:00Mark Seemann
<div id="post">
<p>
<em>Yes, it involves JSON and regular expressions.</em>
</p>
<p>
Ever since I <a href="/2013/03/03/moving-the-blog-to-jekyll">migrated the blog off dasBlog</a> I've been <a href="https://rakhim.org/honestly-undefined/19/">writing the articles in raw HTML</a>. The reason is mostly a historical artefact: Originally, I used <a href="https://en.wikipedia.org/wiki/Windows_Live_Writer">Windows Live Writer</a>, but <a href="https://jekyllrb.com/">Jekyll</a> had no support for that, and since I'd been doing web development for more than a decade already, raw HTML seemed like a reliable and durable alternative. I increasingly find that relying on skill and knowledge is a far more durable strategy than relying on technology.
</p>
<p>
For a decade I used <a href="https://www.sublimetext.com/">Sublime Text</a> to write articles, but over the years, I found it degrading in quality. I only used Sublime Text to author blog posts, so when I recently repaved my machine, I decided to see if I could do without it.
</p>
<p>
Since I was already using <a href="https://code.visualstudio.com/">Visual Studio Code</a> for much of my programming, I decided to give it a go for articles as well. It always takes time when you decide to move off a tool you've been used for a decade, but after some initial frustrations, I quickly found a new modus operandi.
</p>
<p>
One benefit of rocking the boat is that it prompts you to reassess the way you do things. Naturally, this happened here as well.
</p>
<h3 id="28218d2cd10945e0886bd528cf2d792f">
My quest for relative URLs <a href="#28218d2cd10945e0886bd528cf2d792f">#</a>
</h3>
<p>
I'd been using a few Sublime Text snippets to automate a few things, like the markup for the section heading you see above this paragraph. Figuring out how to replicate that snippet in Visual Studio Code wasn't too hard, but as I was already perusing <a href="https://code.visualstudio.com/docs/editor/userdefinedsnippets">the snippet documentation</a>, I started investigating other options.
</p>
<p>
One little annoyance I'd lived with for years was adding links to other articles on the blog.
</p>
<p>
While I write an article, I run the site on my local machine. When linking to other articles, I sometimes use the existing page address off the public site, and sometimes I just copy the page address from <code>localhost</code>. In both cases, I want the URL to be relative so that I can navigate the site even if I'm offline. I've written enough articles on planes or while travelling without internet that this is an important use case for me.
</p>
<p>
For example, if I want to link to the article <a href="/2023/01/02/adding-nuget-packages-when-offline">Adding NuGet packages when offline</a>, I want the URL to be <code>/2023/01/02/adding-nuget-packages-when-offline</code>, but that's not the address I get when I copy from the browser's address bar. Here, I get the full URL, with either <code>http://localhost:4000/</code> or <code>https://blog.ploeh.dk/</code> as the origin.
</p>
<p>
For years, I've been manually stripping the origin away, as well as the trailing <code>/</code>. Looking through the Visual Studio Code snippet documentation, however, I eyed an opportunity to automate that workflow.
</p>
<h3 id="f13d4bb7acf84183b9ac18088206f0ca">
Snippet <a href="#f13d4bb7acf84183b9ac18088206f0ca">#</a>
</h3>
<p>
I wanted a piece of editor automation that could modify a URL after I'd pasted it into the article. After a few iterations, I've settled on a <em>surround-with</em> snippet that works pretty well. It looks like this:
</p>
<p>
<pre><span style="color:#2e75b6;">"Make URL relative"</span>: {
<span style="color:#2e75b6;">"prefix"</span>: <span style="color:#a31515;">"urlrel"</span>,
<span style="color:#2e75b6;">"body"</span>: [ <span style="color:#a31515;">"${TM_SELECTED_TEXT/^(?:http(?:s?):\\/\\/(?:[^\\/]+))(.+)\\//$1/}"</span> ],
<span style="color:#2e75b6;">"description"</span>: <span style="color:#a31515;">"Make URL relative."</span>
}</pre>
</p>
<p>
Don't you just love regular expressions? Write once, scrutinise forever.
</p>
<p>
I don't want to go over all the details, because I've already forgotten most of them, but essentially this expression strips away the URL origin starting with either <code>http</code> or <code>https</code> until it finds the first slash <code>/</code>.
</p>
<p>
The thing that makes it useful, though, is the <code>TM_SELECTED_TEXT</code> variable that tells Visual Studio Code that this snippet works on <em>selected</em> text.
</p>
<p>
When I paste a URL into an <code>a</code> tag, at first nothing happens because no text is selected. I can then use <kbd>Shift</kbd> + <kbd>Alt</kbd> + <kbd>→</kbd> to expand the selection, at which point the Visual Studio Code lightbulb (<em>Code Action</em>) appears:
</p>
<p>
<img src="/content/binary/make-url-relative-screen-shot.png" alt="Screen shot of the make-URL-relative code snippet in action.">
</p>
<p>
Running the snippet removes the URL's origin, as well as the trailing slash, and I can move on to write the link text.
</p>
<h3 id="4e72443f63fe42e382e854fdc9a8d07a">
Conclusion <a href="#4e72443f63fe42e382e854fdc9a8d07a">#</a>
</h3>
<p>
After I started using Visual Studio Code to write blog posts, I've created a few custom snippets to support my authoring workflow. Most of them are fairly mundane, but the <em>make-URLs-relative</em> snippet took me a few iterations to get right.
</p>
<p>
I'm not expecting many of my readers to have this particular need, but I hope that this outline showcases the capabilities of Visual Studio Code snippets, and perhaps inspires you to look into creating custom snippets for your own purposes.
</p>
</div>
<div id="comments">
<hr />
<h2 id="comments-header">
Comments
</h2>
<div class="comment" id="8d84d3c52d134dcda81f7b63faccb58b">
<div class="comment-author"><a href="https://chamook.lol">Adam Guest</a></div>
<div class="comment-content">
<p>
Seems like a useful function to have, so I naturally wondered if I could <del>make it worse</del>
<ins>implement a similar function in Emacs</ins>.
</p>
<p>
Emacs lisp has support for regular expressions, only typically with a bunch of extra slashes
included, so I needed to figure out how to work with the currently selected text to get this to work.
The currently selected text is referred to as the "region" and by specifying <code>"r"</code> as a parameter
for the <code>interactive</code> call we can pass the start and end positions for the region directly to the function.
</p>
<p>
I came up with this rather basic function:
</p>
<p>
<pre>
(defun make-url-relative (start end)
"Converts the selected uri from an absolute url and converts it to a relative one.
This is very simple and relies on the url starting with http/https, and removes each character to the
first slash in the path"
(interactive "r")
(replace-regexp-in-region "http[s?]:\/\/.+\/" "" start end))
</pre>
</p>
<p>
With this function included in config somewhere: it can be called by selecting a url, and using <kbd>M-x</kbd>
<code>make-url-relative</code> (or assigned to a key binding as required)
</p>
<p>
I'm not sure if there's an already existing package for this functionality, but I hadn't really thought to look for it before
so thanks for the idea 😊
</p>
</div>
<div class="comment-date">2023-05-24 11:20 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>.Folders versus namespaceshttps://blog.ploeh.dk/2023/05/15/folders-versus-namespaces2023-05-15T06:01:00+00:00Mark Seemann
<div id="post">
<p>
<em>What if you allow folder and namespace structure to diverge?</em>
</p>
<p>
I'm currently writing C# code with some first-year computer-science students. Since most things are new to them, they sometimes do things in a way that are 'not the way we usually do things'. As an example, teachers have instructed them to use namespaces, but apparently no-one have told them that the file folder structure has to mirror the namespace structure.
</p>
<p>
The compiler doesn't care, but as long as I've been programming in C#, it's been idiomatic to do it that way. There's even <a href="https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0130">a static code analysis rule</a> about it.
</p>
<p>
The first couple of times they'd introduce a namespace without a corresponding directory, I'd point out that they are supposed to keep those things in sync. One day, however, it struck me: What happens if you flout that convention?
</p>
<h3 id="dac7601856e94a4e88315cb2e80f74e5">
A common way to organise code files <a href="#dac7601856e94a4e88315cb2e80f74e5">#</a>
</h3>
<p>
Code scaffolding tools and wizards will often nudge you to organise your code according to technical concerns: Controllers, models, views, etc. I'm sure you've encountered more than one code base organised like this:
</p>
<p>
<img src="/content/binary/code-organised-by-tech-responsibility.png" alt="Code organised into folders like Controllers, Models, DataAccess, etc.">
</p>
<p>
You'll put all your Controller classes in the <em>Controllers</em> directory, and make sure that the namespace matches. Thus, in such a code base, the full name of the <code>ReservationsController</code> might be <code>Ploeh.Samples.Restaurants.RestApi.Controllers.ReservationsController</code>.
</p>
<p>
A common criticism is that this is the <em>wrong</em> way to organise the code.
</p>
<h3 id="ea3a6df18fa641638f18e0b554c1ee7c">
The problem with trees <a href="#ea3a6df18fa641638f18e0b554c1ee7c">#</a>
</h3>
<p>
The complaint that this is the wrong way to organise code implies that a correct way exists. I write about this in <a href="/2021/06/14/new-book-code-that-fits-in-your-head">Code That Fits in Your Head</a>:
</p>
<blockquote>
<p>
Should you create a subdirectory for Controllers, another for Models, one for Filters, and so on? Or should you create a subdirectory for each feature?
</p>
<p>
Few people like my answer: <em>Just put all files in one directory.</em> Be wary of creating subdirectories just for the sake of 'organising' the code.
</p>
<p>
File systems are <em>hierarchies</em>; they are trees: a specialised kind of acyclic graph in which any two vertices are connected by exactly one path. Put another way, each vertex can have at most one parent. Even more bluntly: If you put a file in a hypothetical <code>Controllers</code> directory, you can't <em>also</em> put it in a <code>Calendar</code> directory.
</p>
</blockquote>
<p>
But what if you could?
</p>
<h3 id="bcdc2397846c45a9bcb3cea0e71cfa7a">
Namespaces disconnected from directory hierarchy <a href="#bcdc2397846c45a9bcb3cea0e71cfa7a">#</a>
</h3>
<p>
The code that accompanies <em>Code That Fits in Your Head</em> is organised as advertised: 65 files in a single directory. (Tests go in separate directories, though, as they belong to separate libraries.)
</p>
<p>
If you decide to ignore the convention that namespace structure should mirror folder structure, however, you now have a second axis of variability.
</p>
<p>
As an experiment, I decided to try that idea with the book's code base. The above screen shot shows the stereotypical organisation according to technical responsibility, after I moved things around. To be clear: This isn't how the book's example code is organised, but an experiment I only now carried out.
</p>
<p>
If you open the <code>ReservationsController.cs</code> file, however, I've now declared that it belongs to a namespace called <code>Ploeh.Samples.Restaurants.RestApi.Reservations</code>. Using Visual Studio's <em>Class View</em>, things look different from the <em>Solution Explorer:</em>
</p>
<p>
<img src="/content/binary/code-organised-by-namespace.png" alt="Code organised into namespaces according to feature: Calandar, Reservations, etc.">
</p>
<p>
Here I've organised the namespaces according to feature, rather than technical role. The screen shot shows the <em>Reservations</em> feature opened, while other features remain closed.
</p>
<h3 id="19763ef496cc424f8fd419bc4ad699d6">
Initial reactions <a href="#19763ef496cc424f8fd419bc4ad699d6">#</a>
</h3>
<p>
This article isn't a recommendation. It's nothing but an initial exploration of an idea.
</p>
<p>
Do I like it? So far, I think I still prefer flat directory structures. Even though this idea gives two axes of variability, you still have to make judgment calls. It's easy enough with Controllers, but where do you put cross-cutting concerns? Where do you put domain logic that seems to encompass everything else?
</p>
<p>
As an example, the code base that accompanies <em>Code That Fits in Your Head</em> is a multi-tenant system. Each restaurant is a separate tenant, but I've modelled restaurants as part of the domain model, and I've put that 'feature' in its own namespace. Perhaps that's a mistake; at least, I now have the code wart that I have to import the <code>Ploeh.Samples.Restaurants.RestApi.Restaurants</code> namespace to implement the <code>ReservationsController</code>, because its constructor looks like this:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:#2b91af;">ReservationsController</span>(
IClock <span style="font-weight:bold;color:#1f377f;">clock</span>,
IRestaurantDatabase <span style="font-weight:bold;color:#1f377f;">restaurantDatabase</span>,
IReservationsRepository <span style="font-weight:bold;color:#1f377f;">repository</span>)
{
Clock = clock;
RestaurantDatabase = restaurantDatabase;
Repository = repository;
}</pre>
</p>
<p>
The <code>IRestaurantDatabase</code> interface is defined in the <code>Restaurants</code> namespace, but the Controller needs it in order to look up the restaurant (i.e. tenant) in question.
</p>
<p>
You could argue that this isn't a problem with namespaces, but rather a code smell indicating that I should have organised the code in a different way.
</p>
<p>
That may be so, but then implies a deeper problem: Assigning files to hierarchies may not, after all, help much. It looks as though things are organised, but if the assignment of things to buckets is done without a predictable system, then what benefit does it provide? Does it make things easier to find, or is the sense of order mostly illusory?
</p>
<p>
I tend to still believe that this is the case. This isn't a nihilistic or defeatist position, but rather a realisation that order must arise from other origins.
</p>
<h3 id="305d423972e0422fa5ecdd04326cd132">
Conclusion <a href="#305d423972e0422fa5ecdd04326cd132">#</a>
</h3>
<p>
I was recently repeatedly encountering student code with a disregard for the convention that namespace structure should follow directory structure (or the other way around). Taking a cue from <a href="https://en.wikipedia.org/wiki/Kent_Beck">Kent Beck</a> I decided to investigate what happens if you forget about the rules and instead pursue what that new freedom might bring.
</p>
<p>
In this article, I briefly show an example where I reorganised a code base so that the file structure is according to implementation detail, but the namespace hierarchy is according to feature. Clearly, I could also have done it the other way around.
</p>
<p>
What if, instead of two, you have three organising principles? I don't know. I can't think of a third kind of hierarchy in a language like C#.
</p>
<p>
After a few hours reorganising the code, I'm not scared away from this idea. It might be worth to revisit in a larger code base. On the other hand, I'm still not convinced that forcing a hierarchy over a sophisticated software design is particularly beneficial.
</p>
<p>
<ins datetime="2023-05-30T12:22Z"><strong>P.S. 2023-05-30.</strong> This article is only a report on an experiment. For my general recommendation regarding code file organisation, see <a href="/2023/05/29/favour-flat-code-file-folders">Favour flat code file folders</a>.</ins>
</p>
</div>
<div id="comments">
<hr>
<h2 id="comments-header">
Comments
</h2>
<div class="comment" id="6c209fa61ad34ef3aa8290b06a964aaf">
<div class="comment-author"><a href="http://github.com/m4rsh">Markus Schmits</a></div>
<div class="comment-content">
<p>
Hi Mark,
<br> While reading your book "Code That Fits in Your Head", your latest blog entry caught my attention, as I am struggling in software development with similar issues.
<br> I find it hard, to put all classes into one project directory, as it feels overwhelming, when the number of classes increases.
<br> In the following, I would like to specify possible organising principles in my own words.
<p> <b> Postulations </b>
<br>- Folders should help the programmer (and reader) to keep the code organised
<br> - Namespaces should reflect the hierarchical organisation of the code base
<br> - Cross-cutting concerns should be addressed by modularity.
</p>
<p> <b> Definitions </b>
<br> 1. Folders
<br> - the allocation of classes in a project with similar technical concerns into folders should help the programmer in the first place, by visualising this similarity
<br> - the benefit lies just in the organisation, i.e. storage of code, not in the expression of hierarchy
</p>
<p>
2. Namespaces
<br> - expression of hierarchy can be achieved by namespaces, which indicate the relationship between allocated classes
<br> - classes can be organised in folders with same designation
<br> - the namespace designation could vary by concerns, although the classes are placed in same folders, as the technical concern of the class shouldn't affect the hierarchical organisation
</p>
<p>
3. Cross-cutting concerns
<br> - classes, which aren't related to a single task, could be indicated by a special namespace
<br> - they could be placed in a different folder, to signalize different affiliations
<br> - or even placed in a different assembly
</p>
<p>
<b> Summing up </b>
<br> A hierarchy should come by design. The organisation of code in folders should help the programmer or reader to grasp the file structure, not necessarily the program hierarchy.
<br>Folders should be a means, not an expression of design. Folders and their designations could change (or disappear) over time in development. Thus, explicit connection of namespace to folder designation seems not desirable, but it's not forbidden.
</p>
All views above are my own. Please let me know, what you think.
<p>
Best regards,
<br>Markus
</p>
</p>
</div>
<div class="comment-date">2023-05-18 19:13 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>.Is cyclomatic complexity really related to branch coverage?https://blog.ploeh.dk/2023/05/08/is-cyclomatic-complexity-really-related-to-branch-coverage2023-05-08T05:38:00+00:00Mark Seemann
<div id="post">
<p>
<em>A genuine case of doubt and bewilderment.</em>
</p>
<p>
Regular readers of this blog may be used to its confident and opinionated tone. I write that way, not because I'm always convinced that I'm right, but because prose with too many caveats and qualifications tends to bury the message in verbose and circumlocutory ambiguity.
</p>
<p>
This time, however, I write to solicit feedback, and because I'm surprised to the edge of bemusement by a recent experience.
</p>
<h3 id="6ebe2eae2250441c918433ba40ce8e86">
Collatz sequence <a href="#6ebe2eae2250441c918433ba40ce8e86">#</a>
</h3>
<p>
Consider the following code:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">Collatz</span>
{
<span style="color:blue;">public</span> <span style="color:blue;">static</span> IReadOnlyCollection<<span style="color:blue;">int</span>> <span style="color:#74531f;">Sequence</span>(<span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">n</span>)
{
<span style="font-weight:bold;color:#8f08c4;">if</span> (n < 1)
<span style="font-weight:bold;color:#8f08c4;">throw</span> <span style="color:blue;">new</span> ArgumentOutOfRangeException(
nameof(n),
<span style="color:#a31515;">$"Only natural numbers allowed, but given </span>{n}<span style="color:#a31515;">."</span>);
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">sequence</span> = <span style="color:blue;">new</span> List<<span style="color:blue;">int</span>>();
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">current</span> = n;
<span style="font-weight:bold;color:#8f08c4;">while</span> (current != 1)
{
sequence.Add(current);
<span style="font-weight:bold;color:#8f08c4;">if</span> (current % 2 == 0)
current = current / 2;
<span style="font-weight:bold;color:#8f08c4;">else</span>
current = current * 3 + 1;
}
sequence.Add(current);
<span style="font-weight:bold;color:#8f08c4;">return</span> sequence;
}
}</pre>
</p>
<p>
As the names imply, the <code>Sequence</code> function calculates the <a href="https://en.wikipedia.org/wiki/Collatz_conjecture">Collatz sequence</a> for a given natural number.
</p>
<p>
Please don't tune out if that sounds mathematical and difficult, because it really isn't. While the Collatz conjecture still evades mathematical proof, the sequence is easy to calculate and understand. Given a number, produce a sequence starting with that number and stop when you arrive at 1. Every new number in the sequence is based on the previous number. If the input is even, divide it by two. If it's odd, multiply it by three and add one. Repeat until you arrive at one.
</p>
<p>
The conjecture is that any natural number will produce a finite sequence. That's the unproven part, but that doesn't concern us. In this article, I'm only interested in the above code, which computes such sequences.
</p>
<p>
Here are few examples:
</p>
<p>
<pre>> Collatz.Sequence(1)
List<<span style="color:blue;">int</span>>(1) { 1 }
> Collatz.Sequence(2)
List<<span style="color:blue;">int</span>>(2) { 2, 1 }
> Collatz.Sequence(3)
List<<span style="color:blue;">int</span>>(8) { 3, 10, 5, 16, 8, 4, 2, 1 }
> Collatz.Sequence(4)
List<<span style="color:blue;">int</span>>(3) { 4, 2, 1 }</pre>
</p>
<p>
While there seems to be a general tendency for the sequence to grow as the input gets larger, that's clearly not a rule. The examples show that the sequence for <code>3</code> is longer than the sequence for <code>4</code>.
</p>
<p>
All this, however, just sets the stage. The problem doesn't really have anything to do with Collatz sequences. I only ran into it while working with a Collatz sequence implementation that looked a lot like the above.
</p>
<h3 id="08c0cb2794184e9da8b9f72e6c9ce985">
Cyclomatic complexity <a href="#08c0cb2794184e9da8b9f72e6c9ce985">#</a>
</h3>
<p>
What is the <a href="https://en.wikipedia.org/wiki/Cyclomatic_complexity">cyclomatic complexity</a> of the above <code>Sequence</code> function? If you need a reminder of how to count cyclomatic complexity, this is a good opportunity to take a moment to refresh your memory, count the number, and compare it with my answer.
</p>
<p>
Apart from the opportunity for exercise, it was a rhetorical question. The answer is <em>4</em>.
</p>
<p>
This means that we'd need <a href="/2019/12/09/put-cyclomatic-complexity-to-good-use">at least four unit test to cover all branches</a>. Right? Right?
</p>
<p>
Okay, let's try.
</p>
<h3 id="d10688e0a13241c7b7124a5ce8f063ef">
Branch coverage <a href="#d10688e0a13241c7b7124a5ce8f063ef">#</a>
</h3>
<p>
Before we start, let's make the ritual <a href="/2015/11/16/code-coverage-is-a-useless-target-measure">denouncement of code coverage as a target metric</a>. The point isn't to reach 100% code coverage as such, but to <a href="/2018/11/12/what-to-test-and-not-to-test">gain confidence that you've added tests that cover whatever is important to you</a>. Also, the best way to do that is usually with TDD, which isn't the situation I'm discussing here.
</p>
<p>
The first branch that we might want to cover is the Guard Clause. This is easily addressed with an <a href="https://xunit.net/">xUnit.net</a> test:
</p>
<p>
<pre>[Fact]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> <span style="font-weight:bold;color:#74531f;">ThrowOnInvalidInput</span>()
{
Assert.Throws<ArgumentOutOfRangeException>(() => Collatz.Sequence(0));
}</pre>
</p>
<p>
This test calls the <code>Sequence</code> function with <code>0</code>, which (in this context, at least) isn't a <a href="https://en.wikipedia.org/wiki/Natural_number">natural number</a>.
</p>
<p>
If you measure test coverage (or, in this case, just think it through), there are no surprises yet. One branch is covered, the rest aren't. That's 25%.
</p>
<p>
(If you use the <a href="https://learn.microsoft.com/dotnet/core/testing/unit-testing-code-coverage">free code coverage option for .NET</a>, it will surprisingly tell you that you're only at 16% branch coverage. It deems the cyclomatic complexity of the <code>Sequence</code> function to be 6, not 4, and 1/6 is 16.67%. Why it thinks it's 6 is not entirely clear to me, but Visual Studio agrees with me that the cyclomatic complexity is 4. In this particular case, it doesn't matter anyway. The conclusion that follows remains the same.)
</p>
<p>
Let's add another test case, and perhaps one that gives the algorithm a good exercise.
</p>
<p>
<pre>[Fact]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> <span style="font-weight:bold;color:#74531f;">Example</span>()
{
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">actual</span> = Collatz.Sequence(5);
Assert.Equal(<span style="color:blue;">new</span>[] { 5, 16, 8, 4, 2, 1 }, actual);
}</pre>
</p>
<p>
As expected, the test passes. What's the branch coverage now?
</p>
<p>
Try to think it through instead of relying exclusively on a tool. The algorithm isn't more complicated that you can emulate execution in your head, or perhaps with the assistance of a notepad. How many branches does it execute when the input is <code>5</code>?
</p>
<p>
Branch coverage is now 100%. (Even the <em>dotnet</em> coverage tool agrees, despite its weird cyclomatic complexity value.) All branches are exercised.
</p>
<p>
Two tests produce 100% branch coverage of a function with a cyclomatic complexity of 4.
</p>
<h3 id="7a4d9c5fbb8e4e94a52c61990565e38f">
Surprise <a href="#7a4d9c5fbb8e4e94a52c61990565e38f">#</a>
</h3>
<p>
That's what befuddles me. I thought that cyclomatic complexity and branch coverage were related. I thought, that the number of branches was a good indicator of the number of tests you'd need to cover all branches. I even wrote <a href="/2019/12/09/put-cyclomatic-complexity-to-good-use">an article to that effect</a>, and no-one contradicted me.
</p>
<p>
That, in itself, is no proof of anything, but the notion that the article presents seems to be widely accepted. I never considered it controversial, and the only reason I didn't cite anyone is that this seems to be 'common knowledge'. I wasn't aware of a particular source I could cite.
</p>
<p>
Now, however, it seems that it's wrong. Is it wrong, or am I missing something?
</p>
<p>
To be clear, I completely understand why the above two tests are sufficient to fully cover the function. I also believe that I fully understand why the cyclomatic complexity is 4.
</p>
<p>
I am also painfully aware that the above two tests in no way fully specify the Collatz sequence. That's not the point.
</p>
<p>
The point is that it's possible to cover this function with only two tests, despite the cyclomatic complexity being 4. That surprises me.
</p>
<p>
Is this a known thing?
</p>
<p>
I'm sure it is. I've long since given up discovering anything new in programming.
</p>
<h3 id="829b5f9b3e9449d1a023d2bacff5b58c">
Conclusion <a href="#829b5f9b3e9449d1a023d2bacff5b58c">#</a>
</h3>
<p>
I recently encountered a function that performed a Collatz calculation similar to the one I've shown here. It exhibited the same trait, and since it had no Guard Clause, I could fully cover it with a single test case. That function even had a cyclomatic complexity of 6, so you can perhaps imagine my befuddlement.
</p>
<p>
Is it wrong, then, that cyclomatic complexity suggests a minimum number of test cases in order to cover all branches?
</p>
<p>
It seems so, but that's new to me. I don't mind being wrong on occasion. It's usually an opportunity to learn something new. If you have any insights, please <a href="https://github.com/ploeh/ploeh.github.com#comments">leave a comment</a>.
</p>
</div>
<div id="comments">
<hr>
<h2 id="comments-header">
Comments
</h2>
<div class="comment" id="02568f995d91432da540858644b61e89">
<div class="comment-author"><a href="http://github.com/neongraal">Struan Judd</a></div>
<div class="comment-content">
<p>
My first thought is that the code looks like an unrolled recursive function, so perhaps if it's
refactored into a driver function and a "continuation passing style" it might make the cyclomatic
complexity match the covering tests.
</p>
<p>
So given the following:
<pre>public delegate void ResultFunc(IEnumerable<int> result);
public delegate void ContFunc(int n, ResultFunc result, ContFunc cont);
public static void Cont(int n, ResultFunc result, ContFunc cont) {
if (n == 1) {
result(new[] { n });
return;
}
void Result(IEnumerable<int> list) => result(list.Prepend(n));
if (n % 2 == 0)
cont(n / 2, Result, cont);
else
cont(n * 3 + 1, Result, cont);
}
public static IReadOnlyCollection<int> Continuation(int n) {
if (n < 1)
throw new ArgumentOutOfRangeException(
nameof(n),
$"Only natural numbers allowed, but given {n}.");
var output = new List<int>();
void Output(IEnumerable<int> list) => output = list.ToList();
Cont(n, Output, Cont);
return output;
}</pre>
</p>
<p>
I calculate the Cyclomatic complexity of <code>Continuation</code> to be <em>2</em> and <code>Step</code> to be <em>3</em>.
</p>
<p>
And it would seem you need 5 tests to properly cover the code, 3 for <code>Step</code> and 2 for <code>Continuation</code>.
</p>
<p>
But however you write the "n >=1" case for <code>Continuation</code> you will have to cover some of <code>Step</code>.
</p>
</div>
<div class="comment-date">2023-05-08 10:11 UTC</div>
</div>
<div class="comment" id="896f7e7c979144438a6e7f1a66dd72ea">
<div class="comment-author">Jeroen Heijmans</div>
<div class="comment-content">
<p>
There is a relation between cyclomatic complexity and branches to cover, but it's not one of equality, cyclomatic
complexity is an upper bound for the number of branches. There's a nice example illustrating this in the
<a href="https://en.wikipedia.org/w/index.php?title=Cyclomatic_complexity#Implications_for_software_testing">Wikipedia
article on cyclomatic complexity</a> that explains this, as well as the relation with path coverage (for which
cyclomatic complexity is a lower bound).
</p>
</div>
<div class="comment-date">2023-05-08 15:03 UTC</div>
</div>
<div class="comment" id="b683f78855f8440389b973e24c88c253">
<div class="comment-author"><a href="https://github.com/bretthall">Brett Hall</a></div>
<div class="comment-content">
<p>
I find cyclomatic complexity to be overly pedantic at times, and you will need four tests if you get really pedantic.
First, test the guard clause as you already did. Then, test with 1 in order to test the <pre>while</pre> loop body
not being run. Then, test with 2 in order to test that the <pre>while</pre> is executed, but we only hit the <pre>if</pre>
part of the <pre>if/else</pre>. Finally, test with 3 in order to hit the <pre>else</pre> inside of the <pre>while</pre>.
That's four tests where each test is only testing one of the branches (some tests hit more than one branch, but the
"extra branch" is already covered by another test). Again, this is being really pedantic and I wouldn't test this
function as laid out above (I'd probaby put in the test with 1, since it's an edge case, but otherwise test as you did).
</p>
<p>
I don't think there's a rigorous relationship between cyclomatic complexity and number of tests. In simple cases, treating
things as though the relationship exists can be helpful. But once you start having iterrelated branches in a function,
things get murky, and you may have to go to pedantic lengths in order to maintain the relationship. The same
thing goes for code coverage, which can be 100% even though you haven't actually tested all paths through your code if
there are multiple branches in the function that depend on each other.
</p>
</div>
<div class="comment-date">2023-05-08 15:30 UTC</div>
</div>
<div class="comment" id="61939b516c0e4c2caab7c6e8a3302595">
<div class="comment-author"><a href="/">Mark Seemann</a></div>
<div class="comment-content">
<p>
Thank you, all, for writing. I'm extraordinarily busy at the moment, so it'll take me longer than usual to respond. Rest assured, however, that I haven't forgotten.
</p>
</div>
<div class="comment-date">2023-05-11 12:42 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>.Refactoring pure function composition without breaking existing testshttps://blog.ploeh.dk/2023/05/01/refactoring-pure-function-composition-without-breaking-existing-tests2023-05-01T06:44:00+00:00Mark Seemann
<div id="post">
<p>
<em>An example modifying a Haskell Gossiping Bus Drivers implementation.</em>
</p>
<p>
This is an article in an series of articles about the <a href="/2023/02/13/epistemology-of-interaction-testing">epistemology of interaction testing</a>. In short, this collection of articles discusses how to test the composition of <a href="https://en.wikipedia.org/wiki/Pure_function">pure functions</a>. While a pure function is <a href="/2015/05/07/functional-design-is-intrinsically-testable">intrinsically testable</a>, how do you test the composition of pure functions? As the introductory article outlines, I consider it mostly a matter of establishing confidence. With <a href="/2018/11/12/what-to-test-and-not-to-test">enough test coverage</a> you can be confident that the composition produces the desired outputs.
</p>
<p>
Keep in mind that if you compose pure functions into a larger pure function, the composition is still pure. This implies that you can still test it by supplying input and verifying that the output is correct.
</p>
<p>
Tests that exercise the composition do so by verifying observable behaviour. This makes them more robust to refactoring. You'll see an example of that later in this article.
</p>
<h3 id="32b583422c354d0f8468406f0486a762">
Gossiping bus drivers <a href="#32b583422c354d0f8468406f0486a762">#</a>
</h3>
<p>
I recently did the <a href="https://kata-log.rocks/gossiping-bus-drivers-kata">Gossiping Bus Drivers</a> kata in <a href="https://www.haskell.org/">Haskell</a>. At first, I added the tests suggested in the kata description.
</p>
<p>
<pre>{-# OPTIONS_GHC -Wno-type-defaults #-}
<span style="color:blue;">module</span> Main <span style="color:blue;">where</span>
<span style="color:blue;">import</span> GossipingBusDrivers
<span style="color:blue;">import</span> Test.HUnit
<span style="color:blue;">import</span> Test.Framework.Providers.HUnit (<span style="color:#2b91af;">hUnitTestToTests</span>)
<span style="color:blue;">import</span> Test.Framework (<span style="color:#2b91af;">defaultMain</span>)
<span style="color:#2b91af;">main</span> <span style="color:blue;">::</span> <span style="color:#2b91af;">IO</span> ()
main = defaultMain $ hUnitTestToTests $ TestList [
<span style="color:#a31515;">"Kata examples"</span> ~: <span style="color:blue;">do</span>
(routes, expected) <-
[
([[3, 1, 2, 3],
[3, 2, 3, 1],
[4, 2, 3, 4, 5]],
Just 5),
([[2, 1, 2],
[5, 2, 8]],
Nothing)
]
<span style="color:blue;">let</span> actual = drive routes
<span style="color:blue;">return</span> $ expected ~=? actual
]</pre>
</p>
<p>
As I prefer them, these tests are <a href="/2018/04/30/parametrised-unit-tests-in-haskell">parametrised HUnit tests</a>.
</p>
<p>
The problem with those suggested test cases is that they don't provide enough confidence that an implementation is correct. In fact, I wrote this implementation to pass them:
</p>
<p>
<pre>drive routes = <span style="color:blue;">if</span> <span style="color:blue;">length</span> routes == 3 <span style="color:blue;">then</span> Just 5 <span style="color:blue;">else</span> Nothing</pre>
</p>
<p>
This is clearly incorrect. It just looks at the number of routes and returns a fixed value for each count. It doesn't look at the contents of the routes.
</p>
<p>
Even if you don't <a href="/2019/10/07/devils-advocate">try to deliberately cheat</a> I'm not convinced that these two tests are enough. You could <em>try</em> to write the correct implementation, but how do you know that you've correctly dealt with various edge cases?
</p>
<h3 id="0e40e3994772481f855b266452685852">
Helper function <a href="#0e40e3994772481f855b266452685852">#</a>
</h3>
<p>
The kata description isn't hard to understand, so while the suggested test cases seem insufficient, I knew what was required. Perhaps I could write a proper implementation without additional tests. After all, I was convinced that it'd be possible to do it with a <a href="https://en.wikipedia.org/wiki/Cyclomatic_complexity">cyclomatic complexity</a> of <em>1</em>, and since <a href="/2013/04/02/why-trust-tests">a test function also has a cyclomatic complexity of <em>1</em></a>, there's always that tension in test-driven development: Why write test code to exercise code with a cyclomatic complexity of <em>1?</em>.
</p>
<p>
To be clear: There are often good reasons to write tests even in this case, and this seems like one of them. <a href="/2019/12/09/put-cyclomatic-complexity-to-good-use">Cyclomatic complexity indicates a minimum number of test cases</a>, not necessarily a sufficient number.
</p>
<p>
Even though Haskell's type system is expressive, I soon found myself second-guessing the behaviour of various expressions that I'd experimented with. Sometimes I find GHCi (the Haskell <a href="https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop">REPL</a>) sufficiently edifying, but in this case I thought that I might want to keep some test cases around for a helper function that I was developing:
</p>
<p>
<pre><span style="color:blue;">import</span> Data.List
<span style="color:blue;">import</span> <span style="color:blue;">qualified</span> Data.Map.Strict <span style="color:blue;">as</span> Map
<span style="color:blue;">import</span> Data.Map.Strict (<span style="color:#2b91af;">(!)</span>)
<span style="color:blue;">import</span> <span style="color:blue;">qualified</span> Data.Set <span style="color:blue;">as</span> Set
<span style="color:blue;">import</span> Data.Set (<span style="color:blue;">Set</span>)
<span style="color:#2b91af;">evaluateStop</span> <span style="color:blue;">::</span> (<span style="color:blue;">Functor</span> f, <span style="color:blue;">Foldable</span> f, <span style="color:blue;">Ord</span> k, <span style="color:blue;">Ord</span> a)
=> f (k, Set a) -> f (k, Set a)
evaluateStop stopsAndDrivers =
<span style="color:blue;">let</span> gossip (stop, driver) = Map.insertWith Set.union stop driver
gossipAtStops = <span style="color:blue;">foldl</span>' (<span style="color:blue;">flip</span> gossip) Map.empty stopsAndDrivers
<span style="color:blue;">in</span> <span style="color:blue;">fmap</span> (\(stop, _) -> (stop, gossipAtStops ! stop)) stopsAndDrivers</pre>
</p>
<p>
I was fairly confident that this function worked as I intended, but I wanted to be sure. I needed some examples, so I added these tests:
</p>
<p>
<pre><span style="color:#a31515;">"evaluateStop examples"</span> ~: <span style="color:blue;">do</span>
(stopsAndDrivers, expected) <- [
([(1, fromList [1]), (2, fromList [2]), (1, fromList [1])],
[(1, fromList [1]), (2, fromList [2]), (1, fromList [1])]),
([(1, fromList [1]), (2, fromList [2]), (1, fromList [2])],
[(1, fromList [1, 2]), (2, fromList [2]), (1, fromList [1, 2])]),
([(1, fromList [1, 2, 3]), (1, fromList [2, 3, 4])],
[(1, fromList [1, 2, 3, 4]), (1, fromList [1, 2, 3, 4])])
]
<span style="color:blue;">let</span> actual = evaluateStop stopsAndDrivers
<span style="color:blue;">return</span> $ fromList expected ~=? fromList actual</pre>
</p>
<p>
They do, indeed, pass.
</p>
<p>
The idea behind that <code>evaluateStop</code> function is to evaluate the state at each 'minute' of the simulation. The first line of each test case is the state before the drivers meet, and the second line is the <em>expected</em> state after all drivers have gossiped.
</p>
<p>
My plan was to use some sort of left fold to keep evaluating states until all information has disseminated to all drivers.
</p>
<h3 id="06888628b5da4b4bb76fc59812c019da">
Property <a href="#06888628b5da4b4bb76fc59812c019da">#</a>
</h3>
<p>
Since I have already extolled the virtues of property-based testing in this article series, I wondered whether I could add some properties instead of relying on examples. Well, I did manage to add one <a href="https://hackage.haskell.org/package/QuickCheck">QuickCheck</a> property:
</p>
<p>
<pre>testProperty <span style="color:#a31515;">"drive image"</span> $ \ (routes :: [NonEmptyList Int]) ->
<span style="color:blue;">let</span> actual = drive $ <span style="color:blue;">fmap</span> getNonEmpty routes
<span style="color:blue;">in</span> isJust actual ==>
<span style="color:blue;">all</span> (\i -> 0 <= i && i <= 480) actual</pre>
</p>
<p>
There's not much to talk about here. The property only states that the result of the <code>drive</code> function must be between <code>0</code> and <code>480</code>, if it exists.
</p>
<p>
Such a property could vacuously pass if <code>drive</code> always returns <code>Nothing</code>, so I used the <code>==></code> QuickCheck combinator to make sure that the property is actually exercising only the <code>Just</code> cases.
</p>
<p>
Since the <code>drive</code> function only returns a number, apart from verifying its <a href="https://en.wikipedia.org/wiki/Image_(mathematics)">image</a> I couldn't think of any other general property to add.
</p>
<p>
You can always come up with more specific properties that explicitly set up more constrained test scenarios, but is it worth it?
</p>
<p>
It's always worthwhile to stop and think. If you're writing a 'normal' example-based test, consider whether a property would be better. Likewise, if you're about to write a property, consider whether an example would be better.
</p>
<p>
'Better' can mean more than one thing. Preventing regressions is one thing, but making the code maintainable is another. If you're writing a property that is too complicated, it might be better to write a simpler example-based test.
</p>
<p>
I could definitely think of some complicated properties, but I found that more examples might make the test code easier to understand.
</p>
<h3 id="64eac896c8ea4127bacccb8ca01cf2fb">
More examples <a href="#64eac896c8ea4127bacccb8ca01cf2fb">#</a>
</h3>
<p>
After all that angst and soul-searching, I added a few more examples to the first parametrised test:
</p>
<p>
<pre><span style="color:#a31515;">"Kata examples"</span> ~: <span style="color:blue;">do</span>
(routes, expected) <-
[
([[3, 1, 2, 3],
[3, 2, 3, 1],
[4, 2, 3, 4, 5]],
Just 5),
([[2, 1, 2],
[5, 2, 8]],
Nothing),
([[1, 2, 3, 4, 5],
[5, 6, 7, 8],
[3, 9, 6]],
Just 13),
([[1, 2, 3],
[2, 1, 3],
[2, 4, 5, 3]],
Just 5),
([[1, 2],
[2, 1]],
Nothing),
([[1]],
Just 0),
([[2],
[2]],
Just 1)
]
<span style="color:blue;">let</span> actual = drive routes
<span style="color:blue;">return</span> $ expected ~=? actual</pre>
</p>
<p>
The first two test cases are the same as before, and the last two are some edge cases I added myself. The middle three I adopted from <a href="https://dodona.ugent.be/en/activities/1792896126/">another page about the kata</a>. Since those examples turned out to be off by one, I did those examples on paper to verify that I understood what the expected value was. Then I adjusted them to my one-indexed results.
</p>
<h3 id="52417ab56528457891928ea551017f75">
Drive <a href="#52417ab56528457891928ea551017f75">#</a>
</h3>
<p>
The <code>drive</code> function now correctly implements the kata, I hope. At least it passes all the tests.
</p>
<p>
<pre><span style="color:#2b91af;">drive</span> <span style="color:blue;">::</span> (<span style="color:blue;">Num</span> b, <span style="color:blue;">Enum</span> b, <span style="color:blue;">Ord</span> a) <span style="color:blue;">=></span> [[a]] <span style="color:blue;">-></span> <span style="color:#2b91af;">Maybe</span> b
drive routes =
<span style="color:green;">-- Each driver starts with a single gossip. Any kind of value will do, as
</span> <span style="color:green;">-- long as each is unique. Here I use the one-based index of each route,
</span> <span style="color:green;">-- since it fulfills the requirements.
</span> <span style="color:blue;">let</span> drivers = <span style="color:blue;">fmap</span> Set.singleton [1 .. <span style="color:blue;">length</span> routes]
goal = Set.unions drivers
stops = transpose $ <span style="color:blue;">fmap</span> (<span style="color:blue;">take</span> 480 . <span style="color:blue;">cycle</span>) routes
propagation =
<span style="color:blue;">scanl</span> (\ds ss -> <span style="color:blue;">snd</span> <$> evaluateStop (<span style="color:blue;">zip</span> ss ds)) drivers stops
<span style="color:blue;">in</span> <span style="color:blue;">fmap</span> <span style="color:blue;">fst</span> $ find (<span style="color:blue;">all</span> (== goal) . <span style="color:blue;">snd</span>) $ <span style="color:blue;">zip</span> [0 ..] propagation</pre>
</p>
<p>
Haskell code can be information-dense, and if you don't have an integrated development environment (IDE) around, this may be hard to read.
</p>
<p>
<code>drivers</code> is a list of sets. Each set represents the gossip that a driver knows. At the beginning, each only knows one piece of gossip. The expression initialises each driver with a <code>singleton</code> set. Each piece of gossip is represented by a number, simply going from <code>1</code> to the number of routes. Incidentally, this is also the number of drivers, so you can consider the number <code>1</code> as a placeholder for the gossip that driver <em>1</em> knows, and so on.
</p>
<p>
The <code>goal</code> is the union of all the gossip. Once every driver's knowledge is equal to the <code>goal</code> the simulation can stop.
</p>
<p>
Since <code>evaluateStop</code> simulates one stop, the <code>drive</code> function needs a list of stops to fold. That's the <code>stops</code> value. In the very first example, you have three routes: <code>[3, 1, 2, 3]</code>, <code>[3, 2, 3, 1]</code>, and <code>[4, 2, 3, 4, 5]</code>. The first time the drivers stop (after one minute), the stops are <code>3</code>, <code>3</code>, and <code>4</code>. That is, the first element in <code>stops</code> would be the list <code>[3, 3, 4]</code>. The next one would be <code>[1, 2, 2]</code>, then <code>[2, 3, 3]</code>, and so on.
</p>
<p>
My plan all along was to use some sort of left fold to repeatedly run <code>evaluateStop</code> over each minute. Since I need to produce a list of states, <code>scanl</code> was an appropriate choice. The lambda expression that I have to pass to it, though, is more complicated than I appreciate. We'll return to that in a moment.
</p>
<p>
The <code>drive</code> function can now index the <code>propagation</code> list by zipping it with the infinite list <code>[0 ..]</code>, <code>find</code> the first element where <code>all</code> sets are equal to the <code>goal</code> set, and then return that index. That produces the correct results.
</p>
<h3 id="2b84136e78154ebdb81654efabf3d987">
The need for a better helper function <a href="#2b84136e78154ebdb81654efabf3d987">#</a>
</h3>
<p>
As I already warned, I wasn't happy with the lambda expression passed to <code>scanl</code>. It looks complicated and arcane. Is there a better way to express the same behaviour? Usually, when confronted with a nasty lambda expression like that, in Haskell my first instinct is to see if <a href="https://pointfree.io/">pointfree.io</a> has a better option. Alas, <code>(((<span style="color:blue;">snd</span> <$>) . evaluateStop) .) . <span style="color:blue;">flip</span> <span style="color:blue;">zip</span></code> hardly seems an improvement. That <code>flip zip</code> expression to the right, however, suggests that it might help flipping the arguments to <code>evaluateStop</code>.
</p>
<p>
When I developed the <code>evaluateStop</code> helper function, I found it intuitive to define it over a list of tuples, where the first element in the tuple is the stop, and the second element is the set of gossip that the driver at that stop knows.
</p>
<p>
The tuples don't <em>have</em> to be in that order, though. Perhaps if I flip the tuples that would make the lambda expression more readable. It was worth a try.
</p>
<h3 id="ca808b5a5fa3473c9046704e4bcc7357">
Confidence <a href="#ca808b5a5fa3473c9046704e4bcc7357">#</a>
</h3>
<p>
Since this article is part of a small series about the epistemology of testing composed functions, let's take a moment to reflect on the confidence we may have in the <code>drive</code> function.
</p>
<p>
Keep in mind the goal of the kata: Calculate the number of minutes it takes for all gossip to spread to all drivers. There's a few tests that verify that; seven examples and a fairly vacuous QuickCheck property. Is that enough to be confident that the function is correct?
</p>
<p>
If it isn't, I think the best option you have is to add more examples. For the sake of argument, however, let's assume that the tests are good enough.
</p>
<p>
When summarising the tests that cover the <code>drive</code> function, I didn't count the three examples that exercise <code>evaluateStop</code>. Do these three test cases improve your confidence in the <code>drive</code> function? A bit, perhaps, but keep in mind that <em>the kata description doesn't mandate that function.</em> It's just a helper function I created in order to decompose the problem.
</p>
<p>
Granted, having tests that cover a helper function does, to a degree, increase my confidence in the code. I have confidence in the function itself, but that is largely irrelevant, because the problem I'm trying to solve is <em>not</em> implementing this particular function. On the other hand, my confidence in <code>evaluateStop</code> means that I have increased confidence in the code that calls it.
</p>
<p>
Compared to interaction-based testing, I'm not <em>testing</em> that <code>drive</code> calls <code>evaluateStop</code>, but I can still verify that this happens. I can just look at the code.
</p>
<p>
The composition is already there in the code. What do I gain from replicating that composition with <a href="http://xunitpatterns.com/Test%20Stub.html">Stubs</a> and <a href="http://xunitpatterns.com/Test%20Spy.html">Spies</a>?
</p>
<p>
It's not a breaking change if I decide to implement <code>drive</code> in a different way.
</p>
<p>
What gives me confidence when composing pure functions isn't that I've subjected the composition to an interaction-based test. Rather, it's that the function is composed from trustworthy components.
</p>
<h3 id="a414a1e6b9e947d2b4632fcea7b916cf">
Strangler <a href="#a414a1e6b9e947d2b4632fcea7b916cf">#</a>
</h3>
<p>
My main grievance with Stubs and Spies is that <a href="/2022/10/17/stubs-and-mocks-break-encapsulation">they break encapsulation</a>. This may sound abstract, but is a real problem. This is the underlying reason that so many tests break when you refactor code.
</p>
<p>
This example code base, as other functional code that I write, avoids interaction-based testing. This makes it easier to refactor the code, as I will now demonstrate.
</p>
<p>
My goal is to change the <code>evaluateStop</code> helper function by flipping the tuples. If I just edit it, however, I'm going to (temporarily) break the <code>drive</code> function.
</p>
<p>
Katas typically result in small code bases where you can get away with a lot of bad practices that wouldn't work in a larger code base. To be honest, the refactoring I have in mind can be completed in a few minutes with a brute-force approach. Imagine, however, that we can't break compatibility of the <code>evaluateStop</code> function for the time being. Perhaps, had we had a larger code base, there were other code that depended on this function. At the very least, the tests do.
</p>
<p>
Instead of brute-force changing the function, I'm going to make use of the <a href="https://martinfowler.com/bliki/StranglerFigApplication.html">Strangler</a> pattern, as I've also described in my book <a href="/2021/06/14/new-book-code-that-fits-in-your-head">Code That Fits in Your Head</a>.
</p>
<p>
Leave the existing function alone, and add a new one. You can typically copy and paste the existing code and then make the necessary changes. In that way, you break neither client code nor tests, because there are none.
</p>
<p>
<pre><span style="color:#2b91af;">evaluateStop'</span> <span style="color:blue;">::</span> (<span style="color:blue;">Functor</span> f, <span style="color:blue;">Foldable</span> f, <span style="color:blue;">Ord</span> k, <span style="color:blue;">Ord</span> a)
=> f (Set a, k) -> f (Set a, k)
evaluateStop' driversAndStops =
<span style="color:blue;">let</span> gossip (driver, stop) = Map.insertWith Set.union stop driver
gossipAtStops = <span style="color:blue;">foldl</span>' (<span style="color:blue;">flip</span> gossip) Map.empty driversAndStops
<span style="color:blue;">in</span> <span style="color:blue;">fmap</span> (\(_, stop) -> (gossipAtStops ! stop, stop)) driversAndStops</pre>
</p>
<p>
In a language like C# you can often get away with overloading a method name, but Haskell doesn't have overloading. Since I consider this side-by-side situation to be temporary, I've appended a prime after the function name. This is a fairly normal convention in Haskell, I gather.
</p>
<p>
The only change this function represents is that I've swapped the tuple order.
</p>
<p>
Once you've added the new function, you may want to copy, paste and edit the tests. Or perhaps you want to do the tests first. During this process, make <a href="https://www.industriallogic.com/blog/whats-this-about-micro-commits/">micro-commits</a> so that you can easily suspend your 'refactoring' activity if something more important comes up.
</p>
<p>
Once everything is in place, you can change the <code>drive</code> function:
</p>
<p>
<pre><span style="color:#2b91af;">drive</span> <span style="color:blue;">::</span> (<span style="color:blue;">Num</span> b, <span style="color:blue;">Enum</span> b, <span style="color:blue;">Ord</span> a) <span style="color:blue;">=></span> [[a]] <span style="color:blue;">-></span> <span style="color:#2b91af;">Maybe</span> b
drive routes =
<span style="color:green;">-- Each driver starts with a single gossip. Any kind of value will do, as
</span> <span style="color:green;">-- long as each is unique. Here I use the one-based index of each route,
</span> <span style="color:green;">-- since it fulfills the requirements.
</span> <span style="color:blue;">let</span> drivers = <span style="color:blue;">fmap</span> Set.singleton [1 .. <span style="color:blue;">length</span> routes]
goal = Set.unions drivers
stops = transpose $ <span style="color:blue;">fmap</span> (<span style="color:blue;">take</span> 480 . <span style="color:blue;">cycle</span>) routes
propagation =
<span style="color:blue;">scanl</span> (\ds ss -> <span style="color:blue;">fst</span> <$> evaluateStop' (<span style="color:blue;">zip</span> ds ss)) drivers stops
<span style="color:blue;">in</span> <span style="color:blue;">fmap</span> <span style="color:blue;">fst</span> $ find (<span style="color:blue;">all</span> (== goal) . <span style="color:blue;">snd</span>) $ <span style="color:blue;">zip</span> [0 ..] propagation</pre>
</p>
<p>
Notice that the type of <code>drive</code> hasn't change, and neither has the behaviour. This means that although I've changed the composition (the <em>interaction</em>) no tests broke.
</p>
<p>
Finally, once I moved all code over, I deleted the old function and renamed the new one to take its place.
</p>
<h3 id="6be4ec66c14c4adbbb8bcb60307c7ba3">
Was it all worth it? <a href="#6be4ec66c14c4adbbb8bcb60307c7ba3">#</a>
</h3>
<p>
At first glance, it doesn't look as though much was gained. What happens if I eta-reduce the new lambda expression?
</p>
<p>
<pre><span style="color:#2b91af;">drive</span> <span style="color:blue;">::</span> (<span style="color:blue;">Num</span> b, <span style="color:blue;">Enum</span> b, <span style="color:blue;">Ord</span> a) <span style="color:blue;">=></span> [[a]] <span style="color:blue;">-></span> <span style="color:#2b91af;">Maybe</span> b
drive routes =
<span style="color:green;">-- Each driver starts with a single gossip. Any kind of value will do, as
</span> <span style="color:green;">-- long as each is unique. Here I use the one-based index of each route,
</span> <span style="color:green;">-- since it fulfills the requirements.
</span> <span style="color:blue;">let</span> drivers = <span style="color:blue;">fmap</span> Set.singleton [1 .. <span style="color:blue;">length</span> routes]
goal = Set.unions drivers
stops = transpose $ <span style="color:blue;">fmap</span> (<span style="color:blue;">take</span> 480 . <span style="color:blue;">cycle</span>) routes
propagation = <span style="color:blue;">scanl</span> (((<span style="color:blue;">fmap</span> <span style="color:blue;">fst</span> . evaluateStop) .) . <span style="color:blue;">zip</span>) drivers stops
<span style="color:blue;">in</span> <span style="color:blue;">fmap</span> <span style="color:blue;">fst</span> $ find (<span style="color:blue;">all</span> (== goal) . <span style="color:blue;">snd</span>) $ <span style="color:blue;">zip</span> [0 ..] propagation</pre>
</p>
<p>
Not much better. I can now fit the <code>propagation</code> expression on a single line of code and still stay within a <a href="/2019/11/04/the-80-24-rule">80x24 box</a>, but that's about it. Is <code>((<span style="color:blue;">fmap</span> <span style="color:blue;">fst</span> . evaluateStop) .) . <span style="color:blue;">zip</span></code> more readable than what we had before?
</p>
<p>
Hardly, I admit. I might consider reverting, and since I've been <a href="https://stackoverflow.blog/2022/12/19/use-git-tactically/">using Git tactically</a>, I have that option.
</p>
<p>
If I hadn't tried, though, I wouldn't have known.
</p>
<h3 id="5bf92cabf46e4ec9a6a41b51dd29e876">
Conclusion <a href="#5bf92cabf46e4ec9a6a41b51dd29e876">#</a>
</h3>
<p>
When composing one pure function with another, how can you test that the outer function correctly calls the inner function?
</p>
<p>
By the same way that you test any other pure function. The only way you can observe whether a pure function works as intended is to compare its actual output to the output you expect its input to produce. How it arrives at that output is irrelevant. It could be looking up all results in a big table. As long as the result is correct, the function is correct.
</p>
<p>
In this article, you saw an example of how to test a composed function, as well as how to refactor it without breaking tests.
</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>.Are pull requests bad because they originate from open-source development?https://blog.ploeh.dk/2023/04/24/are-pull-requests-bad-because-they-originate-from-open-source-development2023-04-24T06:08:00+00:00Mark Seemann
<div id="post">
<p>
<em>I don't think so, and at least find the argument flawed.</em>
</p>
<p>
Increasingly I come across a quote that goes like this:
</p>
<blockquote>
<p>
Pull requests were invented for open source projects where you want to gatekeep changes from people you don't know and don't trust to change the code safely.
</p>
</blockquote>
<p>
If you're wondering where that 'quote' comes from, then read on. I'm not trying to stand up a straw man, but I had to do a bit of digging in order to find the source of what almost seems like a <a href="https://en.wikipedia.org/wiki/Meme">meme</a>.
</p>
<h3 id="c347774c419941a9987c74c95b6f91cd">
Quote investigation <a href="#c347774c419941a9987c74c95b6f91cd">#</a>
</h3>
<p>
The quote is usually attributed to <a href="https://www.davefarley.net/">Dave Farley</a>, who is a software luminary that <a href="https://www.goodreads.com/review/show/4812673890">I respect tremendously</a>. Even with the attribution, the source is typically missing, but after asking around, <a href="https://twitter.com/MitjaBezensek/status/1626165418296590336">Mitja Bezenšek pointed me in the right direction</a>.
</p>
<p>
The source is most likely a video, from which I've transcribed a longer passage:
</p>
<blockquote>
<p>
"Pull requests were invented to gatekeep access to open-source projects. In open source, it's very common that not everyone is given free access to changing the code, so contributors will issue a pull request so that a trusted person can then approve the change.
</p>
<p>
"I think this is really bad way to organise a development team.
</p>
<p>
"If you can't trust your team mates to make changes carefully, then your version control system is not going to fix that for you."
</p>
<footer><cite><a href="https://youtu.be/UQrlEXU6RM8">Dave Farley</a></cite></footer>
</blockquote>
<p>
I've made an effort to transcribe as faithfully as possible, but if you really want to be sure what Dave Farley said, watch the video. The quote comes twelve minutes in.
</p>
<h3 id="60fb5776c68b464d9ae77ad601e8c99b">
My biases <a href="#60fb5776c68b464d9ae77ad601e8c99b">#</a>
</h3>
<p>
I agree that the argument sounds compelling, but I find it flawed. Before I proceed to put forward my arguments I want to make my own biases clear. Arguing against someone like Dave Farley is not something I take lightly. As far as I can tell, he's worked on systems more impressive than any I can showcase. I also think he has more industry experience than I have.
</p>
<p>
That doesn't necessarily make him right, but on the other hand, why should you side with me, with my less impressive résumé?
</p>
<p>
My objective is not to attack Dave Farley, or any other person for that matter. My agenda is the argument itself. I do, however, find it intellectually honest to cite sources, with the associated risk that my argument may look like a personal attack. To steelman my opponent, then, I'll try to put my own biases on display. To the degree I'm aware of them.
</p>
<p>
I prefer pull requests over pair and ensemble programming. I've tried all three, and I do admit that real-time collaboration has obvious advantages, but I find pairing or ensemble programming exhausting.
</p>
<p>
Since <a href="https://www.goodreads.com/review/show/440837121">I read <em>Quiet</em></a> a decade ago, I've been alert to the introspective side of my personality. Although I agree with <a href="http://www.exampler.com/about/">Brian Marick</a> that one should <a href="https://podcast.oddly-influenced.dev/episodes/not-a-ted-talk-relevant-results-from-psychology">be wary of understanding personality traits as destiny</a>, I mostly prefer solo activities.
</p>
<p>
Increasingly, since I became self-employed, I've arranged my life to maximise the time I can work from home. The exercise regimen I've chosen for myself is independent of other people: I run, and lift weights at home. You may have noticed that I like writing. I like reading as well. And, hardly surprising, I prefer writing code in splendid isolation.
</p>
<p>
Even so, I find it perfectly possible to have meaningful relationships with other people. After all, I've been married to the same woman for decades, my (mostly) grown kids haven't fled from home, and I have friends that I've known for decades.
</p>
<p>
In a toot that I can no longer find, Brian Marick asked (and I paraphrase from memory): <em>If you've tried a technique and didn't like it, what would it take to make you like it?</em>
</p>
<p>
As a self-professed introvert, social interaction <em>does</em> tire me, but I still enjoy hanging out with friends or family. What makes those interactions different? Well, often, there's good food and wine involved. Perhaps ensemble programming would work better for me with a bottle of Champagne.
</p>
<p>
Other forces influence my preferences as well. I like the <a href="/2023/02/20/a-thought-on-workplace-flexibility-and-asynchrony">flexibility provided by asynchrony</a>, and similarly dislike having to be somewhere at a specific time.
</p>
<p>
Having to be somewhere also involves transporting myself there, which I also don't appreciate.
</p>
<p>
In short, I prefer pull requests over pairing and ensemble programming. All of that, however, is just my subjective opinion, and <a href="/2020/10/12/subjectivity">that's not an argument</a>.
</p>
<h3 id="c83cc60f53e049edbdae29dca4402563">
Counter-examples <a href="#c83cc60f53e049edbdae29dca4402563">#</a>
</h3>
<p>
The above tirade about my biases is <em>not</em> a refutation of Dave Farley's argument. Rather, I wanted to put my own blind spots on display. If you suspect me of <a href="https://en.wikipedia.org/wiki/Motivated_reasoning">motivated reasoning</a>, that just might be the case.
</p>
<p>
All that said, I want to challenge the argument.
</p>
<p>
First, it includes an appeal to <em>trust</em>, which is <a href="/2023/03/20/on-trust-in-software-development">a line of reasoning with which I don't agree</a>. You can't trust your colleagues, just like you can't trust yourself. A code review serves more purposes than keeping malicious actors out of the code base. It also helps catch mistakes, security issues, or misunderstandings. It can also improve shared understanding of common goals and standards. Yes, this is <em>also</em> possible with other means, such as pair or ensemble programming, but from that, it doesn't follow that code reviews <em>can't</em> do that. They can. I've lived that dream.
</p>
<p>
If you take away the appeal to trust, though, there isn't much left of the argument. What remains is essentially: <em>Pull requests were invented to solve a particular problem in open-source development. Internal software development is not open source. Pull requests are bad for internal software development.</em>
</p>
<p>
That an invention was done in one context, however, doesn't preclude it from being useful in another. Git was invented to address an open-source problem. Should we stop using Git for internal software development?
</p>
<p>
<a href="https://en.wikipedia.org/wiki/Solar_cell">Solar panels were originally developed for satellites and space probes</a>. Does that mean that we shouldn't use them on Earth?
</p>
<p>
<a href="https://en.wikipedia.org/wiki/Global_Positioning_System">GPS was invented for use by the US military</a>. Does that make civilian use wrong?
</p>
<h3 id="a30f67d73f0e488aac23dccb723370f8">
Are pull requests bad? <a href="#a30f67d73f0e488aac23dccb723370f8">#</a>
</h3>
<p>
I find the original <em>argument</em> logically flawed, but if I insist on logic, I'm also obliged to admit that my <a href="/ref/predicate-logic">possible-world counter-examples</a> don't prove that pull requests are good.
</p>
<p>
Dave Farley's claim may still turn out to be true. Not because of the argument he gives, but perhaps for other reasons.
</p>
<p>
I think I understand where the dislike of pull requests come from. As they are often practised, pull requests can sit for days with no-one looking at them. This creates unnecessary delays. If this is the only way you know of working with pull requests, no wonder you don't like them.
</p>
<p>
<a href="/2021/06/21/agile-pull-requests">I advocate a more agile workflow for pull requests</a>. I consider that congruent with <a href="/2023/01/23/agilean">my view on agile development</a>.
</p>
<h3 id="e0d3bb23dda34ae98241ff2bad442794">
Conclusion <a href="#e0d3bb23dda34ae98241ff2bad442794">#</a>
</h3>
<p>
Pull requests are often misused, but they don't have to be. On the other hand, that's just my experience and subjective preference.
</p>
<p>
Dave Farley has argued that pull requests are a bad way to organise a development team. I've argued that the argument is logically flawed.
</p>
<p>
The question remains unsettled. I've attempted to refute one particular argument, and even if you accept my counter-examples, pull requests may still be bad. Or good.
</p>
</div>
<div id="comments">
<hr>
<h2 id="comments-header">
Comments
</h2>
<div class="comment" id="bdd051fb26464bdbbc056ddea07712d5">
<div class="comment-author"><a href="https://cwb.dk/">Casper Weiss Bang</a></div>
<div class="comment-content">
<p>
Another important angle, for me, is that pull requests are not merely code review. It can also be a way of enforcing a variety of automated checks, i.e. running tests or linting etc. This enforces quality too - so I'd argue to use pull requests even if you don't do peer review (I do on my hobby projects atleast, for the exact reasons you mentioned in <a href="https://blog.ploeh.dk/2023/03/20/on-trust-in-software-development/">On trust in software development</a> - I don't trust myself to be perfect.)
</p>
</div>
<div class="comment-date">2023-04-26 10:26 UTC</div>
</div>
<div class="comment" id="9b022dd663d34feba170006de5b66af4">
<div class="comment-author"><a href="/">Mark Seemann</a></div>
<div class="comment-content">
<p>
Casper, thank you for writing. Indeed, other readers have made similar observations on other channels (Twitter, Mastodon). That, too, can be a benefit.
</p>
<p>
In order to once more steel-man 'the other side', they'd probably say that you can run automated checks in your Continuous Delivery pipeline, and halt it if automated checks fail.
</p>
<p>
When done this way, it's useful to be able to also run the same tests on your dev box. I consider that a good practice anyway.
</p>
</div>
<div class="comment-date">2023-04-28 14:49 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>.A restaurant example of refactoring from example-based to property-based testinghttps://blog.ploeh.dk/2023/04/17/a-restaurant-example-of-refactoring-from-example-based-to-property-based-testing2023-04-17T06:37:00+00:00Mark Seemann
<div id="post">
<p>
<em>A C# example with xUnit.net and FsCheck.</em>
</p>
<p>
This is the second comprehensive example that accompanies the article <a href="/2023/02/13/epistemology-of-interaction-testing">Epistemology of interaction testing</a>. In that article, I argue that in a code base that leans toward functional programming (FP), property-based testing is a better fit than interaction-based testing. In this example, I will show how to refactor realistic <a href="/2019/02/18/from-interaction-based-to-state-based-testing">state-based tests</a> into (state-based) property-based tests.
</p>
<p>
The <a href="/2023/04/03/an-abstract-example-of-refactoring-from-interaction-based-to-property-based-testing">previous article</a> showed a <a href="https://en.wikipedia.org/wiki/Minimal_reproducible_example">minimal and self-contained example</a> that had the advantage of being simple, but the disadvantage of being perhaps too abstract and unrelatable. In this article, then, I will attempt to show a more realistic and concrete example. It actually doesn't start with interaction-based testing, since it's already written in the style of <a href="https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell">Functional Core, Imperative Shell</a>. On the other hand, it shows how to refactor from concrete example-based tests to property-based tests.
</p>
<p>
I'll use the online restaurant reservation code base that accompanies my book <a href="/2021/06/14/new-book-code-that-fits-in-your-head">Code That Fits in Your Head</a>.
</p>
<h3 id="e7aaa6310292411ab830de17f5906777">
Smoke test <a href="#e7aaa6310292411ab830de17f5906777">#</a>
</h3>
<p>
I'll start with a simple test which was, if I remember correctly, the second test I wrote for this code base. It was a smoke test that I wrote to drive a <a href="https://wiki.c2.com/?WalkingSkeleton">walking skeleton</a>. It verifies that if you post a valid reservation request to the system, you receive an HTTP response in the <code>200</code> range.
</p>
<p>
<pre>[Fact]
<span style="color:blue;">public</span> <span style="color:blue;">async</span> Task <span style="font-weight:bold;color:#74531f;">PostValidReservation</span>()
{
<span style="color:blue;">using</span> <span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">api</span> = <span style="color:blue;">new</span> LegacyApi();
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">expected</span> = <span style="color:blue;">new</span> ReservationDto
{
At = DateTime.Today.AddDays(778).At(19, 0)
.ToIso8601DateTimeString(),
Email = <span style="color:#a31515;">"katinka@example.com"</span>,
Name = <span style="color:#a31515;">"Katinka Ingabogovinanana"</span>,
Quantity = 2
};
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">response</span> = <span style="color:blue;">await</span> api.PostReservation(expected);
response.EnsureSuccessStatusCode();
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">actual</span> = <span style="color:blue;">await</span> response.ParseJsonContent<ReservationDto>();
Assert.Equal(expected, actual, <span style="color:blue;">new</span> ReservationDtoComparer());
}</pre>
</p>
<p>
Over the lifetime of the code base, I embellished and edited the test to reflect the evolution of the system as well as my understanding of it. Thus, when I wrote it, it may not have looked exactly like this. Even so, I kept it around even though other, more detailed tests eventually superseded it.
</p>
<p>
One characteristic of this test is that it's quite concrete. When I originally wrote it, I hard-coded the date and time as well. Later, however, <a href="/2021/01/11/waiting-to-happen">I discovered that I had to make the time relative to the system clock</a>. Thus, as you can see, the <code>At</code> property isn't a literal value, but all other properties (<code>Email</code>, <code>Name</code>, and <code>Quantity</code>) are.
</p>
<p>
This test is far from abstract or data-driven. Is it possible to turn such a test into a property-based test? Yes, I'll show you how.
</p>
<p>
A word of warning before we proceed: Tests with concrete, literal, easy-to-understand examples are valuable as programmer documentation. A person new to the code base can peruse such tests and learn about the system. Thus, this test is <em>already quite valuable as it is</em>. In a real, living code base, I'd prefer leaving it as it is, instead of turning it into a property-based test.
</p>
<p>
Since it's a simple and concrete test, on the other hand, it's easy to understand, and thus also a a good place to start. Thus, I'm going to refactor it into a property-based test; not because I think that you should (I don't), but because I think it'll be easy for you, the reader, to follow along. In other words, it's a good introduction to the process of turning a concrete test into a property-based test.
</p>
<h3 id="9dabcfae9e284a0ab9748cf817f4b2f9">
Adding parameters <a href="#9dabcfae9e284a0ab9748cf817f4b2f9">#</a>
</h3>
<p>
This code base already uses <a href="https://fscheck.github.io/FsCheck/">FsCheck</a> so it makes sense to stick to that framework for property-based testing. While it's written in <a href="https://fsharp.org/">F#</a> you can use it from C# as well. The easiest way to use it is as a parametrised test. This is possible with the <a href="https://www.nuget.org/packages/FsCheck.Xunit">FsCheck.Xunit</a> glue library. In fact, as I refactor the <code>PostValidReservation</code> test, it'll look much like the <a href="https://github.com/AutoFixture/AutoFixture">AutoFixture</a>-driven tests from <a href="/2023/04/03/an-abstract-example-of-refactoring-from-interaction-based-to-property-based-testing">the previous article</a>.
</p>
<p>
When turning concrete examples into properties, it helps to consider whether literal values are representative of an equivalence class. In other words, is that particular value important, or is there a wider set of values that would be just as good? For example, why is the test making a reservation 778 days in the future? Why not 777 or 779? Is the value <em>778</em> important? Not really. What's important is that the reservation is in the future. How far in the future actually isn't important. Thus, we can replace the literal value <code>778</code> with a parameter:
</p>
<p>
<pre>[Property]
<span style="color:blue;">public</span> <span style="color:blue;">async</span> Task <span style="font-weight:bold;color:#74531f;">PostValidReservation</span>(PositiveInt <span style="font-weight:bold;color:#1f377f;">days</span>)
{
<span style="color:blue;">using</span> <span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">api</span> = <span style="color:blue;">new</span> LegacyApi();
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">expected</span> = <span style="color:blue;">new</span> ReservationDto
{
At = DateTime.Today.AddDays((<span style="color:blue;">int</span>)days).At(19, 0)
.ToIso8601DateTimeString(),
<span style="color:green;">// The rest of the test...</span></pre>
</p>
<p>
Notice that I've replaced the literal value <code>778</code> with the method parameter <code>days</code>. The <code>PositiveInt</code> type is a type from FsCheck. It's a wrapper around <code>int</code> that guarantees that the value is positive. This is important because we don't want to make a reservation in the past. The <code>PositiveInt</code> type is a good choice because it's a type that's already available with FsCheck, and the framework knows how to generate valid values. Since it's a wrapper, though, the test needs to unwrap the value before using it. This is done with the <code>(int)days</code> cast.
</p>
<p>
Notice, also, that I've replaced the <code>[Fact]</code> attribute with the <code>[Property]</code> attribute that comes with FsCheck.Xunit. This is what enables FsCheck to automatically generate test cases and feed them to the test method. You can't always do this, as you'll see later, but when you can, it's a nice and succinct way to express a property-based test.
</p>
<p>
Already, the <code>PostValidReservation</code> test method is 100 test cases (the FsCheck default), rather than one.
</p>
<p>
What about <code>Email</code> and <code>Name</code>? Is it important for the test that these values are exactly <em>katinka@example.com</em> and <em>Katinka Ingabogovinanana</em> or might other values do? The answer is that it's not important. What's important is that the values are valid, and essentially any non-null string is. Thus, we can replace the literal values with parameters:
</p>
<p>
<pre>[Property]
<span style="color:blue;">public</span> <span style="color:blue;">async</span> Task <span style="font-weight:bold;color:#74531f;">PostValidReservation</span>(
PositiveInt <span style="font-weight:bold;color:#1f377f;">days</span>,
StringNoNulls <span style="font-weight:bold;color:#1f377f;">email</span>,
StringNoNulls <span style="font-weight:bold;color:#1f377f;">name</span>)
{
<span style="color:blue;">using</span> <span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">api</span> = <span style="color:blue;">new</span> LegacyApi();
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">expected</span> = <span style="color:blue;">new</span> ReservationDto
{
At = DateTime.Today.AddDays((<span style="color:blue;">int</span>)days).At(19, 0)
.ToIso8601DateTimeString(),
Email = email.Item,
Name = name.Item,
Quantity = 2
};
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">response</span> = <span style="color:blue;">await</span> api.PostReservation(expected);
response.EnsureSuccessStatusCode();
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">actual</span> = <span style="color:blue;">await</span> response.ParseJsonContent<ReservationDto>();
Assert.Equal(expected, actual, <span style="color:blue;">new</span> ReservationDtoComparer());
}</pre>
</p>
<p>
The <code>StringNoNulls</code> type is another FsCheck wrapper, this time around <code>string</code>. It ensures that FsCheck will generate no null strings. This time, however, a cast isn't possible, so instead I had to pull the wrapped string out of the value with the <code>Item</code> property.
</p>
<p>
That's enough conversion to illustrate the process.
</p>
<p>
What about the literal values <em>19</em>, <em>0</em>, or <em>2?</em> Shouldn't we parametrise those as well? While we could, that takes a bit more effort. The problem is that with these values, any old positive integer isn't going to work. For example, the number <em>19</em> is the hour component of the reservation time; that is, the reservation is for 19:00. Clearly, we can't just let FsCheck generate any positive integer, because most integers aren't going to work. For example, <em>5</em> doesn't work because it's in the early morning, and the restaurant isn't open at that time.
</p>
<p>
Like other property-based testing frameworks FsCheck has an API that enables you to constrain value generation, but it doesn't work with the type-based approach I've used so far. Unlike <code>PositiveInt</code> there's no <code>TimeBetween16And21</code> wrapper type.
</p>
<p>
You'll see what you can do to control how FsCheck generates values, but I'll use another test for that.
</p>
<h3 id="80844424b40a48f4931c78d91d865323">
Parametrised unit test <a href="#80844424b40a48f4931c78d91d865323">#</a>
</h3>
<p>
The <code>PostValidReservation</code> test is a high-level smoke test that gives you an idea about how the system works. It doesn't, however, reveal much about the possible variations in input. To drive such behaviour, I wrote and evolved the following state-based test:
</p>
<p>
<pre>[Theory]
[InlineData(1049, 19, 00, <span style="color:#a31515;">"juliad@example.net"</span>, <span style="color:#a31515;">"Julia Domna"</span>, 5)]
[InlineData(1130, 18, 15, <span style="color:#a31515;">"x@example.com"</span>, <span style="color:#a31515;">"Xenia Ng"</span>, 9)]
[InlineData( 956, 16, 55, <span style="color:#a31515;">"kite@example.edu"</span>, <span style="color:blue;">null</span>, 2)]
[InlineData( 433, 17, 30, <span style="color:#a31515;">"shli@example.org"</span>, <span style="color:#a31515;">"Shanghai Li"</span>, 5)]
<span style="color:blue;">public</span> <span style="color:blue;">async</span> Task <span style="font-weight:bold;color:#74531f;">PostValidReservationWhenDatabaseIsEmpty</span>(
<span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">days</span>,
<span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">hours</span>,
<span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">minutes</span>,
<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">email</span>,
<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">name</span>,
<span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">quantity</span>)
{
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">at</span> = DateTime.Now.Date + <span style="color:blue;">new</span> TimeSpan(days, hours, minutes, 0);
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">db</span> = <span style="color:blue;">new</span> FakeDatabase();
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">sut</span> = <span style="color:blue;">new</span> ReservationsController(
<span style="color:blue;">new</span> SystemClock(),
<span style="color:blue;">new</span> InMemoryRestaurantDatabase(Grandfather.Restaurant),
db);
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">expected</span> = <span style="color:blue;">new</span> Reservation(
<span style="color:blue;">new</span> Guid(<span style="color:#a31515;">"B50DF5B1-F484-4D99-88F9-1915087AF568"</span>),
at,
<span style="color:blue;">new</span> Email(email),
<span style="color:blue;">new</span> Name(name ?? <span style="color:#a31515;">""</span>),
quantity);
<span style="color:blue;">await</span> sut.Post(expected.ToDto());
Assert.Contains(expected, db.Grandfather);
}</pre>
</p>
<p>
This test gives more details, without exercising all possible code paths of the system. It's still a <a href="/2012/06/27/FacadeTest">Facade Test</a> that covers 'just enough' of the integration with underlying components to provide confidence that things work as they should. All the business logic is implemented by a class called <code>MaitreD</code>, which is covered by its own set of targeted unit tests.
</p>
<p>
While parametrised, this is still only four test cases, so perhaps you don't have sufficient confidence that everything works as it should. Perhaps, as I've outlined in <a href="/2023/02/13/epistemology-of-interaction-testing">the introductory article</a>, it would help if we converted it to an FsCheck property.
</p>
<h3 id="707d58026e914b708e6394b5d1d2abad">
Parametrised property <a href="#707d58026e914b708e6394b5d1d2abad">#</a>
</h3>
<p>
I find it safest to refactor this parametrised test to a property in a series of small steps. This implies that I need to keep the <code>[InlineData]</code> attributes around for a while longer, removing one or two literal values at a time, turning them into randomly generated values.
</p>
<p>
From the previous test we know that the <code>Email</code> and <code>Name</code> values are almost unconstrained. This means that they are trivial in themselves to have FsCheck generate. That change, in itself, is easy, which is good, because combining an <code>[InlineData]</code>-driven <code>[Theory]</code> with an FsCheck property is enough of a mouthful for one refactoring step:
</p>
<p>
<pre>[Theory]
[InlineData(1049, 19, 00, 5)]
[InlineData(1130, 18, 15, 9)]
[InlineData( 956, 16, 55, 2)]
[InlineData( 433, 17, 30, 5)]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> <span style="font-weight:bold;color:#74531f;">PostValidReservationWhenDatabaseIsEmpty</span>(
<span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">days</span>,
<span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">hours</span>,
<span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">minutes</span>,
<span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">quantity</span>)
{
Prop.ForAll(
(<span style="color:blue;">from</span> r <span style="color:blue;">in</span> Gens.Reservation
<span style="color:blue;">select</span> r).ToArbitrary(),
<span style="color:blue;">async</span> <span style="font-weight:bold;color:#1f377f;">r</span> =>
{
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">at</span> = DateTime.Now.Date + <span style="color:blue;">new</span> TimeSpan(days, hours, minutes, 0);
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">db</span> = <span style="color:blue;">new</span> FakeDatabase();
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">sut</span> = <span style="color:blue;">new</span> ReservationsController(
<span style="color:blue;">new</span> SystemClock(),
<span style="color:blue;">new</span> InMemoryRestaurantDatabase(Grandfather.Restaurant),
db);
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">expected</span> = r
.WithQuantity(quantity)
.WithDate(at);
<span style="color:blue;">await</span> sut.Post(expected.ToDto());
Assert.Contains(expected, db.Grandfather);
}).QuickCheckThrowOnFailure();
}</pre>
</p>
<p>
I've now managed to get rid of the <code>email</code> and <code>name</code> parameters, so I've also removed those values from the <code>[InlineData]</code> attributes. Instead, I've asked FsCheck to generate a valid reservation <code>r</code>, which comes with both valid <code>Email</code> and <code>Name</code>.
</p>
<p>
It turned out that this code base already had some custom generators in a static class called <code>Gens</code>, so I reused those:
</p>
<p>
<pre><span style="color:blue;">internal</span> <span style="color:blue;">static</span> Gen<Email> Email =>
<span style="color:blue;">from</span> s <span style="color:blue;">in</span> ArbMap.Default.GeneratorFor<NonWhiteSpaceString>()
<span style="color:blue;">select</span> <span style="color:blue;">new</span> Email(s.Item);
<span style="color:blue;">internal</span> <span style="color:blue;">static</span> Gen<Name> Name =>
<span style="color:blue;">from</span> s <span style="color:blue;">in</span> ArbMap.Default.GeneratorFor<StringNoNulls>()
<span style="color:blue;">select</span> <span style="color:blue;">new</span> Name(s.Item);
<span style="color:blue;">internal</span> <span style="color:blue;">static</span> Gen<Reservation> Reservation =>
<span style="color:blue;">from</span> id <span style="color:blue;">in</span> ArbMap.Default.GeneratorFor<Guid>()
<span style="color:blue;">from</span> d <span style="color:blue;">in</span> ArbMap.Default.GeneratorFor<DateTime>()
<span style="color:blue;">from</span> e <span style="color:blue;">in</span> Email
<span style="color:blue;">from</span> n <span style="color:blue;">in</span> Name
<span style="color:blue;">from</span> q <span style="color:blue;">in</span> ArbMap.Default.GeneratorFor<PositiveInt>()
<span style="color:blue;">select</span> <span style="color:blue;">new</span> Reservation(id, d, e, n, q.Item);</pre>
</p>
<p>
As was also the case with <a href="https://github.com/AnthonyLloyd/CsCheck">CsCheck</a> you typically use <a href="/2022/03/28/monads">syntactic sugar for monads</a> (which in C# is query syntax) to compose complex <a href="/2023/02/27/test-data-generator-monad">test data generators</a> from simpler generators. This enables me to generate an entire <code>Reservation</code> object with a single expression.
</p>
<h3 id="05d4d9e8c07b4162bd1b65347200456f">
Time of day <a href="#05d4d9e8c07b4162bd1b65347200456f">#</a>
</h3>
<p>
Some of the values (such as the reservation's name and email address) that are involved in the <code>PostValidReservationWhenDatabaseIsEmpty</code> test don't really matter. Other values are constrained in some way. Even for the reservation <code>r</code> the above version of the test has to override the arbitrarily generated <code>r</code> value with a specific <code>quantity</code> and a specific <code>at</code> value. This is because you can't just reserve any quantity at any time of day. The restaurant has opening hours and actual tables. Most likely, it doesn't have a table for 100 people at 3 in the morning.
</p>
<p>
This particular test actually exercises a particular restaurant called <code>Grandfather.Restaurant</code> (because it was the original restaurant that was <a href="https://en.wikipedia.org/wiki/Grandfather_clause">grandfathered in</a> when the system was expanded to a multi-tenant system). It opens at 16 and has the last seating at 21. This means that the <code>at</code> value has to be between 16 and 21. What's the best way to generate a <code>DateTime</code> value that satisfies this constraint?
</p>
<p>
You could, naively, ask FsCheck to generate an integer between these two values. You'll see how to do that when we get to the <code>quantity</code>. While that would work for the <code>at</code> value, it would only generate the whole hours <em>16:00</em>, <em>17:00</em>, <em>18:00</em>, etcetera. It would be nice if the test could also exercise times such as <em>18:30</em>, <em>20:45</em>, and so on. On the other hand, perhaps we don't want weird reservation times such as <em>17:09:23.282</em>. How do we tell FsCheck to generate a <code>DateTime</code> value like that?
</p>
<p>
It's definitely possible to do from scratch, but I chose to do something else. The following shows how test code and production code can co-exist in a symbiotic relationship. The main business logic component that deals with reservations in the system is a class called <code>MaitreD</code>. One of its methods is used to generate a list of time slots for every day. A user interface can use that list to populate a drop-down list of available times. The method is called <code>Segment</code> and can also be used as a data source for an FsCheck test data generator:
</p>
<p>
<pre><span style="color:blue;">internal</span> <span style="color:blue;">static</span> Gen<TimeSpan> <span style="color:#74531f;">ReservationTime</span>(
Restaurant <span style="font-weight:bold;color:#1f377f;">restaurant</span>,
DateTime <span style="font-weight:bold;color:#1f377f;">date</span>)
{
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">slots</span> = restaurant.MaitreD
.Segment(date, Enumerable.Empty<Reservation>())
.Select(<span style="font-weight:bold;color:#1f377f;">ts</span> => ts.At.TimeOfDay);
<span style="font-weight:bold;color:#8f08c4;">return</span> Gen.Elements(slots);
}</pre>
</p>
<p>
The <code>Gen.Elements</code> function is an FsCheck combinator that randomly picks a value from a collection. This one, then, picks one of the <code>DataTime</code> values generated by <code>MaitreD.Segment</code>.
</p>
<p>
The <code>PostValidReservationWhenDatabaseIsEmpty</code> test can now use the <code>ReservationTime</code> generator to produce a time of day:
</p>
<p>
<pre>[Theory]
[InlineData(5)]
[InlineData(9)]
[InlineData(2)]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> <span style="font-weight:bold;color:#74531f;">PostValidReservationWhenDatabaseIsEmpty</span>(<span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">quantity</span>)
{
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">today</span> = DateTime.Now.Date;
Prop.ForAll(
(<span style="color:blue;">from</span> days <span style="color:blue;">in</span> ArbMap.Default.GeneratorFor<PositiveInt>()
<span style="color:blue;">from</span> t <span style="color:blue;">in</span> Gens.ReservationTime(Grandfather.Restaurant, today)
<span style="color:blue;">let</span> offset = TimeSpan.FromDays((<span style="color:blue;">int</span>)days) + t
<span style="color:blue;">from</span> r <span style="color:blue;">in</span> Gens.Reservation
<span style="color:blue;">select</span> (r, offset)).ToArbitrary(),
<span style="color:blue;">async</span> <span style="font-weight:bold;color:#1f377f;">t</span> =>
{
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">at</span> = today + t.offset;
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">db</span> = <span style="color:blue;">new</span> FakeDatabase();
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">sut</span> = <span style="color:blue;">new</span> ReservationsController(
<span style="color:blue;">new</span> SystemClock(),
<span style="color:blue;">new</span> InMemoryRestaurantDatabase(Grandfather.Restaurant),
db);
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">expected</span> = t.r
.WithQuantity(quantity)
.WithDate(at);
<span style="color:blue;">await</span> sut.Post(expected.ToDto());
Assert.Contains(expected, db.Grandfather);
}).QuickCheckThrowOnFailure();
}</pre>
</p>
<p>
Granted, the test code is getting more and more busy, but there's room for improvement. Before I simplify it, though, I think that it's more prudent to deal with the remaining literal values.
</p>
<p>
Notice that the <code>InlineData</code> attributes now only supply a single value each: The <code>quantity</code>.
</p>
<h3 id="e551e156b8344bc0bd5379084bd8a7ed">
Quantity <a href="#e551e156b8344bc0bd5379084bd8a7ed">#</a>
</h3>
<p>
Like the <code>at</code> value, the <code>quantity</code> is constrained. It must be a positive integer, but it can't be larger than the largest table in the restaurant. That number, however, isn't that hard to find:
</p>
<p>
<pre><span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">maxCapacity</span> = restaurant.MaitreD.Tables.Max(<span style="font-weight:bold;color:#1f377f;">t</span> => t.Capacity);</pre>
</p>
<p>
The FsCheck API includes a function that generates a random number within a given range. It's called <code>Gen.Choose</code>, and now that we know the range, we can use it to generate the <code>quantity</code> value. Here, I'm only showing the test-data-generator part of the test, since the rest doesn't change that much. You'll see the full test again after a few more refactorings.
</p>
<p>
<pre><span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">today</span> = DateTime.Now.Date;
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">restaurant</span> = Grandfather.Restaurant;
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">maxCapacity</span> = restaurant.MaitreD.Tables.Max(<span style="font-weight:bold;color:#1f377f;">t</span> => t.Capacity);
Prop.ForAll(
(<span style="color:blue;">from</span> days <span style="color:blue;">in</span> ArbMap.Default.GeneratorFor<PositiveInt>()
<span style="color:blue;">from</span> t <span style="color:blue;">in</span> Gens.ReservationTime(restaurant, today)
<span style="color:blue;">let</span> offset = TimeSpan.FromDays((<span style="color:blue;">int</span>)days) + t
<span style="color:blue;">from</span> quantity <span style="color:blue;">in</span> Gen.Choose(1, maxCapacity)
<span style="color:blue;">from</span> r <span style="color:blue;">in</span> Gens.Reservation
<span style="color:blue;">select</span> (r.WithQuantity(quantity), offset)).ToArbitrary(),</pre>
</p>
<p>
There are now no more literal values in the test. In a sense, the refactoring from parametrised test to property-based test is complete. It could do with a bit of cleanup, though.
</p>
<h3 id="53494d59981c4c32b0dbbd93aa857874">
Simplification <a href="#53494d59981c4c32b0dbbd93aa857874">#</a>
</h3>
<p>
There's no longer any need to pass along the <code>offset</code> variable, and the explicit <code>QuickCheckThrowOnFailure</code> also seems a bit redundant. I can use the <code>[Property]</code> attribute from FsCheck.Xunit instead.
</p>
<p>
<pre>[Property]
<span style="color:blue;">public</span> Property <span style="font-weight:bold;color:#74531f;">PostValidReservationWhenDatabaseIsEmpty</span>()
{
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">today</span> = DateTime.Now.Date;
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">restaurant</span> = Grandfather.Restaurant;
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">maxCapacity</span> = restaurant.MaitreD.Tables.Max(<span style="font-weight:bold;color:#1f377f;">t</span> => t.Capacity);
<span style="font-weight:bold;color:#8f08c4;">return</span> Prop.ForAll(
(<span style="color:blue;">from</span> days <span style="color:blue;">in</span> ArbMap.Default.GeneratorFor<PositiveInt>()
<span style="color:blue;">from</span> t <span style="color:blue;">in</span> Gens.ReservationTime(restaurant, today)
<span style="color:blue;">let</span> at = today + TimeSpan.FromDays((<span style="color:blue;">int</span>)days) + t
<span style="color:blue;">from</span> quantity <span style="color:blue;">in</span> Gen.Choose(1, maxCapacity)
<span style="color:blue;">from</span> r <span style="color:blue;">in</span> Gens.Reservation
<span style="color:blue;">select</span> r.WithQuantity(quantity).WithDate(at)).ToArbitrary(),
<span style="color:blue;">async</span> <span style="font-weight:bold;color:#1f377f;">expected</span> =>
{
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">db</span> = <span style="color:blue;">new</span> FakeDatabase();
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">sut</span> = <span style="color:blue;">new</span> ReservationsController(
<span style="color:blue;">new</span> SystemClock(),
<span style="color:blue;">new</span> InMemoryRestaurantDatabase(restaurant),
db);
<span style="color:blue;">await</span> sut.Post(expected.ToDto());
Assert.Contains(expected, db.Grandfather);
});
}</pre>
</p>
<p>
Compared to the initial version of the test, it has become more top-heavy. It's about the same size, though. The original version was 30 lines of code. This version is only 26 lines of code, but it is admittedly more information-dense. The original version had more 'noise' interleaved with the 'signal'. The new variation actually has a better separation of data generation and the test itself. Consider the 'actual' test code:
</p>
<p>
<pre><span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">db</span> = <span style="color:blue;">new</span> FakeDatabase();
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">sut</span> = <span style="color:blue;">new</span> ReservationsController(
<span style="color:blue;">new</span> SystemClock(),
<span style="color:blue;">new</span> InMemoryRestaurantDatabase(restaurant),
db);
<span style="color:blue;">await</span> sut.Post(expected.ToDto());
Assert.Contains(expected, db.Grandfather);</pre>
</p>
<p>
If we could somehow separate the data generation from the test itself, we might have something that was quite readable.
</p>
<h3 id="a23c68b065d140c588e30bd1db228879">
Extract test data generator <a href="#a23c68b065d140c588e30bd1db228879">#</a>
</h3>
<p>
The above data generation consists of a bit of initialisation and a query expression. Like all <a href="https://en.wikipedia.org/wiki/Pure_function">pure functions</a> it's easy to extract:
</p>
<p>
<pre><span style="color:blue;">private</span> <span style="color:blue;">static</span> Gen<(Restaurant, Reservation)>
<span style="color:#74531f;">GenValidReservationForEmptyDatabase</span>()
{
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">today</span> = DateTime.Now.Date;
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">restaurant</span> = Grandfather.Restaurant;
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">capacity</span> = restaurant.MaitreD.Tables.Max(<span style="font-weight:bold;color:#1f377f;">t</span> => t.Capacity);
<span style="font-weight:bold;color:#8f08c4;">return</span> <span style="color:blue;">from</span> days <span style="color:blue;">in</span> ArbMap.Default.GeneratorFor<PositiveInt>()
<span style="color:blue;">from</span> t <span style="color:blue;">in</span> Gens.ReservationTime(restaurant, today)
<span style="color:blue;">let</span> at = today + TimeSpan.FromDays((<span style="color:blue;">int</span>)days) + t
<span style="color:blue;">from</span> quantity <span style="color:blue;">in</span> Gen.Choose(1, capacity)
<span style="color:blue;">from</span> r <span style="color:blue;">in</span> Gens.Reservation
<span style="color:blue;">select</span> (restaurant, r.WithQuantity(quantity).WithDate(at));
}</pre>
</p>
<p>
While it's quite specialised, it leaves the test itself small and readable:
</p>
<p>
<pre>[Property]
<span style="color:blue;">public</span> Property <span style="font-weight:bold;color:#74531f;">PostValidReservationWhenDatabaseIsEmpty</span>()
{
<span style="font-weight:bold;color:#8f08c4;">return</span> Prop.ForAll(
GenValidReservationForEmptyDatabase().ToArbitrary(),
<span style="color:blue;">async</span> <span style="font-weight:bold;color:#1f377f;">t</span> =>
{
var (<span style="font-weight:bold;color:#1f377f;">restaurant</span>, <span style="font-weight:bold;color:#1f377f;">expected</span>) = t;
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">db</span> = <span style="color:blue;">new</span> FakeDatabase();
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">sut</span> = <span style="color:blue;">new</span> ReservationsController(
<span style="color:blue;">new</span> SystemClock(),
<span style="color:blue;">new</span> InMemoryRestaurantDatabase(restaurant),
db);
<span style="color:blue;">await</span> sut.Post(expected.ToDto());
Assert.Contains(expected, db[restaurant.Id]);
});
}</pre>
</p>
<p>
That's not the only way to separate test and data generation.
</p>
<h3 id="39343db1a22c4d0c93dbfb74e3af6689">
Test as implementation detail <a href="#39343db1a22c4d0c93dbfb74e3af6689">#</a>
</h3>
<p>
The above separation refactors the data-generating expression to a private helper function. Alternatively you can keep all that FsCheck infrastructure code in the public test method and extract the test body itself to a private helper method:
</p>
<p>
<pre>[Property]
<span style="color:blue;">public</span> Property <span style="font-weight:bold;color:#74531f;">PostValidReservationWhenDatabaseIsEmpty</span>()
{
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">today</span> = DateTime.Now.Date;
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">restaurant</span> = Grandfather.Restaurant;
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">capacity</span> = restaurant.MaitreD.Tables.Max(<span style="font-weight:bold;color:#1f377f;">t</span> => t.Capacity);
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">g</span> = <span style="color:blue;">from</span> days <span style="color:blue;">in</span> ArbMap.Default.GeneratorFor<PositiveInt>()
<span style="color:blue;">from</span> t <span style="color:blue;">in</span> Gens.ReservationTime(restaurant, today)
<span style="color:blue;">let</span> at = today + TimeSpan.FromDays((<span style="color:blue;">int</span>)days) + t
<span style="color:blue;">from</span> quantity <span style="color:blue;">in</span> Gen.Choose(1, capacity)
<span style="color:blue;">from</span> r <span style="color:blue;">in</span> Gens.Reservation
<span style="color:blue;">select</span> (restaurant, r.WithQuantity(quantity).WithDate(at));
<span style="font-weight:bold;color:#8f08c4;">return</span> Prop.ForAll(
g.ToArbitrary(),
<span style="font-weight:bold;color:#1f377f;">t</span> => PostValidReservationWhenDatabaseIsEmptyImp(
t.restaurant,
t.Item2));
}</pre>
</p>
<p>
At first glance, that doesn't look like an improvement, but it has the advantage that the actual test method is now devoid of FsCheck details. If we use that as a yardstick for how decoupled the test is from FsCheck, this seems cleaner.
</p>
<p>
<pre><span style="color:blue;">private</span> <span style="color:blue;">static</span> <span style="color:blue;">async</span> Task <span style="color:#74531f;">PostValidReservationWhenDatabaseIsEmptyImp</span>(
Restaurant <span style="font-weight:bold;color:#1f377f;">restaurant</span>, Reservation <span style="font-weight:bold;color:#1f377f;">expected</span>)
{
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">db</span> = <span style="color:blue;">new</span> FakeDatabase();
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">sut</span> = <span style="color:blue;">new</span> ReservationsController(
<span style="color:blue;">new</span> SystemClock(),
<span style="color:blue;">new</span> InMemoryRestaurantDatabase(restaurant),
db);
<span style="color:blue;">await</span> sut.Post(expected.ToDto());
Assert.Contains(expected, db[restaurant.Id]);
}</pre>
</p>
<p>
Using a property-based testing framework in C# is still more awkward than in a language with better support for monadic composition and pattern matching. That said, more recent versions of C# do have better pattern matching on tuples, but this code base is still on C# 8.
</p>
<p>
If you still think that this looks more complicated than the initial version of the test, then I agree. Property-based testing isn't free, but you get something in return. We started with four test cases and ended with 100. And that's just the default. If you want to increase the number of test cases, that's just an API call away. You could run 1,000 or 10,000 test cases if you wanted to. The only real downside is that the tests take longer to run.
</p>
<h3 id="624f8d06db274e54b76af869f1a790c5">
Unhappy paths <a href="#624f8d06db274e54b76af869f1a790c5">#</a>
</h3>
<p>
The tests above all test the happy path. A valid request arrives and the system is in a state where it can accept it. This small article series is, you may recall, a response to an email from Sergei Rogovtsev. In his email, he mentioned the need to test both happy path and various error scenarios. Let's cover a few before wrapping up.
</p>
<p>
As I was developing the system and fleshing out its behaviour, I evolved this parametrised test:
</p>
<p>
<pre>[Theory]
[InlineData(<span style="color:blue;">null</span>, <span style="color:#a31515;">"j@example.net"</span>, <span style="color:#a31515;">"Jay Xerxes"</span>, 1)]
[InlineData(<span style="color:#a31515;">"not a date"</span>, <span style="color:#a31515;">"w@example.edu"</span>, <span style="color:#a31515;">"Wk Hd"</span>, 8)]
[InlineData(<span style="color:#a31515;">"2023-11-30 20:01"</span>, <span style="color:blue;">null</span>, <span style="color:#a31515;">"Thora"</span>, 19)]
[InlineData(<span style="color:#a31515;">"2022-01-02 12:10"</span>, <span style="color:#a31515;">"3@example.org"</span>, <span style="color:#a31515;">"3 Beard"</span>, 0)]
[InlineData(<span style="color:#a31515;">"2045-12-31 11:45"</span>, <span style="color:#a31515;">"git@example.com"</span>, <span style="color:#a31515;">"Gil Tan"</span>, -1)]
<span style="color:blue;">public</span> <span style="color:blue;">async</span> Task <span style="font-weight:bold;color:#74531f;">PostInvalidReservation</span>(
<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">at</span>,
<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">email</span>,
<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">name</span>,
<span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">quantity</span>)
{
<span style="color:blue;">using</span> <span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">api</span> = <span style="color:blue;">new</span> LegacyApi();
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">response</span> = <span style="color:blue;">await</span> api.PostReservation(
<span style="color:blue;">new</span> { at, email, name, quantity });
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
}</pre>
</p>
<p>
The test body itself is about as minimal as it can be. There are four test cases that I added one or two at a time.
</p>
<ul>
<li>The first test case covers what happens if the <code>at</code> value is missing (i.e. null)</li>
<li>The next test case covers a malformed <code>at</code> value</li>
<li>The third test case covers a missing email address</li>
<li>The two last test cases covers non-positive quantities, both <em>0</em> and a negative number</li>
</ul>
<p>
It's possible to combine FsCheck generators that deal with each of these cases, but here I want to demonstrate how it's still possible to keep each error case separate, if that's what you need. First, separate the test body from its data source, like I did above:
</p>
<p>
<pre>[Theory]
[InlineData(<span style="color:blue;">null</span>, <span style="color:#a31515;">"j@example.net"</span>, <span style="color:#a31515;">"Jay Xerxes"</span>, 1)]
[InlineData(<span style="color:#a31515;">"not a date"</span>, <span style="color:#a31515;">"w@example.edu"</span>, <span style="color:#a31515;">"Wk Hd"</span>, 8)]
[InlineData(<span style="color:#a31515;">"2023-11-30 20:01"</span>, <span style="color:blue;">null</span>, <span style="color:#a31515;">"Thora"</span>, 19)]
[InlineData(<span style="color:#a31515;">"2022-01-02 12:10"</span>, <span style="color:#a31515;">"3@example.org"</span>, <span style="color:#a31515;">"3 Beard"</span>, 0)]
[InlineData(<span style="color:#a31515;">"2045-12-31 11:45"</span>, <span style="color:#a31515;">"git@example.com"</span>, <span style="color:#a31515;">"Gil Tan"</span>, -1)]
<span style="color:blue;">public</span> <span style="color:blue;">async</span> Task <span style="font-weight:bold;color:#74531f;">PostInvalidReservation</span>(
<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">at</span>,
<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">email</span>,
<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">name</span>,
<span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">quantity</span>)
{
<span style="color:blue;">await</span> PostInvalidReservationImp(at, email, name, quantity);
}
<span style="color:blue;">private</span> <span style="color:blue;">static</span> <span style="color:blue;">async</span> Task <span style="color:#74531f;">PostInvalidReservationImp</span>(
<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">at</span>,
<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">email</span>,
<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">name</span>,
<span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">quantity</span>)
{
<span style="color:blue;">using</span> <span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">api</span> = <span style="color:blue;">new</span> LegacyApi();
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">response</span> = <span style="color:blue;">await</span> api.PostReservation(
<span style="color:blue;">new</span> { at, email, name, quantity });
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
}</pre>
</p>
<p>
If you consider this refactoring in isolation, it seems frivolous, but it's just preparation for further work. In each subsequent refactoring I'll convert each of the above error cases to a property.
</p>
<h3 id="d1d2ea6091c7440991e24e213c9154b6">
Missing date and time <a href="#d1d2ea6091c7440991e24e213c9154b6">#</a>
</h3>
<p>
Starting from the top, convert the reservation-at-null test case to a property:
</p>
<p>
<pre>[Property]
<span style="color:blue;">public</span> <span style="color:blue;">async</span> Task <span style="font-weight:bold;color:#74531f;">PostReservationAtNull</span>(<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">email</span>, <span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">name</span>, PositiveInt <span style="font-weight:bold;color:#1f377f;">quantity</span>)
{
<span style="color:blue;">await</span> PostInvalidReservationImp(<span style="color:blue;">null</span>, email, name, (<span style="color:blue;">int</span>)quantity);
}</pre>
</p>
<p>
I've left the parametrised <code>PostInvalidReservation</code> test in place, but removed the <code>[InlineData]</code> attribute with the <code>null</code> value for the <code>at</code> parameter:
</p>
<p>
<pre>[Theory]
[InlineData(<span style="color:#a31515;">"not a date"</span>, <span style="color:#a31515;">"w@example.edu"</span>, <span style="color:#a31515;">"Wk Hd"</span>, 8)]
[InlineData(<span style="color:#a31515;">"2023-11-30 20:01"</span>, <span style="color:blue;">null</span>, <span style="color:#a31515;">"Thora"</span>, 19)]
[InlineData(<span style="color:#a31515;">"2022-01-02 12:10"</span>, <span style="color:#a31515;">"3@example.org"</span>, <span style="color:#a31515;">"3 Beard"</span>, 0)]
[InlineData(<span style="color:#a31515;">"2045-12-31 11:45"</span>, <span style="color:#a31515;">"git@example.com"</span>, <span style="color:#a31515;">"Gil Tan"</span>, -1)]
<span style="color:blue;">public</span> <span style="color:blue;">async</span> Task <span style="font-weight:bold;color:#74531f;">PostInvalidReservation</span>(</pre>
</p>
<p>
The <code>PostReservationAtNull</code> property can use the FsCheck.Xunit <code>[Property]</code> attribute, because any <code>string</code> can be used for <code>email</code> and <code>name</code>.
</p>
<p>
To be honest, it is, perhaps, cheating a bit to post any positive quantity, because a number like, say, <em>1837</em> would be a problem even if the posted representation was well-formed and valid, since no table of the restaurant has that capacity.
</p>
<p>
Validation does, however, happen before evaluating business rules and application state, so the way the system is currently implemented, the test never fails because of that. The service never gets to that part of handling the request.
</p>
<p>
One might argue that this is relying on (and thereby coupling to) an implementation detail, but honestly, it seems unlikely that the service would begin processing an invalid request - 'invalid' implying that the request makes no sense. Concretely, if the date and time is missing from a reservation, how can the service begin to process it? On which date? At what time?
</p>
<p>
Thus, it's not that likely that this behaviour would change in the future, and therefore unlikely that the test would fail because of a policy change. It is, however, worth considering.
</p>
<h3 id="a93a77fa6f9f42b9810d37a300c1989a">
Malformed date and time <a href="#a93a77fa6f9f42b9810d37a300c1989a">#</a>
</h3>
<p>
The next error case is when the <code>at</code> value is present, but malformed. You can also convert that case to a property:
</p>
<p>
<pre>[Property]
<span style="color:blue;">public</span> Property <span style="font-weight:bold;color:#74531f;">PostMalformedDateAndTime</span>()
{
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">g</span> = <span style="color:blue;">from</span> at <span style="color:blue;">in</span> ArbMap.Default.GeneratorFor<<span style="color:blue;">string</span>>()
.Where(<span style="font-weight:bold;color:#1f377f;">s</span> => !DateTime.TryParse(s, <span style="color:blue;">out</span> _))
<span style="color:blue;">from</span> email <span style="color:blue;">in</span> Gens.Email
<span style="color:blue;">from</span> name <span style="color:blue;">in</span> Gens.Name
<span style="color:blue;">from</span> quantity <span style="color:blue;">in</span> Gen.Choose(1, 10)
<span style="color:blue;">select</span> (at,
email: email.ToString(),
name: name.ToString(),
quantity);
<span style="font-weight:bold;color:#8f08c4;">return</span> Prop.ForAll(
g.ToArbitrary(),
<span style="font-weight:bold;color:#1f377f;">t</span> => PostInvalidReservationImp(t.at, t.email, t.name, t.quantity));
}</pre>
</p>
<p>
Given how simple <code>PostReservationAtNull</code> turned out to be, you may be surprised that this case takes so much code to express. There's not that much going on, though. I reuse the generators I already have for <code>email</code> and <code>name</code>, and FsCheck's built-in <code>Gen.Choose</code> to pick a <code>quantity</code> between <code>1</code> and <code>10</code>. The only slightly tricky expression is for the <code>at</code> value.
</p>
<p>
The distinguishing part of this test is that the <code>at</code> value should be malformed. A randomly generated <code>string</code> is a good starting point. After all, most strings aren't well-formed date-and-time values. Still, <a href="/2016/01/18/make-pre-conditions-explicit-in-property-based-tests">a random string <em>could</em> be interpreted as a date or time, so it's better to explicitly disallow such values</a>. This is possible with the <code>Where</code> function. It's a filter that only allows values through that are <em>not</em> understandable as dates or times - which is the vast majority of them.
</p>
<h3 id="3b130aa436c44e25b0b4b9d9ccf87e9a">
Null email <a href="#3b130aa436c44e25b0b4b9d9ccf87e9a">#</a>
</h3>
<p>
The penultimate error case is when the email address is missing. That one is as easy to express as the missing <code>at</code> value.
</p>
<p>
<pre>[Property]
<span style="color:blue;">public</span> <span style="color:blue;">async</span> Task <span style="font-weight:bold;color:#74531f;">PostNullEmail</span>(DateTime <span style="font-weight:bold;color:#1f377f;">at</span>, <span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">name</span>, PositiveInt <span style="font-weight:bold;color:#1f377f;">quantity</span>)
{
<span style="color:blue;">await</span> PostInvalidReservationImp(at.ToIso8601DateTimeString(), <span style="color:blue;">null</span>, name, (<span style="color:blue;">int</span>)quantity);
}</pre>
</p>
<p>
Again, with the addition of this specific property, I've removed the corresponding <code>[InlineData]</code> attribute from the <code>PostInvalidReservation</code> test. It only has two remaining test cases, both about non-positive quantities.
</p>
<h3 id="c1897ba360a74189a3c49a1bf05fb46a">
Non-positive quantity <a href="#c1897ba360a74189a3c49a1bf05fb46a">#</a>
</h3>
<p>
Finally, we can add a property that checks what happens if the quantity isn't positive:
</p>
<p>
<pre>[Property]
<span style="color:blue;">public</span> <span style="color:blue;">async</span> Task <span style="font-weight:bold;color:#74531f;">PostNonPositiveQuantity</span>(
DateTime <span style="font-weight:bold;color:#1f377f;">at</span>,
<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">email</span>,
<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">name</span>,
NonNegativeInt <span style="font-weight:bold;color:#1f377f;">quantity</span>)
{
<span style="color:blue;">await</span> PostInvalidReservationImp(at.ToIso8601DateTimeString(), email, name, -(<span style="color:blue;">int</span>)quantity);
}</pre>
</p>
<p>
FsCheck doesn't have a wrapper for non-positive integers, but I can use <code>NonNegativeInt</code> and negate it. The point is that I want to include <em>0</em>, which <code>NonNegativeInt</code> does. That wrapper generates integers greater than or equal to zero.
</p>
<p>
Since I've now modelled each error case as a separate FsCheck property, I can remove the <code>PostInvalidReservation</code> method.
</p>
<h3 id="1da5bfff9de24adba8fe5f3005f35e69">
Conclusion <a href="#1da5bfff9de24adba8fe5f3005f35e69">#</a>
</h3>
<p>
To be honest, I think that turning these parametrised tests into FsCheck properties is overkill. After all, when I wrote the code base, I found the parametrised tests adequate. I used test-driven development all the way through, and while I also kept the <a href="/2019/10/07/devils-advocate">Devil's Advocate</a> in mind, the tests that I wrote gave me sufficient confidence that the system works as it should.
</p>
<p>
The main point of this article is to show how you <em>can</em> convert example-based tests to property-based tests. After all, just because I felt confident in my test suite it doesn't follow that a few parametrised tests does it for you. <a href="/2018/11/12/what-to-test-and-not-to-test">How much testing you need depends on a variety of factors</a>, so you may need the extra confidence that thousands of test cases can give you.
</p>
<p>
The previous article in this series showed an abstract, but minimal example. This one is more realistic, but also more involved.
</p>
<p>
<strong>Next:</strong> <a href="/2023/05/01/refactoring-pure-function-composition-without-breaking-existing-tests">Refactoring pure function composition without breaking existing tests</a>.
</p>
</div>
<div id="comments">
<hr>
<h2 id="comments-header">
Comments
</h2>
<div class="comment" id="d7c5114a287c479db91235ded264bd55">
<div class="comment-author"><a href="https://www.relativisticramblings.com/">Christer van der Meeren</a></div>
<div class="comment-content">
<p>In the section "Missing date and time", you mention that it could be worth considering the coupling of the test to the implementation details regarding validation order and possible false positive test results. Given that you already have a test data generator that produces valid reservations (GenValidReservationForEmptyDatabase), wouldn't it be more or less trivial to just generate valid test data and modify it to make it invalid in the single specific way you want to test?</p>
</div>
<div class="comment-date">2023-04-18 14:00 UTC</div>
</div>
<div class="comment" id="114d5ded264bd7c5a912355287c479db">
<div class="comment-author"><a href="https://github.com/AnthonyLloyd">Anthony Lloyd</a></div>
<div class="comment-content">
<p>Am I right in thinking shrinking doesn't work in FsCheck with the query syntax? I've just tried with two ints. How would you make it work?</p>
<pre><code style="background-color: #eee;border: 1px solid #999;display:block;padding:5px;">[Fact]
public void ShrinkingTest()
{
Prop.ForAll(
(from a1 in Arb.Default.Int32().Generator
from a2 in Arb.Default.Int32().Generator
select (a1, a2)).ToArbitrary(),
t =>
{
if (t.a2 > 10)
throw new System.Exception();
})
.QuickCheckThrowOnFailure();
}</code></pre>
</div>
<div class="comment-date">2023-04-18 19:15 UTC</div>
</div>
<div class="comment" id="a784010d2340448ea69d4b30f82074c2">
<div class="comment-author"><a href="/">Mark Seemann</a></div>
<div class="comment-content">
<p>
Christer, thank you for writing. It wouldn't be impossible to address that concern, but I haven't found a good way of doing it without introducing other problems. So, it's a trade-off.
</p>
<p>
What I meant by my remark in the article is that in order to make an (otherwise) valid request, the test needs to know the maximum valid quantity, which varies from restaurant to restaurant. The problem, in a nutshell, is that the test in question operates exclusively against the REST API of the service, and that API doesn't expose any functionality that enable clients to query the configuration of tables for a given restaurant. There's no way to obtain that information.
</p>
<p>
The only two options I can think of are:
</p>
<ul>
<li>Add such a query API to the REST API. In this case, that seems unwarranted.</li>
<li>Add a <a href="http://xunitpatterns.com/Back%20Door%20Manipulation.html">backdoor API</a> to the self-host (<code>LegacyApi</code>).</li>
</ul>
<p>
If I had to, I'd prefer the second option, but it would still require me to add more (test) code to the code base. There's a cost to every line of code.
</p>
<p>
Here, I'm making a bet that the grandfathered restaurant isn't going to change its configuration. The tests are then written with the implicit knowledge that that particular restaurant has a maximum table size of 10, and also particular opening and closing times.
</p>
<p>
This makes those tests more concrete, which makes them more readable. They serve as easy-to-understand examples of how the system works (once the reader has gained the implicit knowledge I just described).
</p>
<p>
It's not perfect. The tests are, perhaps, too obscure for that reason, and they <em>are</em> vulnerable to configuration changes. Even so, the remedies I can think of come with their own disadvantages.
</p>
<p>
So far, I've decided that the trade-offs are best leaving things as you see them here. That doesn't mean that I wouldn't change that decision in the future if it turns out that these tests are too brittle.
</p>
</div>
<div class="comment-date">2023-04-19 8:18 UTC</div>
</div>
<div class="comment" id="1690c8861d8d44cfbe23b89613825250">
<div class="comment-author"><a href="/">Mark Seemann</a></div>
<div class="comment-content">
<p>
Anthony, thank you for writing. You're correct that in FsCheck shrinking doesn't work with query syntax; at least in the versions I've used. I'm not sure if that's planned for a future release.
</p>
<p>
As far as I can tell, this is a consequence of the maturity of the library. You have the same issue with <a href="https://hackage.haskell.org/package/QuickCheck">QuickCheck</a>, which also distinguishes between <code>Gen</code> and <code>Arbitrary</code>. While <code>Gen</code> is a monad, <code>Arbitrary</code>'s <code>shrink</code> function is <a href="/2022/08/01/invariant-functors">invariant</a>, which prevents it from being a functor (and hence, also from being a monad).
</p>
<p>
FsCheck is a mature port of QuickCheck, so it has the same limitation. No functor, no query syntax.
</p>
<p>
Later, this limitation was solved by modelling shrinking based on a lazily evaluated shrink tree, which does allow for a monad. The first time I saw that in effect was in <a href="https://hedgehog.qa/">Hedgehog</a>.
</p>
</div>
<div class="comment-date">2023-04-21 6:17 UTC</div>
</div>
<div class="comment" id="774e5ded214bd7c5a912355287c479db">
<div class="comment-author"><a href="https://github.com/AnthonyLloyd">Anthony Lloyd</a></div>
<div class="comment-content">
<p>Hedgehog does a little better than FsCheck but it doesn't shrink well when the variables are dependent.</p>
<pre><code style="background-color: #eee;border: 1px solid #999;display:block;padding:5px;">[Fact]
public void ShrinkingTest_Hedgehog()
{
Property.ForAll(
from a1 in Gen.Int32(Range.ConstantBoundedInt32())
from a2 in Gen.Int32(Range.ConstantBoundedInt32())
where a1 > a2
select (a1, a2))
.Select(t =>
{
if (t.a2 > 10)
throw new System.Exception();
})
.Check(PropertyConfig.Default.WithTests(1_000_000).WithShrinks(1_000_000));
}
[Fact]
public void ShrinkingTest_Hedgehog2()
{
Property.ForAll(
from a1 in Gen.Int32(Range.ConstantBoundedInt32())
from a2 in Gen.Int32(Range.Constant(0, a1))
select (a1, a2))
.Select(t =>
{
if (t.a2 > 10)
throw new System.Exception();
})
.Check(PropertyConfig.Default.WithTests(1_000_000).WithShrinks(1_000_000));
}
[Fact]
public void ShrinkingTest_CsCheck()
{
(from a1 in Gen.Int
from a2 in Gen.Int
where a1 > a2
select (a1, a2))
.Sample((_, a2) =>
{
if (a2 > 10)
throw new Exception();
}, iter: 1_000_000);
}
[Fact]
public void ShrinkingTest_CsCheck2()
{
(from a1 in Gen.Int.Positive
from a2 in Gen.Int[0, a1]
select (a1, a2))
.Sample((_, a2) =>
{
if (a2 > 10)
throw new Exception();
}, iter: 1_000_000);
}</code></pre>
<p>This and the syntax complexity I mentioned in the previous post were the reasons I developed CsCheck. Random shrinking is the key innovation that makes it simpler.</p>
</div>
<div class="comment-date">2023-04-21 16:38 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>.Anagrams kata as a one-linerhttps://blog.ploeh.dk/2023/04/10/anagrams-kata-as-a-one-liner2023-04-10T08:08:00+00:00Mark Seemann
<div id="post">
<p>
<em>A futile exercise in code compaction.</em>
</p>
<p>
Recently I was doing the <a href="http://codekata.com/kata/kata06-anagrams/">Anagrams kata</a> in <a href="https://fsharp.org/">F#</a> with <a href="https://github.com/gdziadkiewicz">Grzegorz Dziadkiewicz</a>, and along the way realised that the implementation is essentially a one-liner. I thought it would be fun to redo the exercise in <a href="https://www.haskell.org/">Haskell</a> and see how compact code I could get away with.
</p>
<p>
In short, in the exercise, you're given a list of words, and you need to find all the <a href="https://en.wikipedia.org/wiki/Anagram">anagrams</a> in the list. For example, given the list <em>bar, foo, bra</em>, the result should be <em>bar, bra</em>, and <em>foo</em> shouldn't be part of the output, since it's not an anagram of any other word in the list.
</p>
<h3 id="99c78f1d41a540128c07eb8912e4ca92">
A pipeline of transformations <a href="#99c78f1d41a540128c07eb8912e4ca92">#</a>
</h3>
<p>
My idea was to collect all the words in a <a href="https://hackage.haskell.org/package/containers/docs/Data-Map-Strict.html">Map</a> (dictionary) keyed by the string, but sorted. Even if the sorted string is a nonsense word, all anagrams sort to the same sequence of letters:
</p>
<p>
<pre>ghci> sort "bar"
"abr"
ghci> sort "bra"
"abr"</pre>
</p>
<p>
Each of the keys should contain a <a href="https://hackage.haskell.org/package/containers-0.6.7/docs/Data-Set.html">Set</a> of words, since I don't care about the order.
</p>
<p>
Once I have that map of sets, I can throw away the singleton sets, and then the keys. Or perhaps first throw away the keys, and then the singleton sets. The order of those two steps doesn't matter.
</p>
<p>
The reason I don't want the singleton sets is that a set with only one word means that no anagrams were found.
</p>
<h3 id="53831677170c455cb4624971c8e82249">
Creating the map <a href="#53831677170c455cb4624971c8e82249">#</a>
</h3>
<p>
How to create the desired map? The <code>Map</code> module exports the <a href="https://hackage.haskell.org/package/containers/docs/Data-Map-Strict.html#v:fromListWith">fromListWith</a> function that enables you to go through an <a href="https://en.wikipedia.org/wiki/Association_list">association list</a> and combine values along the way, in case you encounter the key more than once. That sounds useful, but means that first I have to convert the list of words to an association list.
</p>
<p>
Importing <a href="https://hackage.haskell.org/package/base/docs/Control-Arrow.html">Control.Arrow</a>, I can do it like this:
</p>
<p>
<pre>ghci> fmap (sort &&& Set.singleton) ["bar", "foo", "bra"]
[("abr",fromList ["bar"]),("foo",fromList ["foo"]),("abr",fromList ["bra"])]</pre>
</p>
<p>
Each element in the list is a pair of a key, and a set containing a single word. Notice that the set containing <code>"bar"</code> has the same key as the set containing <code>"bra"</code>. When using <code>fromListWith</code>, the function will have to unite these two sets whenever it encounters the same key.
</p>
<p>
<pre>ghci> Map.fromListWith Set.union $ fmap (sort &&& Set.singleton) ["bar", "foo", "bra"]
fromList [("abr",fromList ["bar","bra"]),("foo",fromList ["foo"])]</pre>
</p>
<p>
The two anagrams <code>"bar"</code> and <code>"bra"</code> now belong to the same set, while <code>"foo"</code> is still solitary.
</p>
<h3 id="bbd82971c2324018973182c27d613a64">
Finding the anagrams <a href="#bbd82971c2324018973182c27d613a64">#</a>
</h3>
<p>
Now that we've grouped sets according to key, we no longer need the keys:
</p>
<p>
<pre>ghci> Map.elems $ Map.fromListWith Set.union $ fmap (sort &&& Set.singleton) ["bar", "foo", "bra"]
[fromList ["bar","bra"],fromList ["foo"]]</pre>
</p>
<p>
The anagrams are those sets that have more than one element, so we can throw away those that are smaller.
</p>
<p>
<pre>ghci> filter ((1 <) . Set.size) $ Map.elems $ Map.fromListWith Set.union $
fmap (sort &&& Set.singleton) ["bar", "foo", "bra"]
[fromList ["bar","bra"]]</pre>
</p>
<p>
The expression has now grown to such a width that I've broken it into two lines to make it more readable. It really is just one line, though.
</p>
<h3 id="203f41225d944d1689cf1df0d3f8118f">
Function <a href="#203f41225d944d1689cf1df0d3f8118f">#</a>
</h3>
<p>
To save a bit of space, I eta-reduced the expression before I made it a function:
</p>
<p>
<pre><span style="color:#2b91af;">anagrams</span> <span style="color:blue;">::</span> <span style="color:blue;">Ord</span> a <span style="color:blue;">=></span> [[a]] <span style="color:blue;">-></span> <span style="color:blue;">Set</span> (<span style="color:blue;">Set</span> [a])
anagrams =
Set.fromList . <span style="color:blue;">filter</span> ((1 <) . Set.size) . Map.elems . Map.fromListWith Set.union
. <span style="color:blue;">fmap</span> (sort &&& Set.singleton)</pre>
</p>
<p>
The leftmost <code>Set.fromList</code> converts the list of anagrams to a <code>Set</code> of anagrams, since I didn't think that it was a postcondition that the anagrams should be returned in a specific order.
</p>
<p>
Unfortunately the expression is still so wide that I found it necessary to break it into two lines.
</p>
<p>
Just for the hell of it, I tried to fix the situation by changing the imports:
</p>
<p>
<pre><span style="color:blue;">import</span> Control.Arrow
<span style="color:blue;">import</span> Data.List (<span style="color:#2b91af;">sort</span>)
<span style="color:blue;">import</span> Data.Map.Strict (<span style="color:#2b91af;">fromListWith</span>, <span style="color:#2b91af;">elems</span>)
<span style="color:blue;">import</span> Data.Set (<span style="color:blue;">Set</span>, <span style="color:#2b91af;">fromList</span>, <span style="color:#2b91af;">singleton</span>)</pre>
</p>
<p>
With this very specific set of imports, the expression now barely fits on a single line:
</p>
<p>
<pre><span style="color:#2b91af;">anagrams</span> <span style="color:blue;">::</span> <span style="color:blue;">Ord</span> a <span style="color:blue;">=></span> [[a]] <span style="color:blue;">-></span> <span style="color:blue;">Set</span> (<span style="color:blue;">Set</span> [a])
anagrams = fromList . <span style="color:blue;">filter</span> ((1 <) . <span style="color:blue;">length</span>) . elems . fromListWith <span style="color:#2b91af;">(<>)</span> . <span style="color:blue;">fmap</span> (sort &&& singleton)</pre>
</p>
<p>
Here, I also took advantage of <code>Semigroup</code> <em>append</em> (<code><></code>) being equal to <code>Set.union</code> for <code>Set</code>.
</p>
<p>
Is it readable? Hardly.
</p>
<p>
My main goal with the exercise was to implement the desired functionality as a single expression. Perhaps I was inspired by Dave Thomas, who wrote:
</p>
<blockquote>
<p>
"I hacked a solution together in 25 lines of Ruby."
</p>
<footer><cite><a href="http://codekata.com/kata/kata06-anagrams/">Dave Thomas</a></cite></footer>
</blockquote>
<p>
25 lines of Ruby? I can do it in one line of Haskell!
</p>
<p>
Is that interesting? Does it make sense to compare two languages? Why not? By trying out different languages you learn the strengths and weaknesses of each. There's no denying that Haskell is <em>expressive</em>. On the other hand, what you can't see in this blog post is that compilation takes forever. Not for this code in particular, but in general.
</p>
<p>
I'm sure Dave Thomas was done with his Ruby implementation before my machine had even finished compiling the empty, scaffolded Haskell code.
</p>
<h3 id="3ee6ff0610174f3ea5293baaefbc9ee3">
Performance <a href="#3ee6ff0610174f3ea5293baaefbc9ee3">#</a>
</h3>
<p>
Dave Thomas also wrote:
</p>
<blockquote>
<p>
"It runs on <a href="http://codekata.com/data/wordlist.txt">this wordlist</a> in 1.8s on a 1.7GHz i7."
</p>
</blockquote>
<p>
Usually I don't care that much about performance as long as it's adequate. Or rather, I find that good software architecture with poor algorithms usually beats bad architecture with good algorithms. But I digress.
</p>
<p>
How fares my one-liner against Dave Thomas' implementation?
</p>
<p>
<pre>ghci> :set +s
ghci> length . anagrams . lines <$> readFile "wordlist.txt"
20683
(3.56 secs, 1,749,984,448 bytes)</pre>
</p>
<p>
Oh, 3.56 seconds isn't particularly g <em>Holy thunk, Batman! 1.7 gigabytes!</em>
</p>
<p>
That's actually disappointing, I admit. If only I could excuse this by running on a weaker machine, but mine is a 1.9 GHz i7. Nominally faster than Dave Thomas' machine.
</p>
<p>
At least, the time it takes to run through that 3.7 MB file is the same order of magnitude.
</p>
<h3 id="224925799e714bb1922f9c41a68207a3">
Tests <a href="#224925799e714bb1922f9c41a68207a3">#</a>
</h3>
<p>
Since I had a good idea about the kind of implementation I was aiming for, I didn't write that many tests. Only three, actually.
</p>
<p>
<pre><span style="color:#2b91af;">main</span> <span style="color:blue;">::</span> <span style="color:#2b91af;">IO</span> ()
main = defaultMain $ hUnitTestToTests (TestList [
<span style="color:#a31515;">"Examples"</span> ~: <span style="color:blue;">do</span>
(<span style="color:blue;">words</span>, expected) <-
[
([<span style="color:#a31515;">"foo"</span>, <span style="color:#a31515;">"bar"</span>, <span style="color:#a31515;">"baz"</span>], Set.empty),
([<span style="color:#a31515;">"bar"</span>, <span style="color:#a31515;">"foo"</span>, <span style="color:#a31515;">"bra"</span>], Set.fromList [Set.fromList [<span style="color:#a31515;">"bar"</span>, <span style="color:#a31515;">"bra"</span>]]),
([<span style="color:#a31515;">"foo"</span>, <span style="color:#a31515;">"bar"</span>, <span style="color:#a31515;">"bra"</span>, <span style="color:#a31515;">"oof"</span>],
Set.fromList [
Set.fromList [<span style="color:#a31515;">"foo"</span>, <span style="color:#a31515;">"oof"</span>], Set.fromList [<span style="color:#a31515;">"bar"</span>, <span style="color:#a31515;">"bra"</span>]])
]
<span style="color:blue;">let</span> actual = anagrams <span style="color:blue;">words</span>
<span style="color:blue;">return</span> $ expected ~=? actual
])</pre>
</p>
<p>
As I usually do it in Haskell, these are <a href="/2018/05/07/inlined-hunit-test-lists">inlined</a> <a href="/2018/04/30/parametrised-unit-tests-in-haskell">parametrised HUnit tests</a>.
</p>
<h3 id="3b4f477f18954c5095d48f450f935092">
Conclusion <a href="#3b4f477f18954c5095d48f450f935092">#</a>
</h3>
<p>
<a href="/2020/01/13/on-doing-katas">Doing katas</a> is a good way to try out new ideas, dumb or otherwise. Implementing the Anagrams kata as a one-liner was fun, but the final code shown here is sufficiently unreadable that I wouldn't recommend it.
</p>
<p>
You could still write the <code>anagrams</code> function based on the idea presented here, but in a shared code base with an indefinite life span, I'd break it up into multiple expressions with descriptive names.
</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>.An abstract example of refactoring from interaction-based to property-based testinghttps://blog.ploeh.dk/2023/04/03/an-abstract-example-of-refactoring-from-interaction-based-to-property-based-testing2023-04-03T06:02:00+00:00Mark Seemann
<div id="post">
<p>
<em>A C# example with xUnit.net and CsCheck</em>
</p>
<p>
This is the first comprehensive example that accompanies the article <a href="/2023/02/13/epistemology-of-interaction-testing">Epistemology of interaction testing</a>. In that article, I argue that in a code base that leans toward functional programming (FP), property-based testing is a better fit than interaction-based testing. In this example, I will show how to refactor simple interaction-based tests into a property-based tests.
</p>
<p>
This small article series was prompted by an email from Sergei Rogovtsev, who was kind enough to furnish <a href="https://github.com/srogovtsev/mocks-in-tests">example code</a>. I'll use his code as a starting point for this example, so I've <a href="https://github.com/ploeh/mocks-in-tests">forked the repository</a>. If you want to follow along, all my work is in a branch called <em>no-mocks</em>. That branch simply continues off the <em>master</em> branch.
</p>
<h3 id="5fe789d2b85b449fa2677bbcbf095bfc">
Interaction-based testing <a href="#5fe789d2b85b449fa2677bbcbf095bfc">#</a>
</h3>
<p>
Sergei Rogovtsev writes:
</p>
<blockquote>
<p>
"A major thing to point out here is that I'm not following TDD here not by my own choice, but because my original question arose in a context of a legacy system devoid of tests, so I choose to present it to you in the same way. I imagine that working from tests would avoid a lot of questions."
</p>
</blockquote>
<p>
Even when using test-driven development (TDD), most code bases I've seen make use of <a href="http://xunitpatterns.com/Test%20Stub.html">Stubs</a> and <a href="http://xunitpatterns.com/Mock%20Object.html">Mocks</a> (or, rather, <a href="http://xunitpatterns.com/Test%20Spy.html">Spies</a>). In an object-oriented context this can make much sense. After all, a catch phrase of object-oriented programming is <em>tell, don't ask</em>.
</p>
<p>
If you base API design on that principle, you're modelling side effects, and it makes sense that tests use Spies to verify those side effects. The book <a href="/ref/goos">Growing Object-Oriented Software, Guided by Tests</a> is a good example of this approach. Thus, even if you follow established good TDD practice, you could easily arrive at a code base reminiscent of Sergei Rogovtsev's example. I've written plenty of such code bases myself.
</p>
<p>
Sergei Rogovtsev then extracts a couple of components, leaving him with a <code>Controller</code> class looking like this:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">string</span> <span style="font-weight:bold;color:#74531f;">Complete</span>(<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">state</span>, <span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">code</span>)
{
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">knownState</span> = _repository.GetState(state);
<span style="font-weight:bold;color:#8f08c4;">try</span>
{
<span style="font-weight:bold;color:#8f08c4;">if</span> (_stateValidator.Validate(code, knownState))
<span style="font-weight:bold;color:#8f08c4;">return</span> _renderer.Success(knownState);
<span style="font-weight:bold;color:#8f08c4;">else</span>
<span style="font-weight:bold;color:#8f08c4;">return</span> _renderer.Failure(knownState);
}
<span style="font-weight:bold;color:#8f08c4;">catch</span> (Exception <span style="font-weight:bold;color:#1f377f;">e</span>)
{
<span style="font-weight:bold;color:#8f08c4;">return</span> _renderer.Error(knownState, e);
}
}</pre>
</p>
<p>
This code snippet doesn't show the entire class, but only its solitary action method. Keep in mind that the entire repository is available on GitHub if you want to see the surrounding code.
</p>
<p>
The <code>Complete</code> method orchestrates three injected dependencies: <code>_repository</code>, <code>_stateValidator</code>, and <code>_renderer</code>. The question that Sergei Rogovtsev asks is how to test this method. You may think that it's so simple that you don't need to test it, but keep in mind that this is a <a href="https://en.wikipedia.org/wiki/Minimal_reproducible_example">minimal and self-contained example</a> that stands in for something more complicated.
</p>
<p>
The method has a cyclomatic complexity of <em>3</em>, so <a href="/2019/12/09/put-cyclomatic-complexity-to-good-use">you need at least three test cases</a>. That's also what Sergei Rogovtsev's code contains. I'll show each test case in turn, while I refactor them.
</p>
<p>
The overall question is still this: Both <code>IStateValidator</code> and <code>IRenderer</code> interfaces have only a single production implementation, and in both cases the implementations are <a href="https://en.wikipedia.org/wiki/Pure_function">pure functions</a>. If interaction-based testing is suboptimal, is there a better way to test this code?
</p>
<p>
As I outlined in <a href="/2023/02/13/epistemology-of-interaction-testing">the introductory article</a>, I consider property-based testing a good alternative. In the following, I'll refactor the tests. Since the tests already use <a href="https://github.com/AutoFixture/AutoFixture">AutoFixture</a>, most of the preliminary work can be done without choosing a property-based testing framework. I'll postpone that decision until I need it.
</p>
<h3 id="ca095000df004ef9b7cb7c022071f76b">
State validator <a href="#ca095000df004ef9b7cb7c022071f76b">#</a>
</h3>
<p>
The <code>IStateValidator</code> interface has a single implementation:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">StateValidator</span> : IStateValidator
{
<span style="color:blue;">public</span> <span style="color:blue;">bool</span> <span style="font-weight:bold;color:#74531f;">Validate</span>(<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">code</span>, (<span style="color:blue;">string</span> expectedCode, <span style="color:blue;">bool</span> isMobile, Uri redirect) <span style="font-weight:bold;color:#1f377f;">knownState</span>)
=> code == knownState.expectedCode;
}</pre>
</p>
<p>
The <code>Validate</code> method is a pure function, so it's completely deterministic. It means that you don't have to hide it behind an interface and replace it with a <a href="https://martinfowler.com/bliki/TestDouble.html">Test Double</a> in order to control it. Rather, just feed it proper data. Still, that's not what the interaction-based tests do:
</p>
<p>
<pre>[Theory]
[AutoData]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> <span style="font-weight:bold;color:#74531f;">HappyPath</span>(<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">state</span>, <span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">code</span>, (<span style="color:blue;">string</span>, <span style="color:blue;">bool</span>, Uri) <span style="font-weight:bold;color:#1f377f;">knownState</span>, <span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">response</span>)
{
_repository.Add(state, knownState);
_stateValidator
.Setup(<span style="font-weight:bold;color:#1f377f;">validator</span> => validator.Validate(code, knownState))
.Returns(<span style="color:blue;">true</span>);
_renderer
.Setup(<span style="font-weight:bold;color:#1f377f;">renderer</span> => renderer.Success(knownState))
.Returns(response);
_target
.Complete(state, code)
.Should().Be(response);
}</pre>
</p>
<p>
These tests use AutoFixture, which will make it a bit easier to refactor them to properties. It also makes the test a bit more abstract, since you don't get to see concrete test data. In short, the <code>[AutoData]</code> attribute will generate a random <code>state</code> string, a random <code>code</code> string, and so on. If you want to see an example with concrete test data, the next article shows that variation.
</p>
<p>
The test uses <a href="https://github.com/moq/moq4">Moq</a> to control the behaviour of the Test Doubles. It states that the <code>Validate</code> method will return <code>true</code> when called with certain arguments. This is possible because you can redefine its behaviour, but as far as executable specifications go, this test doesn't reflect reality. There's only one <code>Validate</code> implementation, and it doesn't behave like that. Rather, it'll return <code>true</code> when <code>code</code> is equal to <code>knownState.expectedCode</code>. The test poorly communicates that behaviour.
</p>
<p>
Even before I replace AutoFixture with CsCheck, I'll prepare the test by making it more honest. I'll replace the <code>code</code> parameter with a <a href="http://xunitpatterns.com/Derived%20Value.html">Derived Value</a>:
</p>
<p>
<pre>[Theory]
[AutoData]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> <span style="font-weight:bold;color:#74531f;">HappyPath</span>(<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">state</span>, (<span style="color:blue;">string</span>, <span style="color:blue;">bool</span>, Uri) <span style="font-weight:bold;color:#1f377f;">knownState</span>, <span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">response</span>)
{
var (<span style="font-weight:bold;color:#1f377f;">expectedCode</span>, <span style="color:blue;">_</span>, <span style="color:blue;">_</span>) = knownState;
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">code</span> = expectedCode;
<span style="color:green;">// The rest of the test...</span></pre>
</p>
<p>
I've removed the <code>code</code> parameter to replace it with a variable derived from <code>knownState</code>. Notice how this <em>documents</em> the overall behaviour of the (sub-)system.
</p>
<p>
This also means that I can now replace the <code>IStateValidator</code> Test Double with the real, pure implementation:
</p>
<p>
<pre>[Theory]
[AutoData]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> <span style="font-weight:bold;color:#74531f;">HappyPath</span>(<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">state</span>, (<span style="color:blue;">string</span>, <span style="color:blue;">bool</span>, Uri) <span style="font-weight:bold;color:#1f377f;">knownState</span>, <span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">response</span>)
{
var (<span style="font-weight:bold;color:#1f377f;">expectedCode</span>, <span style="color:blue;">_</span>, <span style="color:blue;">_</span>) = knownState;
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">code</span> = expectedCode;
_repository.Add(state, knownState);
_renderer
.Setup(<span style="font-weight:bold;color:#1f377f;">renderer</span> => renderer.Success(knownState))
.Returns(response);
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">sut</span> = <span style="color:blue;">new</span> Controller(_repository, <span style="color:blue;">new</span> StateValidator(), _renderer.Object);
sut
.Complete(state, code)
.Should().Be(response);
}</pre>
</p>
<p>
I give the <code>Failure</code> test case the same treatment:
</p>
<p>
<pre>[Theory]
[AutoData]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> <span style="font-weight:bold;color:#74531f;">Failure</span>(<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">state</span>, (<span style="color:blue;">string</span>, <span style="color:blue;">bool</span>, Uri) <span style="font-weight:bold;color:#1f377f;">knownState</span>, <span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">response</span>)
{
var (<span style="font-weight:bold;color:#1f377f;">expectedCode</span>, <span style="color:blue;">_</span>, <span style="color:blue;">_</span>) = knownState;
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">code</span> = expectedCode + <span style="color:#a31515;">"1"</span>; <span style="color:green;">// Any extra string will do</span>
_repository.Add(state, knownState);
_renderer
.Setup(<span style="font-weight:bold;color:#1f377f;">renderer</span> => renderer.Failure(knownState))
.Returns(response);
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">sut</span> = <span style="color:blue;">new</span> Controller(_repository, <span style="color:blue;">new</span> StateValidator(), _renderer.Object);
sut
.Complete(state, code)
.Should().Be(response);
}</pre>
</p>
<p>
The third test case is a bit more interesting.
</p>
<h3 id="aa150cf1b817416ea49e30cdc8b27ac7">
An impossible case <a href="#aa150cf1b817416ea49e30cdc8b27ac7">#</a>
</h3>
<p>
Before I make any changes to it, the third test case is this:
</p>
<p>
<pre>[Theory]
[AutoData]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> <span style="font-weight:bold;color:#74531f;">Error</span>(
<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">state</span>,
<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">code</span>,
(<span style="color:blue;">string</span>, <span style="color:blue;">bool</span>, Uri) <span style="font-weight:bold;color:#1f377f;">knownState</span>,
Exception <span style="font-weight:bold;color:#1f377f;">e</span>,
<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">response</span>)
{
_repository.Add(state, knownState);
_stateValidator
.Setup(<span style="font-weight:bold;color:#1f377f;">validator</span> => validator.Validate(code, knownState))
.Throws(e);
_renderer
.Setup(<span style="font-weight:bold;color:#1f377f;">renderer</span> => renderer.Error(knownState, e))
.Returns(response);
_target
.Complete(state, code)
.Should().Be(response);
}</pre>
</p>
<p>
This test case verifies the behaviour of the <code>Controller</code> class when the <code>Validate</code> method throws an exception. If we want to instead use the real, pure implementation, how can we get it to throw an exception? Consider it again:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">bool</span> <span style="font-weight:bold;color:#74531f;">Validate</span>(<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">code</span>, (<span style="color:blue;">string</span> expectedCode, <span style="color:blue;">bool</span> isMobile, Uri redirect) <span style="font-weight:bold;color:#1f377f;">knownState</span>)
=> code == knownState.expectedCode;</pre>
</p>
<p>
As far as I can tell, there's no way to get this method to throw an exception. You might suggest passing <code>null</code> as the <code>knownState</code> parameter, but that's not possible. This is a new version of C# and the <a href="https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-types/nullable-reference-types">nullable reference types</a> feature is turned on. I spent some fifteen minutes trying to convince the compiler to pass a <code>null</code> argument in place of <code>knownState</code>, but I couldn't make it work in a unit test.
</p>
<p>
That's interesting. The <code>Error</code> test is exercising a code path that's impossible in production. Is it redundant?
</p>
<p>
It might be, but here I think that it's more an artefact of the process. Sergei Rogovtsev has provided a minimal example, and as it sometimes happens, perhaps it's a bit too minimal. He did write, however, that he considered it essential for the example that the logic involved more that an Boolean <em>true/false</em> condition. In order to keep with the spirit of the example, then, I'm going to modify the <code>Validate</code> method so that it's also possible to make it throw an exception:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">bool</span> <span style="font-weight:bold;color:#74531f;">Validate</span>(<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">code</span>, (<span style="color:blue;">string</span> expectedCode, <span style="color:blue;">bool</span> isMobile, Uri redirect) <span style="font-weight:bold;color:#1f377f;">knownState</span>)
{
<span style="font-weight:bold;color:#8f08c4;">if</span> (knownState == <span style="color:blue;">default</span>)
<span style="font-weight:bold;color:#8f08c4;">throw</span> <span style="color:blue;">new</span> ArgumentNullException(nameof(knownState));
<span style="font-weight:bold;color:#8f08c4;">return</span> code == knownState.expectedCode;
}</pre>
</p>
<p>
The method now throws an exception if you pass it a <code>default</code> value for <code>knownState</code>. From an implementation standpoint, there's no reason to do this, so it's only for the sake of the example. You can now test how the <code>Controller</code> handles an exception:
</p>
<p>
<pre>[Theory]
[AutoData]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> <span style="font-weight:bold;color:#74531f;">Error</span>(<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">state</span>, <span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">code</span>, <span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">response</span>)
{
_repository.Add(state, <span style="color:blue;">default</span>);
_renderer
.Setup(<span style="font-weight:bold;color:#1f377f;">renderer</span> => renderer.Error(<span style="color:blue;">default</span>, It.IsAny<Exception>()))
.Returns(response);
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">sut</span> = <span style="color:blue;">new</span> Controller(_repository, <span style="color:blue;">new</span> StateValidator(), _renderer.Object);
sut
.Complete(state, code)
.Should().Be(response);
}</pre>
</p>
<p>
The test no longer has a reference to the specific <code>Exception</code> object that <code>Validate</code> is going to throw, so instead it has to use Moq's <code>It.IsAny</code> API to configure the <code>_renderer</code>. This is, however, only an interim step, since it's now time to treat that dependency in the same way as the validator.
</p>
<h3 id="389a212d80a4445c99917cbd15b043eb">
Renderer <a href="#389a212d80a4445c99917cbd15b043eb">#</a>
</h3>
<p>
The <code>Renderer</code> class has three methods, and they are all pure functions:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">Renderer</span> : IRenderer
{
<span style="color:blue;">public</span> <span style="color:blue;">string</span> <span style="font-weight:bold;color:#74531f;">Success</span>((<span style="color:blue;">string</span> expectedCode, <span style="color:blue;">bool</span> isMobile, Uri redirect) <span style="font-weight:bold;color:#1f377f;">knownState</span>)
{
<span style="font-weight:bold;color:#8f08c4;">if</span> (knownState.isMobile)
<span style="font-weight:bold;color:#8f08c4;">return</span> <span style="color:#a31515;">"{\"success\": true, \"redirect\": \""</span> + knownState.redirect + <span style="color:#a31515;">"\"}"</span>;
<span style="font-weight:bold;color:#8f08c4;">else</span>
<span style="font-weight:bold;color:#8f08c4;">return</span> <span style="color:#a31515;">"302 Location: "</span> + knownState.redirect;
}
<span style="color:blue;">public</span> <span style="color:blue;">string</span> <span style="font-weight:bold;color:#74531f;">Failure</span>((<span style="color:blue;">string</span> expectedCode, <span style="color:blue;">bool</span> isMobile, Uri redirect) <span style="font-weight:bold;color:#1f377f;">knownState</span>)
{
<span style="font-weight:bold;color:#8f08c4;">if</span> (knownState.isMobile)
<span style="font-weight:bold;color:#8f08c4;">return</span> <span style="color:#a31515;">"{\"success\": false, \"redirect\": \"login\"}"</span>;
<span style="font-weight:bold;color:#8f08c4;">else</span>
<span style="font-weight:bold;color:#8f08c4;">return</span> <span style="color:#a31515;">"302 Location: login"</span>;
}
<span style="color:blue;">public</span> <span style="color:blue;">string</span> <span style="font-weight:bold;color:#74531f;">Error</span>((<span style="color:blue;">string</span> expectedCode, <span style="color:blue;">bool</span> isMobile, Uri redirect) <span style="font-weight:bold;color:#1f377f;">knownState</span>, Exception <span style="font-weight:bold;color:#1f377f;">e</span>)
{
<span style="font-weight:bold;color:#8f08c4;">if</span> (knownState.isMobile)
<span style="font-weight:bold;color:#8f08c4;">return</span> <span style="color:#a31515;">"{\"error\": \""</span> + e.Message + <span style="color:#a31515;">"\"}"</span>;
<span style="font-weight:bold;color:#8f08c4;">else</span>
<span style="font-weight:bold;color:#8f08c4;">return</span> <span style="color:#a31515;">"500"</span>;
}
}</pre>
</p>
<p>
Since all three methods are deterministic, automated tests can control their behaviour simply by passing in the appropriate arguments:
</p>
<p>
<pre>[Theory]
[AutoData]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> <span style="font-weight:bold;color:#74531f;">HappyPath</span>(<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">state</span>, (<span style="color:blue;">string</span>, <span style="color:blue;">bool</span>, Uri) <span style="font-weight:bold;color:#1f377f;">knownState</span>, <span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">response</span>)
{
var (<span style="font-weight:bold;color:#1f377f;">expectedCode</span>, <span style="color:blue;">_</span>, <span style="color:blue;">_</span>) = knownState;
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">code</span> = expectedCode;
_repository.Add(state, knownState);
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">renderer</span> = <span style="color:blue;">new</span> Renderer();
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">sut</span> = <span style="color:blue;">new</span> Controller(_repository, renderer);
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">expected</span> = renderer.Success(knownState);
sut
.Complete(state, code)
.Should().Be(expected);
}</pre>
</p>
<p>
Instead of configuring an <code>IRenderer</code> Stub, the test can state the <code>expected</code> output: That the output is equal to the output that <code>renderer.Success</code> would return.
</p>
<p>
Notice that the test doesn't <em>require</em> that the implementation calls <code>renderer.Success</code>. It only requires that the output is equal to the output that <code>renderer.Success</code> would return. Thus, it has less of an opinion about the implementation, which means that it's marginally less coupled to it.
</p>
<p>
You might protest that the test now duplicates the implementation code. This is partially true, but no more than the previous incarnation of it. Before, the test used Moq to explicitly <em>require</em> that <code>renderer.Success</code> gets called. Now, there's still coupling, but this refactoring reduces it.
</p>
<p>
As a side note, this may partially be an artefact of the process. Here I'm refactoring tests while keeping the implementation intact. Had I started with a property, perhaps the test would have turned out differently, and less coupled to the implementation. If you're interested in a successful exercise in using property-based TDD, you may find my article <a href="/2021/06/28/property-based-testing-is-not-the-same-as-partition-testing">Property-based testing is not the same as partition testing</a> interesting.
</p>
<h3 id="81bbcfc59f5c48df8ee15f9d1bad47cf">
Simplification <a href="#81bbcfc59f5c48df8ee15f9d1bad47cf">#</a>
</h3>
<p>
Once you've refactored the tests to use the pure functions as dependencies, you no longer need the interfaces. The interfaces <code>IStateValidator</code> and <code>IRenderer</code> only existed to support testing. Now that the tests no longer use the interfaces, you can delete them.
</p>
<p>
Furthermore, once you've removed those interfaces, there's no reason for the classes to support instantiation. Instead, make them <code>static</code>:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">StateValidator</span>
{
<span style="color:blue;">public</span> <span style="color:blue;">static</span> <span style="color:blue;">bool</span> <span style="color:#74531f;">Validate</span>(
<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">code</span>,
(<span style="color:blue;">string</span> expectedCode, <span style="color:blue;">bool</span> isMobile, Uri redirect) <span style="font-weight:bold;color:#1f377f;">knownState</span>)
{
<span style="font-weight:bold;color:#8f08c4;">if</span> (knownState == <span style="color:blue;">default</span>)
<span style="font-weight:bold;color:#8f08c4;">throw</span> <span style="color:blue;">new</span> ArgumentNullException(nameof(knownState));
<span style="font-weight:bold;color:#8f08c4;">return</span> code == knownState.expectedCode;
}
}</pre>
</p>
<p>
You can do the same for the <code>Renderer</code> class.
</p>
<p>
This doesn't change the overall <em>flow</em> of the <code>Controller</code> class' <code>Complete</code> method, although the implementation details have changed a bit:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">string</span> <span style="font-weight:bold;color:#74531f;">Complete</span>(<span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">state</span>, <span style="color:blue;">string</span> <span style="font-weight:bold;color:#1f377f;">code</span>)
{
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">knownState</span> = _repository.GetState(state);
<span style="font-weight:bold;color:#8f08c4;">try</span>
{
<span style="font-weight:bold;color:#8f08c4;">if</span> (StateValidator.Validate(code, knownState))
<span style="font-weight:bold;color:#8f08c4;">return</span> Renderer.Success(knownState);
<span style="font-weight:bold;color:#8f08c4;">else</span>
<span style="font-weight:bold;color:#8f08c4;">return</span> Renderer.Failure(knownState);
}
<span style="font-weight:bold;color:#8f08c4;">catch</span> (Exception <span style="font-weight:bold;color:#1f377f;">e</span>)
{
<span style="font-weight:bold;color:#8f08c4;">return</span> Renderer.Error(knownState, e);
}
}</pre>
</p>
<p>
<code>StateValidator</code> and <code>Renderer</code> are no longer injected dependencies, but rather 'modules' that affords pure functions.
</p>
<p>
Both the <code>Controller</code> class and the tests that cover it are simpler.
</p>
<h3 id="984cd44e8f6545ddafa673a411e188f1">
Properties <a href="#984cd44e8f6545ddafa673a411e188f1">#</a>
</h3>
<p>
So far I've been able to make all these changes without introducing a property-based testing framework. This was possible because the tests already used AutoFixture, which, while not a property-based testing framework, already strongly encourages you to write tests without literal test data.
</p>
<p>
This makes it easy to make the final change to property-based testing. On the other hand, it's a bit unfortunate from a pedagogical perspective. This means that you didn't get to see how to refactor a 'traditional' unit test to a property. The next article in this series will plug that hole, as well as show a more realistic example.
</p>
<p>
It's now time to pick a property-based testing framework. On .NET you have a few choices. Since this code base is C#, you may consider a framework written in C#. I'm not convinced that this is necessarily better, but it's a worthwhile experiment. Here I've used <a href="https://github.com/AnthonyLloyd/CsCheck">CsCheck</a>.
</p>
<p>
Since the tests already used randomly generated test data, the conversion to CsCheck is relatively straightforward. I'm only going to show one of the tests. You can always find the rest of the code in the Git repository.
</p>
<p>
<pre>[Fact]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> <span style="font-weight:bold;color:#74531f;">HappyPath</span>()
{
(<span style="color:blue;">from</span> state <span style="color:blue;">in</span> Gen.String
<span style="color:blue;">from</span> expectedCode <span style="color:blue;">in</span> Gen.String
<span style="color:blue;">from</span> isMobile <span style="color:blue;">in</span> Gen.Bool
<span style="color:blue;">let</span> urls = <span style="color:blue;">new</span>[] { <span style="color:#a31515;">"https://example.com"</span>, <span style="color:#a31515;">"https://example.org"</span> }
<span style="color:blue;">from</span> redirect <span style="color:blue;">in</span> Gen.OneOfConst(urls).Select(<span style="font-weight:bold;color:#1f377f;">s</span> => <span style="color:blue;">new</span> Uri(s))
<span style="color:blue;">select</span> (state, (expectedCode, isMobile, redirect)))
.Sample((<span style="font-weight:bold;color:#1f377f;">state</span>, <span style="font-weight:bold;color:#1f377f;">knownState</span>) =>
{
var (<span style="font-weight:bold;color:#1f377f;">expectedCode</span>, <span style="color:blue;">_</span>, <span style="color:blue;">_</span>) = knownState;
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">code</span> = expectedCode;
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">repository</span> = <span style="color:blue;">new</span> RepositoryStub();
repository.Add(state, knownState);
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">sut</span> = <span style="color:blue;">new</span> Controller(repository);
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">expected</span> = Renderer.Success(knownState);
sut
.Complete(state, code)
.Should().Be(expected);
});
}</pre>
</p>
<p>
Compared to the AutoFixture version of the test, this looks more complicated. Part of it is that CsCheck (as far as I know) doesn't have the same <a href="https://www.nuget.org/packages/AutoFixture.Xunit2/">integration with xUnit.net that AutoFixture has</a>. That might be an issue that someone could address; after all, <a href="https://fscheck.github.io/FsCheck/RunningTests.html">FsCheck has framework integration</a>, to name an example.
</p>
<p>
<a href="/2023/02/13/epistemology-of-interaction-testing">Test data generators are monads</a> so you typically leverage whatever syntactic sugar a language offers to simplify monadic composition. <a href="/2022/03/28/monads">In C# that syntactic sugar is query syntax</a>, which explains that initial <code>from</code> block.
</p>
<p>
The test does look too top-heavy for my taste. An equivalent problem appears in the next article, where I also try to address it. In general, the better monad support a language offers, the more elegantly you can address this kind of problem. C# isn't really there yet, whereas languages like <a href="https://fsharp.org/">F#</a> and <a href="https://www.haskell.org/">Haskell</a> offer superior alternatives.
</p>
<h3 id="b0e7738d8b0440bba33caa470fd440fb">
Conclusion <a href="#b0e7738d8b0440bba33caa470fd440fb">#</a>
</h3>
<p>
In this article I've tried to demonstrate how property-based testing is a viable alternative to using Stubs and Mocks for verification of composition. You can try to sabotage the <code>Controller.Complete</code> method in the <em>no-mocks</em> branch and see that one or more properties will fail.
</p>
<p>
While the example code base that I've used for this article has the strength of being small and self-contained, it also suffers from a few weaknesses. It's perhaps a bit too abstract to truly resonate. It also uses AutoFixture to generate test data, which already takes it halfway towards property-based testing. While that makes the refactoring easier, it also means that it may not fully demonstrate how to refactor an example-based test to a property. I'll try to address these shortcomings in the next article.
</p>
<p>
<strong>Next:</strong> <a href="/2023/04/17/a-restaurant-example-of-refactoring-from-example-based-to-property-based-testing">A restaurant example of refactoring from example-based to property-based testing</a>.
</p>
</div>
<div id="comments">
<hr>
<h2 id="comments-header">
Comments
</h2>
<div class="comment" id="0510331b953a4c308c3b01a918d2b65c">
<div class="comment-author"><a href="https://github.com/srogovtsev">Sergei Rogovtcev</a></div>
<div class="comment-content">
<p>First of all, thanks again for continuing to explore this matter. This was very enlightening, but in the end, I was left with is a sense of subtle wrongness, which is very hard to pin down, and even harder to tell apart between "this is actually not right for me" and "this is something new I'm not accustomed to".</p>
<p>I suppose that my main question would center around difference between your tests for <code>IStateValidator</code> and <code>IRenderer</code>. Let's start with the latter:</p>
<blockquote><p>Instead of configuring an <code>IRenderer</code> Stub, the test can state the expected output: That the output is equal to the output that <code>renderer.Success</code> would return.</p></blockquote>
<p>Coupled with the explanation ("[the test] has less of an opinion about the implementation, which means that it's marginally less coupled to it"), this makes a lot of sense, with the only caveat that in more production-like cases comparing the output would be harder (e.g., if <code>IRenderer</code> operates on <code>HttpContext</code> to produce a full HTTP response), but that's a technicality that can be sorted out with proper assertion library. But let's now look at the <code>IStateValidator</code> part:</p>
<blockquote><p>as far as executable specifications go, this test doesn't reflect reality. There's only one <code>Validate</code> implementation, and it doesn't behave like that. Rather, it'll return true when code is equal to <code>knownState.expectedCode</code>. The test poorly communicates that behaviour. </p></blockquote>
<p>Here you act with the opposite intent: you want the test to communicate the specification, and thus be explicitly tied to the logic in the implementation (if not the actual code of it). There are two thing about that that bother me. First of all, it's somewhat inconsistent, so it makes it harder for me to choose which path to follow when testing the next code I'd write (or articulating to another developer how they should do it). But what's more important - and that comes from my example being <em>minimal</em>, as you've already noted - is that the validation logic might be more complicated, and thus the setup would be complicated as well. And as you've already mentioned on Twitter, when chaging the code in the validator implementation, you might be forced to change the implementation in the test, even if the test is more about the controller itself.</p>
<p>There's also another frame for the same issue: the original test read as (at least for me): "if the state is valid, we return successful response based on this state". It didn't matter what is "valid" not did it matter what is "successful response". The new tests reads as "if state in the repository matches passed code, we return successful response for the state". It still doesn't matter what is "successful response", but the definition of validity <em>does</em> matter. For me, this is a change of test meaning, and I'm not sure I understand where that leads me.</p>
<p>Let's consider the following scenario: we need to add another validity criteria, such as "state in repository has an expiration date, and this date should be in the future". We obviously need to add a couple of tests for this (negative and positive). Where do we add them? I'd say we add them into the tests for the validator itself (which are "not shown" for the purposes of brevity), but then it feels weird that we <em>also</em> need to change this "happy path" test...</p>
</div>
<div class="comment-date">2023-04-03 21:24 UTC</div>
</div>
<div class="comment" id="1a4c308c3b01a85c1b953d2051033b69">
<div class="comment-author"><a href="https://github.com/AnthonyLloyd">Anthony Lloyd</a></div>
<div class="comment-content">
<p>Thanks for showing CsCheck. I've put in a PR to show how I would refactor the CsCheck tests and will attempt to explain some of the design choices of CsCheck.</p>
<p>First of all, it may be a personal opinion but I don't really tend to use query syntax for CsCheck. I prefer to see the SelectManys and there are a number of additional overloads that simplify ranging and composing Gens.</p>
<p>On the design of CsCheck, I build it to not use reflection, attributes or target test frameworks. I've seen the very difficult problems these lead to (for author and user) when you try to move past simple examples.</p>
<p>I wanted the user to be able to move from simple general type generators to ranged complex types easily in a fluent style. No Arbs, attributes, PositiveInt type etc.</p>
<p>CsCheck has automatic shrinking even for the most complex types that just comes out of composing Gens.</p>
<p>I think some of the reason it was so easy to extend the library to areas such as concurrency testing was because of this simplicity (as well as the random shrinking insight).</p>
<pre><code style="background-color: #eee;border: 1px solid #999;display:block;padding:5px;">Gen<Uri> _genRedirect = Gen.OneOfConst(new Uri("https://example.com"), new Uri("https://example.org"));
[Fact]
public void HappyPath()
{
Gen.Select(Gen.String, Gen.String, Gen.Bool, _genRedirect)
.Sample((state, expectedCode, isMobile, redirect) =>
{
var code = expectedCode;
var knownState = (expectedCode, isMobile, redirect);
var repository = new RepositoryStub { { state, knownState } };
var sut = new Controller(repository);
var actual = sut.Complete(state, code);
var expected = Renderer.Success(knownState);
return actual == expected;
});
}</code></pre>
</div>
<div class="comment-date">2023-04-04 23:56 UTC</div>
</div>
<div class="comment" id="076f05eef3f649eab07392dc2ac83023">
<div class="comment-author"><a href="/">Mark Seemann</a></div>
<div class="comment-content">
<p>
Sergei, thank you for writing. I'm afraid all of this is context-dependent, and I seem to constantly fail giving enough context. It's a fair criticism that I seem to employ inconsistent heuristics when making technical decisions. Part of it is caused by my lack of context. The code base is deliberately stripped of context, which has many other benefits, but gives me little to navigate after. I'm flying blind, so to speak. I've had to (implicitly) imagine some forces acting on the software in order to make technical decisions. Since we haven't explicitly outlined such forces, I've had to make them up as I went. It's quite possible, even, that I've imagined one set of forces in one place, and another set somewhere else. If so, no wonder the decisions are inconsistent.
</p>
<p>
What do I mean by <em>forces?</em> I'm thinking of the surrounding context that you have to take into a account when making technical decisions about code: Is the current feature urgent? Is it a bug already in production? Is this a new system with a small code base? Or is it an old system with a large code base? Do you have good automated tests? Do you have a Continuous Delivery pipeline? Are you experiencing problems with code quality? What does the team makeup look like? Do you have mostly seasoned veterans who've worked in that code base for years? Or do you have many newcomers? Is the system public-facing or internal? Is it a system, even, or a library or framework? What sort of organisation owns the software? Is it a product group? Or a cost centre? What is the organization's goals? How are you incentivized? How are other stakeholders incentivized?
</p>
<p>
As you can imagine, I can keep going, asking questions like these, and they may all be relevant. Clearly, we can't expect a self-contained minimal example to also include all such superstructure, so that's what I (inconsistently) have to imagine, on the fly.
</p>
<p>
I admit that the decisions I describe seem inconsistent, and the explanation may simply be what is already implied above: I may have had a different context in mind when I made one, and a variation in mind when I made the other.
</p>
<p>
That's hardly the whole story, though. I didn't start my answer with the above litany of forces only to make a bad excuse for myself. Rather, what I had in mind was to argue that I use a wider context when making decisions. That context is not just technical, but includes, among many other considerations, the team structure.
</p>
<p>
As an example, I was recently working with some students in a university setting. These are people in their early twenties, with only a few months of academic programming under their belt, as well as, perhaps, a few years of hobby programming. They'd just been introduced to Git and GitHub a few weeks earlier, C# a month before that. I was trying to teach them how to use Git and GitHub, how to structure decent C# code, and many other things. During our project, they did send me a few pull requests I would have immediately rejected from a professional programmer. In this particular context, however, that would have been counter-productive. These students were doing a good job, based on their level of experience, and they needed the sense of accomplishment that I would (often, but not always) accept their code.
</p>
<p>
I could have insisted on a higher code quality, and I would also have been able to teach it to anyone patient enough to listen. One thing I've learned all too slowly in my decades of working with other people is that most people aren't as patient with me as I'd like them to be. I need to explicitly consider how to motivate my collaborators.
</p>
<p>
Here's another example: Years ago, I worked with a rag-tag team hastily assembled via word-of-mouth of some fine European freelancers. My challenge here was another. These people were used to be on top of their game - usually the ones brought in to an organisation because they were the best. I needed them to work together, and among other things, it meant showing them that even though they might think that their way was the best way, other ways exist. I wanted them to be able to work together and produce code with shared ownership. At the beginning, I was rather strict with my standards, clearly bruising a few egos, but ultimately several members have told what a positive transformative experience it was for them. It was a positive transformative experience for me, too.
</p>
<p>
I discuss all of this because you, among various points, mention the need to be able to articulate to other developers how to make technical decisions about tests. The point is that there's a lot of context that goes into making decisions, and hardly a one-size-fits-all heuristic.
</p>
<p>
What <em>usually</em> guides me is an emphasis on <em>coupling</em>, and that's also, I believe, what ultimately motivated me here. There's always going to be <em>some</em> coupling between tests and production code, but the less the better. For example, when considering whether how to write an assertion, I consider whether a change in production code's behaviour would cause a test to break.
</p>
<p>
Consider, for example, the <code>renderer</code> in the present example. How important is the exact output? What happens if I change a character in the string that is being returned?
</p>
<p>
That's a good example of context being important. If that output is part of an implementation of a network protocol or some other technical spec, just one character change could, indeed, imply that your implementation is off spec. In that case, we do want to test the exact output, and we do want the test to fail if the output changes.
</p>
<p>
On the other hand, if the output is a piece of UI, or perhaps an error message, then the exact wording is likely to change over time. Since this doesn't really imply a change in <em>behaviour</em>, changing such a string output shouldn't break a test.
</p>
<p>
You need that wider context in order to make decisions like that: If we change the System Under Test in this way, will the test break? Should it? What if we change it in another way?
</p>
<p>
This is relevant in order to address your final concern: What if you now decide that the expiration date should be in the future? The way you describe it, it sounds like this strengthens the preconditions of the system - in other words, it <a href="/2021/12/13/backwards-compatibility-as-a-profunctor">breaks backwards compatibility</a>. So yes, making that change may break existing tests, but this could be an indication that it's also going to break existing clients.
</p>
<p>
<em>If</em> you have any clients, that is. Again, you know your context better than I do, so only you can decide whether making such a change is okay. I can think of situations where is, but I usually find myself in contexts where it isn't, so I tend to err on the side of avoiding breaking changes.
</p>
</div>
<div class="comment-date">2023-04-09 14:28 UTC</div>
</div>
<div class="comment" id="f2fe826964404792954ddaa4155c7be6">
<div class="comment-author"><a href="https://github.com/srogovtsev">Sergei Rogovtcev</a></div>
<div class="comment-content">
<p>Mark, thank you for taking the time to discuss this.</p>
<p>Having the magic word "architect" somewhere in my title, I know the importance of context, and in fact that would usually be the first counter-question that I have for somebody coming at me with a question: "what is your context?". So here we are, me being contractually obliged to strip as much context from my code as possible, and you having to reinvent it back from your experience. On the other hand, this allows us to point out which decisions are actually context-driven, and how different contexts affect them.</p>
<p>With that in mind, I can actually propose two different contexts to reframe the decisions above, so that we could arrive at more insights.</p>
<p>The first would be an imaginary context, which I had in mind when writing the code, but haven't thought of communicating: the <code>renderer</code> is as important as the <code>validator</code>. In case of "mobile" state the consumer is actually a mobile application, so we need to know we've produced the right JSON it will consume, and in case of non-"mobile" state the consumer is the browser, which again needs to be properly redirected. In my mind, this is no less important than the validation logic itself, because breaking it will break at least one consumer (mobile), and more likely both of them. Thus, according to the logic above, this is a compatibility issue, and as such we need to explicitly spell this behavior in the tests. Which gives us six outcome branches... six tests? Or something more complicated? This is especially interesting, considering the fact that we can test the <code>renderer</code> in isolation, so we'd be either duplicating our tests... or just just discarding the isolated tests for the <code>renderer</code>?</p>
<p>And then here's the actual real context, which I can thankfully divulge to this extent: this is, in fact, a <em>migration</em> problem, when we move from one externally-facing framework (i.e. ASP.NET Web API) to another (i.e. ASP.NET Core). So I am not, in fact, concerned about the validation at all - I'm concerned about the data being properly <em>passed</em> to the validator (because the validator already existed, and worked properly, I'm just calling it from another framework), its result properly handled in the controller (which I am replacing), and then I'm concerned that despite the heavy changes between ASP.NET versions I'm still rendering the output in the exactly same way.</p>
<p>Now that I'm thinking about it, it seems grossly unfair that I've hidden this context beforehand, but then, I didn't see how it was affecting the decisions in test design. So hopefully we can still find some use in this.</p>
</div>
<div class="comment-date">2023-04-10 18:03 UTC</div>
</div>
<div class="comment" id="82b07a802bd54507afb0aa90bfd827c8">
<div class="comment-author"><a href="/">Mark Seemann</a></div>
<div class="comment-content">
<p>
Anthony, thank you for writing. I didn't intend to disparage CsCheck. Having once run <a href="https://github.com/AutoFixture/AutoFixture/">a moderately successful open source project</a>, I've learned that it's a good idea to limit the scope to a functional minimum. I'm not complaining about the design decisions made for CsCheck.
</p>
<p>
I was a bit concerned that a casual reader might compare the CsCheck example with the previous code and be put off by the apparent complexity. I admit that your example looks less complex than mine, so to address that particular concern, I could have used code similar to yours.
</p>
<p>
Whether one prefers the syntactic sugar of query syntax or the more explicit use of <code>SelectMany</code> is, to a degree, subjective. There are, on the other hand, some cases where one is objectively better than the other. One day I should write an article about that.
</p>
<p>
I agree that the test-framework integration that exists in FsCheck is less than ideal. I'm not wishing for anything like that. Something declarative, however, would be nice. Contrary to you, I consider wrapper types like <code>PositiveInt</code> to be a boon, but perhaps not like they're implemented in FsCheck. (And this, by the way, isn't to harp on FsCheck either; I only bring up those examples because FsCheck has more of that kind of API than Hedgehog does.) The Haskell <a href="https://hackage.haskell.org/package/QuickCheck">QuickCheck</a> approach is nice: While a wrapper like <a href="https://hackage.haskell.org/package/QuickCheck/docs/Test-QuickCheck.html#t:Positive">Positive</a> is predefined in the package, it's just an <code>Arbitrary</code> instance. There's really nothing special about it, and you can easily define domain-specific wrappers for your own testing purposes. Here's an example: <a href="/2019/09/02/naming-newtypes-for-quickcheck-arbitraries">Naming newtypes for QuickCheck Arbitraries</a>. I'm wondering if something similar wouldn't be possible with interfaces in .NET.
</p>
</div>
<div class="comment-date">2023-04-13 8:46 UTC</div>
</div>
<div class="comment" id="ee233e2d67954197afcaa98d7637fda1">
<div class="comment-author"><a href="/">Mark Seemann</a></div>
<div class="comment-content">
<p>
Sergei, thank you for writing. I'm sorry if I came across as condescending or implying that you weren't aware that context matters. Of course you do. I was mostly trying to reconstruct my own decision process, which is far less explicit than you might like.
</p>
<p>
Regarding the renderer component, I understand that testing such a thing in reality may be more involved than the toy example we're looking at. My first concern is to avoid duplicating efforts too much. Again, however, the external behaviour should be the primary concern. I'm increasingly <a href="/2021/03/01/pendulum-swing-internal-by-default">shifting towards making more and more things internal</a>, as long as I can still test them via the application boundary. As I understand it, this is the same concern that <a href="https://dannorth.net/introducing-bdd/">made Dan North come up with behaviour-driven development</a>. I'm also concerned primarily with testing the behaviour of systems, just without all the Gherkin overhead.
</p>
<p>
There comes a time, however, where testing everything through an external API becomes too awkward. I'm not adverse to introduce or make public classes or functions to enable testing at a different abstraction level. Doing that, however, represents a bet that it's possible to keep the new component's API stable enough that it isn't going to cause too much test churn. Still, if we imagine that we've already made such a decision, and that we now have some renderer component, then it's only natural to test it thoroughly. Then, in order to avoid duplicating assertions, we can state, as I did in this article, that the overall system should expect to see whatever the renderer component returns.
</p>
<p>
That was, perhaps, too wordy an explanation. Perhaps this is more helpful: Don't repeat yourself. What has been asserted in one place shouldn't be asserted in another place.
</p>
<p>
The other example you mention, about migrating to another framework, reminds me of two things.
</p>
<p>
The first is that we shouldn't forget about other ways of verifying code correctness. We've mostly been discussing black-box testing, and while it can be <a href="/2019/10/07/devils-advocate">an interesting exercise to imagine an adversary developer</a>, in general <a href="/2023/03/20/on-trust-in-software-development">that's rarely the reality</a>. Are there other ways to verify that methods are called with the correct values? How about <em>looking</em> at the code? Consistent code reviews are good at detecting bugs.
</p>
<p>
The second observation is that if you already have two working components (validator and renderer) you can treat them as <a href="https://en.wikipedia.org/wiki/Test_oracle">Test Oracles</a>. This still works well with property-based testing. Write tests based on equivalence classes and get a property-based testing framework to sample from those classes. Then use the Test Oracles to define the expected output. That's essentially what I have done in this article.
</p>
<p>
Does it <em>prove</em> that your framework-based code calls the components with the correct arguments? No, not like if you'd used a Test Spy. Property-based testing produces knowledge reminiscent of the kind of knowledge produced by experimental physics; not the kind of axiomatic knowledge produced by mathematics. That's why I named this article series <em>Epistemology of interaction testing.</em>
</p>
<p>
Is it wrong to test with Stubs or Spies in a case like this? Not necessarily. Ultimately, what I try to do with this blog is to investigate and present alternatives. Only once we have alternatives do we have choices.
</p>
</div>
<div class="comment-date">2023-04-15 15:53 UTC</div>
</div>
</div>
<hr>
This blog is totally free, but if you like it, please consider <a href="https://blog.ploeh.dk/support">supporting it</a>.More functional pits of successhttps://blog.ploeh.dk/2023/03/27/more-functional-pits-of-success2023-03-27T05:36:00+00:00Mark Seemann
<div id="post">
<p>
<em>FAQ: What are the other pits of successes of functional programming?</em>
</p>
<p>
People who have seen my presentation <a href="https://youtu.be/US8QG9I1XW0">Functional architecture: the pits of success</a> occasionally write to ask: <em>What are the other pits?</em>
</p>
<p>
The talk is about some of the design goals that we often struggle with in object-oriented programming, but which tend to happen automatically in functional programming (FP). In the presentation I cover three pits of success, but I also mention that there are more. In a one-hour conference presentation, I simply didn't have time to discuss more than three.
</p>
<p>
It's a natural question, then, to ask what are the pits of success that I don't cover in the talk?
</p>
<p>
I've been digging through my notes and found the following:
</p>
<ul>
<li>Parallelism</li>
<li>Ports and adapters</li>
<li>Services, Entities, Value Objects</li>
<li>Testability</li>
<li>Composition</li>
<li>Package and component principles</li>
<li>CQS</li>
<li>Encapsulation</li>
</ul>
<p>
Finding a lost list like this, more than six years after I jotted it down, presents a bit of a puzzle to me, too. In this post, I'll see if I can reconstruct some of the points.
</p>
<h3 id="08cc3545b4324d0ab76e8f38d6367324">
Parallelism <a href="#08cc3545b4324d0ab76e8f38d6367324" title="permalink">#</a>
</h3>
<p>
When most things are immutable you don't have to worry about multiple threads updating the same shared resource. Much has already been said and written about this in the context of functional programming, to the degree that for some people, it's the main (or only?) reason to adopt FP.
</p>
<p>
Even so, I had (and still have) a version of the presentation that included this advantage. When I realised that I had to cut some content for time, it was easy to cut this topic in favour of other benefits. After all, this one was already well known in 2016.
</p>
<h3 id="243b258ac0ad4d8fa517bcbc7f2b5e7a">
Ports and adapters <a href="#243b258ac0ad4d8fa517bcbc7f2b5e7a" title="permalink">#</a>
</h3>
<p>
This was one of the three benefits I kept in the talk. I've also covered it on my blog in the article <a href="/2016/03/18/functional-architecture-is-ports-and-adapters">Functional architecture is Ports and Adapters</a>.
</p>
<h3 id="18060ca17da341148f9027a290f06652">
Services, Entities, Value Objects <a href="#18060ca17da341148f9027a290f06652" title="permalink">#</a>
</h3>
<p>
This was the second topic I included in the talk. I don't think that there's an explicit article here on the blog that deals with this particular subject matter, so if you want the details, you'll have to view the recording.
</p>
<p>
In short, though, what I had in mind was that <a href="/ref/ddd">Domain-Driven Design</a> explicitly distinguishes between Services, Entities, and Value Objects, which often seems to pull in the opposite direction of the object-oriented notion of <em>data with behaviour</em>. In FP, on the contrary, it's natural to separate data from behaviour. Since behaviour often implements business logic, and since business logic tends to change at a different rate than data, it's a good idea to keep them apart.
</p>
<h3 id="17d84bcee48a42a989760327b779bf59">
Testability <a href="#17d84bcee48a42a989760327b779bf59" title="permalink">#</a>
</h3>
<p>
The third pit of success I covered in the talk was testability. I've also covered this here on the blog: <a href="/2015/05/07/functional-design-is-intrinsically-testable">Functional design is intrinsically testable</a>. <a href="https://en.wikipedia.org/wiki/Pure_function">Pure functions</a> are trivial to test: Supply some input and verify the output.
</p>
<h3 id="d2ac6cdd43794ade93ad664d72ed1ea1">
Composition <a href="#d2ac6cdd43794ade93ad664d72ed1ea1" title="permalink">#</a>
</h3>
<p>
Pure functions compose. In the simplest case, use the return value from one function as input for another function. In more complex cases, you may need various combinators in order to be able to 'click' functions together.
</p>
<p>
I don't have a single article about this. Rather, I have scores: <a href="/2017/10/04/from-design-patterns-to-category-theory">From design patterns to category theory</a>.
</p>
<h3 id="c3137baaeb50413e9caa4ebf2acde8e3">
Package and component principles <a href="#c3137baaeb50413e9caa4ebf2acde8e3" title="permalink">#</a>
</h3>
<p>
When it comes to this one, I admit, I no longer remember what I had in mind. Perhaps I was thinking about <a href="https://fsharpforfunandprofit.com/posts/cycles-and-modularity-in-the-wild/">Scott Wlaschin's studies of cycles and modularity</a>. Perhaps I did, again, have <a href="/2016/03/18/functional-architecture-is-ports-and-adapters">my article about Ports and Adapters</a> in mind, or perhaps it was my later articles on <a href="/2017/02/02/dependency-rejection">dependency rejection</a> that already stirred.
</p>
<h3 id="3554fe1eca684683bb793df1b1d23a87">
CQS <a href="#3554fe1eca684683bb793df1b1d23a87" title="permalink">#</a>
</h3>
<p>
The <a href="https://en.wikipedia.org/wiki/Command%E2%80%93query_separation">Command Query Separation</a> principle states that an operation (i.e. a method) should be either a Command or a Query, but not both. In most programming languages, the onus is on you to maintain that discipline. It's not a design principle that comes easy to most object-oriented programmers.
</p>
<p>
Functional programming, on the other hand, emphasises pure functions, which are all Queries. Commands have side effects, and pure functions can't have side effects. <a href="https://www.haskell.org/">Haskell</a> even makes sure to type-check that pure functions don't perform side effects. If you're interested in a C# explanation of how that works, see <a href="/2020/06/08/the-io-container">The IO Container</a>.
</p>
<p>
What impure actions remain after you've implemented most of your code base as pure functions can violate or follow CQS as you see fit. I usually still follow that principle, but since the impure parts of a functional code base tends to be fairly small and isolated to the edges of the application, even if you decide to violate CQS there, it probably makes little difference.
</p>
<h3 id="da267445bdae46bd97249acb0ea12246">
Encapsulation <a href="#da267445bdae46bd97249acb0ea12246" title="permalink">#</a>
</h3>
<p>
Functional programmers don't talk much about <em>encapsulation</em>, but you'll often hear them say that we should <a href="https://blog.janestreet.com/effective-ml-video/">make illegal states unrepresentable</a>. I recently wrote an article that explains that this tends to originate from the same motivation: <a href="/2022/10/24/encapsulation-in-functional-programming">Encapsulation in Functional Programming</a>.
</p>
<p>
In languages like <a href="https://fsharp.org/">F#</a> and Haskell, most type definitions require a single line of code, in contrast to object-oriented programming where types are normally classes, which take up a whole file each. This makes it much easier and succinct to define <a href="https://www.hillelwayne.com/post/constructive/">constructive data</a> in proper FP languages.
</p>
<p>
Furthermore, perhaps most importantly, pure functions are <a href="https://en.wikipedia.org/wiki/Referential_transparency">referentially transparent</a>, and <a href="/2021/07/28/referential-transparency-fits-in-your-head">referential transparency fits in your head</a>.
</p>
<h3 id="f89e19457a344cfc9bd2c38e5d5c5f2b">
Conclusion <a href="#f89e19457a344cfc9bd2c38e5d5c5f2b" title="permalink">#</a>
</h3>
<p>
In a recording of the talk titled <em>Functional architecture: the pits of success</em> I explain that the presentation only discusses three pits of success, but that there are more. Consulting my notes, I found five more that I didn't cover. I've now tried to remedy this lapse.
</p>
<p>
I don't, however, believe that this list is exhaustive. Why should it be?
</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>.On trust in software developmenthttps://blog.ploeh.dk/2023/03/20/on-trust-in-software-development2023-03-20T08:55:00+00:00Mark Seemann
<div id="post">
<p>
<em>Can you trust your colleagues to write good code? Can you trust yourself?</em>
</p>
<p>
I've recently noticed a trend among some agile thought leaders. They talk about <em>trust</em> and <em>gatekeeping</em>. It goes something like this:
</p>
<blockquote>
<p>
Why put up barriers to prevent people from committing code? Don't you trust your colleagues?
</p>
<p>
Gated check-ins, pull requests, reviews are a sign of a dysfunctional organisation.
</p>
</blockquote>
<p>
I'm deliberately paraphrasing. While I could cite multiple examples, I wish to engage with the idea rather than the people who propose it. Thus, I apologise for the seeming use of <a href="https://en.wikipedia.org/wiki/Weasel_word">weasel words</a> in the above paragraph, but my agenda is the opposite of appealing to anonymous authority.
</p>
<p>
If someone asks me: "Don't you trust your colleagues?", my answer is:
</p>
<p>
No, I don't trust my colleagues, as I don't trust myself.
</p>
<h3 id="25501f07623946a1925a83af5b5198a3">
Framing <a href="#25501f07623946a1925a83af5b5198a3">#</a>
</h3>
<p>
I don't trust myself to write defect-free code. I don't trust that I've always correctly understood the requirements. I don't trust that I've written the code in the best possible way. Why should I trust my colleagues to be superhumanly perfect?
</p>
<p>
The <em>trust</em> framing is powerful because few people like to be labeled as <em>mistrusting</em>. When asked <em>"don't you trust your colleagues?"</em> you don't want to answer in the affirmative. You don't want to come across as suspicious or paranoid. You want to <em>belong</em>.
</p>
<p>
<a href="https://en.wikipedia.org/wiki/Belongingness">The need to belong is fundamental to human nature</a>. When asked if you trust your colleagues, saying "no" implicitly disassociates you from the group.
</p>
<p>
Sometimes the trust framing goes one step further and labels processes such as code reviews or pull requests as <em>gatekeeping</em>. This is still the same framing, but now turns the group dynamics around. Now the question isn't whether <em>you</em> belong, but whether you're excluding others from the group. Most people (me included) want to be nice people, and excluding other people is bullying. Since you don't want to be a bully, you don't want to be a gatekeeper.
</p>
<p>
Framing a discussion about software engineering as one of trust and belonging is powerful and seductive. You're inclined to accept arguments made from that position, and you may not discover the sleight of hand. It's subliminal.
</p>
<p>
Most likely, it's such a fundamental and subconscious part of human psychology that the thought leaders who make the argument don't realise what they are doing. Many of them are professionals that I highly respect; people with more merit, experience, and education than I have. I don't think they're deliberately trying to put one over you.
</p>
<p>
I do think, on the other hand, that this is an argument to be challenged.
</p>
<h3 id="1a98f4b52b824194b23b5bb836efacb7">
Two kinds of trust <a href="#1a98f4b52b824194b23b5bb836efacb7">#</a>
</h3>
<p>
On the surface, the trust framing seems to be about belonging, or its opposite, exclusion. It implies that if you don't trust your co-workers, you suspect them of malign intent. Organisational dysfunction, it follows, is a Hobbesian state of nature where everyone is out for themselves: Expect your colleague to be a back-stabbing liar out to get you.
</p>
<p>
Indeed, the word <em>trust</em> implies that, too, but that's usually not the reason to introduce guardrails and checks to a software engineering process.
</p>
<p>
Rather, another fundamental human characteristic is <em>fallibility</em>. We make mistakes in all sorts of way, and we don't make them from malign intent. We make them because we're human.
</p>
<p>
Do we trust our colleagues to make no mistakes? Do we trust that our colleagues have perfect knowledge of requirement, goals, architecture, coding standards, and so on? I don't, just as I don't trust myself to have those qualities.
</p>
<p>
This interpretation of <em>trust</em> is, I believe, better aligned with software engineering. If we institute formal sign-offs, code reviews, and other guardrails, it's not that we suspect co-workers of ill intent. Rather, we're trying to prevent mistakes.
</p>
<h3 id="020b7202b31d421baa9e612ca168f767">
Two wrongs... <a href="#020b7202b31d421baa9e612ca168f767">#</a>
</h3>
<p>
That's not to say that all guardrails are necessary all of the time. The thought leaders I so vaguely refer to will often present alternatives: Pair programming instead of pull requests. Indeed, that can be an efficient and confidence-inducing way to work, in certain contexts. I describe advantages as well as disadvantages in my book <a href="/2021/06/14/new-book-code-that-fits-in-your-head">Code That Fits in Your Head</a>.
</p>
<p>
I've warned about the <em>trust framing</em>, but that doesn't mean that pull requests, code reviews, gated check-ins, or feature branches are always a good idea. Just because one argument is flawed it does't mean that the message is wrong. It could be correct for other reasons.
</p>
<p>
I agree with the likes of <a href="https://martinfowler.com/">Martin Fowler</a> and <a href="https://www.davefarley.net/">Dave Farley</a> that feature branching is a bad idea, and that you should adopt <a href="https://en.wikipedia.org/wiki/Continuous_delivery">Continuous Delivery</a>. <a href="/ref/accelerate">Accelerate</a> strongly suggests that.
</p>
<p>
I also agree that pull requests and formal reviews with sign-offs, <em>as they're usually practised</em>, is at odds with even <a href="https://en.wikipedia.org/wiki/Continuous_integration">Continuous Integration</a>. Again, be aware of common pitfalls in logic. Just because one way to do reviews is counter-productive, it doesn't follow that all reviews are bad.
</p>
<p>
As I have outlined in another article, under the right circumstances, <a href="/2021/06/21/agile-pull-requests">agile pull requests</a> are possible. I've had good result with pull requests like that. Reviewing was everyone's job, and we integrated multiple times a day.
</p>
<p>
Is that way to work always possible? Is it always the best way to work? No, of course not. Context matters. I've worked with another team where it was evident that that process had little chance of working. On the other hand, that team wasn't keen on pair programming either. Then what do you do?
</p>
<h3 id="1c3ff2a877214b76934d3817f24c1318">
Mistakes were made <a href="#1c3ff2a877214b76934d3817f24c1318">#</a>
</h3>
<p>
I rarely have reason to believe that co-workers have malign intent. When we are working together towards a common goal, I trust that they have as much interest in reaching that goal as I have.
</p>
<p>
Does that trust mean that everyone is free to do whatever they want? Of course not. Even with the best of intentions, we make mistakes, there are misunderstandings, or we have incomplete information.
</p>
<p>
This is one among several reasons I practice test-driven development (TDD). Writing a test before implementation code catches many mistakes early in the process. In this context, the point is that I don't trust myself to be perfect.
</p>
<p>
Even with TDD and the best of intentions, there are other reasons to look at other people's work.
</p>
<p>
Last year, I did some freelance programming for a customer, and sometimes I would receive feedback that a function I'd included in a pull request already existed in the code base. I didn't have that knowledge, but the review caught it.
</p>
<p>
Could we have caught that with pair or ensemble programming? Yes, that would work too. There's more than one way to make things work, and they tend to be context-dependent.
</p>
<p>
If everyone on a team have the luxury of being able to work together, then pair or ensemble programming is an efficient way to coordinate work. Little extra process may be required, because everyone is already on the same page.
</p>
<p>
If team members are less fortunate, or have different preferences, they may need to rely on the <a href="/2023/02/20/a-thought-on-workplace-flexibility-and-asynchrony">flexibility offered by asynchrony</a>. This doesn't mean that you can't do Continuous Delivery, even with pull requests and code reviews, but <a href="/2020/03/16/conways-law-latency-versus-throughput">the trade-offs are different</a>.
</p>
<h3 id="8cf2f27540de4461826bfe2b9ef88405">
Conclusion <a href="#8cf2f27540de4461826bfe2b9ef88405">#</a>
</h3>
<p>
There are many good reasons to be critical of code reviews, pull requests, and other processes that seem to slow things down. The lack of trust in co-workers is, however, not one of them.
</p>
<p>
You can easily be swayed by that argument because it touches something deep in our psyche. We want to be trusted, and we want to trust our colleagues. We want to <em>belong</em>.
</p>
<p>
The argument is visceral, but it misrepresents the motivation for process. We don't review code because we believe that all co-workers are really North Korean agents looking to sneak in security breaches if we look away.
</p>
<p>
We look at each other's work because it's human to make mistakes. If we can't all be in the same office at the same time, fast but asynchronous reviews also work.
</p>
</div>
<div id="comments">
<hr>
<h2 id="comments-header">
Comments
</h2>
<div class="comment" id="f2faef409ab74134938a6ae77404ec43">
<div class="comment-author"><a href="https://about.me/tysonwilliams">Tyson Williams</a></div>
<div class="comment-content">
<p>
This reminds me of <a href="https://en.wikipedia.org/wiki/Hanlon%27s_razor">Hanlon's razor</a>.
</p>
<blockquote>
Never attribute to malice that which is adequately explained by stupidity.
</blockquote>
</div>
<div class="comment-date">2023-03-23 23:29 UTC</div>
</div>
<div class="comment" id="c46f7f22b22941f6a24858a40093424c">
<div class="comment-author"><a href="mailto:danielfrostdk@outlook.com">Daniel Frost</a></div>
<div class="comment-content">
<p>
Too much technical attibution is still being presented on a whole, into a field which
is far more of a social and psycological construct. What's even worse is the evidence around organisation and team capabilities is pretty clear towards what makes a good team and organisation.
<br><br>
The technical solutions for reaching trust or beloningness is somewhat a menas to an end. They can't stand alone because it only takes two humans to side track them.
<br><br>
therefore I still absolutely believe that the technical parts of software engineering is by far the less demanding. As technical work most often still are done as individual contributions
based on loose requirements, equally loose leadership and often non-existing enforcement from tooling and scattered human ownership. Even worse subjective perceptions.
That I believe on the other hand has everything to do with trust, gatekeeping, belonging and other human psycology needs.
</p>
</div>
<div class="comment-date">2023-03-27 11:29 UTC</div>
</div>
<div class="comment" id="ebc68487f13d470a92260d91a890c5ad">
<div class="comment-author"><a href="https://www.linkedin.com/in/jakub-kwasniewski/">Jakub Kwaśniewski</a></div>
<div class="comment-content">
<p>
I like to look at it from the other side - I ask my colleagues for reviewing my code, because I trust them.
I trust they can help me make it better and it's in all of us interests to make it better - as soon as the code gets in to the main branch, it's not my code anymore - it's teams code.
</p>
<p>
Also, not tightly connected to the topic of code reviews and pull requests, but still about trust in software development, I had this general thought about trusting yourself in software programming:
<em>Don't trust your past self. Do trust your future self.</em><br/>
Don't trust your past self in the meaning: don't hesitate to refactor your code. If you've written the code a while ago, even with the best intentions of making it readable, as you normally have, but now you read it and you don't understand it - don't make too much effort into trying to understand it. If you don't understand it, others won't as well. Rewrite it to make it better.<br/>
Do trust your future self in the meaning: don't try to be smarter than you are now. If you don't know all the requirements or answers to all the questions, don't guess them when you don't have to. Don't create an abstraction from one use case you have - in future you will have more use cases and you will be able to create a better abstraction - trust me, or actually trust yourself. I guess it's just YAGNI rephrased ;)
</p>
</div>
<div class="comment-date">2023-05-16 21:22 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>.Confidence from Facade Testshttps://blog.ploeh.dk/2023/03/13/confidence-from-facade-tests2023-03-13T07:15:00+00:00Mark Seemann
<div id="post">
<p>
<em>Recycling an old neologism of mine, I try to illustrate a point about the epistemology of testing function composition.</em>
</p>
<p>
This article continues the introduction of a series on the <a href="/2023/02/13/epistemology-of-interaction-testing">epistemology of interaction testing</a>. In the first article, I attempted to explain how to test the composition of functions. Despite my best efforts, I felt that that article somehow fell short of its potential. Particularly, I felt that I ought to have been able to provide some illustrations.
</p>
<p>
After publishing the first article, I finally found a way to illustrate what I'd been trying to communicate. That's this article. Better late than never.
</p>
<h3 id="0c1034fd05cb4b14a3e6ed985e98d6a3">
Previously, on epistemology of interaction testing <a href="#0c1034fd05cb4b14a3e6ed985e98d6a3">#</a>
</h3>
<p>
A brief summary of the previous article may be in order. The question this article series tries to address is how to unit test composition of functions - particularly <a href="https://en.wikipedia.org/wiki/Pure_function">pure functions</a>.
</p>
<p>
Consider the illustration from the previous article, repeated here for your convenience:
</p>
<p>
<img src="/content/binary/component-graph.png" alt="Example component graph with four leaves.">
</p>
<p>
When the leaves are pure functions they are <a href="/2015/05/07/functional-design-is-intrinsically-testable">intrinsically testable</a>. That's not the hard part, but how do we test the internal nodes or the root?
</p>
<p>
While most people would reach for <a href="http://xunitpatterns.com/Test%20Stub.html">Stubs</a> and <a href="http://xunitpatterns.com/Test%20Spy.html">Spies</a>, those kinds of <a href="https://martinfowler.com/bliki/TestDouble.html">Test Doubles</a> tend to <a href="/2022/10/17/stubs-and-mocks-break-encapsulation">break encapsulation</a>.
</p>
<p>
What are the alternatives?
</p>
<p>
An alternative I find useful is to test groups of functions composed together. Particularly when they are pure functions, you have no problem with non-deterministic behaviour. On the other hand, this approach seems to run afoul of the problem with combinatorial explosion of integration testing <a href="https://www.infoq.com/presentations/integration-tests-scam/">so eloquently explained by J.B. Rainsberger</a>.
</p>
<p>
What I suggest, however, isn't quite integration testing.
</p>
<h3 id="bec86a649bfb420abbf0a333dd663b57">
Neologism <a href="#bec86a649bfb420abbf0a333dd663b57">#</a>
</h3>
<p>
If it isn't integration testing, then what is it? What do we call it?
</p>
<p>
I'm going to resurrect and recycle an old term of mine: <a href="/2012/06/27/FacadeTest">Facade Tests</a>. Ten years ago I had a more narrow view of a term like 'unit test' than I do today, but the overall idea seems apt in this new context. A Facade Test is a test that exercises a <a href="https://en.wikipedia.org/wiki/Facade_pattern">Facade</a>.
</p>
<p>
These days, I don't find it productive to distinguish narrowly between different kinds of tests. At least not to the the degree that I wish to fight over terminology. On the other hand, occasionally it's useful to have a name for a thing, in order to be able to differentiate it from some other thing.
</p>
<p>
The term <em>Facade Tests</em> is my attempt at a <a href="https://martinfowler.com/bliki/Neologism.html">neologism</a>. I hope it helps.
</p>
<h3 id="11713bd3f4bc48d8a9c82b3f955066ad">
Code coverage as a proxy for confidence <a href="#11713bd3f4bc48d8a9c82b3f955066ad">#</a>
</h3>
<p>
The question I'm trying to address is how to test functions that compose other functions - the internal nodes or the root in the above graph. As I tried to explain in the previous article, you need to build confidence that various parts of the composition work. How do you gain confidence in the leaves?
</p>
<p>
One way is to test each leaf individually.
</p>
<p>
<img src="/content/binary/test-and-leaf-no-test.png" alt="A single leaf node and a test module pointing to it.">
</p>
<p>
The first test or two may exercise a tiny slice of the System Under Test (SUT):
</p>
<p>
<img src="/content/binary/test-and-leaf-one-test.png" alt="A single leaf node with a thin slice of space filled in green, driven by a test.">
</p>
<p>
The next few tests may exercise another part of the SUT:
</p>
<p>
<img src="/content/binary/test-and-leaf-two-tests.png" alt="A single leaf node with two thin slices of space filled in green, driven by tests.">
</p>
<p>
Keep adding more tests:
</p>
<p>
<img src="/content/binary/test-and-leaf-several-tests.png" alt="A single leaf node with a triangle of space filled in green, driven by tests.">
</p>
<p>
Stop when you have good confidence that the SUT works as intended:
</p>
<p>
<img src="/content/binary/test-and-leaf-full-coverage.png" alt="A single leaf node fully filled in green, indicating full code coverage by tests.">
</p>
<p>
If you're now thinking of code coverage, I can't blame you. To be clear, I haven't changed my position about code coverage. <a href="/2015/11/16/code-coverage-is-a-useless-target-measure">Code coverage is a useless target measure</a>. On the other hand, there's no harm in having a high degree of code coverage. It still might give you confidence that the SUT works as intended.
</p>
<p>
You may think of the amount of green in the above diagrams as a proxy for confidence. The more green, the more confident you are in the SUT.
</p>
<p>
None of the arguments here hinge on <em>code coverage</em> per se. What matters is confidence.
</p>
<h3 id="1b6d2872c49c4f22aa3f84e541989be7">
Facade testing confidence <a href="#1b6d2872c49c4f22aa3f84e541989be7">#</a>
</h3>
<p>
With all the leaves covered, you can move on to the internal nodes. This is the actual problem that I'm trying to address. We would like to test an internal node, but it has dependencies. Fortunately, the context of this article is that the dependencies are pure functions, so we don't have a problem with non-deterministic behaviour. No need for Test Doubles.
</p>
<p>
It's really simple, then. Just test the internal node until you're confident that it works:
</p>
<p>
<img src="/content/binary/test-and-internal-node-full-coverage.png" alt="An internal node fully filled in blue, indicating full code coverage by tests. Dependencies are depicted as boxes below the internal node, but with only slivers of coverage.">
</p>
<p>
The goal is to build confidence in the internal node, the new SUT. While it has dependencies, covering those with tests is no longer the goal. This is the key difference between Facade Testing and Integration Testing. You're not trying to cover all combinations of code paths in the integrated set of components. You're still just trying to test the new SUT.
</p>
<p>
Whether or not these tests exercise the leaves is irrelevant. The leaves are already covered by other tests. What 'coverage' you get of the leaves is incidental.
</p>
<p>
Once you've built confidence in internal nodes, you can repeat the process with the root node:
</p>
<p>
<img src="/content/binary/test-and-root-full-coverage.png" alt="A root node fully filled in blue, indicating full code coverage by tests. Dependencies are depicted as trees below the root node, but with only slivers of coverage.">
</p>
<p>
The test covers enough of the root node to give you confidence in it. Some of the dependencies are also partially exercised by the tests, but this is still secondary. The way I've drawn the diagram, the left internal node is exercised in such a way that <em>its</em> dependencies (the leaves) are partially exercised. The test apparently also exercises the right internal node, but none of that activity makes it interact with the leaves.
</p>
<p>
These aren't integration tests, so they avoid the problem of combinatorial explosion.
</p>
<h3 id="8eeade5dc4f0433cbb2506dc50973e48">
Conclusion <a href="#8eeade5dc4f0433cbb2506dc50973e48">#</a>
</h3>
<p>
This article was an attempt to illustrate the prose in the previous article. You can unit test functions that compose other functions by first unit testing the leaf functions and then the compositions. While these tests exercise an 'integration' of components, the purpose is <em>not</em> to test the integration. Thus, they aren't integration tests. They're facade tests.
</p>
<p>
<strong>Next:</strong> <a href="/2023/04/03/an-abstract-example-of-refactoring-from-interaction-based-to-property-based-testing">An abstract example of refactoring from interaction-based to property-based testing</a>.
</p>
</div>
<div id="comments">
<hr>
<h2 id="comments-header">
Comments
</h2>
<div class="comment" id="3d4420c5b9f9425384a480be778993db">
<div class="comment-author"><a href="https://www.relativisticramblings.com/">Christer van der Meeren</a></div>
<div class="comment-content">
<p>I really appreciate that you are writing about testing compositions of pure functions. As an F# dev who tries to adhere to the <a href='https://blog.ploeh.dk/2020/03/02/impureim-sandwich/'>impureim sandwich</a> (which, indeed, you <a href='https://blog.ploeh.dk/2022/02/14/a-conditional-sandwich-example/'>helped me with before</a>), this is something I have also been struggling with, and failing to find good answers to.</p>
<p><strong>But following your suggestion, aren’t we testing implementation details?</strong></p>
<p>Using the terminology in this article, I often have a root function that is public, which composes and delegates work to private helper functions. Compared to having all the logic directly in the root function, the code is, unsurprisingly, easier to read and maintain this way. However, all the private helper functions (internal nodes and leaves) as well as the particularities of how the root and the internal nodes compose their “children”, are very much just implementation details of the root function.</p>
<p>I occasionally need to change such code in a way that does not change the public API (at least not significantly enough to cause excessive test maintenance), but which significantly restructures the internal helpers. If I were to test as suggested in this article, I would have many broken tests on my hands. These would be tests of the internal nodes and leaves (which may not exist at all after the refactor, having been replaced with completely different functions) as well as tests of how the root node composes the other functions (which, presumably, would still pass but may not actually test anything useful anymore).</p>
<p>In short, testing in the way suggested here would act as a force to avoid refactoring, which seems counter-productive.</p>
<p>One would also need to use <code>InternalsVisibleTo</code> or similar in order to test those helpers. I’m not very concerned about that on its own (though I’d like to keep the helpers <code>private</code>), but it always smells of testing implementation details, which, as I argue, is what I think we’re doing. (One could alternatively make the helpers public – they’re pure, after all, so presumably no harm done – but that would expose a public API that no-one should actually use, and doesn’t avoid the main problem anyway.)</p>
<p>As a motivating example from my world, consider a system for sending email notifications. The root function accepts a list of notifications that should be sent, together with any auxiliary data (names and other data from all users referenced by the notifications; translated strings; any environment-specific data such as base URLs for links; etc.), and returns the email HTML (or at least a structure that maps trivially to HTML). In doing this, the code has to group notifications in several levels, sort them in various ways, merge similar consecutive notifications in non-trivial ways, hide notifications that the user has not asked to receive (but which must still be passed to the root function since they are needed for other logic), and so on. All in all, I have almost 600 lines of pure code that does this. (In addition, I have 150 lines that fetches everything from the DB and creates necessary lookup maps of auxiliary data to pass to the root function. I consider this code “too boring to fail”.)</p>
<p>The pure part of the code was recently significantly revamped. Had I had tests for private/internal helpers, the refactor would likely have been much more painful.</p>
<p>I expect there is no perfect way to make the code both testable and easy to refactor. But I am still eager to hear your thoughts on my concern: <strong>Following your suggestion, aren’t we testing implementation details?</strong></p>
</div>
<div class="comment-date">2023-03-13 14:00 UTC</div>
</div>
<div class="comment" id="af0abf6dad214bfbb452488ca09c8a27">
<div class="comment-author"><a href="/">Mark Seemann</a></div>
<div class="comment-content">
<p>
Christer, thank you for writing. The short answer is: <em>yes</em>.
</p>
<p>
Isn't this a separate problem, though? If you're using Stubs and Spies to test interaction, and other tests to verify your implementations, then isn't that a similar problem?
</p>
<p>
I'm going to graze this topic in the future article in this series tentatively titled <em>Refactoring pure function composition without breaking existing tests</em>, but I should probably write another article more specifically about this topic...
</p>
</div>
<div class="comment-date">2023-03-14 9:06 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>.Warnings-as-errors frictionhttps://blog.ploeh.dk/2023/03/06/warnings-as-errors-friction2023-03-06T07:17:00+00:00Mark Seemann
<div id="post">
<p>
<em>TDD friction. Surely that's a bad thing(?)</em>
</p>
<p>
<a href="https://furlough.merecomplexities.com/">Paul Wilson</a> recently wrote on Mastodon:
</p>
<blockquote>
<p>
Software development opinion (warnings as errors)
</p>
<p>
Just seen this via Elixir Radar, <a href="https://curiosum.com/til/warnings-as-errors-elixir-mix-compile">https://curiosum.com/til/warnings-as-errors-elixir-mix-compile</a> on on treating warnings as errors, and yeah don't integrate code with warnings. But ....
</p>
<p>
Having worked on projects with this switched on in dev, it's an annoying bit of friction when Test Driving code. Yes, have it switched on in CI, but don't make me fix all the warnings before I can run my failing test.
</p>
<p>
(Using an env variable for the switch is a good compromise here, imo).
</p>
<footer><cite><a href="https://mastodon.social/@paulwilson/109433259807695275">Paul Wilson</a></cite></footer>
</blockquote>
<p>
This made me reflect on similar experiences I've had. I thought perhaps I should write them down.
</p>
<p>
To be clear, <em>this article is not an attack on Paul Wilson</em>. He's right, but since he got me thinking, I only find it honest and respectful to acknowledge that.
</p>
<p>
The remark does, I think, invite more reflection.
</p>
<h3 id="512ad9e57e7b4c3c849cfc5e78c8b977">
Test friction example <a href="#512ad9e57e7b4c3c849cfc5e78c8b977" title="permalink">#</a>
</h3>
<p>
<a href="http://www.exampler.com/">An example would be handy right about now</a>.
</p>
<p>
As I was writing the example code base for <a href="/2021/06/14/new-book-code-that-fits-in-your-head">Code That Fits in Your Head</a>, I was following the advice of the book:
</p>
<ul>
<li>Turn on <a href="https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-types/nullable-reference-types">Nullable reference types</a> (only relevant for C#)</li>
<li>Turn on static code analysis or <a href="https://en.wikipedia.org/wiki/Lint_(software)">linters</a></li>
<li>Treat warnings as errors. Yes, also the warnings produced by the two above steps</li>
</ul>
<p>
As Paul Wilson points out, this tends to create friction with test-driven development (TDD). When I started the code base, this was the first TDD test I wrote:
</p>
<p>
<pre>[Fact]
<span style="color:blue;">public</span> <span style="color:blue;">async</span> Task PostValidReservation()
{
<span style="color:blue;">var</span> response = <span style="color:blue;">await</span> PostReservation(<span style="color:blue;">new</span> {
date = <span style="color:#a31515;">"2023-03-10 19:00"</span>,
email = <span style="color:#a31515;">"katinka@example.com"</span>,
name = <span style="color:#a31515;">"Katinka Ingabogovinanana"</span>,
quantity = 2 });
Assert.True(
response.IsSuccessStatusCode,
<span style="color:#a31515;">$"Actual status code: </span>{response.StatusCode}<span style="color:#a31515;">."</span>);
}</pre>
</p>
<p>
Looks good so far, doesn't it? Are any of the warnings-as-errors settings causing friction? Not directly, but now regard the <code>PostReservation</code> helper method:
</p>
<p>
<pre>[SuppressMessage(
<span style="color:#a31515;">"Usage"</span>,
<span style="color:#a31515;">"CA2234:Pass system uri objects instead of strings"</span>,
Justification = <span style="color:#a31515;">"URL isn't passed as variable, but as literal."</span>)]
<span style="color:blue;">private</span> <span style="color:blue;">async</span> Task<HttpResponseMessage> PostReservation(
<span style="color:blue;">object</span> reservation)
{
<span style="color:blue;">using</span> <span style="color:blue;">var</span> factory = <span style="color:blue;">new</span> WebApplicationFactory<Startup>();
<span style="color:blue;">var</span> client = factory.CreateClient();
<span style="color:blue;">string</span> json = JsonSerializer.Serialize(reservation);
<span style="color:blue;">using</span> <span style="color:blue;">var</span> content = <span style="color:blue;">new</span> StringContent(json);
content.Headers.ContentType.MediaType = <span style="color:#a31515;">"application/json"</span>;
<span style="color:blue;">return</span> <span style="color:blue;">await</span> client.PostAsync(<span style="color:#a31515;">"reservations"</span>, content);
}</pre>
</p>
<p>
Notice the <code>[SuppressMessage]</code> attribute. Without it, the compiler emits this error:
</p>
<blockquote>
error CA2234: Modify 'ReservationsTests.PostReservation(object)' to call 'HttpClient.PostAsync(Uri, HttpContent)' instead of 'HttpClient.PostAsync(string, HttpContent)'.
</blockquote>
<p>
That's an example of friction in TDD. I could have fixed the problem by changing the last line to:
</p>
<p>
<pre><span style="color:blue;">return</span> <span style="color:blue;">await</span> client.PostAsync(<span style="color:blue;">new</span> Uri(<span style="color:#a31515;">"reservations"</span>, UriKind.Relative), content);</pre>
</p>
<p>
This makes the actual code more obscure, which is the reason I didn't like that option. Instead, I chose to add the <code>[SuppressMessage]</code> attribute and write a <code>Justification</code>. It is, perhaps, not much of an explanation, but my position is that, in general, I consider <a href="https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2234">CA2234</a> a good and proper rule. It's a specific example of favouring stronger types over <a href="https://blog.codinghorror.com/new-programming-jargon/">stringly typed code</a>. I'm <a href="/2015/01/19/from-primitive-obsession-to-domain-modelling">all for it</a>.
</p>
<p>
If you <a href="/ref/stranger-in-a-strange-land">grok</a> the motivation for the rule (which, evidently, the <a href="https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2234">documentation</a> code-example writer didn't) you also know when to safely ignore it. Types are useful because they enable you to encapsulate knowledge and guarantees about data in a way that strings and ints typically don't. Indeed, if you are passing URLs around, pass them around as <a href="https://learn.microsoft.com/dotnet/api/system.uri">Uri</a> objects rather than strings. This prevents simple bugs, such as accidentally swapping the place of two variables because they're both strings.
</p>
<p>
In the above example, however, a URL isn't being passed around as a variable. <em>The value is hard-coded right there in the code.</em> Wrapping it in a <code>Uri</code> object doesn't change that.
</p>
<p>
But I digress...
</p>
<p>
This is an example of friction in TDD. Instead of being able to just plough through, I had to stop and deal with a Code Analysis rule.
</p>
<h3 id="3265182ae4114b9da00d91fe0763f36e">
SUT friction example <a href="#3265182ae4114b9da00d91fe0763f36e" title="permalink">#</a>
</h3>
<p>
But wait! There's more.
</p>
<p>
To pass the test, I had to add this class:
</p>
<p>
<pre> [Route(<span style="color:#a31515;">"[controller]"</span>)]
<span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">ReservationsController</span>
{
<span style="color:gray;">#pragma</span> <span style="color:gray;">warning</span> <span style="color:gray;">disable</span> CA1822 <span style="color:green;">// Mark members as static</span>
<span style="color:blue;">public</span> <span style="color:blue;">void</span> Post() { }
<span style="color:gray;">#pragma</span> <span style="color:gray;">warning</span> <span style="color:gray;">restore</span> CA1822 <span style="color:green;">// Mark members as static</span>
}</pre>
</p>
<p>
I had to suppress <a href="https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1822">CA1822</a> as well, because it generated this error:
</p>
<blockquote>
error CA1822: Member Post does not access instance data and can be marked as static (Shared in VisualBasic)
</blockquote>
<p>
Keep in mind that because of my settings, it's an <em>error</em>. The code doesn't compile.
</p>
<p>
You can try to fix it by making the method <code>static</code>, but this then triggers another error:
</p>
<blockquote>
error CA1052: Type 'ReservationsController' is a static holder type but is neither static nor NotInheritable
</blockquote>
<p>
In other words, the class should be static as well:
</p>
<p>
<pre>[Route(<span style="color:#a31515;">"[controller]"</span>)]
<span style="color:blue;">public</span> <span style="color:blue;">static</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">ReservationsController</span>
{
<span style="color:blue;">public</span> <span style="color:blue;">static</span> <span style="color:blue;">void</span> Post() { }
}</pre>
</p>
<p>
This compiles. What's not to like? Those Code Analysis rules are there for a reason, aren't they? Yes, but they are general rules that can't predict every corner case. While the code compiles, the test fails.
</p>
<p>
Out of the box, that's just not how that version of ASP.NET works. The MVC model of ASP.NET expects <em>action methods</em> to be instance members.
</p>
<p>
(I'm sure that there's a way to tweak ASP.NET so that it allows static HTTP handlers as well, but I wasn't interested in researching that option. After all, the above code only represents an interim stage during a longer TDD session. Subsequent tests would prompt me to give the <code>Post</code> method some proper behaviour that would make it an instance method anyway.)
</p>
<p>
So I kept the method as an instance method and suppressed the Code Analysis rule.
</p>
<p>
Friction? Demonstrably.
</p>
<h3 id="06c8473479aa404486a88a99fd90cea9">
Opt in <a href="#06c8473479aa404486a88a99fd90cea9" title="permalink">#</a>
</h3>
<p>
Is there a way to avoid the friction? Paul Wilson mentions a couple of options: Using an environment variable, or only turning warnings into errors in your deployment pipeline. A variation on using an environment variable is to only turn on errors for Release builds (for languages where that distinction exists).
</p>
<p>
In general, if you have a useful tool that unfortunately takes a long time to run, making it a scheduled or opt-in tool may be the way to go. A <a href="https://en.wikipedia.org/wiki/Mutation_testing">mutation testing</a> tool like <a href="https://stryker-mutator.io/">Stryker</a> can easily run for hours, so it's not something you want to do for every change you make.
</p>
<p>
Another example is dependency analysis. One of my recent clients had a tool that scanned their code dependencies (NuGet, npm) for versions with known vulnerabilities. This tool would also take its time before delivering a verdict.
</p>
<p>
Making tools opt-in is definitely an option.
</p>
<p>
You may be concerned that this requires discipline that perhaps not all developers have. If a tool is opt-in, will anyone remember to run it?
</p>
<p>
As I also describe in <a href="/code-that-fits-in-your-head">Code That Fits in Your Head</a>, you could address that issue with a checklist.
</p>
<p>
Yeah, but <em>do we then need a checklist to remind us to look at the checklist?</em> Right, <a href="https://en.wikipedia.org/wiki/Quis_custodiet_ipsos_custodes%3F">quis custodiet ipsos custodes?</a> Is it going to be <a href="https://en.wikipedia.org/wiki/Turtles_all_the_way_down">turtles all the way down</a>?
</p>
<p>
Well, if no-one in your organisation can be trusted to follow <em>any</em> commonly-agreed-on rules on a regular basis, you're in trouble anyway.
</p>
<h3 id="cad76f35e04f46b9b2703759c03aa3eb">
Good friction? <a href="#cad76f35e04f46b9b2703759c03aa3eb" title="permalink">#</a>
</h3>
<p>
So far, I've spent some time describing the problem. When encountering resistance your natural reaction is to find it disagreeable. You want to accomplish something, and then this rule/technique/tool gets in the way!
</p>
<p>
Despite this, is it possible that this particular kind of friction is beneficial?
</p>
<p>
By (subconsciously, I'm sure) picking a word like 'friction', you've already chosen sides. That word, in general, has a negative connotation. Is it the only word that describes the situation? What if we talked about it instead in terms of safety, assistance, or predictability?
</p>
<p>
Ironically, <em>friction</em> was a main complaint about TDD when it was first introduced.
</p>
<p>
<em>"What do you mean? I have to write a test</em> before <em>I write the implementation? That's going to slow me down!"</em>
</p>
<p>
The TDD and agile movement developed a whole set of standard responses to such objections. <em>Brakes enable you to go faster. If it hurts, do it more often.</em>
</p>
<p>
Try those on for size, only now applied to warnings as errors. Friction is what makes brakes work.
</p>
<h3 id="456884d28f9b484f961f0b142993e042">
Additive mindset <a href="#456884d28f9b484f961f0b142993e042" title="permalink">#</a>
</h3>
<p>
As I age, I'm becoming increasingly aware of a tendency in the software industry. Let's call it the <em>additive mindset</em>.
</p>
<p>
It's a reflex to consider <em>addition</em> a good thing. An API with a wide array of options is better than a narrow API. Software with more features is better than software with few features. More log data provides better insight.
</p>
<p>
More code is better than less code.
</p>
<p>
Obviously, that's not true, but we. keep. behaving as though it is. Just look at the recent hubbub about <a href="https://openai.com/blog/chatgpt/">ChatGPT</a>, or <a href="https://github.com/features/copilot">GitHub Copilot</a>, which I <a href="/2022/12/05/github-copilot-preliminary-experience-report">recently wrote about</a>. Everyone reflexively view them as productivity tools because the can help us produce more code faster.
</p>
<p>
I had a cup of coffee with my wife as I took a break from writing this article, and I told her about it. Her immediate reaction when told about friction is that it's a benefit. She's a doctor, and naturally view procedure, practice, regulation, etcetera as occasionally annoying, but essential to the practice of medicine. Without procedures, patients would die from preventable mistakes and doctors would prescribe morphine to themselves. Checking boxes and signing off on decisions slow you down, and that's half the point. Making you slow down can give you the opportunity to realise that you're about to do something stupid.
</p>
<blockquote>
<p>
Worried that TDD will slow down your programmers? Don't. They probably need slowing down.
</p>
<footer><cite><a href="https://twitter.com/jbrains/status/167297606698008576">J. B. Rainsberger</a></cite></footer>
</blockquote>
<p>
But if TDD is already being touted as a process to make us slow down and think, is it a good idea, then, to slow down TDD with warnings as errors? Are we not interfering with a beneficial and essential process?
</p>
<h3 id="efed5514b66e4da5ab36690d3288ca84">
Alternatives to TDD <a href="#efed5514b66e4da5ab36690d3288ca84" title="permalink">#</a>
</h3>
<p>
I don't have a confident answer to that question. What follows is tentative. I've been doing TDD since 2003 and while I was also an <a href="/2010/12/22/TheTDDApostate">early critic</a>, it's still central to how I write code.
</p>
<p>
When I began doing TDD with all the errors <a href="https://en.wikipedia.org/wiki/Up_to_eleven">dialled to 11</a> I was concerned about the friction, too. While I also believe in linters, the two seem to work at cross purposes. The rule about static members in the above example seems clearly counterproductive. After all, a few commits later I'd written enough code for the <code>Post</code> method that it <em>had</em> to be an instance method after all. The degenerate state was temporary, an artefact of the TDD process, but the rule triggered anyway.
</p>
<p>
What should I think of that?
</p>
<p>
I don't <em>like</em> having to deal with such <a href="https://en.wikipedia.org/wiki/False_positives_and_false_negatives">false positives</a>. The question is whether treating warnings as errors is a net positive or a net negative?
</p>
<p>
It may help to recall why TDD is a useful practice. A major reason is that it provides rapid feedback. There are, however, <a href="/2011/04/29/Feedbackmechanismsandtradeoffs">other ways to produce rapid feedback</a>. Static types, compiler warnings, and static code analysis are other ways.
</p>
<p>
I don't think of these as alternatives to TDD, but rather as complementary. Tests can produce feedback about some implementation details. <a href="https://www.hillelwayne.com/post/constructive/">Constructive data</a> is another option. Compiler warnings and linters enter that mix as well.
</p>
<p>
Here I again speak with some hesitation, but it looks to me as though the TDD practice originated in dynamically typed tradition (<a href="https://en.wikipedia.org/wiki/Smalltalk">Smalltalk</a>), and even though some Java programmers were early adopters as well, from my perspective it's always looked stronger among the dynamic languages than the compiled languages. The unadulterated TDD tradition still seems to largely ignore the existence of other forms of feedback. Everything must be tested.
</p>
<p>
At the risk of repeating myself, I find TDD invaluable, but I'm happy to receive rapid feedback from heterogeneous sources: Tests, type checkers, compilers, linters, fellow ensemble programmers.
</p>
<p>
This suggests that TDD isn't the only game in town. This may also imply that the friction to TDD caused by treating warnings as errors may not be as costly as first perceived. After all, slowing down something that you rely on 75% of the time isn't quite as bad as slowing down something you rely on 100% of the time.
</p>
<p>
While it's a cost, perhaps it went down...
</p>
<h3 id="235a1aa10437465b945242f8b6a29873">
Simplicity <a href="#235a1aa10437465b945242f8b6a29873" title="permalink">#</a>
</h3>
<p>
As always, circumstances matter. Is it always a good idea to treat warnings as errors?
</p>
<p>
Not really. To be honest, treating warnings as errors is another case of treating a symptom. The reason I recommend it is that I've seen enough code bases where compiler warnings (not errors) have accumulated. In a setting where that happens, treating (new) warnings as errors can help get the situation under control.
</p>
<p>
When I work alone, I don't allow warnings to build up. I rarely tell the compiler to treat warnings as errors in my personal code bases. There's no need. I have zero tolerance for compiler warnings, and I do spot them.
</p>
<p>
If you have a team that never allows compiler warnings to accumulate, is there any reason to treat them as errors? Probably not.
</p>
<p>
This underlines an important point about productivity: A good team without strict process can outperform a poor team with a clearly defined process. Mindset beats tooling. Sometimes.
</p>
<p>
Which mindset is that? Not the additive mindset. Rather, I believe in focusing on simplicity. The alternative to adding things isn't to blindly remove things. You can't add features to a program <em>only</em> by deleting code. Rather, add code, but keep it simple. <a href="/2022/11/21/decouple-to-delete">Decouple to delete</a>.
</p>
<blockquote>
<p>
perfection is attained not when there is nothing more to add, but when there is nothing more to remove.
</p>
<footer><cite>Antoine de Saint Exupéry, <a href="/ref/wind-sand-stars">Wind, Sand And Stars</a></cite></footer>
</blockquote>
<p>
Simple code. Simple tests. Be warned, however, that code simplicity does not imply naive code understandable by everyone. I'll refer you to <a href="https://en.wikipedia.org/wiki/Rich_Hickey">Rich Hickey</a>'s wonderful talk <a href="https://www.infoq.com/presentations/Simple-Made-Easy/">Simple Made Easy</a> and remind you that this was the line of thinking that lead to <a href="https://clojure.org/">Clojure</a>.
</p>
<p>
Along the same lines, I tend to consider <a href="https://www.haskell.org/">Haskell</a> to be a vehicle for expressing my thoughts in a <em>simpler</em> way than I can do in <a href="https://fsharp.org/">F#</a>, which again enables simplicity not available in C#. Simpler, not easier.
</p>
<h3 id="eb224aa293984475bf9b105e191b362c">
Conclusion <a href="#eb224aa293984475bf9b105e191b362c" title="permalink">#</a>
</h3>
<p>
Does treating warnings as errors imply TDD friction? It certainly looks that way.
</p>
<p>
Is it worth it, nonetheless? Possibly. It depends on why you need to turn warnings into errors in the first place. In some settings, the benefits of treating warnings as errors may be greater than the cost. If that's the only way you can keep compiler warnings down, then do treat warnings as errors. Such a situation, however, is likely to be a symptom of a more fundamental mindset problem.
</p>
<p>
This almost sounds like a moral judgement, I realise, but that's not my intent. Mindset is shaped by personal preference, but also by organisational and peer pressure, as well as knowledge. If you only know of one way to achieve a goal, you have no choice. Only if you know of more than one way can you choose.
</p>
<p>
Choose the way that leaves the code simpler than the other.
</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>.Test Data Generator monadhttps://blog.ploeh.dk/2023/02/27/test-data-generator-monad2023-02-27T07:10:00+00:00Mark Seemann
<div id="post">
<p>
<em>With examples in C# and F#.</em>
</p>
<p>
This article is an instalment in <a href="/2022/03/28/monads">an article series about monads</a>. In other related series previous articles described <a href="/2017/09/18/the-test-data-generator-functor">Test Data Generator as a functor</a>, as well as <a href="/2018/11/26/the-test-data-generator-applicative-functor">Test Data Generator as an applicative functor</a>. As is the case with many (but not all) <a href="/2018/03/22/functors">functors</a>, this one also forms a monad.
</p>
<p>
This article expands on the code from the above-mentioned articles about Test Data Generators. Keep in mind that the code is a simplified version of what you'll find in a real property-based testing framework. It lacks shrinking and referentially transparent (pseudo-)random value generation. Probably more things than that, too.
</p>
<h3 id="0855f8f4840c4efc96f102e3913e7357">
SelectMany <a href="#0855f8f4840c4efc96f102e3913e7357">#</a>
</h3>
<p>
A monad must define either a <em>bind</em> or <em>join</em> function. In C#, monadic bind is called <code>SelectMany</code>. For the <code><span style="color:#2b91af;">Generator</span><<span style="color:#2b91af;">T</span>></code> class, you can implement it as an instance method like this:
</p>
<p>
<pre><span style="color:blue;">public</span> Generator<TResult> <span style="font-weight:bold;color:#74531f;">SelectMany</span><<span style="color:#2b91af;">TResult</span>>(Func<T, Generator<TResult>> <span style="font-weight:bold;color:#1f377f;">selector</span>)
{
Func<Random, TResult> <span style="font-weight:bold;color:#1f377f;">newGenerator</span> = <span style="font-weight:bold;color:#1f377f;">r</span> =>
{
Generator<TResult> <span style="font-weight:bold;color:#1f377f;">g</span> = selector(generate(r));
<span style="font-weight:bold;color:#8f08c4;">return</span> g.Generate(r);
};
<span style="font-weight:bold;color:#8f08c4;">return</span> <span style="color:blue;">new</span> Generator<TResult>(newGenerator);
}</pre>
</p>
<p>
<code>SelectMany</code> enables you to chain generators together. You'll see an example later in the article.
</p>
<h3 id="36a3fb07ddc9428cb334939251deea36">
Query syntax <a href="#36a3fb07ddc9428cb334939251deea36">#</a>
</h3>
<p>
As the <a href="/2022/03/28/monads">monad article</a> explains, you can enable C# query syntax by adding a special <code>SelectMany</code> overload:
</p>
<p>
<pre><span style="color:blue;">public</span> Generator<TResult> <span style="font-weight:bold;color:#74531f;">SelectMany</span><<span style="color:#2b91af;">U</span>, <span style="color:#2b91af;">TResult</span>>(
Func<T, Generator<U>> <span style="font-weight:bold;color:#1f377f;">k</span>,
Func<T, U, TResult> <span style="font-weight:bold;color:#1f377f;">s</span>)
{
<span style="font-weight:bold;color:#8f08c4;">return</span> SelectMany(<span style="font-weight:bold;color:#1f377f;">x</span> => k(x).Select(<span style="font-weight:bold;color:#1f377f;">y</span> => s(x, y)));
}</pre>
</p>
<p>
The implementation body always looks the same; only the method signature varies from monad to monad. Again, I'll show you an example of using query syntax later in the article.
</p>
<h3 id="3486b1debaf34921b03fd307d03fadce">
Flatten <a href="#3486b1debaf34921b03fd307d03fadce">#</a>
</h3>
<p>
In <a href="/2022/03/28/monads">the introduction</a> you learned that if you have a <code>Flatten</code> or <code>Join</code> function, you can implement <code>SelectMany</code>, and the other way around. Since we've already defined <code>SelectMany</code> for <code><span style="color:#2b91af;">Generator</span><<span style="color:#2b91af;">T</span>></code>, we can use that to implement <code>Flatten</code>. In this article I use the name <code>Flatten</code> rather than <code>Join</code>. This is an arbitrary choice that doesn't impact behaviour. Perhaps you find it confusing that I'm inconsistent, but I do it in order to demonstrate that the behaviour is the same even if the name is different.
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> Generator<T> <span style="color:#74531f;">Flatten</span><<span style="color:#2b91af;">T</span>>(<span style="color:blue;">this</span> Generator<Generator<T>> <span style="font-weight:bold;color:#1f377f;">generator</span>)
{
<span style="font-weight:bold;color:#8f08c4;">return</span> generator.SelectMany(<span style="font-weight:bold;color:#1f377f;">x</span> => x);
}</pre>
</p>
<p>
As you can tell, this function has to be an extension method, since we can't have a class typed <code>Generator<Generator<T>></code>. As usual, when you already have <code>SelectMany</code>, the body of <code>Flatten</code> (or <code>Join</code>) is always the same.
</p>
<h3 id="347da42ffc7a4c8296743de68cf6a622">
Return <a href="#347da42ffc7a4c8296743de68cf6a622">#</a>
</h3>
<p>
Apart from monadic bind, a monad must also define a way to put a normal value into the monad. Conceptually, I call this function <em>return</em> (because that's the name that <a href="https://www.haskell.org/">Haskell</a> uses):
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> Generator<T> <span style="color:#74531f;">Return</span><<span style="color:#2b91af;">T</span>>(T <span style="font-weight:bold;color:#1f377f;">value</span>)
{
<span style="font-weight:bold;color:#8f08c4;">return</span> <span style="color:blue;">new</span> Generator<T>(<span style="font-weight:bold;color:#1f377f;">_</span> => value);
}</pre>
</p>
<p>
This function ignores the random number generator and always returns <code>value</code>.
</p>
<h3 id="60fdd02680034ebe8ec21cff4fdb47e6">
Left identity <a href="#60fdd02680034ebe8ec21cff4fdb47e6">#</a>
</h3>
<p>
We needed to identify the <em>return</em> function in order to examine <a href="/2022/04/11/monad-laws">the monad laws</a>. Let's see what they look like for the Test Data Generator monad, starting with the left identity law.
</p>
<p>
<pre>[Theory]
[InlineData(17, 0)]
[InlineData(17, 8)]
[InlineData(42, 0)]
[InlineData(42, 1)]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> <span style="font-weight:bold;color:#74531f;">LeftIdentityLaw</span>(<span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">x</span>, <span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">seed</span>)
{
Func<<span style="color:blue;">int</span>, Generator<<span style="color:blue;">string</span>>> <span style="font-weight:bold;color:#1f377f;">h</span> = <span style="font-weight:bold;color:#1f377f;">i</span> => <span style="color:blue;">new</span> Generator<<span style="color:blue;">string</span>>(<span style="font-weight:bold;color:#1f377f;">r</span> => r.Next(i).ToString());
Assert.Equal(
Generator.Return(x).SelectMany(h).Generate(<span style="color:blue;">new</span> Random(seed)),
h(x).Generate(<span style="color:blue;">new</span> Random(seed)));
}</pre>
</p>
<p>
Notice that the test can't directly compare the two generators, because equality isn't clearly defined for that class. Instead, the test has to call <code>Generate</code> in order to produce comparable values; in this case, strings.
</p>
<p>
Since <code>Generate</code> is non-deterministic, the test has to <code>seed</code> the random number generator argument in order to get reproducible results. It can't even declare one <code>Random</code> object and share it across both method calls, since generating values changes the state of the object. Instead, the test has to generate two separate <code>Random</code> objects, one for each call to <code>Generate</code>, but with the same <code>seed</code>.
</p>
<h3 id="eed0615f4fce4cd79ecc57a734a358ea">
Right identity <a href="#eed0615f4fce4cd79ecc57a734a358ea">#</a>
</h3>
<p>
In a manner similar to above, we can showcase the right identity law as a test.
</p>
<p>
<pre>[Theory]
[InlineData(<span style="color:#a31515;">'a'</span>, 0)]
[InlineData(<span style="color:#a31515;">'a'</span>, 8)]
[InlineData(<span style="color:#a31515;">'j'</span>, 0)]
[InlineData(<span style="color:#a31515;">'j'</span>, 5)]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> <span style="font-weight:bold;color:#74531f;">RightIdentityLaw</span>(<span style="color:blue;">char</span> <span style="font-weight:bold;color:#1f377f;">letter</span>, <span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">seed</span>)
{
Func<<span style="color:blue;">char</span>, Generator<<span style="color:blue;">string</span>>> <span style="font-weight:bold;color:#1f377f;">f</span> = <span style="font-weight:bold;color:#1f377f;">c</span> => <span style="color:blue;">new</span> Generator<<span style="color:blue;">string</span>>(<span style="font-weight:bold;color:#1f377f;">r</span> => <span style="color:blue;">new</span> <span style="color:blue;">string</span>(c, r.Next(100)));
Generator<<span style="color:blue;">string</span>> <span style="font-weight:bold;color:#1f377f;">m</span> = f(letter);
Assert.Equal(
m.SelectMany(Generator.Return).Generate(<span style="color:blue;">new</span> Random(seed)),
m.Generate(<span style="color:blue;">new</span> Random(seed)));
}</pre>
</p>
<p>
As always, even a parametrised test constitutes no <em>proof</em> that the law holds. I show the tests to illustrate what the laws look like in 'real' code.
</p>
<h3 id="bca718938dd84e3f9d650e42094768f9">
Associativity <a href="#bca718938dd84e3f9d650e42094768f9">#</a>
</h3>
<p>
The last monad law is the associativity law that describes how (at least) three functions compose. We're going to need three functions. For the demonstration test I'm going to conjure three nonsense functions. While this may not be as intuitive, it on the other hand reduces the noise that more realistic code tends to produce. Later in the article you'll see a more realistic example.
</p>
<p>
<pre>[Theory]
[InlineData(<span style="color:#a31515;">'t'</span>, 0)]
[InlineData(<span style="color:#a31515;">'t'</span>, 28)]
[InlineData(<span style="color:#a31515;">'u'</span>, 0)]
[InlineData(<span style="color:#a31515;">'u'</span>, 98)]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> <span style="font-weight:bold;color:#74531f;">AssociativityLaw</span>(<span style="color:blue;">char</span> <span style="font-weight:bold;color:#1f377f;">a</span>, <span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">seed</span>)
{
Func<<span style="color:blue;">char</span>, Generator<<span style="color:blue;">string</span>>> <span style="font-weight:bold;color:#1f377f;">f</span> = <span style="font-weight:bold;color:#1f377f;">c</span> => <span style="color:blue;">new</span> Generator<<span style="color:blue;">string</span>>(<span style="font-weight:bold;color:#1f377f;">r</span> => <span style="color:blue;">new</span> <span style="color:blue;">string</span>(c, r.Next(100)));
Func<<span style="color:blue;">string</span>, Generator<<span style="color:blue;">int</span>>> <span style="font-weight:bold;color:#1f377f;">g</span> = <span style="font-weight:bold;color:#1f377f;">s</span> => <span style="color:blue;">new</span> Generator<<span style="color:blue;">int</span>>(<span style="font-weight:bold;color:#1f377f;">r</span> => r.Next(s.Length));
Func<<span style="color:blue;">int</span>, Generator<TimeSpan>> <span style="font-weight:bold;color:#1f377f;">h</span> =
<span style="font-weight:bold;color:#1f377f;">i</span> => <span style="color:blue;">new</span> Generator<TimeSpan>(<span style="font-weight:bold;color:#1f377f;">r</span> => TimeSpan.FromDays(r.Next(i)));
Generator<<span style="color:blue;">string</span>> <span style="font-weight:bold;color:#1f377f;">m</span> = f(a);
Assert.Equal(
m.SelectMany(g).SelectMany(h).Generate(<span style="color:blue;">new</span> Random(seed)),
m.SelectMany(<span style="font-weight:bold;color:#1f377f;">x</span> => g(x).SelectMany(h)).Generate(<span style="color:blue;">new</span> Random(seed)));
}</pre>
</p>
<p>
All tests pass.
</p>
<h3 id="3bcc2327700747008fbc5b00865fffc3">
CPR example <a href="#3bcc2327700747008fbc5b00865fffc3">#</a>
</h3>
<p>
Formalities out of the way, let's look at a more realistic example. In the article about the <a href="/2018/11/26/the-test-data-generator-applicative-functor">Test Data Generator applicative functor</a> you saw an example of parsing a <a href="https://en.wikipedia.org/wiki/Personal_identification_number_(Denmark)">Danish personal identification number</a>, in Danish called <em>CPR-nummer</em> (<em>CPR number</em>) for <em>Central Person Register</em>. (It's not a register of central persons, but rather the central register of persons. Danish works slightly differently than English.)
</p>
<p>
CPR numbers have a simple format: <code>DDMMYY-SSSS</code>, where the first six digits indicate a person's birth date, and the last four digits are a sequence number. An example could be <code>010203-1234</code>, which indicates a woman born February 1, 1903.
</p>
<p>
In C# you might model a CPR number as a class with a constructor like this:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:#2b91af;">CprNumber</span>(<span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">day</span>, <span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">month</span>, <span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">year</span>, <span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">sequenceNumber</span>)
{
<span style="font-weight:bold;color:#8f08c4;">if</span> (year < 0 || 99 < year)
<span style="font-weight:bold;color:#8f08c4;">throw</span> <span style="color:blue;">new</span> ArgumentOutOfRangeException(
nameof(year),
<span style="color:#a31515;">"Year must be between 0 and 99, inclusive."</span>);
<span style="font-weight:bold;color:#8f08c4;">if</span> (month < 1 || 12 < month)
<span style="font-weight:bold;color:#8f08c4;">throw</span> <span style="color:blue;">new</span> ArgumentOutOfRangeException(
nameof(month),
<span style="color:#a31515;">"Month must be between 1 and 12, inclusive."</span>);
<span style="font-weight:bold;color:#8f08c4;">if</span> (sequenceNumber < 0 || 9999 < sequenceNumber)
<span style="font-weight:bold;color:#8f08c4;">throw</span> <span style="color:blue;">new</span> ArgumentOutOfRangeException(
nameof(sequenceNumber),
<span style="color:#a31515;">"Sequence number must be between 0 and 9999, inclusive."</span>);
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">fourDigitYear</span> = CalculateFourDigitYear(year, sequenceNumber);
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">daysInMonth</span> = DateTime.DaysInMonth(fourDigitYear, month);
<span style="font-weight:bold;color:#8f08c4;">if</span> (day < 1 || daysInMonth < day)
<span style="font-weight:bold;color:#8f08c4;">throw</span> <span style="color:blue;">new</span> ArgumentOutOfRangeException(
nameof(day),
<span style="color:#a31515;">$"Day must be between 1 and </span>{daysInMonth}<span style="color:#a31515;">, inclusive."</span>);
<span style="color:blue;">this</span>.day = day;
<span style="color:blue;">this</span>.month = month;
<span style="color:blue;">this</span>.year = year;
<span style="color:blue;">this</span>.sequenceNumber = sequenceNumber;
}</pre>
</p>
<p>
The system has been around since 1968 so clearly suffers from a <a href="https://en.wikipedia.org/wiki/Year_2000_problem">Y2k problem</a>, as years are encoded with only two digits. The workaround for this is that the most significant digit of the sequence number encodes the century. At the time I'm writing this, <a href="https://da.wikipedia.org/wiki/CPR-nummer">the Danish-language wikipedia entry for CPR-nummer</a> still includes a table that shows how one can derive the century from the sequence number. This enables the CPR system to handle birth dates between 1858 and 2057.
</p>
<p>
The <code>CprNumber</code> constructor has to consult that table in order to determine the century. It uses the <code>CalculateFourDigitYear</code> function for that. Once it has the four-digit year, it can use the <a href="https://learn.microsoft.com/dotnet/api/system.datetime.daysinmonth">DateTime.DaysInMonth</a> method to determine the number of days in the given month. This is used to validate the day parameter.
</p>
<p>
The <a href="/2018/11/26/the-test-data-generator-applicative-functor">previous article</a> showed a test that made use of a Test Data Generator for the <code>CprNumber</code> class. The generator was referenced as <code>Gen.CprNumber</code>, but how do you define such a generator?
</p>
<h3 id="02e0bc1c345c4c2b910abd5fa338b30c">
CPR number generator <a href="#02e0bc1c345c4c2b910abd5fa338b30c">#</a>
</h3>
<p>
The constructor arguments for <code>month</code>, <code>year</code>, and <code>sequenceNumber</code> are easy to generate. You need a basic generator that produces values between two boundaries. Both <a href="https://en.wikipedia.org/wiki/QuickCheck">QuickCheck</a> and <a href="https://fscheck.github.io/FsCheck">FsCheck</a> call it <code>choose</code>, so I'll reuse that name:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> Generator<<span style="color:blue;">int</span>> <span style="color:#74531f;">Choose</span>(<span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">min</span>, <span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">max</span>)
{
<span style="font-weight:bold;color:#8f08c4;">return</span> <span style="color:blue;">new</span> Generator<<span style="color:blue;">int</span>>(<span style="font-weight:bold;color:#1f377f;">r</span> => r.Next(min, max + 1));
}</pre>
</p>
<p>
The <code>choose</code> functions of QuickCheck and FsCheck consider both boundaries to be inclusive, so I've done the same. That explains the <code>+ 1</code>, since <a href="https://learn.microsoft.com/dotnet/api/system.random.next">Random.Next</a> excludes the upper boundary.
</p>
<p>
You can now combine <code>choose</code> with <code>DateTime.DaysInMonth</code> to generate a valid day:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> Generator<<span style="color:blue;">int</span>> <span style="color:#74531f;">Day</span>(<span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">year</span>, <span style="color:blue;">int</span> <span style="font-weight:bold;color:#1f377f;">month</span>)
{
<span style="color:blue;">var</span> <span style="font-weight:bold;color:#1f377f;">daysInMonth</span> = DateTime.DaysInMonth(year, month);
<span style="font-weight:bold;color:#8f08c4;">return</span> Gen.Choose(1, daysInMonth);
}</pre>
</p>
<p>
Let's pause and consider the implications. The point of this example is to demonstrate why it's practically useful that Test Data Generators are monads. Keep in mind that monads are functors you can flatten. When do you need to flatten a functor? Specifically, when do you need to flatten a Test Data Generator? Right now, as it turns out.
</p>
<p>
The <code>Day</code> method returns a <code>Generator<<span style="color:blue;">int</span>></code>, but where do the <code>year</code> and <code>month</code> arguments come from? They'll typically be produced by another Test Data Generator such as <code>choose</code>. Thus, if you only <em>map</em> (<code>Select</code>) over previous Test Data Generators, you'll produce a <code>Generator<Generator<<span style="color:blue;">int</span>>></code>:
</p>
<p>
<pre>Generator<<span style="color:blue;">int</span>> <span style="font-weight:bold;color:#1f377f;">genYear</span> = Gen.Choose(1970, 2050);
Generator<<span style="color:blue;">int</span>> <span style="font-weight:bold;color:#1f377f;">genMonth</span> = Gen.Choose(1, 12);
Generator<(<span style="color:blue;">int</span>, <span style="color:blue;">int</span>)> <span style="font-weight:bold;color:#1f377f;">genYearAndMonth</span> = genYear.Apply(genMonth);
Generator<Generator<<span style="color:blue;">int</span>>> <span style="font-weight:bold;color:#1f377f;">genDay</span> =
genYearAndMonth.Select(<span style="font-weight:bold;color:#1f377f;">t</span> => Gen.Choose(1, DateTime.DaysInMonth(t.Item1, t.Item2)));</pre>
</p>
<p>
This example uses an <code>Apply</code> overload to combine <code>genYear</code> and <code>genMonth</code>. As long as the two generators are independent of each other, you can use the <a href="/2018/10/01/applicative-functors">applicative functor</a> capability to combine them. When, however, you need to produce a new generator from a value produced by a previous generator, the functor or applicative functor capabilities are insufficient. If you try to use <code>Select</code>, as in the above example, you'll produce a nested generator.
</p>
<p>
Since it's a monad, however, you can <code>Flatten</code> it:
</p>
<p>
<pre>Generator<<span style="color:blue;">int</span>> <span style="font-weight:bold;color:#1f377f;">flattened</span> = genDay.Flatten();</pre>
</p>
<p>
Or you can use <code>SelectMany</code> (monadic <em>bind</em>) to flatten as you go. The <code>CprNumber</code> generator does that, although it uses query syntax syntactic sugar to make the code more readable:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> Generator<CprNumber> CprNumber =>
<span style="color:blue;">from</span> sequenceNumber <span style="color:blue;">in</span> Gen.Choose(0, 9999)
<span style="color:blue;">from</span> year <span style="color:blue;">in</span> Gen.Choose(0, 99)
<span style="color:blue;">from</span> month <span style="color:blue;">in</span> Gen.Choose(1, 12)
<span style="color:blue;">let</span> fourDigitYear =
TestDataBuilderFunctor.CprNumber.CalculateFourDigitYear(year, sequenceNumber)
<span style="color:blue;">from</span> day <span style="color:blue;">in</span> Gen.Day(fourDigitYear, month)
<span style="color:blue;">select</span> <span style="color:blue;">new</span> CprNumber(day, month, year, sequenceNumber);</pre>
</p>
<p>
The expression first uses <code>Gen.Choose</code> to produce three independent <code>int</code> values: <code>sequenceNumber</code>, <code>year</code>, and <code>month</code>. It then uses the <code>CalculateFourDigitYear</code> function to look up the proper century based on the two-digit <code>year</code> and the <code>sequenceNumber</code>. With that information it can call <code>Gen.Day</code>, and since the expression uses monadic composition, it's flattening as it goes. Thus <code>day</code> is an <code>int</code> value rather than a generator.
</p>
<p>
Finally, the entire expression can compose the four <code>int</code> values into a valid <code>CprNumber</code> object.
</p>
<p>
You can consult the <a href="/2018/11/26/the-test-data-generator-applicative-functor">previous article</a> to see <code>Gen.CprNumber</code> in use.
</p>
<h3 id="f3947d3a3c364fb28fb264aff59f7fe7">
Hedgehog CPR generator <a href="#f3947d3a3c364fb28fb264aff59f7fe7">#</a>
</h3>
<p>
You can reproduce the CPR example in F# using one of several property-based testing frameworks. In this example, I'll continue the example from the <a href="/2018/11/26/the-test-data-generator-applicative-functor">previous article</a> as well as the article <a href="/2018/12/10/danish-cpr-numbers-in-f">Danish CPR numbers in F#</a>. You can see a couple of tests in these articles. They use the <code>cprNumber</code> generator, but never show the code.
</p>
<p>
In all the property-based testing frameworks I've seen, generators are called <code>Gen</code>. This is also the case for Hedgehog. The <code>Gen</code> <a href="https://bartoszmilewski.com/2014/01/14/functors-are-containers">container</a> is a monad, and there's a <code>gen</code> <a href="https://learn.microsoft.com/dotnet/fsharp/language-reference/computation-expressions">computation expression</a> that supplies syntactic sugar.
</p>
<p>
You can translate the above example to a Hedgehog <code>Gen</code> value like this:
</p>
<p>
<pre><span style="color:blue;">let</span> cprNumber =
gen {
<span style="color:blue;">let!</span> sequenceNumber = Range.linear 0 9999 |> Gen.int32
<span style="color:blue;">let!</span> year = Range.linear 0 99 |> Gen.int32
<span style="color:blue;">let!</span> month = Range.linear 1 12 |> Gen.int32
<span style="color:blue;">let</span> fourDigitYear = Cpr.calculateFourDigitYear year sequenceNumber
<span style="color:blue;">let</span> daysInMonth = DateTime.DaysInMonth (fourDigitYear, month)
<span style="color:blue;">let!</span> day = Range.linear 1 daysInMonth |> Gen.int32
<span style="color:blue;">return</span> Cpr.tryCreate day month year sequenceNumber }
|> Gen.some</pre>
</p>
<p>
To keep the example simple, I haven't defined an explicit <code>day</code> generator, but instead just inlined <code>DateTime.DaysInMonth</code>.
</p>
<p>
Consult the articles that I linked above to see the <code>Gen.cprNumber</code> generator in use.
</p>
<h3 id="15d1feac289e426ebd5845fc59d3f33e">
Conclusion <a href="#15d1feac289e426ebd5845fc59d3f33e">#</a>
</h3>
<p>
Test Data Generators form monads. This is useful when you need to generate test data that depend on other generated test data. Monadic <em>bind</em> (<code>SelectMany</code> in C#) can flatten the generator functor as you go. This article showed examples in both C# and F#.
</p>
<p>
The same abstraction also exists in the Haskell QuickCheck library, but I haven't shown any Haskell examples. If you've taken the trouble to learn Haskell (which you should), you already know what a monad is.
</p>
<p>
<strong>Next:</strong> <a href="/2022/07/11/functor-relationships">Functor relationships</a>.
</p>
</div>
<div id="comments">
<hr>
<h2 id="comments-header">
Comments
</h2>
<div class="comment" id="771023c319fb4f03bce6e3beb79294e6">
<div class="comment-author"><a href="https://github.com/AnthonyLloyd">Anthony Lloyd</a></div>
<div class="comment-content">
<p>
<a href="https://github.com/AnthonyLloyd/CsCheck">CsCheck</a> is a full implementation of something along these lines. It uses the same random sample generation in the shrinking step always reducing a Size measure. It turns out to be a better way of shrinking than the QuickCheck way.
</p>
</div>
<div class="comment-date">2023-02-27 22:51 UTC</div>
</div>
<div class="comment" id="21f1a20a1a5944fbbbdd300c8f0e89b0">
<div class="comment-author"><a href="/">Mark Seemann</a></div>
<div class="comment-content">
<p>
Anthony, thank you for writing. You'll be pleased to learn, I take it, that the next article in the series about the <a href="/2023/02/13/epistemology-of-interaction-testing">epistemology of interaction testing</a> uses CsCheck as the example framework.
</p>
</div>
<div class="comment-date">2023-02-28 7:33 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>.A thought on workplace flexibility and asynchronyhttps://blog.ploeh.dk/2023/02/20/a-thought-on-workplace-flexibility-and-asynchrony2023-02-20T07:03:00+00:00Mark Seemann
<div id="post">
<p>
<em>Is an inclusive workplace one that enables people to work at different hours?</em>
</p>
<p>
In the early <a href="https://en.wikipedia.org/wiki/Aughts">noughties</a> I worked for Microsoft Consulting Service in Denmark. In some sense it was quite the competitive working environment with an unhealthy focus on billable hours, customer satisfaction surveys, and stack ranking. On the other hand, since I was mostly on my own on customer engagements, my managers didn't care when and how I worked. As long as I billed and customers were happy, they were happy.
</p>
<p>
That sometimes allowed me great flexibility.
</p>
<p>
At one time I was on a project for a customer in another part of Denmark, and while Denmark isn't that big, it was still understood that I would do most of my work remotely. The main deliverable was the code base for a software system, and while I might email and otherwise communicate with the customer and a few colleagues during the day, we didn't have any fixed schedules. In other words, I could work whenever I wanted, as long as I got the work done.
</p>
<p>
My daughter was a toddler at the time, and as is the norm in Denmark, already in day nursery. My wife is a doctor and was, at that time, working in hospitals - some of the most inflexible workplaces I can think of. She had to leave early in the morning because the hospitals run on fixed schedules.
</p>
<p>
I'd get up to have breakfast with her. After she left for work, I'd work until my daughter woke up. She typically woke up between 8 and 9, so I'd already be 1-2 hours into my work day. I'd stop working, make her breakfast, and take her to day care. We'd typically arrive between 10 and 11 in good spirits. I'd then bicycle home and work until my wife came home with our daughter. Perhaps I'd get a few more hours of work done in the evening.
</p>
<p>
I worked odd hours, and I loved the flexibility. My customers expected me to deliver iterations of the software and generally stay in touch, but they were perfectly happy with mostly asynchronous communication. Back then, it mostly meant email.
</p>
<p>
During the normal work day, I might be unavailable for hours, taking care of my daughter, exercising, grocery shopping, etc. Yet, I still billed more hours than most of my colleagues, and ultimately received an award for my work.
</p>
<p>
In the decades that followed, I haven't always had such flexibility, but that early experience gave me a strong appreciation for asynchronous work.
</p>
<h3 id="3d5f041e6a4d46d5997c67e7693c3006">
Lockdown work wasn't flexible <a href="#3d5f041e6a4d46d5997c67e7693c3006">#</a>
</h3>
<p>
When COVID-19 hit and most countries went into lockdown, many office workers got their first taste of remote work. Many struggled, for a variety of reasons. Some of those reasons are quite real. If you don't have a well-equipped home office, spending eight hours a day on a kitchen chair is hardly ideal working conditions. And no, the sofa isn't a good long-term solution either.
</p>
<p>
Another problem during lockdown is that your entire family may be home, too. If you have kids, you'll have to attend to them. To be clear, if you've only experience working from home during COVID-19 lockdown, you may have suffered from many of these problems without realising the benefits of flexibility.
</p>
<p>
To add spite to injury, many workplaces tried to carry on as if nothing had changed, apart from the physical location of people. Office hours were still in effect, and work now took place over video calls. If you spent eight hours on Teams or Zoom, that's not flexible working conditions. Rather, it's the worst of both worlds. The only benefit is that you avoid the commute.
</p>
<h3 id="ac7c2c6f7cf54f0ab882275944262f71">
Remote compared to asynchronous work <a href="#ac7c2c6f7cf54f0ab882275944262f71">#</a>
</h3>
<p>
As outlined above, remote work isn't necessarily flexible. Flexibility comes from asynchronous work processes more than physical location. The flexibility is a result of the freedom to chose <em>when</em> to work, more than <em>where</em> to work.
</p>
<p>
Based on my decades of experience working asynchronously from home, I published <a href="/2020/03/16/conways-law-latency-versus-throughput">an article about the trade-off between latency and throughput</a>, comparing working together in an office with working asynchronously from home. The point is that you can make both work, but the way you organise work matters. In-office work is efficient if everyone is at the office at the same time. Remote work is efficient if people can work asynchronously.
</p>
<p>
As is usually the case, there are trade-offs. The disadvantage of working together is that you must all be present simultaneously. Thus, you don't get the flexibility of choosing when to work. The benefits of working asynchronously is exactly that flexibility, but on the other hand, you lose the advantage of the efficient, high-bandwidth communication that comes from being physically in the same room as others.
</p>
<h3 id="219d3cd5d3c94996b5d3b2993b8a5512">
Inclusion through flexibility? <a href="#219d3cd5d3c94996b5d3b2993b8a5512">#</a>
</h3>
<p>
I was recently listening to an episode of the <a href="https://freakonomics.com/series/freakonomics-radio/">Freakonomics Radio</a> podcast. As a side remark, someone mentioned that for women an important workplace criterion is <em>flexibility</em>. This, clearly, has some implications for this discussion.
</p>
<p>
There's a strong statistical tendency for women to have work-life priorities different from men. For example, <a href="https://ec.europa.eu/eurostat/web/products-eurostat-news/-/EDN-20200306-1">Eurostat reports that women are more likely to work part-time</a>. That may be a signifier that although women want to work, they may want to work less than men. Or perhaps with more flexible hours.
</p>
<p>
If that's true, what does it mean for software development?
</p>
<p>
If you want to include people who value flexibility highly (e.g. some women, but also me) then work should be structured to enable people to engage with it when they have the time. That might include early in the morning, late in the evening, or during the weekend.
</p>
<p>
Two workers who value flexibility may not be on the same schedule. When collaborating, they may have to do so asynchronously. Emails, work item trackers, pull requests.
</p>
<h3 id="554f4dbddb6746fe9ca2224df4714049">
Inclusive collaboration <a href="#554f4dbddb6746fe9ca2224df4714049">#</a>
</h3>
<p>
Most software development takes place in teams. Various team members have different skills, which is good, because a modern software system comprises more components than most people can overcome. Unless you're one of those rainbow unicorns who master modern front-end development, back-end development, DevOps, database design and administration, graphical design, security concerns, cloud computing platforms, reporting and analytics, etc. you'll need to collaborate with team members.
</p>
<p>
You can do so with short-lived Git branches, <a href="/2021/06/21/agile-pull-requests">agile pull requests</a>, and generally well-written communication. No, pull requests and asynchronous reviews don't have to be slow.
</p>
<p>
Recently, I've noticed an increased tendency among some software development thought leaders to extol the virtues of pair- and ensemble programming. These are great collaboration techniques. I've used them with great success in specific contexts. I also write about their advantages in my book <a href="/2021/06/14/new-book-code-that-fits-in-your-head">Code That Fits in Your Head</a>.
</p>
<p>
Pair- and ensemble programming are synchronous collaboration techniques. There are clear advantages to them, but it's a requirement that team members participate at the same time.
</p>
<p>
I'm sure it's fun and stimulating if you're already mostly extravert, but it doesn't strike me as particularly inclusive, time-wise.
</p>
<p>
If you can't be at the office 9-17 you can't participate. Sorry, we can't use you then.
</p>
<p>
What's that, you say? You can work <em>some</em> hours during the day, evenings, and sometimes weekends? But only twenty-five hours a week? Sorry, that doesn't fit our process.
</p>
<h3 id="cd6fdd9f987041e18e35f699952124b2">
A high-throughput alternative <a href="#cd6fdd9f987041e18e35f699952124b2">#</a>
</h3>
<p>
Pair- and ensemble programming are great collaboration techniques, but I've noticed an increased tendency to contrast them to a particular style of siloed, slow solo work with which I'm honestly not familiar. I do, however, consider that a false dichotomy.
</p>
<p>
The alternative to ensemble programming doesn't <em>have</em> to be slow, waterfall-like, feature-branch-based solo work heavy on misunderstandings, integration problems, and rework. It can be asynchronous, pull-based work. <a href="/2023/01/23/agilean">Lean</a>.
</p>
<p>
I've lived that dream. I know that it <em>can</em> work. Is it easy? No. Does it require discipline? Yes. But it's possible, and it's <em>flexible</em>. It enables people to work when they have the time.
</p>
<h3 id="ebbf4488a29a44569e92c491886c3e83">
Conclusion <a href="#ebbf4488a29a44569e92c491886c3e83">#</a>
</h3>
<p>
There are people who would like to work, just not 9-17. Perhaps they <em>can't</em> (for all sorts of socio-economic reasons), or perhaps that just doesn't align with their life choices. Perhaps they're just <a href="/2015/12/04/the-rules-of-attraction-location">not in your time zone</a>.
</p>
<p>
Do you want to include these people, or exclude 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>.Epistemology of interaction testinghttps://blog.ploeh.dk/2023/02/13/epistemology-of-interaction-testing2023-02-13T06:48:00+00:00Mark Seemann
<div id="post">
<p>
<em>How do we know that components interact correctly?</em>
</p>
<p>
Most software systems are composed as a graph of components. To be clear, I use the word <em>component</em> loosely to mean a collection of functionality - it may be an object, a module, a function, a data type, or perhaps something else I haven't thought of. Some components deal with the bigger picture and will typically coordinate other components that perform more specific tasks. If we think of a component graph as a tree, then some components are leaves.
</p>
<p>
<img src="/content/binary/component-graph.png" alt="Example component graph with four leaves.">
</p>
<p>
Leaf components, being self-contained and without dependencies, are typically the easiest to test. Most test-driven development (TDD) katas focus on these kinds of components: <a href="https://codingdojo.org/kata/Tennis/">Tennis</a>, <a href="https://codingdojo.org/kata/Bowling/">bowling</a>, <a href="http://claysnow.co.uk/recycling-tests-in-tdd/">diamond</a>, <a href="https://codingdojo.org/kata/RomanNumerals/">Roman numerals</a>, <a href="https://kata-log.rocks/gossiping-bus-drivers-kata">gossiping bus drivers</a>, and so on. Even the <a href="https://www.devjoy.com/blog/legacy-code-katas/">legacy security manager kata</a> is simple and quite self-contained. There's nothing wrong with that, and there's good reason to keep such exercises simple. After all, you want to be able to <a href="/2020/01/13/on-doing-katas">complete a kata</a> in a few hours. You can hardly do that if the exercise is to develop an entire web site with user interface, persistent data storage, security, data validation, business logic, third-party integration, emails, instrumentation and logging, and so on.
</p>
<p>
This means that even if you get good at TDD against 'leaf' functionality, you may be struggling when it comes to higher-level components. How does one unit test code that has dependencies?
</p>
<h3 id="66efa9d72a62458e93ff8490ef7585e9">
Interaction-based testing <a href="#66efa9d72a62458e93ff8490ef7585e9">#</a>
</h3>
<p>
A common solution is to <a href="https://en.wikipedia.org/wiki/Dependency_inversion_principle">invert the dependencies</a>. You can, for example, use <a href="/dippp">Dependency Injection</a> to inject <a href="https://martinfowler.com/bliki/TestDouble.html">Test Doubles</a> into the System Under Test (SUT). This enables you to control the behaviour of the dependencies and to verify that the SUT behaves as expected. Not only that, but you can also verify that the SUT interacts with the dependencies as expected. This is called <em>interaction-based testing</em>. It is, perhaps, the most common form of unit testing in the industry, and exemplary explained in <a href="/ref/goos">Growing Object-Oriented Software, Guided by Tests</a>.
</p>
<p>
The kinds of Test Doubles most useful with interaction-based testing are <a href="http://xunitpatterns.com/Test%20Stub.html">Stubs</a> and <a href="http://xunitpatterns.com/Mock%20Object.html">Mocks</a>. They are, however, problematic because <a href="/2022/10/17/stubs-and-mocks-break-encapsulation">they break encapsulation</a>. And encapsulation, to be clear, is <a href="/2022/10/24/encapsulation-in-functional-programming">also a concern in functional programming</a>.
</p>
<p>
I have already described how to move <a href="/2019/02/18/from-interaction-based-to-state-based-testing">from interaction-based to state-based testing</a>, and why <a href="/2015/05/07/functional-design-is-intrinsically-testable">functional programming is intrinsically more testable</a>.
</p>
<h3 id="db90b714ddc24393b4340cdd98a19082">
How to test composition of pure functions? <a href="#db90b714ddc24393b4340cdd98a19082">#</a>
</h3>
<p>
When you adopt functional programming (FP) you'll sooner or later need to compose or orchestrate pure functions. How do you test that the composition of pure functions is correct? That's what you can test with a Mock or <a href="http://xunitpatterns.com/Test%20Spy.html">Spy</a>.
</p>
<p>
You've developed component <em>A</em>, perhaps as a <a href="https://en.wikipedia.org/wiki/Higher-order_function">higher-order function</a>, that depends on another component <em>B</em>. You want to test that <em>A</em> correctly interacts with <em>B</em>, but if interaction-based testing is no longer 'allowed' (because it breaks encapsulation), then what do you do?
</p>
<p>
For a long time, I pondered that question myself, while I was busy enjoying FP making most things easier. It took me some time to understand that the answer, as is often the case, is <a href="https://en.wikipedia.org/wiki/Mu_(negative)">mu</a>. I'll get back to that later.
</p>
<p>
I'm not the only one struggling with this question. Sergei Rogovtcev writes and asks what I interpret as the same question:
</p>
<blockquote>
<p>
"I do have a component A, which is, frankly, some controller doing some checks and processing around a fairly complex state. This process can have several outcomes, let's call them Success, Fail, and Missing (the actual states are not important, but I'd like to have more than two). Then we have a component B, which is responsible for the rendering of the result. Of course, three different states lead to three different renderings, but the renderings are also influenced by state (let's say we have browser, mobile and native clients, and we need to provide different renderings). Originally the components are objects, B having three separate methods, but I can express them as pure functions, at least for the purpose of this discussion - A, and then BSuccess, BFail and BMissing. I can easily test each part of B in isolation; the problem comes when I need to test A, which calls different parts of B. If I use mocks, the solution is simple - I inject a mock of B to A, and then verify that A calls appropriate parts according to the process result. This requires knowing the innards of A, but otherwise it is a well-known and well-understood approach. But if I want to avoid mocks, what do I do? I cannot test A without relying on some code path in B, and this to me means that I'm losing the benefits of unit testing and entering the realm of integration testing."
</p>
</blockquote>
<p>
In his email Sergei Rogovtcev has explicitly given me permission to quote him and engage with this question. As I've outlined, I've grappled with that question myself, so I find the question worthwhile. I can't, however, work with it without questioning the premise. This is not an attack on Sergei Rogovtcev; after all, I had that question myself, so any critique I make is directed as much at my former self as at him.
</p>
<h3 id="034c99ad20644781af4f28db0f45b2dd">
Axiomatic versus scientific knowledge <a href="#034c99ad20644781af4f28db0f45b2dd">#</a>
</h3>
<p>
It may be helpful to elevate the discussion. How do we know that software (or a subsystem thereof) works? You could say that one answer to that is: <em>Passing tests</em>. If all tests are passing, we may have high confidence that the system works.
</p>
<p>
In the parlance of Sergei Rogovtcev, we can easily unit test component <em>B</em> because it's composed from <a href="https://en.wikipedia.org/wiki/Pure_function">pure functions</a>.
</p>
<p>
How do we unit test component <em>A</em>, though? With Mocks and Stubs, you can prove that the interaction works as intended. The keyword here is <em>prove</em>. If you assume that component <em>B</em> works correctly, 'all' you have to do is to demonstrate that component <em>A</em> correctly interacts with component <em>B</em>. I used to do that all the time and called it <a href="/2013/10/23/mocks-for-commands-stubs-for-queries">data-flow verification</a> or <a href="/2013/04/04/structural-inspection">structural inspection</a>. The idea was that if you could demonstrate that component <em>A</em> correctly interacts with <em>any</em> <a href="https://en.wikipedia.org/wiki/Liskov_substitution_principle">LSP</a>-compliant implementation of component <em>B</em>, and then also demonstrate that in reality (when composed in the <a href="/2011/07/28/CompositionRoot">Composition Root</a>) component <em>A</em> is composed with a component <em>B</em> that has also been demonstrated to work correctly, then the (sub-)system works correctly.
</p>
<p>
This is almost like a mathematical proof. First prove <em>lemma B</em>, then prove <em>theorem A</em> using <em>lemma B</em>. Finally, state <em>corollary C</em>: <em>b</em> is a special case handled by <em>lemma B</em>, so therefore <em>a</em> is covered by <em>theorem A</em>. <a href="https://en.wikipedia.org/wiki/Q.E.D.">Q.E.D.</a>
</p>
<p>
It's a logical and deductive approach to the problem of verifying the composition of the whole from verified parts. It's almost mathematical in the sense that it tries to erect an <a href="https://en.wikipedia.org/wiki/Axiomatic_system">axiomatic system</a>.
</p>
<p>
It's also fundamentally flawed.
</p>
<p>
I didn't understand that a decade ago, and in practice, the method worked well enough - apart from all the problems stemming from poor encapsulation. The problem with that approach is that an axiomatic system is only as strong as its <a href="https://en.wikipedia.org/wiki/Axiom">axioms</a>. What are the axioms in this system? The axioms, or premises, are that each of the components (<em>A</em> and <em>B</em>) are already correct. Based on these premises, this testing approach then proves that the composition is also correct.
</p>
<p>
How do we know that the components work correctly?
</p>
<p>
In this context, the answer is that they pass all tests. This, however, doesn't constitute any kind of <em>proof</em>. Rather, this is experimental knowledge, more reminiscent of science than of mathematics.
</p>
<p>
Why are we trying to <em>prove</em>, then, that composition works correctly? Why not just <em>test</em> it?
</p>
<p>
This observation cuts to the heart of the epistemology of testing. How do we know that software works? Typically not by <em>proving</em> it correct, but by subjecting it to experiments. As I've also outlined in <a href="/2021/06/14/new-book-code-that-fits-in-your-head">Code That Fits in Your Head</a>, we can regard automated tests as scientific experiments that we repeat over and over.
</p>
<h3 id="604436572933477d86d64349357d84ae">
Integration testing <a href="#604436572933477d86d64349357d84ae">#</a>
</h3>
<p>
To outline the argument so far: While you <em>can</em> use Mocks and Spies to verify that a component correctly interacts with another component, this may be overkill. You're essentially trying to prove a conjecture based on doubtful evidence.
</p>
<p>
Does it really matter that two components <em>interact</em> correctly? Aren't the components implementation details? Do users care?
</p>
<p>
Users and other stakeholders care about the <em>behaviour</em> of the software system. Why not test that?
</p>
<p>
This is, unfortunately, easier said than done. Sergei Rogovtcev strongly implies that he isn't keen on integration testing. While he doesn't explicitly state why, there are good reasons to be wary of integration testing. <a href="https://www.infoq.com/presentations/integration-tests-scam/">As J.B. Rainsberger eloquently explained</a>, a major problem with integration testing is the combinatorial explosion of test cases. If you ought to write 53,000 test cases to cover all combinations of pathways through integrated components, which test cases do you write? Surely not all 53,000.
</p>
<p>
J.B. Rainsberger's argument is that if you're going to write no more than a dozen unit tests, you're unlikely to cover enough test cases to be confident that the system works.
</p>
<p>
What if, however, you could write hundreds or thousands of test cases?
</p>
<h3 id="3d43f77a5480418780816b3d6a8b9a0f">
Property-based testing <a href="#3d43f77a5480418780816b3d6a8b9a0f">#</a>
</h3>
<p>
You may recall that the premise of this article is functional programming (FP), where <em>property-based testing</em> is a common testing technique. While you can, to a degree, also use this technique in object-oriented programming (OOP), it's often difficult because of side effects and non-deterministic behaviour.
</p>
<p>
When you write a property-based test, you write a single piece of code that evaluates a <em>property</em> of the SUT. The property looks like a parametrised unit test; the difference is that the input is generated randomly, but in a fashion you can control. This enables you to write hundreds or thousands of test cases without having to write them explicitly.
</p>
<p>
Thus, epistemologically, you can use property-based testing with integrated components to produce confidence that the (sub-)system works. In practice, I find that the confidence I get from this technique is at least as high as the one I used to get from unit testing with Stubs and Spies.
</p>
<h3 id="9edd8d0a18cd4e1abbfaad2d7a3a650a">
Examples <a href="#9edd8d0a18cd4e1abbfaad2d7a3a650a">#</a>
</h3>
<p>
All of this is abstract and theoretical, I realise. <a href="http://www.exampler.com/">An example would be handy right about now</a>. Such examples, however, are complex enough to warrant their own articles:
</p>
<ul>
<li><a href="/2023/03/13/confidence-from-facade-tests">Confidence from Facade Tests</a></li>
<li><a href="/2023/04/03/an-abstract-example-of-refactoring-from-interaction-based-to-property-based-testing">An abstract example of refactoring from interaction-based to property-based testing</a></li>
<li><a href="/2023/04/17/a-restaurant-example-of-refactoring-from-example-based-to-property-based-testing">A restaurant example of refactoring from example-based to property-based testing</a></li>
<li><a href="/2023/05/01/refactoring-pure-function-composition-without-breaking-existing-tests">Refactoring pure function composition without breaking existing tests</a></li>
</ul>
<p>
Sergei Rogovtcev was kind enough to furnish a rather abstract, but <a href="https://en.wikipedia.org/wiki/Minimal_reproducible_example">minimal and self-contained</a>, example. I'll go through that first, and then follow up with a more realistic example.
</p>
<h3 id="2908ce4d26244c90bf20db829888205e">
Conclusion <a href="#2908ce4d26244c90bf20db829888205e">#</a>
</h3>
<p>
How do you know that a software system works correctly? Ultimately, if it behaves in the way it's supposed to, it works correctly. Testing an entire system from the outside, however, is rarely viable in itself. The number of possible test cases is just too large.
</p>
<p>
You can partially address that problem by decomposing the system into components. You can then test the components individually, and verify that they interact correctly. This last part is the topic of this article. A common way to to address this problem is to use Mocks and Spies to prove interactions correct. It does solve the problem of correctness quite neatly, but has the undesirable side effect of making the tests brittle.
</p>
<p>
An alternative is to use property-based testing to verify that the components integrate correctly. Rather than something that looks like a proof, this is a question of numbers. Throw enough random test cases at the system, and you'll be confident that it works. How many? <a href="/2018/11/12/what-to-test-and-not-to-test">Enough</a>.
</p>
<p>
<strong>Next:</strong> <a href="/2023/03/13/confidence-from-facade-tests">Confidence from Facade Tests</a>.
</p>
</div>
<div id="comments">
<hr>
<h2 id="comments-header">
Comments
</h2>
<div class="comment" id="f30e0d110f6c42feb75100e08c78beab">
<div class="comment-author"><a href="https://github.com/srogovtsev">Sergei Rogovtcev</a></div>
<div class="comment-content">
<p>First of all, let me thank you for taking time and effort to discuss this.</p>
<p>There's a minor point about integration testing:</p>
<blockquote><p>[SR] strongly implies that he isn't keen on integration testing. While he doesn't explicitly state why...</p></blockquote>
<p>The situation is somewhat more complicated: in fact, I tend to have at least a few integration tests for a feature I'm involved with, starting the coverage from the happy paths (the minimum requirement being to verify that we've wired correctly as many components as can be verified), and then, if possible, extending to error paths, edge cases and so on. Even the code from my email originally had integration tests covering all the outcomes for a single rendering (browser). The problem that I've faced then, and which prompted my question, was exactly the one that you quote from J.B. Rainsberger: combinatorial explosion. As soon as I decided to cover a second rendering (mobile), I saw that I needed to replicate the setups for outcomes (success/fail/missing), but modify the asserts for their rendering. And then again the same for the native client. Unit tests, even with their ungainly break in encapsulation, gave the simple appeal of writing less code...</p>
<p>Hopefully, this seem to be the very same premise that you explore towards the end of your post, leading to the property-based testing - which I was trying to incorporate into my toolset for quite some time, but was always somewhat baffled at how it should work and integrate into object-oriented (and C#-based) code. So I'm very much looking forward for your next installment in this series.</p>
<p>And again, thank you for exploring these matters.</p>
</div>
<div class="comment-date">2023-02-21 13:52 UTC</div>
</div>
<div class="comment" id="73cb2b8d15bf4e10a9e20a89dbad4374">
<div class="comment-author"><a href="/">Mark Seemann</a></div>
<div class="comment-content">
<p>
Sergei, thank you for writing. I hope that this small series of articles will be able to at least give you some ideas. I am, however, concerned that I may miss the mark.
</p>
<p>
When discussing problems like this, there's always a risk that the examples we look at are too simple; that they don't adequately represent the real world. For instance, we may look at the example code in the next few articles and calculate how well we've covered all combinations.
</p>
<p>
Perhaps we may find that the combinatorial 'explosion' is only in the ten-thousands, which is within reasonable reach of well-written properties.
</p>
<p>
Then, when we come back to our 'real' problems, the combinatorial explosion may be orders of magnitudes larger. You can easily ask a property-based framework to run a property millions of time, but it'll take time. Perhaps this makes the tests so slow that it's not a practical solution.
</p>
<p>
All that said, I think that not all is lost. Part of the solution, however, may be found elsewhere.
</p>
<p>
The more I learn about functional programming (FP), the more I'm amazed at the alternative mindset it offers. Solutions that look in one way in object-oriented programming (OOP) may look completely different in FP. You've probably noticed this yourself. Often, you have to turn a problem on its head to see it 'the FP way'.
</p>
<p>
The following is something that I've not yet thought through rigorously, so perhaps there are flaws in my thinking. I offer it for peer review here.
</p>
<p>
OOP composition tends to be 'deep'. If we think of object composition as a directed (acyclic, hopefully!) graph, typical OOP composition might resemble a graph where each node has only few children, but the distance from the root to each leaf is great. Since, every time you compose two objects, you have to multiply the number of pathways, this gives you this combinatorial explosion we've discussed. The deeper the graph, the worse it is.
</p>
<p>
In FP I typically find myself composing functions in a more shallow fashion. Instead of having functions that call other functions that call other functions, etc. I tend to have functions that return values that I then pass to other functions, and so on. This produces a shallower and wider composition graph. Doesn't it also reduce the combinations that we need to consider for testing?
</p>
<p>
I haven't subjected this idea to a more formal analysis yet, so this may be wrong. If I'm right, though, this could mean that property-based testing is still a viable solution to the problem.
</p>
<p>
Identifying useful properties is another problem that you also bring up, particularly in the context of OOP. So far, property-based testing is more prevalent in FP, and perhaps there's a reason for that.
</p>
<p>
It seems to me that there's a connection between property-based testing and encapsulation. Essentially, a property is an executable description of some invariant, or pre- or post-condition. Most real-world object-oriented code I've seen, however, isn't encapsulated. If you have poor encapsulation, it's no wonder that it's hard to identify useful properties.
</p>
<p>
Even so, Identifying good properties is a skill that you have to learn. It's fairly easy to construct properties that, in a sense, 'reproduce the implementation'. The challenge is to avoid that, and that's not always easy. As an example, it took me years before I found <a href="/2021/06/28/property-based-testing-is-not-the-same-as-partition-testing">a good way to express properties of FizzBuzz without repeating the implementation</a>.
</p>
</div>
<div class="comment-date">2023-02-22 8:00 UTC</div>
</div>
<div class="comment" id="6a9753ec6d54462c9d500112a55105b6">
<div class="comment-author"><a href="https://github.com/srogovtsev">Sergei Rogovtcev</a></div>
<div class="comment-content">
<blockquote><p>This produces a shallower and wider composition graph. Doesn't it also reduce the combinations that we need to consider for testing?</p></blockquote>
<p>Intuitively I'd say that it shouldn't (reduce), because in the end the number of combinations that we consider for testing is the number states our SUT can be in, which is defined as a combination of all its inputs. But I may, of course, miss something important here.</p>
<p>My own opinion on this, coming from a short-ish brush with FP, is that FP, or, more precisely, more expressive type systems, reduce the number of combinations by reducing the number of possible inputs by the virtue of more expressive types. My favorite example is that even less expressive type system, one with simple <em>int</em> and <em>string</em> instead of all-encompassing <em>var</em>/<em>object</em>, allows us to get rid off all the tests where we pass "foo" to a function that only works on numbers. Explicit nullability gets rid of all the <em>null</em>-related test-cases (and we get an indication where we lack such cases for <em>null</em>-accepting functions). This can be continued by adding more and more cases until we arrive at the (in)famous "if it compiles, is works".</p>
<p>I don't remember whether I've included this guard case in my original email, but I definitely remember thinking of mentioning that I'm confined to a less-expressive type system of C#. Even comparing to F# (as I remember it from my side studies), I can see how some tests can be made redundant by, for example, introducing a sum type and then relying on compiler to check for exhaustive match. Sometimes I wonder what would a more expressive type system do to these problems...</p>
</div>
<div class="comment-date">2023-02-22 14:40 UTC</div>
</div>
<div class="comment" id="9fa9a41fd827458aa0a87d854e5e8228">
<div class="comment-author"><a href="/">Mark Seemann</a></div>
<div class="comment-content">
<p>
Sergei, thank you for writing. A more expressive type system certainly does reduce the amount of testing required. While I prefer <a href="https://fsharp.org/">F#</a>, the good news is that most of what F# can do, C# can do, too. Everything is just more verbose in C#. The main stumbling block that people usually complain about is the lack of <a href="https://en.wikipedia.org/wiki/Tagged_union">sum types</a>, but you can use <a href="/2018/06/25/visitor-as-a-sum-type">Visitors as sum types</a>. You get the same benefits as with F# discriminated unions, except with much more <a href="/2019/12/16/zone-of-ceremony">ceremony</a>.
</p>
</div>
<div class="comment-date">2023-02-25 17:50 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>.Contravariant functors as invariant functorshttps://blog.ploeh.dk/2023/02/06/contravariant-functors-as-invariant-functors2023-02-06T06:42:00+00:00Mark Seemann
<div id="post">
<p>
<em>Another most likely useless set of invariant functors that nonetheless exist.</em>
</p>
<p>
This article is part of <a href="/2022/08/01/invariant-functors">a series of articles about invariant functors</a>. An invariant functor is a <a href="/2018/03/22/functors">functor</a> that is neither covariant nor contravariant. See the series introduction for more details.
</p>
<p>
It turns out that all <a href="/2021/09/02/contravariant-functors">contravariant functors</a> are also invariant functors.
</p>
<p>
Is this useful? Let me, like in <a href="/2022/12/26/functors-as-invariant-functors">the previous article</a>, be honest and say that if it is, I'm not aware of it. Thus, if you're interested in practical applications, you can stop reading here. This article contains nothing of practical use - as far as I can tell.
</p>
<h3 id="fda7d35329c74cf9ab9753d0b25d1f08">
Because it's there <a href="#fda7d35329c74cf9ab9753d0b25d1f08" title="permalink">#</a>
</h3>
<p>
Why describe something of no practical use?
</p>
<p>
Why do some people climb <a href="https://en.wikipedia.org/wiki/Mount_Everest">Mount Everest</a>? <em>Because it's there</em>, or for other irrational reasons. Which is fine. I've no personal goals that involve climbing mountains, but <a href="/2020/10/12/subjectivity">I happily engage in other irrational and subjective activities</a>.
</p>
<p>
One of them, apparently, is to write articles of software constructs of no practical use, <em>because it's there</em>.
</p>
<p>
All contravariant functors are also invariant functors, even if that's of no practical use. That's just the way it is. This article explains how, and shows a few (useless) examples.
</p>
<p>
I'll start with a few <a href="https://www.haskell.org/">Haskell</a> examples and then move on to showing the equivalent examples in C#. If you're unfamiliar with Haskell, you can skip that section.
</p>
<h3 id="61d5b82994f941db98cb933e6311d396">
Haskell package <a href="#61d5b82994f941db98cb933e6311d396" title="permalink">#</a>
</h3>
<p>
For Haskell you can find an existing definition and implementations in the <a href="https://hackage.haskell.org/package/invariant">invariant</a> package. It already makes most 'common' contravariant functors <code>Invariant</code> instances, including <code>Predicate</code>, <code>Comparison</code>, and <code>Equivalence</code>. Here's an example of using <code>invmap</code> with a predicate.
</p>
<p>
First, we need a predicate. Consider a function that evaluates whether a number is divisible by three:
</p>
<p>
<pre>isDivisbleBy3 :: Integral a => a -> Bool
isDivisbleBy3 = (0 ==) . (`mod` 3)</pre>
</p>
<p>
While this is already <a href="/2021/09/09/the-specification-contravariant-functor">conceptually a contravariant functor</a>, in order to make it an <code>Invariant</code> instance, we have to enclose it in the <code>Predicate</code> wrapper:
</p>
<p>
<pre>ghci> :t Predicate isDivisbleBy3
Predicate isDivisbleBy3 :: Integral a => Predicate a</pre>
</p>
<p>
This is a predicate of some kind of integer. What if we wanted to know if a given duration represented a number of picoseconds divisible by three? Silly example, I know, but in order to demonstrate invariant mapping, we need types that are isomorphic, and <a href="https://hackage.haskell.org/package/time/docs/Data-Time-Clock.html#t:NominalDiffTime">NominalDiffTime</a> is isomorphic to a number of picoseconds via its <code>Enum</code> instance.
</p>
<p>
<pre>p :: Enum a => Predicate a
p = invmap toEnum fromEnum $ Predicate isDivisbleBy3</pre>
</p>
<p>
In other words, it's possible to map the <code>Integral</code> predicate to an <code>Enum</code> predicate, and since <code>NominalDiffTime</code> is an <code>Enum</code> instance, you can now evaluate various durations:
</p>
<p>
<pre>ghci> (getPredicate p) $ secondsToNominalDiffTime 60
True
ghci> (getPredicate p) $ secondsToNominalDiffTime 61
False</pre>
</p>
<p>
This is, as I've already announced, hardly useful, but it's still possible. Unless you have an API that <em>requires</em> an <code>Invariant</code> instance, it's also redundant, because you could just have used <code>contramap</code> with the predicate:
</p>
<p>
<pre>ghci> (getPredicate $ contramap fromEnum $ Predicate isDivisbleBy3) $ secondsToNominalDiffTime 60
True
ghci> (getPredicate $ contramap fromEnum $ Predicate isDivisbleBy3) $ secondsToNominalDiffTime 61
False</pre>
</p>
<p>
When mapping a contravariant functor, only the contravariant mapping argument is required. The <code>Invariant</code> instances for <code>Contravariant</code> simply ignores the covariant mapping argument.
</p>
<h3 id="5a36c7d729f54ce98f21cd714f050d55">
Specification as an invariant functor in C# <a href="#5a36c7d729f54ce98f21cd714f050d55" title="permalink">#</a>
</h3>
<p>
My earlier article <a href="/2021/09/09/the-specification-contravariant-functor">The Specification contravariant functor</a> takes a more object-oriented view on predicates by examining the <a href="https://en.wikipedia.org/wiki/Specification_pattern">Specification pattern</a>.
</p>
<p>
As outlined in <a href="/2022/08/01/invariant-functors">the introduction</a>, while it's possible to add a method called <code>InvMap</code>, it'd be more <a href="/2015/08/03/idiomatic-or-idiosyncratic">idiomatic</a> to add a non-standard <code>Select</code> method:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> ISpecification<T1> Select<<span style="color:#2b91af;">T</span>, <span style="color:#2b91af;">T1</span>>(
<span style="color:blue;">this</span> ISpecification<T> source,
Func<T, T1> tToT1,
Func<T1, T> t1ToT)
{
<span style="color:blue;">return</span> source.ContraMap(t1ToT);
}</pre>
</p>
<p>
This implementation ignores <code>tToT1</code> and delegates to the existing <code>ContraMap</code> method.
</p>
<p>
Here's a unit test that demonstrates an example equivalent to the above Haskell example:
</p>
<p>
<pre>[Theory]
[InlineData(60, <span style="color:blue;">true</span>)]
[InlineData(61, <span style="color:blue;">false</span>)]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> InvariantMappingExample(<span style="color:blue;">long</span> seconds, <span style="color:blue;">bool</span> expected)
{
ISpecification<<span style="color:blue;">long</span>> spec = <span style="color:blue;">new</span> IsDivisibleBy3Specification();
ISpecification<TimeSpan> mappedSpec =
spec.Select(ticks => <span style="color:blue;">new</span> TimeSpan(ticks), ts => ts.Ticks);
Assert.Equal(
expected,
mappedSpec.IsSatisfiedBy(TimeSpan.FromSeconds(seconds)));
}</pre>
</p>
<p>
Again, while this is hardly useful, it's possible.
</p>
<h3 id="d016726d91834c73998a7615aeab6c3a">
Conclusion <a href="#d016726d91834c73998a7615aeab6c3a" title="permalink">#</a>
</h3>
<p>
All contravariant functors are invariant functors. You simply use the 'normal' contravariant mapping function (<code>contramap</code> in Haskell). This enables you to add an invariant mapping (<code>invmap</code>) that only uses the contravariant argument (<code>b -> a</code>) and ignores the covariant argument (<code>a -> b</code>).
</p>
<p>
Invariant functors are, however, not particularly useful, so neither is this result. Still, it's there, so deserves a mention. Enough of that, though.
</p>
<p>
<strong>Next:</strong> <a href="/2022/03/28/monads">Monads</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>.Built-in alternatives to applicative assertionshttps://blog.ploeh.dk/2023/01/30/built-in-alternatives-to-applicative-assertions2023-01-30T08:08:00+00:00Mark Seemann
<div id="post">
<p>
<em>Why make things so complicated?</em>
</p>
<p>
Several readers reacted to my small article series on <a href="/2022/11/07/applicative-assertions">applicative assertions</a>, pointing out that error-collecting assertions are already supported in more than one unit-testing framework.
</p>
<blockquote>
<p>
"In the Java world this seems similar to the result gained by Soft Assertions in AssertJ. <a href="https://assertj.github.io/doc/#assertj-core-soft-assertions">https://assertj.github.io/doc/#assertj-c...</a> if you’re after a target for functionality (without the adventures through monad land)"
</p>
<footer><cite><a href="https://twitter.com/joshuamck/status/1597190184134590464">Josh McK</a></cite></footer>
</blockquote>
<p>
While I'm not familiar with the details of Java unit-testing frameworks, the situation is similar in .NET, it turns out.
</p>
<blockquote>
<p>
"Did you know there is Assert.Multiple in NUnit and now also in xUnit .Net? It seems to have quite an overlap with what you're doing here.
</p>
<p>
"For a quick overview, I found this blogpost helpful: <a href="https://www.thomasbogholm.net/2021/11/25/xunit-2-4-2-pre-multiple-asserts-in-one-test/">https://www.thomasbogholm.net/2021/11/25/xunit-2-4-2-pre-multiple-asserts-in-one-test/</a>"
</p>
<footer><cite><a href="https://twitter.com/DoCh_Dev/status/1597158737357459456">DoCh_Dev</a></cite></footer>
</blockquote>
<p>
I'm not surprised to learn that something like this exists, but let's take a quick look.
</p>
<h3 id="d7c0c78093084c08aa22ccaa7b86cb8a">
NUnit Assert.Multiple <a href="#d7c0c78093084c08aa22ccaa7b86cb8a" title="permalink">#</a>
</h3>
<p>
Let's begin with <a href="https://nunit.org/">NUnit</a>, as this seems to be the first .NET unit-testing framework to support error-collecting assertions. As a beginning, the <a href="https://docs.nunit.org/articles/nunit/writing-tests/assertions/multiple-asserts.html">documentation example</a> works as it's supposed to:
</p>
<p>
<pre>[Test]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> ComplexNumberTest()
{
ComplexNumber result = SomeCalculation();
Assert.Multiple(() =>
{
Assert.AreEqual(5.2, result.RealPart, <span style="color:#a31515;">"Real part"</span>);
Assert.AreEqual(3.9, result.ImaginaryPart, <span style="color:#a31515;">"Imaginary part"</span>);
});
}</pre>
</p>
<p>
When you run the test, it fails (as expected) with this error message:
</p>
<p>
<pre>Message:
Multiple failures or warnings in test:
1) Real part
Expected: 5.2000000000000002d
But was: 5.0999999999999996d
2) Imaginary part
Expected: 3.8999999999999999d
But was: 4.0d</pre>
</p>
<p>
That seems to work well enough, but how does it actually work? I'm not interested in reading the NUnit source code - after all, the concept of <a href="/encapsulation-and-solid">encapsulation</a> is that one should be able to make use of the capabilities of an object without knowing all implementation details. Instead, I'll guess: Perhaps <code>Assert.Multiple</code> executes the code block in a <code>try/catch</code> block and collects the various exceptions thrown by the nested assertions.
</p>
<p>
Does it catch all exception types, or only a subset?
</p>
<p>
Let's try with the kind of composed assertion that I <a href="/2022/11/28/an-initial-proof-of-concept-of-applicative-assertions-in-c">previously investigated</a>:
</p>
<p>
<pre>[Test]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> HttpExample()
{
<span style="color:blue;">var</span> deleteResp = <span style="color:blue;">new</span> HttpResponseMessage(HttpStatusCode.BadRequest);
<span style="color:blue;">var</span> getResp = <span style="color:blue;">new</span> HttpResponseMessage(HttpStatusCode.OK);
Assert.Multiple(() =>
{
deleteResp.EnsureSuccessStatusCode();
Assert.That(getResp.StatusCode, Is.EqualTo(HttpStatusCode.NotFound));
});
}</pre>
</p>
<p>
This test fails (again, as expected). What's the error message?
</p>
<p>
<pre>Message:
System.Net.Http.HttpRequestException :↩
Response status code does not indicate success: 400 (Bad Request).</pre>
</p>
<p>
(I've wrapped the result over multiple lines for readability. The <code>↩</code> symbol indicates where I've wrapped the text. I'll do that again later in this article.)
</p>
<p>
Notice that I'm using <a href="/2020/09/28/ensuresuccessstatuscode-as-an-assertion">EnsureSuccessStatusCode as an assertion</a>. This seems to spoil the behaviour of <code>Assert.Multiple</code>. It only reports the first status code error, but not the second one.
</p>
<p>
I admit that I don't fully understand what's going on here. In fact, I <em>have</em> taken a cursory glance at the relevant NUnit source code without being enlightened.
</p>
<p>
One hypothesis might be that NUnit assertions throw special <code>Exception</code> sub-types that <code>Assert.Multiple</code> catch. In order to test that, I wrote a few more tests in <a href="https://fsharp.org/">F#</a> with <a href="http://www.swensensoftware.com/unquote/">Unquote</a>, assuming that, since Unquote hardly throws NUnit exceptions, the behaviour might be similar to above.
</p>
<p>
<pre>[<Test>]
<span style="color:blue;">let</span> Test4 () =
<span style="color:blue;">let</span> x = 1
<span style="color:blue;">let</span> y = 2
<span style="color:blue;">let</span> z = 3
Assert.Multiple (<span style="color:blue;">fun</span> () <span style="color:blue;">-></span>
x =! y
y =! z)</pre>
</p>
<p>
The <code>=!</code> operator is an Unquote operator that I usually read as <em>must equal</em>. How does that error message look?
</p>
<p>
<pre>Message:
Multiple failures or warnings in test:
1)
1 = 2
false
2)
2 = 3
false</pre>
</p>
<p>
Somehow, <code>Assert.Multiple</code> understands Unquote error messages, but not <code>HttpRequestException</code>. As I wrote, I don't fully understand why it behaves this way. To a degree, I'm intellectually curious enough that I'd like to know. On the other hand, from a maintainability perspective, as a user of NUnit, I shouldn't have to understand such details.
</p>
<h3 id="1f28e534b0f94e93bb12cbb951fa663f">
xUnit.net Assert.Multiple <a href="#1f28e534b0f94e93bb12cbb951fa663f" title="permalink">#</a>
</h3>
<p>
How fares the <a href="https://xunit.net/">xUnit.net</a> port of <code>Assert.Multiple</code>?
</p>
<p>
<pre>[Fact]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> HttpExample()
{
<span style="color:blue;">var</span> deleteResp = <span style="color:blue;">new</span> HttpResponseMessage(HttpStatusCode.BadRequest);
<span style="color:blue;">var</span> getResp = <span style="color:blue;">new</span> HttpResponseMessage(HttpStatusCode.OK);
Assert.Multiple(
() => deleteResp.EnsureSuccessStatusCode(),
() => Assert.Equal(HttpStatusCode.NotFound, getResp.StatusCode));
}</pre>
</p>
<p>
The API is, you'll notice, not quite identical. Where the NUnit <code>Assert.Multiple</code> method takes a single delegate as input, the xUnit.net method takes an array of actions. The difference is not only at the level of API; the behaviour is different, too:
</p>
<p>
<pre>Message:
Multiple failures were encountered:
---- System.Net.Http.HttpRequestException :↩
Response status code does not indicate success: 400 (Bad Request).
---- Assert.Equal() Failure
Expected: NotFound
Actual: OK</pre>
</p>
<p>
This error message reports both problems, as we'd like it to do.
</p>
<p>
I also tried writing equivalent tests in F#, with and without Unquote, and they behave consistently with this result.
</p>
<p>
If I had to use something like <code>Assert.Multiple</code>, I'd trust the xUnit.net variant more than NUnit's implementation.
</p>
<h3 id="c51fb932618c4464a2e9be05869005d4">
Assertion scopes <a href="#c51fb932618c4464a2e9be05869005d4" title="permalink">#</a>
</h3>
<p>
Apparently, <a href="https://fluentassertions.com/">Fluent Assertions</a> offers yet another alternative.
</p>
<blockquote>
<p>
"Hey @ploeh, been reading your applicative assertion series. I recently discovered Assertion Scopes, so I'm wondering what is your take on them since it seems to me they are solving this problem in C# already. <a href="https://fluentassertions.com/introduction#assertion-scopes">https://fluentassertions.com/introduction#assertion-scopes</a></a>"
</p>
<footer><cite><a href="https://twitter.com/JernejGoricki/status/1597704973839904768">Jernej Gorički</a></cite></footer>
</blockquote>
<p>
The linked documentation contains this example:
</p>
<p>
<pre>[Fact]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> DocExample()
{
<span style="color:blue;">using</span> (<span style="color:blue;">new</span> AssertionScope())
{
5.Should().Be(10);
<span style="color:#a31515;">"Actual"</span>.Should().Be(<span style="color:#a31515;">"Expected"</span>);
}
}</pre>
</p>
<p>
It fails in the expected manner:
</p>
<p>
<pre>Message:
Expected value to be 10, but found 5 (difference of -5).
Expected string to be "Expected" with a length of 8, but "Actual" has a length of 6,↩
differs near "Act" (index 0).</pre>
</p>
<p>
How does it fare when subjected to the <code>EnsureSuccessStatusCode</code> test?
</p>
<p>
<pre>[Fact]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> HttpExample()
{
<span style="color:blue;">var</span> deleteResp = <span style="color:blue;">new</span> HttpResponseMessage(HttpStatusCode.BadRequest);
<span style="color:blue;">var</span> getResp = <span style="color:blue;">new</span> HttpResponseMessage(HttpStatusCode.OK);
<span style="color:blue;">using</span> (<span style="color:blue;">new</span> AssertionScope())
{
deleteResp.EnsureSuccessStatusCode();
getResp.StatusCode.Should().Be(HttpStatusCode.NotFound);
}
}</pre>
</p>
<p>
That test produces this error output:
</p>
<p>
<pre>Message:
System.Net.Http.HttpRequestException :↩
Response status code does not indicate success: 400 (Bad Request).</pre>
</p>
<p>
Again, <code>EnsureSuccessStatusCode</code> prevents further assertions from being evaluated. I can't say that I'm that surprised.
</p>
<h3 id="2f325809027243889d703e927a115efc">
Implicit or explicit <a href="#2f325809027243889d703e927a115efc" title="permalink">#</a>
</h3>
<p>
You might protest that using <code>EnsureSuccessStatusCode</code> and treating the resulting <code>HttpRequestException</code> as an assertion is unfair and unrealistic. Possibly. As usual, such considerations are subject to a multitude of considerations, and there's no one-size-fits-all answer.
</p>
<p>
My intent with this article isn't to attack or belittle the APIs I've examined. Rather, I wanted to explore their boundaries by stress-testing them. That's one way to gain a better understanding. Being aware of an API's limitations and quirks can prevent subtle bugs.
</p>
<p>
Even if you'd <em>never</em> use <code>EnsureSuccessStatusCode</code> as an assertion, perhaps you or a colleague might inadvertently do something to the same effect.
</p>
<p>
I'm not surprised that both NUnit's <code>Assert.Multiple</code> and Fluent Assertions' <code>AssertionScope</code> behaves in a less consistent manner than xUnit.net's <code>Assert.Multiple</code>. The clue is in the API.
</p>
<p>
The xUnit.net API looks like this:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> <span style="color:blue;">void</span> <span style="color:#74531f;">Multiple</span>(<span style="color:blue;">params</span> Action[] <span style="color:#1f377f;">checks</span>)</pre>
</p>
<p>
Notice that each assertion is explicitly a separate action. This enables the implementation to isolate it and treat it independently of other actions.
</p>
<p>
Neither the NUnit nor the Fluent Assertions API is that explicit. Instead, you can write arbitrary code inside the 'scope' of multiple assertions. For <code>AssertionScope</code>, the notion of a 'scope' is plain to see. For the NUnit API it's more implicit, but the scope is effectively the extent of the method:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> <span style="color:blue;">void</span> <span style="color:#74531f;">Multiple</span>(TestDelegate <span style="color:#1f377f;">testDelegate</span>)</pre>
</p>
<p>
That <code>testDelegate</code> can have as many (nested, even) assertions as you'd like, so the <code>Multiple</code> implementation needs to somehow demarcate when it begins and when it ends.
</p>
<p>
The <code>testDelegate</code> can be implemented in a different file, or even in a different library, and it has no way to communicate or coordinate with its surrounding scope. This reminds me of an Ambient Context, an idiom that <a href="/2019/01/21/some-thoughts-on-anti-patterns">Steven van Deursen convinced me was an anti-pattern</a>. The surrounding context changes the behaviour of the code block it surrounds, and it's quite implicit.
</p>
<blockquote>
<p>
Explicit is better than implicit.
</p>
<footer><cite>Tim Peters, <a href="https://peps.python.org/pep-0020/">The Zen of Python</a></cite></footer>
</blockquote>
<p>
The xUnit.net API, at least, looks a bit saner. Still, this kind of API is quirky enough that it reminds me of <a href="https://en.wikipedia.org/wiki/Greenspun%27s_tenth_rule">Greenspun's tenth rule</a>; that these APIs are ad-hoc, informally-specified, bug-ridden, slow implementations of half of <a href="/2018/10/01/applicative-functors">applicative functors</a>.
</p>
<h3 id="95b723f05a7f4b4c88b5e716f5f82989">
Conclusion <a href="#95b723f05a7f4b4c88b5e716f5f82989" title="permalink">#</a>
</h3>
<p>
Not surprisingly, popular unit-testing and assertion libraries come with facilities to compose assertions. Also, not surprisingly, these APIs are crude and require you to learn their implementation details.
</p>
<p>
Would I use them if I had to? I probably would. As <a href="https://www.infoq.com/presentations/Simple-Made-Easy/">Rich Hickey put it</a>, they're already <em>at hand</em>. That makes them easy, but not necessarily simple. APIs that compel you to learn their internal implementation details aren't simple.
</p>
<p>
<a href="/2017/10/04/from-design-patterns-to-category-theory">Universal abstractions</a>, on the other hand, you only have to learn one time. Once you understand what an applicative functor is, you know what to expect from it, and which capabilities it has.
</p>
<p>
In languages with good support for applicative functors, I would favour an assertion API based on that abstraction, if given a choice. At the moment, though, that's not much of an option. Even <a href="https://hackage.haskell.org/package/HUnit/docs/Test-HUnit-Base.html#t:Assertion">HUnit assertions</a> are based on side effects.
</p>
</div>
<div id="comments">
<hr>
<h2 id="comments-header">
Comments
</h2>
<div class="comment" id="e3269279066146f985c8405f6d3ad286">
<div class="comment-author">Joker_vD</div>
<div class="comment-content">
<p>
Just a reminder: in .NET, method's execution <b>cannot</b> be resumed after an exception is thrown, there is just simply no
way to do this, at all.
Which means that NUnit's Assert.Multiple absolutely cannot work the way you guess it probably does, by running the delegate and
resuming its execution after it throws an exception until the delegate returns.
</p>
<p>
How could it work then? Well, considering that documentation to almost every Assert's method has
"Returns without throwing an exception when inside a multiple assert block" line in it,
I would assume that Assert.Multiple sets a global flag which makes actual assertions to store the failures in some global hidden
context instead on throwing them, then runs the delegate and after it finishes or throws, collects and clears all those failures
from the context and resets the global flag.
</p>
<p>
Cursory inspection of NUnit's source code supports this idea, except that apparently it's not just a boolean flag but a
"depth" counter; and assertions report the failures
<a href="https://github.com/nunit/nunit/blob/62059054137de84b711353765d474779db95f731/src/NUnitFramework/framework/Assert.cs#L371">just the way I've speculated</a>.
I personally hate such side-channels but you have to admit, they allow for some nifty, seemingly impossible magical tricks
(a.k.a. "spooky action at the distance").
</p>
<p>
Also, why do you assume that Unquote would not throw NUnit's assertions?
It literally has "Unquote integrates configuration-free with all exception-based unit testing frameworks including xUnit.net,
NUnit, MbUnit, Fuchu, and MSTest" in its README, and indeed, if you look at
<a href="https://github.com/SwensenSoftware/unquote/blob/78b071043c42372f3693a07e5562520046873ebc/src/Unquote/Assertions.fs">its source code</a>,
you'll see that at runtime it tries to locate any testing framework it's aware of and use its assertions.
More funny party tricks, this time with reflection!
</p>
<p>
I understand that after working in more pure/functional programming environments one does start to slowly forget about
those terrible things, but: those horrorterrors <i>still</i> exist, and people <i>keep making</i> more of them.
Now, if you can, have a good night :)
</p>
</div>
<div class="comment-date">2023-01-31 03:00 UTC</div>
</div>
<div class="comment" id="e0e7c5b258d54c30b87f157e8746150d">
<div class="comment-author"><a href="/">Mark Seemann</a></div>
<div class="comment-content">
<p>
Joker_vD, thank you for explaining those details. I admit that I hadn't thought too deeply about implementation details, for the reasons I briefly mentioned in the post.
</p>
<blockquote>
<p>
"I understand that after working in more pure/functional programming environments one does start to slowly forget about those terrible things"
</p>
</blockquote>
<p>
Yes, that summarises my current thinking well, I'm afraid.
</p>
</div>
<div class="comment-date">2023-01-30 6:49 UTC</div>
</div>
<div class="comment" id="821541be129a4ea7976ab33f71d3637a">
<div class="comment-author"><a href="https://github.com/MaxKot">Max Kiselev</a></div>
<div class="comment-content">
<p>
NUnit has <a href="https://docs.nunit.org/articles/nunit/writing-tests/assertions/classic-assertions/Assert.DoesNotThrow.html">Assert.DoesNotThrow</a>
and Fluent Assertions has <a href="https://fluentassertions.com/exceptions/">.Should().NotThrow()</a>. I did not check Fluent Assertions, but NUnit
does gather failures of Assert.DoesNotThrow inside Assert.Multiple into a multi-error report. One might argue that asserting that a delegate should not
throw is another application of the "explicit is better than implicit" philosophy. Here's what Fluent Assertions has to say on that matter:
</p>
<blockquote>
<p>
"We know that a unit test will fail anyhow if an exception was thrown, but this syntax returns a clearer description of the exception that was thrown
and fits better to the AAA syntax."
</p>
</blockquote>
<p>
As a side note, you might also want to take a look on NUnits Assert.That syntax. It allows to construct complex conditions tested against a single
actual value:
</p>
<p>
<pre style="font-family:Consolas;font-size:13px;color:black;background:white;"><span style="color:blue;">int</span> <span style="color:#1f377f;">actual</span> = 3;
Assert.That (actual, Is.GreaterThan (0).And.LessThanOrEqualTo (2).And.Matches (Has.Property (<span style="color:#a31515;">"P"</span>).EqualTo (<span style="color:#a31515;">"a"</span>)));</pre>
</p>
<p>
A failure is then reported like this:
</p>
<p>
<pre>Expected: greater than 0 and less than or equal to 2 and property P equal to "a"
But was: 3</pre>
</p>
</div>
<div class="comment-date">2023-01-31 18:35 UTC</div>
</div>
<div class="comment" id="815b4f0e18284dccb3ce38dbb476eb4d">
<div class="comment-author"><a href="/">Mark Seemann</a></div>
<div class="comment-content">
<p>
Max, thank you for writing. I have to admit that I never understood the point of <a href="https://docs.nunit.org/articles/nunit/writing-tests/assertions/assertion-models/constraint.html">NUnit's constraint model</a>, but your example clearly illustrates how it may be useful. It enables you to compose assertions.
</p>
<p>
It's interesting to try to understand the underlying reason for that. I took a cursory glance at that <code>IResolveConstraint</code> API, and as far as I can tell, it may form a <a href="/2017/10/06/monoids">monoid</a> (I'm not entirely sure about the <code>ConstraintStatus</code> enum, but even so, it may be 'close enough' to be composable).
</p>
<p>
I can see how that may be useful when making assertions against complex objects (i.e. object composed from other objects).
</p>
<p>
In xUnit.net you'd typically address that problem with custom <a href="https://learn.microsoft.com/dotnet/api/system.collections.generic.iequalitycomparer-1">IEqualityComparers</a>. This is more verbose, but also strikes me as more reusable. One disadvantage of that approach, however, is that when tests fail, the assertion message is typically useless.
</p>
<p>
This is the reason I favour Unquote: Instead of inventing a Boolean algebra(?) from scratch, it uses the existing language and still gives you good error messages. Alas, that only works in F#.
</p>
<p>
In general, though, I'm inclined to think that all of these APIs address symptoms rather than solve real problems. Granted, they're useful whenever you need to make assertions against values that you don't control, but for your own APIs, <a href="/2021/05/03/structural-equality-for-better-tests">a simpler solution is to model values as immutable data with structural equality</a>.
</p>
<p>
Another question is whether aiming for clear assertion messages is optimising for the right concern. At least with TDD, <a href="/2022/12/12/when-do-tests-fail">I don't think that it is</a>.
</p>
</div>
<div class="comment-date">2023-02-02 7:53 UTC</div>
</div>
</div>
<hr>
This blog is totally free, but if you like it, please consider <a href="https://blog.ploeh.dk/support">supporting it</a>.Agileanhttps://blog.ploeh.dk/2023/01/23/agilean2023-01-23T07:55:00+00:00Mark Seemann
<div id="post">
<p>
<em>There are other agile methodologies than scrum.</em>
</p>
<p>
More than twenty years after <a href="https://agilemanifesto.org/">the Agile Manifesto</a> it looks as though there's only one kind of agile process left: <a href="https://en.wikipedia.org/wiki/Scrum_(software_development)">Scrum</a>.
</p>
<p>
I recently held a workshop and as a side remark I mentioned that I don't consider scrum the best development process. This surprised some attendees, who politely inquired about my reasoning.
</p>
<h3 id="8837c4f67d694f93ad0b708cc1739705">
My experience with scrum <a href="#8837c4f67d694f93ad0b708cc1739705" title="permalink">#</a>
</h3>
<p>
The first nine years I worked as a professional programmer, the companies I worked in used various <a href="https://en.wikipedia.org/wiki/Waterfall_model">waterfall</a> processes. When I joined the Microsoft Dynamics Mobile team in 2008 they were already using scrum. That was my first exposure to it, and I liked it. Looking back on it today, we weren't particular dogmatic about the process, being more interested in getting things done.
</p>
<p>
One telling fact is that we took turns being Scrum Master. Every sprint we'd rotate that role.
</p>
<p>
We did test-driven development, and had two-week sprints. This being a Microsoft development organisation, we had a dedicated build master, tech writers, specialised testers, and security reviews.
</p>
<p>
I liked it. It's easily one of the most professional software organisations I've worked in. I think it was a good place to work for many reasons. Scrum may have been a contributing factor, but hardly the only reason.
</p>
<p>
I have no issues with scrum as we practised it then. I recall later attending a presentation by <a href="https://en.wikipedia.org/wiki/Mike_Cohn">Mike Cohn</a> where he outlined four quadrants of team maturity. You'd start with scrum, but use retrospectives to evaluate what worked and what didn't. Then you'd adjust. A mature, self-organising team would arrive at its own process, perhaps initiated with scrum, but now having little resemblance with it.
</p>
<p>
I like scrum when viewed like that. When it becomes rigid and empty ceremony, I don't. If all you do is daily stand-ups, sprints, and backlogs, you may be doing scrum, but probably not agile.
</p>
<h3 id="1bb8e521e78341768ca7f5942f3ace4a">
Continuous deployment <a href="#1bb8e521e78341768ca7f5942f3ace4a" title="permalink">#</a>
</h3>
<p>
After Microsoft I joined a startup so small that formal process was unnecessary. Around that time I also became interested in <a href="https://en.wikipedia.org/wiki/Lean_software_development">lean software development</a>. In the beginning, I learned a lot from <a href="https://www.linkedin.com/in/martin-jul-39a12/">Martin Jul</a> who seemed to use the now-defunct <a href="https://ative.dk/">Ative</a> blog as a public notepad as he was reading works of <a href="https://en.wikipedia.org/wiki/W._Edwards_Deming">Deming</a>. I suppose, if you want a more canonical introduction to the topic, that you might start with one of <a href="http://www.poppendieck.com/">the Poppendiecks'</a> books, but since I've only read <a href="/ref/implementing-lean">Implementing Lean Software Development</a>, that's the only one I can recommend.
</p>
<p>
Around 2014 I returned to a regular customer. The team had, in my absence, been busy implementing <a href="https://en.wikipedia.org/wiki/Continuous_deployment">continuous deployment</a>. Instead of artificial periods like 'sprints' we had a <a href="https://en.wikipedia.org/wiki/Kanban_board">kanban board</a> to keep track of our work. We used a variation of <a href="https://en.wikipedia.org/wiki/Feature_toggle">feature flags</a> and marked features as done when they were complete and in production.
</p>
<p>
Why wait until <em>next</em> Friday if the feature is <em>done, done</em> on a Wednesday? Why wait until the <em>next</em> Monday to identify what to work on next, if you're ready to take on new work on a Thursday? Why not move towards <em>one-piece flow?</em>
</p>
<p>
An effective self-organising team typically already knows what it's doing. Much process is introduced in order to give external stakeholders visibility into what a team is doing.
</p>
<p>
I found, in that organisation, that continuous deployment eliminated most of that need. At one time I asked a stakeholder what he thought of the feature I'd deployed a week before - a feature that <em>he had requested</em>. He replied that he hadn't had time to look at it yet.
</p>
<p>
The usual inquires about status (<em>Is it done yet? When is it done?</em>) were gone. The team moved faster than the stakeholders could keep up. That also gave us <a href="/2022/09/19/when-to-refactor">enough slack to keep the code base in good order</a>. We also used test-driven development throughout (TDD).
</p>
<p>
TDD with continuous deployment and a kanban board strikes me as congenial with the ideas of lean software development, but that's not all.
</p>
<h3 id="9f5e725164f54d32b5d56a28d3b1619e">
Stop-the-line issues <a href="#9f5e725164f54d32b5d56a28d3b1619e" title="permalink">#</a>
</h3>
<p>
An <a href="https://en.wikipedia.org/wiki/Andon_(manufacturing)">andon cord</a> is a central concept in <a href="https://en.wikipedia.org/wiki/Lean_manufacturing">lean manufactoring</a>. If a worker (or anyone, really) discovers a problem during production, he or she pulls the andon cord and <em>stops the production line</em>. Then everyone investigates and determines what to do about the problem. Errors are not allowed to accumulate.
</p>
<p>
I think that I've internalised this notion to such a degree that I only recently connected it to lean software development.
</p>
<p>
In <a href="/2021/06/14/new-book-code-that-fits-in-your-head">Code That Fits in Your Head</a>, I recommend turning compiler warnings into errors at the beginning of a code base. Don't allow warnings to pile up. Do the same with static code analysis and linters.
</p>
<p>
When discussing software engineering with developers, I'm beginning to realise that this runs even deeper.
</p>
<ul>
<li>Turn warnings into errors. Don't allow warnings to accumulate.</li>
<li>The correct number of unhandled exceptions in production is zero. If you observe an unhandled exception in your production logs, fix it. Don't let them accumulate.</li>
<li>The correct number of known bugs is zero. Don't let bugs accumulate.</li>
</ul>
<p>
If you're used to working on a code base with hundreds of known bugs, and frequent exceptions in production, this may sound unrealistic. If you deal with issues as soon as they arise, however, this is not only possible - it's faster.
</p>
<p>
In lean software development, bugs are stop-the-line issues. When something unexpected happens, you stop what you're doing and make fixing the problem the top priority. You build quality in.
</p>
<p>
This has been my modus operandi for years, but I only recently connected the dots to realise that this is a typical lean practice. I may have picked it up from there. Or perhaps it's just common sense.
</p>
<h3 id="e2513b8e32b148cbab8dbd6b75c67348">
Conclusion <a href="#e2513b8e32b148cbab8dbd6b75c67348" title="permalink">#</a>
</h3>
<p>
When Agile was new and exciting, there were <a href="https://en.wikipedia.org/wiki/Extreme_programming">extreme programming</a> and scrum, and possibly some lesser known techniques. Lean was around the corner, but didn't come to my attention, at least, until around 2010. Then it seems to have faded away again.
</p>
<p>
Today, agile looks synonymous with scrum, but I find lean software development more efficient. Why divide work into artificial time periods when you can release continuously? Why <em>plan</em> bug fixing when it's more efficient to stop the line and deal with the problem as it arises?
</p>
<p>
That may sound counter-intuitive, but it works because it prevents technical debt from accumulating.
</p>
<p>
Lean software development is, in my experience, a better agile methodology than scrum.
</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>.In the long runhttps://blog.ploeh.dk/2023/01/16/in-the-long-run2023-01-16T08:28:00+00:00Mark Seemann
<div id="post">
<p>
<em>Software design decisions should be time-aware.</em>
</p>
<p>
A common criticism of modern capitalism is that maximising <a href="https://en.wikipedia.org/wiki/Shareholder_value">shareholder value</a> leads to various detrimental outcomes, both societal, but possibly also for the maximising organisation itself. One major problem is when company leadership is incentivised to optimise stock market price for the next quarter, or other short terms. When considering only the short term, decision makers may (rationally) decide to sacrifice long-term benefits for short-term gains.
</p>
<p>
We often see similar behaviour in democracies. Politicians tend to optimise within a time frame that coincides with the election period. Getting re-elected is more important than good policy in the next period.
</p>
<p>
These observations are crude generalisations. Some democratic politicians and CEOs take longer views. Inherent in the context, however, is an incentive to short-term thinking.
</p>
<p>
This, it strikes me, is frequently the case in software development.
</p>
<p>
Particularly in the context of <a href="https://en.wikipedia.org/wiki/Scrum_(software_development)">scrum</a> there's a focus on delivering at the end of every sprint. I've observed developers and other stakeholders together engage in short-term thinking in order to meet those arbitrary and fictitious deadlines.
</p>
<p>
Even when deadlines are more remote than two weeks, project members rarely think beyond some perceived end date. As I describe in <a href="/2021/06/14/new-book-code-that-fits-in-your-head">Code That Fits in Your Head</a>, a <em>project</em> is rarely is good way to organise software development work. Projects end. Successful software doesn't.
</p>
<p>
Regardless of the specific circumstances, a too myopic focus on near-term goals gives you an incentive to cut corners. To not care about code quality.
</p>
<h3 id="5cd528d178504f2ba849019e5d6d425e">
...we're all dead <a href="#5cd528d178504f2ba849019e5d6d425e" title="permalink">#</a>
</h3>
<p>
As <a href="https://en.wikipedia.org/wiki/John_Maynard_Keynes">Keynes</a> once quipped:
</p>
<blockquote>
<p>
"In the long run we are all dead."
</p>
<footer><cite>John Maynard Keynes</cite></footer>
</blockquote>
<p>
Clearly, while you can be too short-sighted, you can also take too long a view. Sometimes deadlines matter, and software not used makes no-one happy.
</p>
<p>
Working software remains the ultimate test of value, but as I've tried to express many times before, this does <em>not</em> imply that anything else is worthless.
</p>
<p>
You can't measure code quality. <a href="/2019/03/04/code-quality-is-not-software-quality">Code quality isn't software quality</a>. Low code quality <a href="https://martinfowler.com/articles/is-quality-worth-cost.html">slows you down</a>, and that, eventually, costs you money, blood, sweat, and tears.
</p>
<p>
This is, however, not difficult to predict. All it takes is a slightly wider time horizon. Consider the impact of your decisions past the next deadline.
</p>
<h3 id="b0f0f05bd00142379c2d713adde6eb77">
Conclusion <a href="#b0f0f05bd00142379c2d713adde6eb77" title="permalink">#</a>
</h3>
<p>
Don't be too short-sighted, but don't forget the immediate value of what you do. Your <a href="/2019/03/18/the-programmer-as-decision-maker">decisions</a> matter. The impact is not always immediate. Consider what consequences short-term optimisations may have in a longer perspective.
</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>.The IO monadhttps://blog.ploeh.dk/2023/01/09/the-io-monad2023-01-09T07:39:00+00:00Mark Seemann
<div id="post">
<p>
<em>The IO container forms a monad. An article for object-oriented programmers.</em>
</p>
<p>
This article is an instalment in <a href="/2022/03/28/monads">an article series about monads</a>. A previous article described <a href="/2020/06/22/the-io-functor">the IO functor</a>. As is the case with many (but not all) <a href="/2018/03/22/functors">functors</a>, this one also forms a monad.
</p>
<h3 id="bee075f5bf474b099146cbc7c96f4888">
SelectMany <a href="#bee075f5bf474b099146cbc7c96f4888" title="permalink">#</a>
</h3>
<p>
A monad must define either a <em>bind</em> or <em>join</em> function. In C#, monadic bind is called <code>SelectMany</code>. In a recent article, I gave an example of <a href="/2020/06/15/io-container-in-a-parallel-c-universe">what <em>IO</em> might look like in C#</a>. Notice that it already comes with a <code>SelectMany</code> function:
</p>
<p>
<pre><span style="color:blue;">public</span> IO<TResult> <span style="color:#74531f;">SelectMany</span><<span style="color:#2b91af;">TResult</span>>(Func<T, IO<TResult>> <span style="color:#1f377f;">selector</span>)</pre>
</p>
<p>
Unlike other monads, the IO implementation is considered a black box, but if you're interested in a prototypical implementation, I already posted <a href="/2020/07/13/implementation-of-the-c-io-container">a sketch</a> in 2020.
</p>
<h3 id="1ba6a4e6da014fc3a511e71bdba4f0a9">
Query syntax <a href="#1ba6a4e6da014fc3a511e71bdba4f0a9" title="permalink">#</a>
</h3>
<p>
I have also, already, demonstrated <a href="/2020/06/29/syntactic-sugar-for-io">syntactic sugar for IO</a>. In that article, however, I used an implementation of the required <code>SelectMany</code> overload that is more explicit than it has to be. The <a href="/2022/03/28/monads">monad introduction</a> makes the prediction that you can always implement that overload in the same way, and yet here I didn't.
</p>
<p>
That's an oversight on my part. You can implement it like this instead:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> IO<TResult> <span style="color:#74531f;">SelectMany</span><<span style="color:#2b91af;">T</span>, <span style="color:#2b91af;">U</span>, <span style="color:#2b91af;">TResult</span>>(
<span style="color:blue;">this</span> IO<T> <span style="color:#1f377f;">source</span>,
Func<T, IO<U>> <span style="color:#1f377f;">k</span>,
Func<T, U, TResult> <span style="color:#1f377f;">s</span>)
{
<span style="color:#8f08c4;">return</span> source.SelectMany(<span style="color:#1f377f;">x</span> => k(x).Select(<span style="color:#1f377f;">y</span> => s(x, y)));
}</pre>
</p>
<p>
Indeed, the conjecture from the introduction still holds.
</p>
<h3 id="f234f9e9d3724a30b8465d176a0d98a6">
Join <a href="#f234f9e9d3724a30b8465d176a0d98a6" title="permalink">#</a>
</h3>
<p>
In <a href="/2022/03/28/monads">the introduction</a> you learned that if you have a <code>Flatten</code> or <code>Join</code> function, you can implement <code>SelectMany</code>, and the other way around. Since we've already defined <code>SelectMany</code> for <code>IO<T></code>, we can use that to implement <code>Join</code>. In this article I use the name <code>Join</code> rather than <code>Flatten</code>. This is an arbitrary choice that doesn't impact behaviour. Perhaps you find it confusing that I'm inconsistent, but I do it in order to demonstrate that the behaviour is the same even if the name is different.
</p>
<p>
The concept of a monad is universal, but the names used to describe its components differ from language to language. What C# calls <code>SelectMany</code>, Scala calls <code>flatMap</code>, and what <a href="https://www.haskell.org/">Haskell</a> calls <code>join</code>, other languages may call <code>Flatten</code>.
</p>
<p>
You can always implement <code>Join</code> by using <code>SelectMany</code> with the identity function:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> IO<T> <span style="color:#74531f;">Join</span><<span style="color:#2b91af;">T</span>>(<span style="color:blue;">this</span> IO<IO<T>> <span style="color:#1f377f;">source</span>)
{
<span style="color:#8f08c4;">return</span> source.SelectMany(<span style="color:#1f377f;">x</span> => x);
}</pre>
</p>
<p>
In C# the identity function is <a href="/2015/08/03/idiomatic-or-idiosyncratic">idiomatically</a> given as the lambda expression <code><span style="color:#1f377f;">x</span> => x</code> since C# doesn't come with a built-in identity function.
</p>
<h3 id="c57bcf1e74144046bc7191280d78519b">
Return <a href="#c57bcf1e74144046bc7191280d78519b" title="permalink">#</a>
</h3>
<p>
Apart from monadic bind, a monad must also define a way to put a normal value into the monad. Conceptually, I call this function <em>return</em> (because that's the name that Haskell uses). In <a href="/2020/06/22/the-io-functor">the IO functor</a> article, I wrote that the <code>IO<T></code> constructor corresponds to <em>return</em>. That's not strictly true, though, since the constructor takes a <code>Func<T></code> and not a <code>T</code>.
</p>
<p>
This issue is, however, trivially addressed:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> IO<T> <span style="color:#74531f;">Return</span><<span style="color:#2b91af;">T</span>>(T <span style="color:#1f377f;">x</span>)
{
<span style="color:#8f08c4;">return</span> <span style="color:blue;">new</span> IO<T>(() => x);
}</pre>
</p>
<p>
Take the value <code>x</code> and wrap it in a lazily-evaluated function.
</p>
<h3 id="e0548aa855224081a5c1c3ec80f23951">
Laws <a href="#e0548aa855224081a5c1c3ec80f23951" title="permalink">#</a>
</h3>
<p>
While <a href="/2020/07/06/referential-transparency-of-io">IO values are referentially transparent</a> you can't compare them. You also can't 'run' them by other means than running a program. This makes it hard to talk meaningfully about the <a href="/2022/04/11/monad-laws">monad laws</a>.
</p>
<p>
For example, the left identity law is:
</p>
<p>
<pre>return >=> h ≡ h</pre>
</p>
<p>
Note the implied equality. The composition of <code>return</code> and <code>h</code> should be equal to <code>h</code>, for some reasonable definition of equality. How do we define that?
</p>
<p>
Somehow we must imagine that two alternative compositions would produce the same observable effects <a href="https://en.wikipedia.org/wiki/Ceteris_paribus">ceteris paribus</a>. If you somehow imagine that you have two parallel universes, one with one composition (say <code>return >=> h</code>) and one with another (<code>h</code>), if all else in those two universes were equal, then you would observe no difference in behaviour.
</p>
<p>
That may be useful as a thought experiment, but isn't particularly practical. Unfortunately, due to side effects, things <em>do</em> change when non-deterministic behaviour and side effects are involved. As a simple example, consider an IO action that gets the current time and prints it to the console. That involves both non-determinism and a side effect.
</p>
<p>
In Haskell, that's a straightforward composition of two <code>IO</code> actions:
</p>
<p>
<pre>> h () = getCurrentTime >>= print</pre>
</p>
<p>
How do we compare two compositions? By running them?
</p>
<p>
<pre>> return () >>= h
2022-06-25 16:47:30.6540847 UTC
> h ()
2022-06-25 16:47:37.5281265 UTC</pre>
</p>
<p>
The outputs are not the same, because time goes by. Can we thereby conclude that the monad laws don't hold for IO? Not quite.
</p>
<p>
The IO Container is referentially transparent, but evaluation isn't. Thus, we have to pretend that two alternatives will lead to the same evaluation behaviour, all things being equal.
</p>
<p>
This property seems to hold for both the identity and associativity laws. Whether or not you compose with <em>return</em>, or in which evaluation order you compose actions, it doesn't affect the outcome.
</p>
<p>
For completeness sake, the <a href="/2020/07/13/implementation-of-the-c-io-container">C# implementation sketch</a> is just a wrapper over a <code>Func<T></code>. We can also think of such a function as a function from <a href="/2018/01/15/unit-isomorphisms">unit</a> to <code>T</code> - in pseudo-C# <code>() => T</code>. That's a function; in other words: <a href="/2022/11/14/the-reader-monad">The Reader monad</a>. We already know that the Reader monad obeys the monad laws, so the C# implementation, at least, should be okay.
</p>
<h3 id="74154d1a95a44a91a8d534fbfda59d8d">
Conclusion <a href="#74154d1a95a44a91a8d534fbfda59d8d" title="permalink">#</a>
</h3>
<p>
IO forms a monad, among other abstractions. This is what enables Haskell programmers to compose an arbitrary number of impure actions with monadic bind without ever having to force evaluation. In C# <a href="/2020/06/15/io-container-in-a-parallel-c-universe">it might have looked the same</a>, except that it doesn't.
</p>
<p>
<strong>Next:</strong> <a href="/2023/02/27/test-data-generator-monad">Test Data Generator monad</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>.Adding NuGet packages when offlinehttps://blog.ploeh.dk/2023/01/02/adding-nuget-packages-when-offline2023-01-02T05:41:00+00:00Mark Seemann
<div id="post">
<p>
<em>A fairly trivial technical detective story.</em>
</p>
<p>
I was recently in an air plane, writing code, when I realised that I needed to add a couple of NuGet packages to my code base. I was on one of those less-travelled flights in Europe, on board an <a href="https://en.wikipedia.org/wiki/Embraer_E-Jet_family">Embraer E190</a>, and as is usually the case on those 1½-hour flights, there was no WiFi.
</p>
<p>
Adding a NuGet package typically requires that you're online so that the tools can query the relevant NuGet repository. You'll need to download the package, so if you're offline, you're just out of luck, right?
</p>
<p>
Fortunately, I'd previously used the packages I needed in other projects, on the same laptop. While <a href="/2014/01/29/nuget-package-restore-considered-harmful">I'm no fan of package restore</a>, I know that the local NuGet tools cache packages somewhere on the local machine.
</p>
<p>
So, perhaps I could entice the tools to reuse a cached package...
</p>
<p>
First, I simply tried adding a package that I needed:
</p>
<p>
<pre>$ dotnet add package unquote
Determining projects to restore...
Writing C:\Users\mark\AppData\Local\Temp\tmpF3C.tmp
info : X.509 certificate chain validation will use the default trust store selected by .NET.
info : Adding PackageReference for package 'unquote' into project '[redacted]'.
error: Unable to load the service index for source https://api.nuget.org/v3/index.json.
error: No such host is known. (api.nuget.org:443)
error: No such host is known.</pre>
</p>
<p>
Fine plan, but no success.
</p>
<p>
Clearly the <code>dotnet</code> tool was trying to access <code>api.nuget.org</code>, which, obviously, couldn't be reached because my laptop was in flight mode. It occurred to me, though, that the reason that the tool was querying <code>api.nuget.org</code> was that it wanted to see which version of the package was the most recent. After all, I hadn't specified a version.
</p>
<p>
What if I were to specify a version? Would the tool use the cached version of the package?
</p>
<p>
That seemed worth a try, but which versions did I already have on my laptop?
</p>
<p>
I don't go around remembering which version numbers I've used of various NuGet packages, but I expected the NuGet tooling to have that information available, somewhere.
</p>
<p>
But where? Keep in mind that I was offline, so couldn't easily look this up.
</p>
<p>
On the other hand, I knew that these days, most Windows applications keep data of that kind somewhere in <code>AppData</code>, so I started spelunking around there, looking for something that might be promising.
</p>
<p>
After looking around a bit, I found a subdirectory named <code>AppData\Local\NuGet\v3-cache</code>. This directory contained a handful of subdirectories obviously named with GUIDs. Each of these contained a multitude of <code>.dat</code> files. The names of those files, however, looked promising:
</p>
<p>
<pre>list_antlr_index.dat
list_autofac.dat
list_autofac.extensions.dependencyinjection.dat
list_autofixture.automoq.dat
list_autofixture.automoq_index.dat
list_autofixture.automoq_range_2.0.0-3.6.7.dat
list_autofixture.automoq_range_3.30.3-3.50.5.dat
list_autofixture.automoq_range_3.50.6-4.17.0.dat
list_autofixture.automoq_range_3.6.8-3.30.2.dat
list_autofixture.dat
...</pre>
</p>
<p>
and so on.
</p>
<p>
These names were clearly(?) named <code>list_[package-name].dat</code> or <code>list_[package-name]_index.dat</code>, so I started looking around for one named after the package I was looking for (<a href="https://www.nuget.org/packages/Unquote/">Unquote</a>).
</p>
<p>
Often, both files are present, which was also the case for Unquote.
</p>
<p>
<pre>$ ls list_unquote* -l
-rw-r--r-- 1 mark 197609 348 Oct 1 18:38 list_unquote.dat
-rw-r--r-- 1 mark 197609 42167 Sep 23 21:29 list_unquote_index.dat</pre>
</p>
<p>
As you can tell, <code>list_unquote_index.dat</code> is much larger than <code>list_unquote.dat</code>. Since I didn't know what the format of these files were, I decided to look at the smallest one first. It had this content:
</p>
<p>
<pre>{
"versions": [
"1.3.0",
"2.0.0",
"2.0.1",
"2.0.2",
"2.0.3",
"2.1.0",
"2.1.1",
"2.2.0",
"2.2.1",
"2.2.2",
"3.0.0",
"3.1.0",
"3.1.1",
"3.1.2",
"3.2.0",
"4.0.0",
"5.0.0",
"6.0.0-rc.1",
"6.0.0-rc.2",
"6.0.0-rc.3",
"6.0.0",
"6.1.0"
]
}</pre>
</p>
<p>
A list of versions. Sterling. It looked as though version 6.1.0 was the most recent one on my machine, so I tried to add that one to my code base:
</p>
<p>
<pre>$ dotnet add package unquote --version 6.1.0
Determining projects to restore...
Writing C:\Users\mark\AppData\Local\Temp\tmp815D.tmp
info : X.509 certificate chain validation will use the default trust store selected by .NET.
info : Adding PackageReference for package 'unquote' into project '[redacted]'.
info : Restoring packages for [redacted]...
info : Package 'unquote' is compatible with all the specified frameworks in project '[redacted]'.
info : PackageReference for package 'unquote' version '6.1.0' added to file '[redacted]'.
info : Generating MSBuild file [redacted].
info : Writing assets file to disk. Path: [redacted]
log : Restored [redacted] (in 397 ms).</pre>
</p>
<p>
Jolly good! That worked.
</p>
<p>
This way I managed to install all the NuGet packages I needed. This was fortunate, because I had so little time to transfer to my connecting flight that I never got to open the laptop before I was airborne again - in another E190 without WiFi, and another session of offline programming.
</p>
</div>
<div id="comments">
<hr>
<h2 id="comments-header">
Comments
</h2>
<div class="comment" id="7387859cda784fdf8612ddb34666d49b">
<div class="comment-author"><a href="https://github.com/asherber">Aaron Sherber</a></div>
<div class="comment-content">
<p>
A postscript to your detective story might note that the primary NuGet cache lives at <code>%userprofile%\.nuget\packages</code> on Windows and <code>~/.nuget/packages</code> on Mac and Linux. The folder names there are much easier to decipher than the folders and files in the http cache.
</p>
</div>
<div class="comment-date">2023-01-02 13:46 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>.Functors as invariant functorshttps://blog.ploeh.dk/2022/12/26/functors-as-invariant-functors2022-12-26T13:05:00+00:00Mark Seemann
<div id="post">
<p>
<em>A most likely useless set of invariant functors that nonetheless exist.</em>
</p>
<p>
This article is part of <a href="/2022/08/01/invariant-functors">a series of articles about invariant functors</a>. An invariant functor is a <a href="/2018/03/22/functors">functor</a> that is neither covariant nor contravariant. See the series introduction for more details.
</p>
<p>
It turns out that all <a href="/2018/03/22/functors">functors</a> are also invariant functors.
</p>
<p>
Is this useful? Let me be honest and say that if it is, I'm not aware of it. Thus, if you're interested in practical applications, you can stop reading here. This article contains nothing of practical use - as far as I can tell.
</p>
<h3 id="d748d07afe5342e9847e858849053911">
Because it's there <a href="#d748d07afe5342e9847e858849053911" title="permalink">#</a>
</h3>
<p>
Why describe something of no practical use?
</p>
<p>
Why do some people climb <a href="https://en.wikipedia.org/wiki/Mount_Everest">Mount Everest</a>? <em>Because it's there</em>, or for other irrational reasons. Which is fine. I've no personal goals that involve climbing mountains, but <a href="/2020/10/12/subjectivity">I happily engage in other irrational and subjective activities</a>.
</p>
<p>
One of them, apparently, is to write articles of software constructs of no practical use, <em>because it's there</em>.
</p>
<p>
All functors are also invariant functors, even if that's of no practical use. That's just the way it is. This article explains how, and shows a few (useless) examples.
</p>
<p>
I'll start with a few <a href="https://www.haskell.org/">Haskell</a> examples and then move on to showing the equivalent examples in C#. If you're unfamiliar with Haskell, you can skip that section.
</p>
<h3 id="268965f94deb48d79335afea6e9b85e4">
Haskell package <a href="#268965f94deb48d79335afea6e9b85e4" title="permalink">#</a>
</h3>
<p>
For Haskell you can find an existing definition and implementations in the <a href="https://hackage.haskell.org/package/invariant">invariant</a> package. It already makes most common functors <code>Invariant</code> instances, including <code>[]</code> (list), <code>Maybe</code>, and <code>Either</code>. Here's an example of using <code>invmap</code> with a small list:
</p>
<p>
<pre>ghci> invmap secondsToNominalDiffTime nominalDiffTimeToSeconds [0.1, 60]
[0.1s,60s]</pre>
</p>
<p>
Here I'm using the <a href="https://hackage.haskell.org/package/time">time</a> package to convert fixed-point decimals into <code>NominalDiffTime</code> values.
</p>
<p>
How is this different from normal functor mapping with <code>fmap</code>? In observable behaviour, it's not:
</p>
<p>
<pre>ghci> fmap secondsToNominalDiffTime [0.1, 60]
[0.1s,60s]</pre>
</p>
<p>
When invariantly mapping a functor, only the covariant mapping function <code>a -> b</code> is used. Here, that's <code>secondsToNominalDiffTime</code>. The contravariant mapping function <code>b -> a</code> (<code>nominalDiffTimeToSeconds</code>) is simply ignored.
</p>
<p>
While the <em>invariant</em> package already defines certain common functors as <code>Invariant</code> instances, every <code>Functor</code> instance can be converted to an <code>Invariant</code> instance. There are two ways to do that: <code>invmapFunctor</code> and <code>WrappedFunctor</code>.
</p>
<p>
In order to demonstrate, we need a custom <code>Functor</code> instance. This one should do:
</p>
<p>
<pre>data Pair a = Pair (a, a) deriving (Eq, Show, Functor)</pre>
</p>
<p>
If you just want to perform an ad-hoc invariant mapping, you can use <code>invmapFunctor</code>:
</p>
<p>
<pre>ghci> invmapFunctor secondsToNominalDiffTime nominalDiffTimeToSeconds $ Pair (0.1, 60)
Pair (0.1s,60s)</pre>
</p>
<p>
I can't think of any reason to do this, but it's possible.
</p>
<p>
<code>WrappedFunctor</code> is perhaps marginally more relevant. If you run into a function that takes an <code>Invariant</code> argument, you can convert any <code>Functor</code> to an <code>Invariant</code> instance by wrapping it in <code>WrappedFunctor</code>:
</p>
<p>
<pre>ghci> invmap secondsToNominalDiffTime nominalDiffTimeToSeconds $ WrapFunctor $ Pair (0.1, 60)
WrapFunctor {unwrapFunctor = Pair (0.1s,60s)}</pre>
</p>
<p>
A realistic, useful example still escapes me, but there it is.
</p>
<h3 id="2578032e937f4a68997f10b0e2412ffb">
Pair as an invariant functor in C# <a href="#2578032e937f4a68997f10b0e2412ffb" title="permalink">#</a>
</h3>
<p>
What would the above Haskell example look like in C#? First, we're going to need a <code>Pair</code> data structure:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">sealed</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">Pair</span><<span style="color:#2b91af;">T</span>>
{
<span style="color:blue;">public</span> <span style="color:#2b91af;">Pair</span>(T x, T y)
{
X = x;
Y = y;
}
<span style="color:blue;">public</span> T X { <span style="color:blue;">get</span>; }
<span style="color:blue;">public</span> T Y { <span style="color:blue;">get</span>; }
<span style="color:green;">// More members follow...</span></pre>
</p>
<p>
Making <code>Pair<T></code> a functor is so easy that Haskell can do it automatically with the <code>DeriveFunctor</code> extension. In C# you must explicitly write the function:
</p>
<p>
<pre><span style="color:blue;">public</span> Pair<T1> Select<<span style="color:#2b91af;">T1</span>>(Func<T, T1> selector)
{
<span style="color:blue;">return</span> <span style="color:blue;">new</span> Pair<T1>(selector(X), selector(Y));
}</pre>
</p>
<p>
An example equivalent to the above <code>fmap</code> example might be this, here expressed as a unit test:
</p>
<p>
<pre>[Fact]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> FunctorExample()
{
Pair<<span style="color:blue;">long</span>> sut = <span style="color:blue;">new</span> Pair<<span style="color:blue;">long</span>>(
TimeSpan.TicksPerSecond / 10,
TimeSpan.TicksPerSecond * 60);
Pair<TimeSpan> actual = sut.Select(ticks => <span style="color:blue;">new</span> TimeSpan(ticks));
Assert.Equal(
<span style="color:blue;">new</span> Pair<TimeSpan>(
TimeSpan.FromSeconds(.1),
TimeSpan.FromSeconds(60)),
actual);
}</pre>
</p>
<p>
You can trivially make <code>Pair<T></code> an invariant functor by giving it a function equivalent to <code>invmap</code>. As I outlined in <a href="/2022/08/01/invariant-functors">the introduction</a> it's possible to add an <code>InvMap</code> method to the class, but it might be more <a href="/2015/08/03/idiomatic-or-idiosyncratic">idiomatic</a> to instead add a <code>Select</code> overload:
</p>
<p>
<pre><span style="color:blue;">public</span> Pair<T1> Select<<span style="color:#2b91af;">T1</span>>(Func<T, T1> tToT1, Func<T1, T> t1ToT)
{
<span style="color:blue;">return</span> Select(tToT1);
}</pre>
</p>
<p>
Notice that this overload simply ignores the <code>t1ToT</code> argument and delegates to the normal <code>Select</code> overload. That's consistent with the Haskell package. This unit test shows an examples:
</p>
<p>
<pre>[Fact]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> InvariantFunctorExample()
{
Pair<<span style="color:blue;">long</span>> sut = <span style="color:blue;">new</span> Pair<<span style="color:blue;">long</span>>(
TimeSpan.TicksPerSecond / 10,
TimeSpan.TicksPerSecond * 60);
Pair<TimeSpan> actual =
sut.Select(ticks => <span style="color:blue;">new</span> TimeSpan(ticks), ts => ts.Ticks);
Assert.Equal(
<span style="color:blue;">new</span> Pair<TimeSpan>(
TimeSpan.FromSeconds(.1),
TimeSpan.FromSeconds(60)),
actual);
}</pre>
</p>
<p>
I can't think of a reason to do this in C#. In Haskell, at least, you have enough power of abstraction to describe something as simply an <code>Invariant</code> functor, and then let client code decide whether to use <code>Maybe</code>, <code>[]</code>, <code>Endo</code>, or a custom type like <code>Pair</code>. You can't do that in C#, so the abstraction is even less useful here.
</p>
<h3 id="8dbd7bd0f9c64fa5a0ac7c397617521b">
Conclusion <a href="#8dbd7bd0f9c64fa5a0ac7c397617521b" title="permalink">#</a>
</h3>
<p>
All functors are invariant functors. You simply use the normal functor mapping function (<code>fmap</code> in Haskell, <code>map</code> in many other languages, <code>Select</code> in C#). This enables you to add an invariant mapping (<code>invmap</code>) that only uses the covariant argument (<code>a -> b</code>) and ignores the contravariant argument (<code>b -> a</code>).
</p>
<p>
Invariant functors are, however, not particularly useful, so neither is this result. Still, it's there, so deserves a mention. The situation is similar for the next article.
</p>
<p>
<strong>Next:</strong> <a href="/2023/02/06/contravariant-functors-as-invariant-functors">Contravariant functors as invariant functors</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>.Error-accumulating composable assertions in C#https://blog.ploeh.dk/2022/12/19/error-accumulating-composable-assertions-in-c2022-12-19T08:39:00+00:00Mark Seemann
<div id="post">
<p>
<em>Perhaps the list monoid is all you need for non-short-circuiting assertions.</em>
</p>
<p>
This article is the second instalment in a small articles series about <a href="/2022/11/07/applicative-assertions">applicative assertions</a>. It explores a way to compose assertions in such a way that failure messages accumulate rather than short-circuit. It assumes that you've read the <a href="/2022/11/07/applicative-assertions">article series introduction</a> and the <a href="/2022/11/28/an-initial-proof-of-concept-of-applicative-assertions-in-c">previous article</a>.
</p>
<p>
Unsurprisingly, the previous article showed that you can use an <a href="/2018/10/01/applicative-functors">applicative functor</a> to create composable assertions that don't short-circuit. It also concluded that, in C# at least, the API is awkward.
</p>
<p>
This article explores a simpler API.
</p>
<h3 id="dc146cd5b792473db7f7e64cac3c4607">
A clue left by the proof of concept <a href="#dc146cd5b792473db7f7e64cac3c4607" title="permalink">#</a>
</h3>
<p>
The previous article's proof of concept left a clue suggesting a simpler API. Consider, again, how the rather horrible <code>RunAssertions</code> method decides whether or not to throw an exception:
</p>
<p>
<pre><span style="color:blue;">string</span> errors = composition.Match(
onFailure: f => <span style="color:blue;">string</span>.Join(Environment.NewLine, f),
onSuccess: _ => <span style="color:blue;">string</span>.Empty);
<span style="color:blue;">if</span> (!<span style="color:blue;">string</span>.IsNullOrEmpty(errors))
<span style="color:blue;">throw</span> <span style="color:blue;">new</span> Exception(errors);</pre>
</p>
<p>
Even though <code><span style="color:#2b91af;">Validated</span><<span style="color:#2b91af;">F</span>, <span style="color:#2b91af;">S</span>></code> is a <a href="https://en.wikipedia.org/wiki/Tagged_union">sum type</a>, the <code>RunAssertions</code> method declines to take advantage of that. Instead, it reduces <code>composition</code> to a simple type: A <code>string</code>. It then decides to throw an exception if the <code>errors</code> value is not null or empty.
</p>
<p>
This suggests that using a sum type may not be necessary to distinguish between the success and the failure case. Rather, an empty error string is all it takes to indicate success.
</p>
<h3 id="801897c3ffc0455e8e7a7ac7531f2be3">
Non-empty errors <a href="#801897c3ffc0455e8e7a7ac7531f2be3" title="permalink">#</a>
</h3>
<p>
The proof-of-concept assertion type is currently defined as <code>Validated</code> with a particular combination of type arguments: <code>Validated<IReadOnlyCollection<<span style="color:blue;">string</span>>, Unit></code>. Consider, again, this <code>Match</code> expression:
</p>
<p>
<pre><span style="color:blue;">string</span> errors = composition.Match(
onFailure: f => <span style="color:blue;">string</span>.Join(Environment.NewLine, f),
onSuccess: _ => <span style="color:blue;">string</span>.Empty);</pre>
</p>
<p>
Does an empty string unambiguously indicate success? Or is it possible to arrive at an empty string even if <code>composition</code> actually represents a failure case?
</p>
<p>
You can arrive at an empty string from a failure case if the collection of error messages is empty. Consider the type argument that takes the place of the <code>F</code> generic type: <code>IReadOnlyCollection<<span style="color:blue;">string</span>></code>. A collection of this type can be empty, which would also cause the above <code>Match</code> to produce an empty string.
</p>
<p>
Even so, the proof-of-concept works in practice. The reason it works is that failure cases will never have empty assertion messages. We know this because (in the proof-of-concept code) only two functions produce assertions, and they each populate the error message collection with a string. You may want to revisit the <code>AssertTrue</code> and <code>AssertEqual</code> functions in the <a href="/2022/11/28/an-initial-proof-of-concept-of-applicative-assertions-in-c">previous article</a> to convince yourself that this is true.
</p>
<p>
This is a good example of knowledge that 'we' as developers know, but the code currently doesn't capture. Having to deal with such knowledge taxes your working memory, so why not <a href="/encapsulation-and-solid">encapsulate</a> such information in the type itself?
</p>
<p>
How do you encapsulate the knowledge that a collection is never empty? Introduce a <code>NotEmptyCollection</code> collection. I'll reuse the class from the article <a href="/2017/12/11/semigroups-accumulate">Semigroups accumulate</a> and add a <code>Concat</code> instance method:
</p>
<p>
<pre><span style="color:blue;">public</span> NotEmptyCollection<T> Concat(NotEmptyCollection<T> other)
{
<span style="color:blue;">return</span> <span style="color:blue;">new</span> NotEmptyCollection<T>(Head, Tail.Concat(other).ToArray());
}</pre>
</p>
<p>
Since the two assertion-producing functions both supply an error message in the failure case, it's trivial to change them to return <code>Validated<NotEmptyCollection<<span style="color:blue;">string</span>>, Unit></code> - just change the types used:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> Validated<NotEmptyCollection<<span style="color:blue;">string</span>>, Unit> AssertTrue(
<span style="color:blue;">this</span> <span style="color:blue;">bool</span> condition,
<span style="color:blue;">string</span> message)
{
<span style="color:blue;">return</span> condition
? Succeed<NotEmptyCollection<<span style="color:blue;">string</span>>, Unit>(Unit.Value)
: Fail<NotEmptyCollection<<span style="color:blue;">string</span>>, Unit>(<span style="color:blue;">new</span> NotEmptyCollection<<span style="color:blue;">string</span>>(message));
}
<span style="color:blue;">public</span> <span style="color:blue;">static</span> Validated<NotEmptyCollection<<span style="color:blue;">string</span>>, Unit> AssertEqual<<span style="color:#2b91af;">T</span>>(
T expected,
T actual)
{
<span style="color:blue;">return</span> Equals(expected, actual)
? Succeed<NotEmptyCollection<<span style="color:blue;">string</span>>, Unit>(Unit.Value)
: Fail<NotEmptyCollection<<span style="color:blue;">string</span>>, Unit>(
<span style="color:blue;">new</span> NotEmptyCollection<<span style="color:blue;">string</span>>(<span style="color:#a31515;">$"Expected </span>{expected}<span style="color:#a31515;">, but got </span>{actual}<span style="color:#a31515;">."</span>));
}</pre>
</p>
<p>
This change guarantees that the <code>RunAssertions</code> method only produces an empty <code>errors</code> string in success cases.
</p>
<h3 id="e5097dc5d94f4a1480eeaf483ac08336">
Error collection isomorphism <a href="#e5097dc5d94f4a1480eeaf483ac08336" title="permalink">#</a>
</h3>
<p>
Assertions are still defined by the <code>Validated</code> sum type, but the <em>success</em> case carries no information: <code>Validated<NotEmptyCollection<T>, Unit></code>, and the <em>failure</em> case is always guaranteed to contain at least one error message.
</p>
<p>
This suggests that a simpler representation is possible: One that uses a normal collection of errors, and where an empty collection indicates an absence of errors:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">Asserted</span><<span style="color:#2b91af;">T</span>>
{
<span style="color:blue;">public</span> <span style="color:#2b91af;">Asserted</span>() : <span style="color:blue;">this</span>(Array.Empty<T>())
{
}
<span style="color:blue;">public</span> <span style="color:#2b91af;">Asserted</span>(T error) : <span style="color:blue;">this</span>(<span style="color:blue;">new</span>[] { error })
{
}
<span style="color:blue;">public</span> <span style="color:#2b91af;">Asserted</span>(IReadOnlyCollection<T> errors)
{
Errors = errors;
}
<span style="color:blue;">public</span> Asserted<T> And(Asserted<T> other)
{
<span style="color:blue;">if</span> (other <span style="color:blue;">is</span> <span style="color:blue;">null</span>)
<span style="color:blue;">throw</span> <span style="color:blue;">new</span> ArgumentNullException(nameof(other));
<span style="color:blue;">return</span> <span style="color:blue;">new</span> Asserted<T>(Errors.Concat(other.Errors).ToList());
}
<span style="color:blue;">public</span> IReadOnlyCollection<T> Errors { <span style="color:blue;">get</span>; }
}</pre>
</p>
<p>
The <code><span style="color:#2b91af;">Asserted</span><<span style="color:#2b91af;">T</span>></code> class is scarcely more than a glorified wrapper around a normal collection, but it's isomorphic to <code>Validated<NotEmptyCollection<T>, Unit></code>, which the following two functions prove:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> Asserted<T> FromValidated<<span style="color:#2b91af;">T</span>>(<span style="color:blue;">this</span> Validated<NotEmptyCollection<T>, Unit> v)
{
<span style="color:blue;">return</span> v.Match(
failures => <span style="color:blue;">new</span> Asserted<T>(failures),
_ => <span style="color:blue;">new</span> Asserted<T>());
}
<span style="color:blue;">public</span> <span style="color:blue;">static</span> Validated<NotEmptyCollection<T>, Unit> ToValidated<<span style="color:#2b91af;">T</span>>(<span style="color:blue;">this</span> Asserted<T> a)
{
<span style="color:blue;">if</span> (a.Errors.Any())
{
<span style="color:blue;">var</span> errors = <span style="color:blue;">new</span> NotEmptyCollection<T>(
a.Errors.First(),
a.Errors.Skip(1).ToArray());
<span style="color:blue;">return</span> Validated.Fail<NotEmptyCollection<T>, Unit>(errors);
}
<span style="color:blue;">else</span>
<span style="color:blue;">return</span> Validated.Succeed<NotEmptyCollection<T>, Unit>(Unit.Value);
}</pre>
</p>
<p>
You can translate back and forth between <code>Validated<NotEmptyCollection<T>, Unit></code> and <code>Asserted<T></code> without loss of information.
</p>
<p>
A collection, however, gives rise to a <a href="/2017/10/06/monoids">monoid</a>, which suggests a much simpler way to compose assertions than using an applicative functor.
</p>
<h3 id="0ccfc89ad23f4b95932637723ff3c29a">
Asserted truth <a href="#0ccfc89ad23f4b95932637723ff3c29a" title="permalink">#</a>
</h3>
<p>
You can now rewrite the assertion-producing functions to return <code>Asserted<<span style="color:blue;">string</span>></code> instead of <code>Validated<NotEmptyCollection<<span style="color:blue;">string</span>>, Unit></code>.
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> Asserted<<span style="color:blue;">string</span>> True(<span style="color:blue;">bool</span> condition, <span style="color:blue;">string</span> message)
{
<span style="color:blue;">return</span> condition ? <span style="color:blue;">new</span> Asserted<<span style="color:blue;">string</span>>() : <span style="color:blue;">new</span> Asserted<<span style="color:blue;">string</span>>(message);
}</pre>
</p>
<p>
This <code>Asserted.True</code> function returns no error messages when <code>condition</code> is <code>true</code>, but a collection with the single element <code>message</code> when it's <code>false</code>.
</p>
<p>
You can use it in a unit test like this:
</p>
<p>
<pre><span style="color:blue;">var</span> assertResponse = Asserted.True(
deleteResp.IsSuccessStatusCode,
<span style="color:#a31515;">$"Actual status code: </span>{deleteResp.StatusCode}<span style="color:#a31515;">."</span>);</pre>
</p>
<p>
You'll see how <code>assertResponse</code> composes with another assertion later in this article. The example continues from <a href="/2022/11/28/an-initial-proof-of-concept-of-applicative-assertions-in-c">the previous article</a>. It's the same test from the same code base.
</p>
<h3 id="519d7e0d757f4dceb6a2833c09d019d8">
Asserted equality <a href="#519d7e0d757f4dceb6a2833c09d019d8" title="permalink">#</a>
</h3>
<p>
You can also rewrite the other assertion-producing function in the same way:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> Asserted<<span style="color:blue;">string</span>> Equal(<span style="color:blue;">object</span> expected, <span style="color:blue;">object</span> actual)
{
<span style="color:blue;">if</span> (Equals(expected, actual))
<span style="color:blue;">return</span> <span style="color:blue;">new</span> Asserted<<span style="color:blue;">string</span>>();
<span style="color:blue;">return</span> <span style="color:blue;">new</span> Asserted<<span style="color:blue;">string</span>>(<span style="color:#a31515;">$"Expected </span>{expected}<span style="color:#a31515;">, but got </span>{actual}<span style="color:#a31515;">."</span>);
}</pre>
</p>
<p>
Again, when the assertion passes, it returns no errors; otherwise, it returns a collection with a single error message.
</p>
<p>
Using it may look like this:
</p>
<p>
<pre><span style="color:blue;">var</span> getResp = <span style="color:blue;">await</span> api.CreateClient().GetAsync(address);
<span style="color:blue;">var</span> assertState = Asserted.Equal(HttpStatusCode.NotFound, getResp.StatusCode);</pre>
</p>
<p>
At this point, each of the assertions are objects that represent a verification step. By themselves, they neither pass nor fail the test. You have to execute them to reach a verdict.
</p>
<h3 id="29825aed26124471803324863ea7d897">
Evaluating assertions <a href="#29825aed26124471803324863ea7d897" title="permalink">#</a>
</h3>
<p>
The above code listing of the <code><span style="color:#2b91af;">Asserted</span><<span style="color:#2b91af;">T</span>></code> class already shows how to combine two <code><span style="color:#2b91af;">Asserted</span><<span style="color:#2b91af;">T</span>></code> objects into one. The <code>And</code> instance method is a binary operation that, together with the parameterless constructor, makes <code><span style="color:#2b91af;">Asserted</span><<span style="color:#2b91af;">T</span>></code> a <a href="/2017/10/06/monoids">monoid</a>.
</p>
<p>
Once you've combined all assertions into a single <code><span style="color:#2b91af;">Asserted</span><<span style="color:#2b91af;">T</span>></code> object, you need to <code>Run</code> it to produce a test outcome:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> <span style="color:blue;">void</span> Run(<span style="color:blue;">this</span> Asserted<<span style="color:blue;">string</span>> assertions)
{
<span style="color:blue;">if</span> (assertions?.Errors.Any() ?? <span style="color:blue;">false</span>)
{
<span style="color:blue;">var</span> messages = <span style="color:blue;">string</span>.Join(Environment.NewLine, assertions.Errors);
<span style="color:blue;">throw</span> <span style="color:blue;">new</span> Exception(messages);
}
}</pre>
</p>
<p>
If there are no errors, <code>Run</code> does nothing; otherwise it combines all the error messages together and throws an exception. As was also the case in the previous article, I've allowed myself a few proof-of-concept shortcuts. <a href="https://learn.microsoft.com/dotnet/standard/design-guidelines/using-standard-exception-types">The framework design guidelines admonishes against throwing System.Exception</a>. It might be more appropriate to introduce a new <code>Exception</code> type that also allows enumerating the error messages.
</p>
<p>
The entire <a href="/2013/06/24/a-heuristic-for-formatting-code-according-to-the-aaa-pattern">assertion phase</a> of the test looks like this:
</p>
<p>
<pre><span style="color:blue;">var</span> assertResponse = Asserted.True(
deleteResp.IsSuccessStatusCode,
<span style="color:#a31515;">$"Actual status code: </span>{deleteResp.StatusCode}<span style="color:#a31515;">."</span>);
<span style="color:blue;">var</span> getResp = <span style="color:blue;">await</span> api.CreateClient().GetAsync(address);
<span style="color:blue;">var</span> assertState = Asserted.Equal(HttpStatusCode.NotFound, getResp.StatusCode);
assertResponse.And(assertState).Run();</pre>
</p>
<p>
You can see the entire test in the previous article. Notice how the two assertion objects are first combined into one with the <code>And</code> binary operation. The result is a single <code>Asserted<<span style="color:blue;">string</span>></code> object on which you can call <code>Run</code>.
</p>
<p>
Like the previous proof of concept, this assertion passes and fails in the same way. It's possible to compose assertions and collect error messages, instead of short-circuiting on the first failure, even without an applicative functor.
</p>
<h3 id="f3d9baf1ad564c05be99b32f0b4a1017">
Method chaining <a href="#f3d9baf1ad564c05be99b32f0b4a1017" title="permalink">#</a>
</h3>
<p>
If you don't like to come up with variable names just to make assertions, it's also possible to use the <code>Asserted</code> API's <a href="https://martinfowler.com/bliki/FluentInterface.html">fluent interface</a>:
</p>
<p>
<pre><span style="color:blue;">var</span> getResp = <span style="color:blue;">await</span> api.CreateClient().GetAsync(address);
Asserted
.True(
deleteResp.IsSuccessStatusCode,
<span style="color:#a31515;">$"Actual status code: </span>{deleteResp.StatusCode}<span style="color:#a31515;">."</span>)
.And(Asserted.Equal(HttpStatusCode.NotFound, getResp.StatusCode))
.Run();</pre>
</p>
<p>
This isn't necessarily better, but it's an option.
</p>
<h3 id="ecabe91c2b9949edbcb4cfed5213ec72">
Conclusion <a href="#ecabe91c2b9949edbcb4cfed5213ec72" title="permalink">#</a>
</h3>
<p>
While it's possible to design non-short-circuiting composable assertions using an applicative functor, it looks as though a simpler solution might solve the same problem. Collect error messages. If none were collected, interpret that as a success.
</p>
<p>
As I wrote in the <a href="/2022/11/07/applicative-assertions">introduction article</a>, however, this may not be the last word. Some assertions return values that can be used for other assertions. That's a scenario that I have not yet investigated in this light, and it may change the conclusion. If so, I'll add more articles to this small article series. As I'm writing this, though, I have no such plans.
</p>
<p>
Did I just, in a roundabout way, write that <em>more research is needed?</em>
</p>
<p>
<strong>Next:</strong> <a href="/2023/01/30/built-in-alternatives-to-applicative-assertions">Built-in alternatives to applicative assertions</a>.
</p>
</div>
<div id="comments">
<hr>
<h2 id="comments-header">
Comments
</h2>
<div class="comment" id="2aae9a7f4c1145aa92b487925f4b46ba">
<div class="comment-author"><a href="https://ptupitsyn.github.io/">Pavel Tupitsyn</a></div>
<div class="comment-content">
<p>
I think NUnit's <a href="https://docs.nunit.org/articles/nunit/writing-tests/assertions/multiple-asserts.html">Assert.Multiple</a> is worth mentioning in this series. It does not require any complicated APIs, just wrap your existing test with multiple asserts into a delegate.
</p>
</div>
<div class="comment-date">2022-12-20 08:02 UTC</div>
</div>
<div class="comment" id="5b34eb2d997f417bac27738ee7cbb16d">
<div class="comment-author"><a href="/">Mark Seemann</a></div>
<div class="comment-content">
<p>
Pavel, thank you for writing. I'm aware of both that API and similar ones for other testing frameworks. As is usually the case, there are trade-offs to consider. I'm currently working on some material that may turn into another article about that.
</p>
</div>
<div class="comment-date">2022-12-21 20:17 UTC</div>
</div>
<div class="comment" id="f244b81042414b98be67a937cf652648">
<div class="comment-author"><a href="/">Mark Seemann</a></div>
<div class="comment-content">
<p>
A new article is now available: <a href="/2023/01/30/built-in-alternatives-to-applicative-assertions">Built-in alternatives to applicative assertions</a>.
</p>
</div>
<div class="comment-date">2023-01-30 12:31 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>.When do tests fail?https://blog.ploeh.dk/2022/12/12/when-do-tests-fail2022-12-12T08:33:00+00:00Mark Seemann
<div id="post">
<p>
<em>Optimise for the common scenario.</em>
</p>
<p>
Unit tests occasionally fail. When does that happen? How often? What triggers it? What information is important when tests fail?
</p>
<p>
Regularly I encounter the viewpoint that it should be easy to understand the purpose of a test <em>when it fails</em>. Some people consider test names important, a topic that <a href="/2022/06/13/some-thoughts-on-naming-tests">I've previously discussed</a>. Recently I discussed the <a href="http://xunitpatterns.com/Assertion%20Roulette.html">Assertion Roulette</a> test smell on Twitter, and again I learned some surprising things about what people value in unit tests.
</p>
<h3 id="6673d3ef3f374f849fe7fe38a7b96985">
The importance of clear assertion messages <a href="#6673d3ef3f374f849fe7fe38a7b96985" title="permalink">#</a>
</h3>
<p>
The Assertion Roulette test smell is often simplified to degeneracy, but it really describes situations where it may be a problem if you can't tell which of several assertions actually caused a test to fail.
</p>
<p>
<a href="https://www.joshka.net">Josh McKinney</a> gave a more detailed example than Gerard Meszaros does in <a href="/ref/xunit-patterns">the book</a>:
</p>
<blockquote>
<p>
"Background. In a legacy product, we saw some tests start failing intermittently. They weren’t just flakey, but also failed without providing enough info to fix. One of things which caused time to fix to increase was multiple ways of a single test to fail."
</p>
<footer><cite><a href="https://twitter.com/joshuamck/status/1572528796125003777">Josh McK</a></cite></footer>
</blockquote>
<p>
He goes on:
</p>
<blockquote>
<p>
"I.e. if you fix the first assertion and you know there still could be flakiness, or long cycle times to see the failure. Multiple assertions makes any test problem worse. In an ideal state, they are fine, but every assertion doubles the amount of failures a test catches."
</p>
<footer><cite><a href="https://twitter.com/joshuamck/status/1572529894361534464">Josh McK</a></cite></footer>
</blockquote>
<p>
and concludes:
</p>
<blockquote>
<p>
"the other main way (unrelated) was things like:
</p>
<p>
assertTrue(someListResult.isRmpty())
</p>
<p>
Which tells you what failed, but nothing about how.
</p>
<p>
But the following is worse. You must run the test twice to fix:
</p>
<p>
assertFalse(someList.isEmpty());<br>
assertEqual(expected, list.get(0));"
</p>
<footer><cite><a href="https://twitter.com/joshuamck/status/1572534297403469824">Josh McK</a></cite></footer>
</blockquote>
<p>
The final point is due to the short-circuiting nature of most assertion libraries. That, however, is <a href="/2022/11/07/applicative-assertions">a solvable problem</a>.
</p>
<p>
I find the above a compelling example of why Assertion Roulette may be problematic.
</p>
<p>
It did give me pause, though. How common is this scenario?
</p>
<h3 id="5ae99f4515444bd6ba483beffb819557">
Out of the blue <a href="#5ae99f4515444bd6ba483beffb819557" title="permalink">#</a>
</h3>
<p>
The situation described by Josh McKinney comes with more than a single warning flag. I hope that it's okay to point some of them out. I didn't get the impression from my interaction with Josh McKinney that he considered the situation ideal in any way.
</p>
<p>
First, of course, there's the lack of information about the problem. Here, that's a real problem. As I understand it, it makes it harder to reproduce the problem in a development environment.
</p>
<p>
Next, there's long cycle times, which I interpret as significant time may pass from when you attempt a fix until you can actually observe whether or not it worked. Josh McKinney doesn't say how long, but I wouldn't surprised if it was measured in days. At least, if the cycle time is measured in days, I can see how this is a problem.
</p>
<p>
Finally, there's the observation that "some tests start failing intermittently". This was the remark that caught my attention. How often does that happen?
</p>
<p>
Tests shouldn't do that. Tests should be deterministic. If they're not, you should work to <a href="https://martinfowler.com/articles/nonDeterminism.html">eradicate non-determinism in tests</a>.
</p>
<p>
I'll be the first to admit that that I also write non-deterministic tests. Not by design, but because I make mistakes. I've written many <a href="http://xunitpatterns.com/Erratic%20Test.html">Erratic Tests</a> in my career, and I've documented a few of them here:
</p>
<ul>
<li><a href="/2021/01/11/waiting-to-happen">Waiting to happen</a></li>
<li><a href="/2022/05/23/waiting-to-never-happen">Waiting to never happen</a></li>
<li><a href="/2020/10/05/fortunately-i-dont-squash-my-commits">Fortunately, I don't squash my commits</a></li>
<li><a href="/2016/01/18/make-pre-conditions-explicit-in-property-based-tests">Make pre-conditions explicit in Property-Based Tests</a></li>
</ul>
<p>
While it <em>can</em> happen, it shouldn't be the norm. When it nonetheless happens, eradicating that source of non-determinism should be top priority. Pull the <a href="https://en.wikipedia.org/wiki/Andon_(manufacturing)">andon cord</a>.
</p>
<h3 id="5fd251665441473ca3048a9137f9bc2b">
When tests fail <a href="#5fd251665441473ca3048a9137f9bc2b" title="permalink">#</a>
</h3>
<p>
Ideally, tests should rarely fail. As examined above, you may have Erratic Tests in your test suite, and if you do, these tests will occasionally (or often) fail. As Martin Fowler writes, this is a problem and you should do something about it. He also outlines strategies for it.
</p>
<p>
Once you've eradicated non-determinism in unit tests, then when do tests fail?
</p>
<p>
I can think of a couple of situations.
</p>
<p>
Tests routinely fail as part of the <a href="/2019/10/21/a-red-green-refactor-checklist">red-green-refactor cycle</a>. This is by design. If no test is failing in the <em>red</em> phase, you probably made a mistake (which also regularly <a href="/2019/10/14/tautological-assertion">happens to me</a>), or you may not really be doing test-driven development (TDD).
</p>
<p>
Another situation that may cause a test to fail is if you changed some code and triggered a regression test.
</p>
<p>
In both cases, tests don't just fail <a href="https://amzn.to/3SPdHAO">out of the blue</a>. They fail as an immediate consequence of something you did.
</p>
<h3 id="aaeebfa1a96b47398219817bc3327a9c">
Optimise for the common scenario <a href="#aaeebfa1a96b47398219817bc3327a9c" title="permalink">#</a>
</h3>
<p>
In both cases you're (hopefully) in a tight feedback loop. If you're in a tight feedback loop, then how important is the assertion message really? How important is the test name?
</p>
<p>
You work on the code base, make some changes, run the tests. If one or more tests fail, it's correlated to the change you just made. You should have a good idea of what went wrong. Are code forensics and elaborate documentation really necessary to understand a test that failed because you just did something a few minutes before?
</p>
<p>
The reason I don't care much about test names or whether there's one or more assertion in a unit test is exactly that: When tests fail, it's usually because of something I just did. I don't need diagnostics tools to find the root cause. The root cause is the change that I just made.
</p>
<p>
That's my common scenario, and I try to optimise my processes for the common scenarios.
</p>
<h3 id="21b16c9b2fb649ec859e53b0a1ab431a">
Fast feedback <a href="#21b16c9b2fb649ec859e53b0a1ab431a" title="permalink">#</a>
</h3>
<p>
There's an implied way of working that affects such attitudes. Since I learned about TDD in 2003 I've always relished the fast feedback I get from a test suite. Since I tried continuous deployment around 2014, I consider it central to <a href="/ref/modern-software-engineering">modern software engineering</a> (and <a href="/ref/accelerate">Accelerate</a> strongly suggests so, too).
</p>
<p>
The modus operandi I outline above is one of fast feedback. If you're sitting on a feature branch for weeks before integrating into master, or if you can only deploy two times a year, this influences what works and what doesn't.
</p>
<p>
Both <em>Modern Software Engineering</em> and <em>Accelerate</em> make a strong case that short feedback cycles are pivotal for successful software development organisations.
</p>
<p>
I also understand that that's not the reality for everyone. When faced with long cycle times, a multitude of Erratic Tests, a legacy code base, and so on, other things become important. In those circumstances, tests may fail for different reasons.
</p>
<p>
When you work with TDD, continuous integration (CI), and continuous deployment (CD), then when do tests fail? They fail because you made them fail, only minutes earlier. Fix your code and move forward.
</p>
<h3 id="53cc6ce19bad4bdea3f40fd752f6338d">
Conclusion <a href="#53cc6ce19bad4bdea3f40fd752f6338d" title="permalink">#</a>
</h3>
<p>
When discussing test names and assertion messages, I've been surprised by the emphasis some people put on what I consider to be of secondary importance. I think the explanation is that circumstances differ.
</p>
<p>
With TDD and CI/CD you mostly look at a unit test when you write it, or if some regression test fails because you changed some code (perhaps in response to a test you just wrote). Your test suite may have hundreds or thousands of tests. Most of these pass every time you run the test suite. That's the normal state of affairs.
</p>
<p>
In other circumstances, you may have Erratic Tests that fail unpredictably. You should make it a priority to stop that, but as part of that process, you may need good assertion messages and good test names.
</p>
<p>
Different circumstances call for different reactions, so what works well in one situation may be a liability in other situations. I hope that this article has shed a little light on the forces you may want to consider.
</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>.GitHub Copilot preliminary experience reporthttps://blog.ploeh.dk/2022/12/05/github-copilot-preliminary-experience-report2022-12-05T08:37:00+00:00Mark Seemann
<div id="post">
<p>
<em>Based on a few months of use.</em>
</p>
<p>
I've been evaluating <a href="https://github.com/features/copilot">GitHub Copilot</a> since August 2022. Perhaps it's time to collect my thoughts so far.
</p>
<p>
In short, it's surprisingly good, but also gets a lot of things wrong. It does seem helpful to the experienced programmer, but I don't see it replacing all programmers yet.
</p>
<h3 id="19d8478cc2d5429f9c62138574a30a45">
Not only for boilerplate code <a href="#19d8478cc2d5429f9c62138574a30a45" title="permalink">#</a>
</h3>
<p>
I was initially doubtful. I'd seen some demos where Copilot created fifteen to twenty lines of code to, say, make a REST API request. These examples mostly struck me as auto-generation of something that ought to be a proper abstraction: A method in a reusable library.
</p>
<p>
In general <a href="/2018/09/17/typing-is-not-a-programming-bottleneck">I don't think that typing is a productivity bottleneck</a>, and I'm <a href="/2013/02/04/BewareofProductivityTools">sceptical of productivity tools</a>, and particularly code generators. The more code a code base contains, the more code there is to read. Accelerating code production doesn't strike me as a goal in itself.
</p>
<p>
On the other hand, I'm past fifty and aware that in my age, one often tends to resist new ideas. Perhaps the above justifications are nothing but <a href="https://en.wikipedia.org/wiki/Motivated_reasoning">motivated reasoning</a>. I decided to install the plug-ins and go about my business to see what would happen.
</p>
<p>
It has surprised and delighted me more than once. It's not only for boilerplate code. Here's a recent example.
</p>
<p>
I was doing an exercise in <a href="https://fsharp.org">F#</a> and wrote this type definition:
</p>
<p>
<pre><span style="color:blue;">type</span> Instruction = Enqueue <span style="color:blue;">of</span> int | Dequeue</pre>
</p>
<p>
I wanted to write a property-based test with this type, and since I was using <a href="https://hedgehog.qa/">Hedgehog</a> I needed a generator for the type. While <a href="https://fscheck.github.io/FsCheck/">FsCheck</a> can automatically generate values of custom <a href="https://learn.microsoft.com/dotnet/fsharp/language-reference/discriminated-unions">discriminated unions</a>, Hedgehog has a more <a href="https://peps.python.org/pep-0020/">explicit-is-better-than-implicit</a> design philosophy. In other words, if there's a way to make Hedgehog automatically generate values of a type like the above <code>Instruction</code>, it has so far escaped me.
</p>
<p>
So I started typing <code><span style="color:blue;">let</span> <span style="color:blue;">private</span> genInstruction =</code> after which Copilot suggested the following:
</p>
<p>
<pre><span style="color:blue;">let</span> <span style="color:blue;">private</span> genInstruction =
Gen.frequency
[ 1, Gen.constant Dequeue
1, Gen.int32 (Range.constant 0 10_000) |> Gen.map Enqueue ]</pre>
</p>
<p>
I was, frankly, stunned. While I do understand that Copilot doesn't actually understand the code it suggests, Hedgehog is sufficiently esoteric that I didn't expect Copilot to have enough training data to enable it to make a useful contribution in this niche. I was wrong. I've repeatedly seen Copilot make suggestions to my F# and <a href="https://www.haskell.org/">Haskell</a> code. It's not just for C#, <a href="https://www.javascript.com">JavaScript</a>, or <a href="https://www.python.org/">python</a> code.
</p>
<p>
The above suggestion was, to be clear, absolutely appropriate and compiled right away. The only detail I decided to change was the <code>Range</code>, which I decided to change to <code>Range.linear</code>. That's not, however, a significant change.
</p>
<p>
Perhaps you're not impressed by three lines of auto-generated code. How much of a productivity improvement is that? Quite a bit, in my case.
</p>
<p>
It wouldn't have taken me long to type those three lines of code, but as I already mentioned, <a href="/2018/09/17/typing-is-not-a-programming-bottleneck">typing isn't a bottleneck</a>. On the other hand, looking up an unfamiliar API can take some time. <a href="/ref/programmers-brain">The Programmer's Brain</a> discusses this kind of problem and suggests exercises to address it. Does Copilot offer a shortcut?
</p>
<p>
While I couldn't remember the details of Hedgehog's API, once I saw the suggestion, I recognised <code>Gen.frequency</code>, so I understood it as an appropriate code suggestion. The productivity gain, if there is one, may come from saving you the effort of looking up unfamiliar APIs, rather than saving you some keystrokes.
</p>
<p>
In this example, I already knew of the <code>Gen.frequency</code> function - I just couldn't recall the exact name and type. This enabled me to evaluate Copilot's suggestion and deem it correct. If I hadn't known that API already, how could I have known whether to trust Copilot?
</p>
<h3 id="424f6a4928d945d7bcb13f2de8f3a98e">
Detectably wrong suggestions <a href="#424f6a4928d945d7bcb13f2de8f3a98e" title="permalink">#</a>
</h3>
<p>
As amazing as Copilot can be, it's hardly faultless. It makes many erroneous suggestions. Sometimes the suggestion is obviously wrong. If you accept it, it doesn't compile. Sometimes, the compilation error is only a little edit from being correct, but at least in such situations you'll be explicitly aware that the suggestion couldn't be used verbatim.
</p>
<p>
Other suggestions are wrong, but less conspicuously so. Here's an example.
</p>
<p>
I was recently subjecting the code base that accompanies <a href="/2021/06/14/new-book-code-that-fits-in-your-head">Code That Fits in Your Head</a> to the <a href="https://en.wikipedia.org/wiki/Mutation_testing">mutation testing</a> tool <a href="https://stryker-mutator.io/">Stryker</a>. Since it did point out a few possible mutations, I decided to add a few tests. One was of a wrapper class called <code>TimeOfDay</code>. Because of static code analysis rules, it came with conversions to and from <a href="https://learn.microsoft.com/dotnet/api/system.timespan">TimeSpan</a>, but these methods weren't covered by any tests.
</p>
<p>
In order to remedy that situation, I started writing an FsCheck property and came as far as:
</p>
<p>
<pre>[Property]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> <span style="color:#74531f;">ConversionsRoundTrip</span>(TimeSpan <span style="color:#1f377f;">timeSpan</span>)</pre>
</p>
<p>
At that point Copilot suggested the following, which I accepted:
</p>
<p>
<pre>[Property]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> <span style="color:#74531f;">ConversionsRoundTrip</span>(TimeSpan <span style="color:#1f377f;">timeSpan</span>)
{
<span style="color:blue;">var</span> <span style="color:#1f377f;">timeOfDay</span> = <span style="color:blue;">new</span> TimeOfDay(timeSpan);
<span style="color:blue;">var</span> <span style="color:#1f377f;">actual</span> = (TimeSpan)timeOfDay;
Assert.Equal(timeSpan, actual);
}</pre>
</p>
<p>
Looks good, doesn't it? Again, I was impressed. It compiled, and it even looks as though Copilot had picked up one of my naming conventions: <a href="/2020/11/30/name-by-role">naming variables by role</a>, in this case <code>actual</code>.
</p>
<p>
While I tend to be on guard, I immediately ran the test suite instead of thinking it through. It failed. Keep in mind that this is a <a href="https://en.wikipedia.org/wiki/Characterization_test">characterisation test</a>, so it was supposed to pass.
</p>
<p>
The <code>TimeOfDay</code> constructor reveals why:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:#2b91af;">TimeOfDay</span>(TimeSpan <span style="color:#1f377f;">durationSinceMidnight</span>)
{
<span style="color:#8f08c4;">if</span> (durationSinceMidnight < TimeSpan.Zero ||
TimeSpan.FromHours(24) < durationSinceMidnight)
<span style="color:#8f08c4;">throw</span> <span style="color:blue;">new</span> ArgumentOutOfRangeException(
nameof(durationSinceMidnight),
<span style="color:#a31515;">"Please supply a TimeSpan between 0 and 24 hours."</span>);
<span style="color:blue;">this</span>.durationSinceMidnight = durationSinceMidnight;
}</pre>
</p>
<p>
While FsCheck knows how to generate <code>TimeSpan</code> values, it'll generate arbitrary durations, including negative values and spans much longer than 24 hours. That explains why the test fails.
</p>
<p>
Granted, this is hardly a searing indictment against Copilot. After all, I could have made this mistake myself.
</p>
<p>
Still, that prompted me to look for more issues with the code that Copilot had suggested. Another problem with the code is that it tests the wrong API. The suggested test tries to round-trip via the <code>TimeOfDay</code> class' explicit cast operators, which were already covered by tests. Well, I might eventually have discovered that, too. Keep in mind that I was adding this test to improve the code base's Stryker score. After running the tool again, I would probably eventually have discovered that the score didn't improve. It takes Stryker around 25 minutes to test this code base, though, so it wouldn't have been rapid feedback.
</p>
<p>
Since, however, I examined the code with a critical eye, I noticed this by myself. This would clearly require changing the test code as well.
</p>
<p>
In the end, I wrote this test:
</p>
<p>
<pre>[Property]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> <span style="color:#74531f;">ConversionsRoundTrip</span>(TimeSpan <span style="color:#1f377f;">timeSpan</span>)
{
<span style="color:blue;">var</span> <span style="color:#1f377f;">expected</span> = ScaleToTimeOfDay(timeSpan);
<span style="color:blue;">var</span> <span style="color:#1f377f;">sut</span> = TimeOfDay.ToTimeOfDay(expected);
<span style="color:blue;">var</span> <span style="color:#1f377f;">actual</span> = TimeOfDay.ToTimeSpan(sut);
Assert.Equal(expected, actual);
}
<span style="color:blue;">private</span> <span style="color:blue;">static</span> TimeSpan <span style="color:#74531f;">ScaleToTimeOfDay</span>(TimeSpan <span style="color:#1f377f;">timeSpan</span>)
{
<span style="color:green;">// Convert an arbitrary TimeSpan to a 24-hour TimeSpan.</span>
<span style="color:green;">// The data structure that underlies TimeSpan is a 64-bit integer,</span>
<span style="color:green;">// so first we need to identify the range of possible TimeSpan</span>
<span style="color:green;">// values. It might be easier to understand to calculate</span>
<span style="color:green;">// TimeSpan.MaxValue - TimeSpan.MinValue, but that underflows.</span>
<span style="color:green;">// Instead, the number of possible 64-bit integer values is the same</span>
<span style="color:green;">// as the number of possible unsigned 64-bit integer values.</span>
<span style="color:blue;">var</span> <span style="color:#1f377f;">range</span> = <span style="color:blue;">ulong</span>.MaxValue;
<span style="color:blue;">var</span> <span style="color:#1f377f;">domain</span> = TimeSpan.FromHours(24).Ticks;
<span style="color:blue;">var</span> <span style="color:#1f377f;">scale</span> = (<span style="color:blue;">ulong</span>)domain / range;
<span style="color:blue;">var</span> <span style="color:#1f377f;">expected</span> = timeSpan * scale;
<span style="color:#8f08c4;">return</span> expected;
}</pre>
</p>
<p>
In this case, Copilot didn't improve my productivity. It may actually have slowed me down a bit.
</p>
<p>
This time, it wasn't too difficult to spot issues with the suggested code. What if the problems are more subtle?
</p>
<h3 id="02cb23fc57394a1c963a2f4ebe75ec48">
Errors that are difficult to detect <a href="#02cb23fc57394a1c963a2f4ebe75ec48" title="permalink">#</a>
</h3>
<p>
How do bugs appear? We write them, thinking that our code is going to do one thing, while the compiler decides otherwise. Even when we actively engage with the code, we may be looking at a bug and still fail to see it.
</p>
<p>
Why should we trust Copilot to produce bug-free code?
</p>
<p>
Here's another example. I was going through the <a href="https://codingdojo.org/kata/Range/">Range kata</a> in F# and made my <code>Endpoint</code> discriminated union a <a href="/2018/03/22/functors">functor</a>:
</p>
<p>
<pre><span style="color:blue;">type</span> Endpoint<'a> = Open <span style="color:blue;">of</span> 'a | Closed <span style="color:blue;">of</span> 'a
<span style="color:blue;">module</span> Endpoint =
<span style="color:blue;">let</span> map f = <span style="color:blue;">function</span>
| Open x <span style="color:blue;">-></span> Open (f x)
| Closed x <span style="color:blue;">-></span> Closed (f x)</pre>
</p>
<p>
Making a type a functor is such a well-understood process that <a href="https://gitlab.haskell.org/ghc/ghc/-/wikis/commentary/compiler/derive-functor">Haskell can automate it</a>. I knew how to write the above <code>map</code> function as well, so I wrote it without testing it.
</p>
<p>
After I'd written the <code>map</code> function, I decided to add tests of the two functor laws. Not because I doubted the implementation, but because I might need that as example code later.
</p>
<p>
Copilot suggested this test after I named it:
</p>
<p>
<pre><span style="color:blue;">open</span> Xunit
<span style="color:blue;">open</span> Hedgehog
[<Fact>]
<span style="color:blue;">let</span> ``First functor law`` () = Property.check <| property {
<span style="color:blue;">let!</span> x = Gen.int32 (Range.linearBounded ())
<span style="color:blue;">let</span> f = (<span style="color:blue;">fun</span> x <span style="color:blue;">-></span> x + 1)
<span style="color:blue;">let</span> g = (<span style="color:blue;">fun</span> x <span style="color:blue;">-></span> x * 2)
<span style="color:blue;">let</span> actual = Endpoint.map f (Endpoint.map g (Open x))
<span style="color:blue;">let</span> expected = Endpoint.map (f >> g) (Open x)
Assert.Equal(expected, actual) }</pre>
</p>
<p>
It compiles. It also fails.
</p>
<p>
What's wrong with it?
</p>
<p>
If you know the functor laws by heart, you'll be able to spot that this is clearly not the first functor law. On the other hand, it looks convincingly like the second functor law. Should I just change the name and move on?
</p>
<p>
I can't, though, since the test fails. Could there be a bug in my <code>map</code> function, after all?
</p>
<p>
No, there's an error in the test. I invite you to spot it.
</p>
<p>
In terms of keystrokes, it's easy to fix the problem:
</p>
<p>
<pre><span style="color:blue;">open</span> Xunit
<span style="color:blue;">open</span> Hedgehog
[<Fact>]
<span style="color:blue;">let</span> ``First functor law`` () = Property.check <| property {
<span style="color:blue;">let!</span> x = Gen.int32 (Range.linearBounded ())
<span style="color:blue;">let</span> f = (<span style="color:blue;">fun</span> x <span style="color:blue;">-></span> x + 1)
<span style="color:blue;">let</span> g = (<span style="color:blue;">fun</span> x <span style="color:blue;">-></span> x * 2)
<span style="color:blue;">let</span> actual = Endpoint.map f (Endpoint.map g (Open x))
<span style="color:blue;">let</span> expected = Endpoint.map (f << g) (Open x)
Assert.Equal(expected, actual) }</pre>
</p>
<p>
Spot the edit. I bet it'll take you longer to find it than it took me to type it.
</p>
<p>
The test now passes, but for one who has spent less time worrying over functor laws than I have, troubleshooting this could have taken a long time.
</p>
<p>
These almost-right suggestions from Copilot both worry me and give me hope.
</p>
<h3 id="7c90d2bd03054906a5f2505baaf78a31">
Copilot for experienced programmers <a href="#7c90d2bd03054906a5f2505baaf78a31" title="permalink">#</a>
</h3>
<p>
When a new technology like Copilot appears, it's natural to speculate on the consequences. <em>Does this mean that programmers will lose their jobs?</em>
</p>
<p>
This is just a preliminary evaluation after a few months, so I could be wrong, but I think we programmers are safe. If you're experienced, you'll be able to tell most of Copilot's hits from its misses. Perhaps you'll get a productivity improvement out of, but it could also slow you down.
</p>
<p>
The tool is likely to improve over time, so I'm hopeful that this could become a net productivity gain. Still, with this high an error rate, I'm not too worried yet.
</p>
<p>
<a href="/ref/pragmatic-programmer">The Pragmatic Programmer</a> describes a programming style named <em>Programming by Coincidence</em>. People who develop software this way have only a partial understanding of the code they write.
</p>
<blockquote>
<p>
"Fred doesn't know why the code is failing because <em>he didn't know why it worked in the first place.</em>"
</p>
<footer><cite>Andy Hunt and Dave Thomas, <a href="/ref/pragmatic-programmer">The Pragmatic Programmer</a></cite></footer>
</blockquote>
<p>
I've encountered my fair share of these people. When editing code, they make small adjustments and do cursory manual testing until 'it looks like it works'. If they have to start a new feature or are otherwise faced with a metaphorical blank page, they'll copy some code from somewhere else and use that as a starting point.
</p>
<p>
You'd think that Copilot could enhance the productivity of such people, but I'm not sure. It might actually slow them down. These people don't fully understand the code they themselves 'write', so why should we expect them to understand the code that Copilot suggests?
</p>
<p>
If faced with a Copilot suggestion that 'almost works', will they be able to spot if it's a genuinely good suggestion, or whether it's off, like I've described above? If the Copilot code doesn't work, how much time will they waste thrashing?
</p>
<h3 id="f3e17cbf9dbc41f19ae46974d2f28a90">
Conclusion <a href="#f3e17cbf9dbc41f19ae46974d2f28a90" title="permalink">#</a>
</h3>
<p>
GitHub Copilot has the potential to be a revolutionary technology, but it's not, yet. So far, I'm not too worried. It's an assistant, like a pairing partner, but it's up to you to evaluate whether the code that Copilot suggests is useful, correct, and safe. How can you do that unless you already know what you're doing?
</p>
<p>
If you don't have the qualifications to evaluate the suggested code, I fail to see how it's going to help you. Granted, it does have potential to help you move on in less time that you would otherwise have spent. In this article, I showed one example where I would have had to spend significant time looking up API documentation. Instead, Copilot suggested the correct code to use.
</p>
<p>
Pulling in the other direction are the many <a href="https://en.wikipedia.org/wiki/False_positives_and_false_negatives">false positives</a>. Copilot makes many suggestions, and many of them are poor. The ones that are recognisably bad are unlikely to slow you down. I'm more concerned with those that are subtly wrong. They have the potential to waste much time.
</p>
<p>
Which of these forces are strongest? The potential for wasting time is infinite, while the maximum productivity gain you can achieve is 100 percent. That's an asymmetric distribution. There's a long tail of time wasters, but there's no equivalent long tail of improvement.
</p>
<p>
I'm not, however, trying to be pessimistic. I expect to keep Copilot around for the time being. It could very well be here to stay. Used correctly, it seems useful.
</p>
<p>
Is it going to replace programmers? Hardly. Rather, it may enable poor developers to make such a mess of things that you need even more good programmers to subsequently fix things.
</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>.An initial proof of concept of applicative assertions in C#https://blog.ploeh.dk/2022/11/28/an-initial-proof-of-concept-of-applicative-assertions-in-c2022-11-28T06:47:00+00:00Mark Seemann
<div id="post">
<p>
<em>Worthwhile? Not obviously.</em>
</p>
<p>
This article is the first instalment in a small articles series about <a href="/2022/11/07/applicative-assertions">applicative assertions</a>. It explores a way to compose assertions in such a way that failure messages accumulate rather than short-circuit. It assumes that you've read the <a href="/2022/11/07/applicative-assertions">article series introduction</a>.
</p>
<p>
Assertions are typically based on throwing exceptions. As soon as one assertion fails, an exception is thrown and no further assertions are evaluated. This is normal short-circuiting behaviour of exceptions. In some cases, however, it'd be useful to keep evaluating other assertions and collect error messages.
</p>
<p>
This article series explores <a href="https://twitter.com/lucasdicioccio/status/1572264819109003265">an intriguing idea</a> to address such issues: Use an <a href="/2018/10/01/applicative-functors">applicative functor</a> to collect multiple assertion messages. I started experimenting with the idea to see where it would lead. The article series serves as a report of what I found. It is neither a recommendation nor a caution. I still find the idea interesting, but I'm not sure whether the complexity is warranted.
</p>
<h3 id="877c6f5ee5b34ecf990d1126b8139720">
Example scenario <a href="#877c6f5ee5b34ecf990d1126b8139720" title="permalink">#</a>
</h3>
<p>
A realistic example is often illustrative, although there's a risk that the realism carries with it some noise that detracts from the core of the matter. I'll reuse an example that I've <a href="https://stackoverflow.blog/2022/11/03/multiple-assertions-per-test-are-fine/">already discussed and explained in greater detail</a>. The code is from the code base that accompanies my book <a href="/2021/06/14/new-book-code-that-fits-in-your-head">Code That Fits in Your Head</a>.
</p>
<p>
This test has two independent assertions:
</p>
<p>
<pre>[Theory]
[InlineData(884, 18, 47, <span style="color:#a31515;">"c@example.net"</span>, <span style="color:#a31515;">"Nick Klimenko"</span>, 2)]
[InlineData(902, 18, 50, <span style="color:#a31515;">"emot@example.gov"</span>, <span style="color:#a31515;">"Emma Otting"</span>, 5)]
<span style="color:blue;">public</span> <span style="color:blue;">async</span> Task DeleteReservation(
<span style="color:blue;">int</span> days, <span style="color:blue;">int</span> hours, <span style="color:blue;">int</span> minutes, <span style="color:blue;">string</span> email, <span style="color:blue;">string</span> name, <span style="color:blue;">int</span> quantity)
{
<span style="color:blue;">using</span> <span style="color:blue;">var</span> api = <span style="color:blue;">new</span> LegacyApi();
<span style="color:blue;">var</span> at = DateTime.Today.AddDays(days).At(hours, minutes)
.ToIso8601DateTimeString();
<span style="color:blue;">var</span> dto = Create.ReservationDto(at, email, name, quantity);
<span style="color:blue;">var</span> postResp = <span style="color:blue;">await</span> api.PostReservation(dto);
Uri address = FindReservationAddress(postResp);
<span style="color:blue;">var</span> deleteResp = <span style="color:blue;">await</span> api.CreateClient().DeleteAsync(address);
Assert.True(
deleteResp.IsSuccessStatusCode,
<span style="color:#a31515;">$"Actual status code: </span>{deleteResp.StatusCode}<span style="color:#a31515;">."</span>);
<span style="color:blue;">var</span> getResp = <span style="color:blue;">await</span> api.CreateClient().GetAsync(address);
Assert.Equal(HttpStatusCode.NotFound, getResp.StatusCode);
}</pre>
</p>
<p>
The test exercises the REST API to first create a reservation, then delete it, and finally check that the reservation no longer exists. Two independent postconditions must be true for the test to pass:
</p>
<ul>
<li>The <code>DELETE</code> request must result in a status code that indicates success.</li>
<li>The resource must no longer exist.</li>
</ul>
<p>
It's conceivable that a bug might fail one of these without invalidating the other.
</p>
<p>
As the test is currently written, it uses <a href="https://xunit.net/">xUnit.net</a>'s standard assertion library. If the <code>Assert.True</code> verification fails, the <code>Assert.Equal</code> statement isn't evaluated.
</p>
<h3 id="cd132aaee5484068a890cc4b7995bed3">
Assertions as validations <a href="#cd132aaee5484068a890cc4b7995bed3" title="permalink">#</a>
</h3>
<p>
Is it possible to evaluate the <code>Assert.Equal</code> postcondition even if the first assertion fails? You could use a <code>try/catch</code> block, but is there a more composable and elegant option? How about an applicative functor?
</p>
<p>
Since I was interested in exploring this question as a proof of concept, I decided to reuse the machinery that I'd already put in place for the article <a href="/2022/07/25/an-applicative-reservation-validation-example-in-c">An applicative reservation validation example in C#</a>: The <code>Validated</code> class and its associated functions. In a sense, you can think of an assertion as a validation of a postcondition.
</p>
<p>
This is not a resemblance I intend to carry too far. What I learn by experimenting with <code>Validated</code> I can apply to a more appropriately-named class like <code>Asserted</code>.
</p>
<p>
Neither of the two above assertions return a value; they are one-stop assertions. If they succeed, they return nothing; if they fail, they produce an error.
</p>
<p>
It's possible to model this kind of behaviour with <code>Validated</code>. You can model a collection of errors with, well, a collection. To keep the proof of concept simple, I decided to use a collection of strings: <code>IReadOnlyCollection<<span style="color:blue;">string</span>></code>. To model 'nothing' I had to add a <a href="/2018/01/15/unit-isomorphisms">unit</a> type:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">sealed</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">Unit</span>
{
<span style="color:blue;">private</span> <span style="color:#2b91af;">Unit</span>() { }
<span style="color:blue;">public</span> <span style="color:blue;">readonly</span> <span style="color:blue;">static</span> Unit Value = <span style="color:blue;">new</span> Unit();
}</pre>
</p>
<p>
This enabled me to define assertions as <code>Validated<IReadOnlyCollection<<span style="color:blue;">string</span>>, Unit></code> values: Either a collection of error messages, or nothing.
</p>
<h3 id="5ac18fb532c04876b00f7de080905a16">
Asserting truth <a href="#5ac18fb532c04876b00f7de080905a16" title="permalink">#</a>
</h3>
<p>
Instead of xUnit.net's <code>Assert.True</code>, you can now define an equivalent function:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> Validated<IReadOnlyCollection<<span style="color:blue;">string</span>>, Unit> AssertTrue(
<span style="color:blue;">this</span> <span style="color:blue;">bool</span> condition,
<span style="color:blue;">string</span> message)
{
<span style="color:blue;">return</span> condition
? Succeed<IReadOnlyCollection<<span style="color:blue;">string</span>>, Unit>(Unit.Value)
: Fail<IReadOnlyCollection<<span style="color:blue;">string</span>>, Unit>(<span style="color:blue;">new</span>[] { message });
}</pre>
</p>
<p>
It simply returns a <code>Success</code> value containing nothing when <code>condition</code> is <code>true</code>, and otherwise a <code>Failure</code> value containing the error <code>message</code>.
</p>
<p>
You can use it like this:
</p>
<p>
<pre><span style="color:blue;">var</span> assertResponse = Validated.AssertTrue(
deleteResp.IsSuccessStatusCode,
<span style="color:#a31515;">$"Actual status code: </span>{deleteResp.StatusCode}<span style="color:#a31515;">."</span>);</pre>
</p>
<p>
Later in the article you'll see how this assertion combines with another assertion.
</p>
<h3 id="adc98673e4734918ac983a5bbb520e15">
Asserting equality <a href="#adc98673e4734918ac983a5bbb520e15" title="permalink">#</a>
</h3>
<p>
Instead of xUnit.net's <code>Assert.Equal</code>, you can also define a function that works the same way but returns a <code>Validated</code> value:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> Validated<IReadOnlyCollection<<span style="color:blue;">string</span>>, Unit> AssertEqual<<span style="color:#2b91af;">T</span>>(
T expected,
T actual)
{
<span style="color:blue;">return</span> Equals(expected, actual)
? Succeed<IReadOnlyCollection<<span style="color:blue;">string</span>>, Unit>(Unit.Value)
: Fail<IReadOnlyCollection<<span style="color:blue;">string</span>>, Unit>(<span style="color:blue;">new</span>[]
{ <span style="color:#a31515;">$"Expected </span>{expected}<span style="color:#a31515;">, but got </span>{actual}<span style="color:#a31515;">."</span> });
}</pre>
</p>
<p>
The <code>AssertEqual</code> function first uses <a href="https://learn.microsoft.com/dotnet/api/system.object.equals">Equals</a> to compare <code>expected</code> with <code>actual</code>. If the result is <code>true</code>, the function returns a <code>Success</code> value containing nothing; otherwise, it returns a <code>Failure</code> value containing a failure message. Since this is only a proof of concept, the failure message is useful, but minimal.
</p>
<p>
Notice that this function returns a value of the same type (<code>Validated<IReadOnlyCollection<<span style="color:blue;">string</span>>, Unit></code>) as <code>AssertTrue</code>.
</p>
<p>
You can use the function like this:
</p>
<p>
<pre><span style="color:blue;">var</span> assertState = Validated.AssertEqual(HttpStatusCode.NotFound, getResp.StatusCode);</pre>
</p>
<p>
Again, you'll see how to combine this assertion with the above <code>assertResponse</code> value later in this article.
</p>
<h3 id="1d29ecff5ea64911918168cb985ed6b5">
Evaluating assertions <a href="#1d29ecff5ea64911918168cb985ed6b5" title="permalink">#</a>
</h3>
<p>
The <code>DeleteReservation</code> test only has two independent assertions, so in my proof of concept, all I needed to do was to figure out a way to combine two applicative assertions into one, and then evaluate it. This rather horrible method does that:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> <span style="color:blue;">void</span> RunAssertions(
Validated<IReadOnlyCollection<<span style="color:blue;">string</span>>, Unit> assertion1,
Validated<IReadOnlyCollection<<span style="color:blue;">string</span>>, Unit> assertion2)
{
<span style="color:blue;">var</span> f = Succeed<IReadOnlyCollection<<span style="color:blue;">string</span>>, Func<Unit, Unit, Unit>>((_, __) => Unit.Value);
Func<IReadOnlyCollection<<span style="color:blue;">string</span>>, IReadOnlyCollection<<span style="color:blue;">string</span>>, IReadOnlyCollection<<span style="color:blue;">string</span>>>
combine = (x, y) => x.Concat(y).ToArray();
Validated<IReadOnlyCollection<<span style="color:blue;">string</span>>, Unit> composition = f
.Apply(assertion1, combine)
.Apply(assertion2, combine);
<span style="color:blue;">string</span> errors = composition.Match(
onFailure: f => <span style="color:blue;">string</span>.Join(Environment.NewLine, f),
onSuccess: _ => <span style="color:blue;">string</span>.Empty);
<span style="color:blue;">if</span> (!<span style="color:blue;">string</span>.IsNullOrEmpty(errors))
<span style="color:blue;">throw</span> <span style="color:blue;">new</span> Exception(errors);</pre>
</p>
<p>
C# doesn't have good language features for applicative functors the same way that <a href="https://fsharp.org/">F#</a> and <a href="https://www.haskell.org/">Haskell</a> do, and although you can use various tricks to make the programming experience better that what is on display here, I was still doing a proof of concept. If it turns out that this approach is useful and warranted, we can introduce some of the facilities to make the API more palatable. For now, though, we're dealing with all the rough edges.
</p>
<p>
The way that applicative functors work, you typically use a 'lifted' function to combine two (or more) 'lifted' values. Here, 'lifted' means 'being inside the <code>Validated</code> <a href="https://bartoszmilewski.com/2014/01/14/functors-are-containers/">container</a>'.
</p>
<p>
Each of the assertions that I want to combine has the same type: <code>Validated<IReadOnlyCollection<<span style="color:blue;">string</span>>, Unit></code>. Notice that the <code>S</code> (<em>success</em>) generic type argument is <code>Unit</code> in both cases. While it seems redundant, formally I needed a 'lifted' function to combine two <code>Unit</code> values into a single value. This single value can (in principle) have any type I'd like it to have, but since you can't extract any information out of a <code>Unit</code> value, it makes sense to use the <a href="/2018/01/15/unit-isomorphisms#4657dbd4b5fc4abda6e8dee2cac67ea9">monoidal nature of unit</a> to combine two into one.
</p>
<p>
Basically, you just ignore the <code>Unit</code> input values because they carry no information. Also, they're all the same value anyway, since the type is a <a href="https://en.wikipedia.org/wiki/Singleton_pattern">Singleton</a>. In its 'naked' form, the function might be implemented like this: <code>(_, __) => Unit.Value</code>. Due to the <a href="/2019/12/16/zone-of-ceremony">ceremony</a> required by the combination of C# and applicative functors, however, this <a href="/2017/10/06/monoids">monoidal</a> binary operation has to be 'lifted' to a <code>Validated</code> value. That's the <code>f</code> value in the <code>RunAssertions</code> function body.
</p>
<p>
The <code>Validated.Apply</code> function requires as an argument a function that combines the generic <code>F</code> (<em>failure</em>) values into one, in order to deal with the case where there's multiple failures. In this case <code>F</code> is <code>IReadOnlyCollection<<span style="color:blue;">string</span>></code>. Since declarations of <code>Func</code> values in C# requires explicit type declaration, that's a bit of a mouthful, but the <code>combine</code> function just concatenates two collections into one.
</p>
<p>
The <code>RunAssertions</code> method can now <code>Apply</code> both <code>assertion1</code> and <code>assertion2</code> to <code>f</code>, which produces a combined <code>Validated</code> value, <code>composition</code>. It then matches on the combined value to produce a <code>string</code> value. If there are no assertion messages, the result is the empty string; otherwise, the function combines the assertion messages with a <code>NewLine</code> between each. Again, this is proof-of-concept code. A more robust and flexible API (if warranted) might keep the errors around as a collection of strongly typed <a href="https://martinfowler.com/bliki/ValueObject.html">Value Objects</a>.
</p>
<p>
Finally, if the resulting <code>errors</code> string is not null or empty, the <code>RunAssertions</code> method throws an exception with the combined error message(s). Here I once more invoked my proof-of-concept privilege to throw an <a href="https://learn.microsoft.com/dotnet/api/system.exception">Exception</a>, even though <a href="https://learn.microsoft.com/dotnet/standard/design-guidelines/using-standard-exception-types">the framework design guidelines admonishes against doing so</a>.
</p>
<p>
Ultimately, then, the <a href="/2013/06/24/a-heuristic-for-formatting-code-according-to-the-aaa-pattern">assert phase</a> of the test looks like this:
</p>
<p>
<pre><span style="color:blue;">var</span> assertResponse = Validated.AssertTrue(
deleteResp.IsSuccessStatusCode,
<span style="color:#a31515;">$"Actual status code: </span>{deleteResp.StatusCode}<span style="color:#a31515;">."</span>);
<span style="color:blue;">var</span> getResp = <span style="color:blue;">await</span> api.CreateClient().GetAsync(address);
<span style="color:blue;">var</span> assertState =
Validated.AssertEqual(HttpStatusCode.NotFound, getResp.StatusCode);
Validated.RunAssertions(assertResponse, assertState);</pre>
</p>
<p>
The rest of the test hasn't changed.
</p>
<h3 id="42e68063b7a3472e960031fde5e3f40d">
Outcomes <a href="#42e68063b7a3472e960031fde5e3f40d" title="permalink">#</a>
</h3>
<p>
Running the test with the applicative assertions passes, as expected. In order to verify that it works as it's supposed to, I tried to sabotage the System Under Test (SUT) in various ways. First, I made the <code>Delete</code> method that handles <code>DELETE</code> requests a <a href="https://en.wikipedia.org/wiki/NOP_(code)">no-op</a>, while still returning <code>200 OK</code>. As you'd expect, the result is a test failure with this message:
</p>
<p>
<pre>Message:
System.Exception : Expected NotFound, but got OK.</pre>
</p>
<p>
This is the assertion that verifies that <code>getResp.StatusCode</code> is <code>404 Not Found</code>. It fails because the sabotaged <code>Delete</code> method doesn't delete the reservation.
</p>
<p>
Then I further sabotaged the SUT to also return an incorrect status code (<code>400 Bad Request</code>), which produced this failure message:
</p>
<p>
<pre>Message:
System.Exception : Actual status code: BadRequest.
Expected NotFound, but got OK.</pre>
</p>
<p>
Notice that the message contains information about both failure conditions.
</p>
<p>
Finally, I re-enabled the correct behaviour (deleting the reservation from the data store) while still returning <code>400 Bad Request</code>:
</p>
<p>
<pre>Message:
System.Exception : Actual status code: BadRequest.</pre>
</p>
<p>
As desired, the assertions collect all relevant failure messages.
</p>
<h3 id="4a2c496da999408ea6c6cddd6a4f33d4">
Conclusion <a href="#4a2c496da999408ea6c6cddd6a4f33d4" title="permalink">#</a>
</h3>
<p>
Not surprisingly, it's possible to design a composable assertion API that collects multiple failure messages using an applicative functor. Anyone who knows how <a href="/2018/11/05/applicative-validation">applicative validation</a> works would have been able to predict that outcome. That's not what the above proof of concept was about. What I wanted to see was rather how it would play out in a realistic scenario, and whether using an applicative functor is warranted.
</p>
<p>
Applicative functors don't gel well with C#, so unsurprisingly the API is awkward. It's likely possible to smooth much of the friction, but without good language support and syntactic sugar, it's unlikely to become <a href="/2015/08/03/idiomatic-or-idiosyncratic">idiomatic</a> C#.
</p>
<p>
Rather than taking the edge off the unwieldy API, the implementation of <code>RunAssertions</code> suggests another alternative.
</p>
<p>
<strong>Next:</strong> <a href="/2022/12/19/error-accumulating-composable-assertions-in-c">Error-accumulating composable assertions in C#</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>.Decouple to deletehttps://blog.ploeh.dk/2022/11/21/decouple-to-delete2022-11-21T08:46:00+00:00Mark Seemann
<div id="post">
<p>
<em>Don't try to predict the future.</em>
</p>
<p>
Do you know why it's called <a href="https://en.wikipedia.org/wiki/Spaghetti_code">spaghetti code</a>? It's a palatable metaphor. You may start with a single spaghetto, but usually, as you wind your fork around it, the whole dish follows along. Unless you're careful, eating spaghetti can be a mess.
</p>
<p>
<img src="/content/binary/spaghetti-le-calandre.jpg" alt="A small spaghetti serving.">
</p>
<p>
Spaghetti code is tangled and everything is directly or transitively connected to everything else. As you try to edit the code, every change you make affects other code. Fix one thing and another thing breaks, cascading through the code base.
</p>
<p>
I was recently <a href="https://www.goodreads.com/review/show/4913194780">reading Clean Architecture</a>, and as <a href="https://en.wikipedia.org/wiki/Robert_C._Martin">Robert C. Martin</a> was explaining the <a href="https://en.wikipedia.org/wiki/Dependency_inversion_principle">Dependency Inversion Principle</a> for the umpteenth time, my brain made a new connection. To be clear: Connecting (coupling) code is bad, but connecting ideas is good.
</p>
<h3 id="51ca1981115f493bb24ac9338419fe91">
What a tangled web we weave <a href="#51ca1981115f493bb24ac9338419fe91" title="permalink">#</a>
</h3>
<p>
It's impractical to write code that depends on nothing else. Most code will call other code, which again calls other code. It behoves us, though, to be careful that the web of dependencies don't get too tangled.
</p>
<p>
Imagine a code base where the dependency graph looks like this:
</p>
<p>
<img src="/content/binary/tangled-dependency-graph.png" alt="A connected graph.">
</p>
<p>
Think of each node as a unit of code; a class or a module. While a dependency graph is a <a href="https://en.wikipedia.org/wiki/Directed_graph">directed graph</a>, I didn't indicate the directions. Imagine that most edges point both ways, so that the nodes are interdependent. In other ways, the graph has <a href="https://en.wikipedia.org/wiki/Cycle_(graph_theory)">cycles</a>. This is <a href="http://evelinag.com/blog/2014/06-09-comparing-dependency-networks/">not uncommon in C# code</a>.
</p>
<p>
Pick any node in such a graph, and chances are that other nodes depend on it. This makes it hard to make changes to the code in that node, because a change may affect the code that depends on it. As you try to fix the depending code, that change, too, ripples through the network.
</p>
<p>
This already explains why tight coupling is problematic.
</p>
<h3 id="61e4982dad794d0085dd7240508f73b7">
It is difficult to make predictions, especially about the future <a href="#61e4982dad794d0085dd7240508f73b7" title="permalink">#</a>
</h3>
<p>
When you write source code, you might be tempted to try to take into account future needs and requirements. There may be a historical explanation for that tendency.
</p>
<blockquote>
<p>
"That is, once it was a sign of failure to change product code. You should have gotten it right the first time."
</p>
<footer><cite><a href="https://twitter.com/marick/status/1566564277573525507">Brian Marick</a></cite></footer>
</blockquote>
<p>
In the days of punchcards, you had to schedule time to use a computer. If you made a mistake in your program, you typically didn't have time to fix it during your timeslot. A mistake could easily cost you days as you scrambled to schedule a new time. Not surprisingly, emphasis was on correctness.
</p>
<p>
With this mindset, it's natural to attempt to future-proof code.
</p>
<h3 id="0f12f362efaf461bbbdf9bddd2e01361">
YAGNI <a href="#0f12f362efaf461bbbdf9bddd2e01361" title="permalink">#</a>
</h3>
<p>
With interactive development environments you can get rapid feedback. If you make a mistake, change the code and observe the outcome. Don't add code because you think that you might need it later. <a href="https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it">You probably will not</a>.
</p>
<p>
While you should avoid <a href="https://wiki.c2.com/?SpeculativeGenerality">speculative generality</a>, that alone is no guarantee of clean code. Unless you're careful, you can easily make a mess by tightly coupling different parts of your code base.
</p>
<p>
How do produce a code base that is as easy to change as possible?
</p>
<h3 id="89bda4d0fd774c7c969c30e1562aa11b">
Write code that is easy to delete <a href="#89bda4d0fd774c7c969c30e1562aa11b" title="permalink">#</a>
</h3>
<p>
Write code that is easy to change. The ultimate change you can make is to delete code. After that, you can write something else that better does what you need.
</p>
<blockquote>
<p>
"A system where you can delete parts without rewriting others is often called loosely coupled"
</p>
<footer><cite><a href="https://programmingisterrible.com/post/139222674273/how-to-write-disposable-code-in-large-systems">tef</a></cite></footer>
</blockquote>
<p>
I don't mean that you should always delete code in order to make changes, but often, looking at extremes can provide insights into less extreme cases.
</p>
<p>
When you have a tangled web as shown above, most of the code is coupled to other parts. If you delete a node, then you break something else. You'd think that deleting code is the easiest thing in the world, but it's not.
</p>
<p>
What if, on the other hand, you have smaller clusters of nodes that are independent?
</p>
<p>
<img src="/content/binary/less-coupled-dependency-graph.png" alt="A disconnected graph with small islands of connected graphs.">
</p>
<p>
If your dependency graph looks like this, you can at least delete each of the 'islands' without impacting the other sub-graphs.
</p>
<p>
<img src="/content/binary/dependency-graph-without-deleted-subgraph.png" alt="The graph from the previous figure, less one sub-graph.">
</p>
<p>
<a href="https://programmingisterrible.com/post/139222674273/how-to-write-disposable-code-in-large-systems">Writing code that is easy to delete</a> may be a good idea, but even <em>that</em> is easier said that done. Loose coupling is, once more, key to good architecture.
</p>
<h3 id="88c387fb34bc48b382d1eefdc3ee6367">
Add something better <a href="#88c387fb34bc48b382d1eefdc3ee6367" title="permalink">#</a>
</h3>
<p>
Once you've deleted a cluster of code, you have the opportunity to add something that is even less coupled than the island you deleted.
</p>
<p>
<img src="/content/binary/dependency-graph-with-new-subgraphs.png" alt="The graph from the previous figure, with new small graphs added.">
</p>
<p>
If you add new code that is less coupled than the code you deleted, it's even easier to delete again.
</p>
<h3 id="8a7a8d9547eb4d3881a1cced603f8422">
Conclusion <a href="#8a7a8d9547eb4d3881a1cced603f8422" title="permalink">#</a>
</h3>
<p>
Coupling is a key factor in code organisation. Tightly coupled code is difficult to change. Loosely coupled code is easier to change. As a thought experiment, consider how difficult it would be to delete a particular piece of code. The easier it is to delete the code, the less coupled it is.
</p>
<p>
Deleting a small piece of code to add new code in its stead is the ultimate change. You can often get by with a less radical edit, but if all else fails, delete part of your code base and start over. The less coupled the code is, the easier it is to change.
</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>.The Reader monadhttps://blog.ploeh.dk/2022/11/14/the-reader-monad2022-11-14T06:50:00+00:00Mark Seemann
<div id="post">
<p>
<em>Normal functions form monads. An article for object-oriented programmers.</em>
</p>
<p>
This article is an instalment in <a href="/2022/03/28/monads">an article series about monads</a>. A previous article described <a href="/2021/08/30/the-reader-functor">the Reader functor</a>. As is the case with many (but not all) <a href="/2018/03/22/functors">functors</a>, Readers also form monads.
</p>
<p>
This article continues where the Reader functor article stopped. It uses the same code base.
</p>
<h3 id="d54d83f22d854e94853271e1a559a1d8">
Flatten <a href="#d54d83f22d854e94853271e1a559a1d8" title="permalink">#</a>
</h3>
<p>
A monad must define either a <em>bind</em> or <em>join</em> function, although you can use other names for both of these functions. <code>Flatten</code> is in my opinion a more intuitive name than <code>join</code>, since a monad is really just a functor that you can flatten. Flattening is relevant if you have a nested functor; in this case a Reader within a Reader. You can flatten such a nested Reader with a <code>Flatten</code> function:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> IReader<R, A> <span style="color:#74531f;">Flatten</span><<span style="color:#2b91af;">R</span>, <span style="color:#2b91af;">A</span>>(
<span style="color:blue;">this</span> IReader<R, IReader<R, A>> <span style="color:#1f377f;">source</span>)
{
<span style="color:#8f08c4;">return</span> <span style="color:blue;">new</span> FlattenReader<R, A>(source);
}
<span style="color:blue;">private</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">FlattenReader</span><<span style="color:#2b91af;">R</span>, <span style="color:#2b91af;">A</span>> : IReader<R, A>
{
<span style="color:blue;">private</span> <span style="color:blue;">readonly</span> IReader<R, IReader<R, A>> source;
<span style="color:blue;">public</span> <span style="color:#2b91af;">FlattenReader</span>(IReader<R, IReader<R, A>> <span style="color:#1f377f;">source</span>)
{
<span style="color:blue;">this</span>.source = source;
}
<span style="color:blue;">public</span> A <span style="color:#74531f;">Run</span>(R <span style="color:#1f377f;">environment</span>)
{
IReader<R, A> <span style="color:#1f377f;">newReader</span> = source.Run(environment);
<span style="color:#8f08c4;">return</span> newReader.Run(environment);
}
}</pre>
</p>
<p>
Since the <code>source</code> Reader is nested, calling its <code>Run</code> method once returns a <code>newReader</code>. You can <code>Run</code> that <code>newReader</code> one more time to get an <code>A</code> value to return.
</p>
<p>
You could easily chain the two calls to <code>Run</code> together, one after the other. That would make the code terser, but here I chose to do it in two explicit steps in order to show what's going on.
</p>
<p>
Like the previous article about <a href="/2022/06/20/the-state-monad">the State monad</a>, a lot of <a href="/2019/12/16/zone-of-ceremony">ceremony</a> is required because this variation of the Reader monad is defined with an interface. You could also define the Reader monad on a 'raw' function of the type <code>Func<R, A></code>, in which case <code>Flatten</code> would be simpler:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> Func<R, A> <span style="color:#74531f;">Flatten</span><<span style="color:#2b91af;">R</span>, <span style="color:#2b91af;">A</span>>(<span style="color:blue;">this</span> Func<R, Func<R, A>> <span style="color:#1f377f;">source</span>)
{
<span style="color:#8f08c4;">return</span> <span style="color:#1f377f;">environment</span> => source(environment)(environment);
}</pre>
</p>
<p>
In this variation <code>source</code> is a function, so you can call it with <code>environment</code>, which returns another function that you can again call with <code>environment</code>. This produces an <code>A</code> value for the function to return.
</p>
<h3 id="e2f72c66681d45949a23a7e574ae5ae7">
SelectMany <a href="#e2f72c66681d45949a23a7e574ae5ae7" title="permalink">#</a>
</h3>
<p>
When you have <code>Flatten</code> you can always define <code>SelectMany</code> (<em>monadic bind</em>) like this:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> IReader<R, B> <span style="color:#74531f;">SelectMany</span><<span style="color:#2b91af;">R</span>, <span style="color:#2b91af;">A</span>, <span style="color:#2b91af;">B</span>>(
<span style="color:blue;">this</span> IReader<R, A> <span style="color:#1f377f;">source</span>,
Func<A, IReader<R, B>> <span style="color:#1f377f;">selector</span>)
{
<span style="color:#8f08c4;">return</span> source.Select(selector).Flatten();
}</pre>
</p>
<p>
First use functor-based mapping. Since the <code>selector</code> returns a Reader, this mapping produces a Reader within a Reader. That's exactly the situation that <code>Flatten</code> addresses.
</p>
<p>
The above <code>SelectMany</code> example works with the <code>IReader<R, A></code> interface, but the 'raw' function version has the exact same implementation:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> Func<R, B> <span style="color:#74531f;">SelectMany</span><<span style="color:#2b91af;">R</span>, <span style="color:#2b91af;">A</span>, <span style="color:#2b91af;">B</span>>(
<span style="color:blue;">this</span> Func<R, A> <span style="color:#1f377f;">source</span>,
Func<A, Func<R, B>> <span style="color:#1f377f;">selector</span>)
{
<span style="color:#8f08c4;">return</span> source.Select(selector).Flatten();
}</pre>
</p>
<p>
Only the method declaration differs.
</p>
<h3 id="8c5f94f7395040a7bcfdb2561c8e3ed3">
Query syntax <a href="#8c5f94f7395040a7bcfdb2561c8e3ed3" title="permalink">#</a>
</h3>
<p>
Monads also enable query syntax in C# (just like they enable other kinds of syntactic sugar in languages like <a href="https://fsharp.org/">F#</a> and <a href="https://www.haskell.org">Haskell</a>). As outlined in the <a href="/2022/03/28/monads">monad introduction</a>, however, you must add a special <code>SelectMany</code> overload:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> IReader<R, T1> <span style="color:#74531f;">SelectMany</span><<span style="color:#2b91af;">R</span>, <span style="color:#2b91af;">T</span>, <span style="color:#2b91af;">U</span>, <span style="color:#2b91af;">T1</span>>(
<span style="color:blue;">this</span> IReader<R, T> <span style="color:#1f377f;">source</span>,
Func<T, IReader<R, U>> <span style="color:#1f377f;">k</span>,
Func<T, U, T1> <span style="color:#1f377f;">s</span>)
{
<span style="color:#8f08c4;">return</span> source.SelectMany(<span style="color:#1f377f;">x</span> => k(x).Select(<span style="color:#1f377f;">y</span> => s(x, y)));
}</pre>
</p>
<p>
As already predicted in the monad introduction, this boilerplate overload is always implemented in the same way. Only the signature changes. With it, you could write an expression like this nonsense:
</p>
<p>
<pre>IReader<<span style="color:blue;">int</span>, <span style="color:blue;">bool</span>> <span style="color:#1f377f;">r</span> =
<span style="color:blue;">from</span> dur <span style="color:blue;">in</span> <span style="color:blue;">new</span> MinutesReader()
<span style="color:blue;">from</span> b <span style="color:blue;">in</span> <span style="color:blue;">new</span> Thingy(dur)
<span style="color:blue;">select</span> b;</pre>
</p>
<p>
Where <code>MinutesReader</code> was already shown in the article <a href="/2021/10/04/reader-as-a-contravariant-functor">Reader as a contravariant functor</a>. I couldn't come up with a good name for another reader, so I went with <a href="https://dannorth.net">Dan North</a>'s naming convention that if you don't yet know what to call a class, method, or function, don't <em>pretend</em> that you know. Be explicit that you don't know.
</p>
<p>
Here it is, for the sake of completion:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">sealed</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">Thingy</span> : IReader<<span style="color:blue;">int</span>, <span style="color:blue;">bool</span>>
{
<span style="color:blue;">private</span> <span style="color:blue;">readonly</span> TimeSpan timeSpan;
<span style="color:blue;">public</span> <span style="color:#2b91af;">Thingy</span>(TimeSpan <span style="color:#1f377f;">timeSpan</span>)
{
<span style="color:blue;">this</span>.timeSpan = timeSpan;
}
<span style="color:blue;">public</span> <span style="color:blue;">bool</span> <span style="color:#74531f;">Run</span>(<span style="color:blue;">int</span> <span style="color:#1f377f;">environment</span>)
{
<span style="color:#8f08c4;">return</span> <span style="color:blue;">new</span> TimeSpan(timeSpan.Ticks * environment).TotalDays < 1;
}
}</pre>
</p>
<p>
I'm not claiming that this class makes sense. These articles are deliberate kept abstract in order to focus on structure and behaviour, rather than on practical application.
</p>
<h3 id="d5d827cf83d242e6baecbda622ca5cb9">
Return <a href="#d5d827cf83d242e6baecbda622ca5cb9" title="permalink">#</a>
</h3>
<p>
Apart from flattening or monadic bind, a monad must also define a way to put a normal value into the monad. Conceptually, I call this function <em>return</em> (because that's the name that Haskell uses):
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> IReader<R, A> <span style="color:#74531f;">Return</span><<span style="color:#2b91af;">R</span>, <span style="color:#2b91af;">A</span>>(A <span style="color:#1f377f;">a</span>)
{
<span style="color:#8f08c4;">return</span> <span style="color:blue;">new</span> ReturnReader<R, A>(a);
}
<span style="color:blue;">private</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">ReturnReader</span><<span style="color:#2b91af;">R</span>, <span style="color:#2b91af;">A</span>> : IReader<R, A>
{
<span style="color:blue;">private</span> <span style="color:blue;">readonly</span> A a;
<span style="color:blue;">public</span> <span style="color:#2b91af;">ReturnReader</span>(A <span style="color:#1f377f;">a</span>)
{
<span style="color:blue;">this</span>.a = a;
}
<span style="color:blue;">public</span> A <span style="color:#74531f;">Run</span>(R <span style="color:#1f377f;">environment</span>)
{
<span style="color:#8f08c4;">return</span> a;
}
}</pre>
</p>
<p>
This implementation returns the <code>a</code> value and completely ignores the <code>environment</code>. You can do the same with a 'naked' function.
</p>
<h3 id="bd79fe3d97644f0f9edb12f08a0b5d01">
Left identity <a href="#bd79fe3d97644f0f9edb12f08a0b5d01" title="permalink">#</a>
</h3>
<p>
We need to identify the <em>return</em> function in order to examine <a href="/2022/04/11/monad-laws">the monad laws</a>. Now that this is accomplished, let's see what the laws look like for the Reader monad, starting with the left identity law.
</p>
<p>
<pre>[Theory]
[InlineData(UriPartial.Authority, <span style="color:#a31515;">"https://example.com/f?o=o"</span>)]
[InlineData(UriPartial.Path, <span style="color:#a31515;">"https://example.net/b?a=r"</span>)]
[InlineData(UriPartial.Query, <span style="color:#a31515;">"https://example.org/b?a=z"</span>)]
[InlineData(UriPartial.Scheme, <span style="color:#a31515;">"https://example.gov/q?u=x"</span>)]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> <span style="color:#74531f;">LeftIdentity</span>(UriPartial <span style="color:#1f377f;">a</span>, <span style="color:blue;">string</span> <span style="color:#1f377f;">u</span>)
{
Func<UriPartial, IReader<Uri, UriPartial>> <span style="color:#1f377f;">@return</span> =
<span style="color:#1f377f;">up</span> => Reader.Return<Uri, UriPartial>(up);
Func<UriPartial, IReader<Uri, <span style="color:blue;">string</span>>> <span style="color:#1f377f;">h</span> =
<span style="color:#1f377f;">up</span> => <span style="color:blue;">new</span> UriPartReader(up);
Assert.Equal(
@return(a).SelectMany(h).Run(<span style="color:blue;">new</span> Uri(u)),
h(a).Run(<span style="color:blue;">new</span> Uri(u)));
}</pre>
</p>
<p>
In order to compare the two Reader values, the test has to <code>Run</code> them and then compare the return values.
</p>
<p>
This test and the next uses a Reader implementation called <code>UriPartReader</code>, which almost makes sense:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">sealed</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">UriPartReader</span> : IReader<Uri, <span style="color:blue;">string</span>>
{
<span style="color:blue;">private</span> <span style="color:blue;">readonly</span> UriPartial part;
<span style="color:blue;">public</span> <span style="color:#2b91af;">UriPartReader</span>(UriPartial <span style="color:#1f377f;">part</span>)
{
<span style="color:blue;">this</span>.part = part;
}
<span style="color:blue;">public</span> <span style="color:blue;">string</span> <span style="color:#74531f;">Run</span>(Uri <span style="color:#1f377f;">environment</span>)
{
<span style="color:#8f08c4;">return</span> environment.GetLeftPart(part);
}
}</pre>
</p>
<p>
Almost.
</p>
<h3 id="ad9edb1097be4eeb96170809272851eb">
Right identity <a href="#ad9edb1097be4eeb96170809272851eb" title="permalink">#</a>
</h3>
<p>
In a similar manner, we can showcase the right identity law as a test.
</p>
<p>
<pre>[Theory]
[InlineData(UriPartial.Authority, <span style="color:#a31515;">"https://example.com/q?u=ux"</span>)]
[InlineData(UriPartial.Path, <span style="color:#a31515;">"https://example.net/q?u=uuz"</span>)]
[InlineData(UriPartial.Query, <span style="color:#a31515;">"https://example.org/c?o=rge"</span>)]
[InlineData(UriPartial.Scheme, <span style="color:#a31515;">"https://example.gov/g?a=rply"</span>)]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> <span style="color:#74531f;">RightIdentity</span>(UriPartial <span style="color:#1f377f;">a</span>, <span style="color:blue;">string</span> <span style="color:#1f377f;">u</span>)
{
Func<UriPartial, IReader<Uri, <span style="color:blue;">string</span>>> <span style="color:#1f377f;">f</span> =
<span style="color:#1f377f;">up</span> => <span style="color:blue;">new</span> UriPartReader(up);
Func<<span style="color:blue;">string</span>, IReader<Uri, <span style="color:blue;">string</span>>> <span style="color:#1f377f;">@return</span> =
<span style="color:#1f377f;">s</span> => Reader.Return<Uri, <span style="color:blue;">string</span>>(s);
IReader<Uri, <span style="color:blue;">string</span>> <span style="color:#1f377f;">m</span> = f(a);
Assert.Equal(
m.SelectMany(@return).Run(<span style="color:blue;">new</span> Uri(u)),
m.Run(<span style="color:blue;">new</span> Uri(u)));
}</pre>
</p>
<p>
As always, even a parametrised test constitutes no <em>proof</em> that the law holds. I show the tests to illustrate what the laws look like in 'real' code.
</p>
<h3 id="67a2f225bd8f432dbeed30c2ba2b623a">
Associativity <a href="#67a2f225bd8f432dbeed30c2ba2b623a" title="permalink">#</a>
</h3>
<p>
The last monad law is the associativity law that describes how (at least) three functions compose. We're going to need three functions. For the purpose of demonstrating the law, any three pure functions will do. While the following functions are silly and not at all 'realistic', they have the virtue of being as simple as they can be (while still providing a bit of variety). They don't 'mean' anything, so don't worry too much about their behaviour. It is, as far as I can tell, nonsensical.
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">sealed</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">F</span> : IReader<<span style="color:blue;">int</span>, <span style="color:blue;">string</span>>
{
<span style="color:blue;">private</span> <span style="color:blue;">readonly</span> <span style="color:blue;">char</span> c;
<span style="color:blue;">public</span> <span style="color:#2b91af;">F</span>(<span style="color:blue;">char</span> <span style="color:#1f377f;">c</span>)
{
<span style="color:blue;">this</span>.c = c;
}
<span style="color:blue;">public</span> <span style="color:blue;">string</span> <span style="color:#74531f;">Run</span>(<span style="color:blue;">int</span> <span style="color:#1f377f;">environment</span>)
{
<span style="color:#8f08c4;">return</span> <span style="color:blue;">new</span> <span style="color:blue;">string</span>(c, environment);
}
}
<span style="color:blue;">public</span> <span style="color:blue;">sealed</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">G</span> : IReader<<span style="color:blue;">int</span>, <span style="color:blue;">bool</span>>
{
<span style="color:blue;">private</span> <span style="color:blue;">readonly</span> <span style="color:blue;">string</span> s;
<span style="color:blue;">public</span> <span style="color:#2b91af;">G</span>(<span style="color:blue;">string</span> <span style="color:#1f377f;">s</span>)
{
<span style="color:blue;">this</span>.s = s;
}
<span style="color:blue;">public</span> <span style="color:blue;">bool</span> <span style="color:#74531f;">Run</span>(<span style="color:blue;">int</span> <span style="color:#1f377f;">environment</span>)
{
<span style="color:#8f08c4;">return</span> environment < 42 || s.Contains(<span style="color:#a31515;">"a"</span>);
}
}
<span style="color:blue;">public</span> <span style="color:blue;">sealed</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">H</span> : IReader<<span style="color:blue;">int</span>, TimeSpan>
{
<span style="color:blue;">private</span> <span style="color:blue;">readonly</span> <span style="color:blue;">bool</span> b;
<span style="color:blue;">public</span> <span style="color:#2b91af;">H</span>(<span style="color:blue;">bool</span> <span style="color:#1f377f;">b</span>)
{
<span style="color:blue;">this</span>.b = b;
}
<span style="color:blue;">public</span> TimeSpan <span style="color:#74531f;">Run</span>(<span style="color:blue;">int</span> <span style="color:#1f377f;">environment</span>)
{
<span style="color:#8f08c4;">return</span> b ?
TimeSpan.FromMinutes(environment) :
TimeSpan.FromSeconds(environment);
}
}</pre>
</p>
<p>
Armed with these three classes, we can now demonstrate the Associativity law:
</p>
<p>
<pre>[Theory]
[InlineData(<span style="color:#a31515;">'a'</span>, 0)]
[InlineData(<span style="color:#a31515;">'b'</span>, 1)]
[InlineData(<span style="color:#a31515;">'c'</span>, 42)]
[InlineData(<span style="color:#a31515;">'d'</span>, 2112)]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> <span style="color:#74531f;">Associativity</span>(<span style="color:blue;">char</span> <span style="color:#1f377f;">a</span>, <span style="color:blue;">int</span> <span style="color:#1f377f;">i</span>)
{
Func<<span style="color:blue;">char</span>, IReader<<span style="color:blue;">int</span>, <span style="color:blue;">string</span>>> <span style="color:#1f377f;">f</span> = <span style="color:#1f377f;">c</span> => <span style="color:blue;">new</span> F(c);
Func<<span style="color:blue;">string</span>, IReader<<span style="color:blue;">int</span>, <span style="color:blue;">bool</span>>> <span style="color:#1f377f;">g</span> = <span style="color:#1f377f;">s</span> => <span style="color:blue;">new</span> G(s);
Func<<span style="color:blue;">bool</span>, IReader<<span style="color:blue;">int</span>, TimeSpan>> <span style="color:#1f377f;">h</span> = <span style="color:#1f377f;">b</span> => <span style="color:blue;">new</span> H(b);
IReader<<span style="color:blue;">int</span>, <span style="color:blue;">string</span>> <span style="color:#1f377f;">m</span> = f(a);
Assert.Equal(
m.SelectMany(g).SelectMany(h).Run(i),
m.SelectMany(<span style="color:#1f377f;">x</span> => g(x).SelectMany(h)).Run(i));
}</pre>
</p>
<p>
In case you're wondering, the four test cases produce the outputs <code>00:00:00</code>, <code>00:01:00</code>, <code>00:00:42</code>, and <code>00:35:12</code>. You can see that reproduced below:
</p>
<h3 id="a46f77dddd914f0b9c8926dd2c06e9d6">
Haskell <a href="#a46f77dddd914f0b9c8926dd2c06e9d6" title="permalink">#</a>
</h3>
<p>
In Haskell, normal functions <code>a -> b</code> are already <code>Monad</code> instances, which means that you can easily replicate the functions from the <code>Associativity</code> test:
</p>
<p>
<pre>> f c = \env -> replicate env c
> g s = \env -> env < 42 || 'a' `elem` s
> h b = \env -> if b then secondsToDiffTime (toEnum env * 60) else secondsToDiffTime (toEnum env)</pre>
</p>
<p>
I've chosen to write the <code>f</code>, <code>g</code>, and <code>h</code> as functions that return lambda expressions in order to emphasise that each of these functions return Readers. Since Haskell functions are already curried, I could also have written them in the more normal function style with two normal parameters, but that might have obscured the Reader aspect of each.
</p>
<p>
Here's the composition in action:
</p>
<p>
<pre>> f 'a' >>= g >>= h $ 0
0s
> f 'b' >>= g >>= h $ 1
60s
> f 'c' >>= g >>= h $ 42
42s
> f 'd' >>= g >>= h $ 2112
2112s</pre>
</p>
<p>
In case you are wondering, 2,112 seconds is 35 minutes and 12 seconds, so all outputs fit with the results reported for the C# example.
</p>
<p>
What the above Haskell GHCi (<a href="https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop">REPL</a>) session demonstrates is that it's possible to compose functions with Haskell's monadic bind operator <code>>>=</code> operator exactly because all functions are (Reader) monads.
</p>
<h3 id="fb5e50be9b66464ca61cd4a45eb7e756">
Conclusion <a href="#fb5e50be9b66464ca61cd4a45eb7e756" title="permalink">#</a>
</h3>
<p>
In Haskell, it can occasionally be useful that a function can be used when a <code>Monad</code> is required. Some Haskell libraries are defined in very general terms. Their APIs may enable you to call functions with any monadic input value. You can, say, pass a <a href="/2022/04/25/the-maybe-monad">Maybe</a>, a <a href="/2022/04/19/the-list-monad">List</a>, an <a href="/2022/05/09/an-either-monad">Either</a>, a State, but you can also pass a function.
</p>
<p>
C# and most other languages (F# included) doesn't come with that level of abstraction, so the fact that a function forms a monad is less useful there. In fact, I can't recall having made explicit use of this knowledge in C#, but one never knows if that day arrives.
</p>
<p>
In a similar vein, knowing that <a href="/2018/04/16/endomorphic-composite-as-a-monoid">endomorphisms form monoids</a> (and thereby also <a href="/2017/11/27/semigroups">semigroups</a>) enabled me to <a href="/2020/12/14/validation-a-solved-problem">quickly identify the correct design for a validation problem</a>.
</p>
<p>
Who knows? One day the knowledge that functions are monads may come in handy.
</p>
<p>
<strong>Next:</strong> <a href="/2023/01/09/the-io-monad">The IO monad</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>.Applicative assertionshttps://blog.ploeh.dk/2022/11/07/applicative-assertions2022-11-07T06:56:00+00:00Mark Seemann
<div id="post">
<p>
<em>An exploration.</em>
</p>
<p>
In a recent Twitter exchange, <a href="https://lucasdicioccio.github.io/">Lucas DiCioccio</a> made an interesting observation:
</p>
<blockquote>
<p>
"Imho the properties you want of an assertion-framework are really close (the same as?) applicative-validation: one assertion failure with multiple bullet points composed mainly from combinators."
</p>
<footer><cite><a href="https://twitter.com/lucasdicioccio/status/1572264819109003265">Lucas DiCioccio</a></cite></footer>
</blockquote>
<p>
In another branch off my initial tweet <a href="https://www.joshka.net/">Josh McKinney</a> pointed out the short-circuiting nature of standard assertions:
</p>
<blockquote>
<p>
"short circuiting often causes weaker error messages in failing tests than running compound assertions. E.g.
</p>
<p>
<pre>TransferTest {
a.transfer(b,50);
a.shouldEqual(50);
b.shouldEqual(150); // never reached?
}</pre>
</p>
<footer><cite><a href="https://twitter.com/joshuamck/status/1572232484884217864">Josh McK</a></cite></footer>
</blockquote>
<p>
Most standard assertion libraries work by throwing exceptions when an assertion fails. Once you throw an exception, remaining code doesn't execute. This means that you only get the first assertion message. Further assertions are not evaluated.
</p>
<p>
Josh McKinney <a href="https://twitter.com/joshuamck/status/1572528796125003777">later gave more details about a particular scenario</a>. Although in the general case I don't consider the short-circuiting nature of assertions to be a problem, I grant that there are cases where proper assertion composition would be useful.
</p>
<p>
Lucas DiCioccio's suggestion seems worthy of investigation.
</p>
<h3 id="54fc71d7459d4251a79dc16f58bd79b3">
Ongoing exploration <a href="#54fc71d7459d4251a79dc16f58bd79b3" title="permalink">#</a>
</h3>
<p>
<a href="https://twitter.com/ploeh/status/1572282314402721805">I asked</a> Lucas DiCioccio whether he'd done any work with his idea, and the day after <a href="https://twitter.com/lucasdicioccio/status/1572639255582867456">he replied</a> with a <a href="https://www.haskell.org">Haskell</a> proof of concept.
</p>
<p>
I found the idea so interesting that I also wanted to carry out a few proofs of concept myself, perhaps within a more realistic setting.
</p>
<p>
As I'm writing this, I've reached some preliminary conclusions, but I'm also aware that they may not hold in more general cases. I'm posting what I have so far, but you should expect this exploration to evolve over time. If I find out more, I'll update this post with more articles.
</p>
<ul>
<li><a href="/2022/11/28/an-initial-proof-of-concept-of-applicative-assertions-in-c">An initial proof of concept of applicative assertions in C#</a></li>
<li><a href="/2022/12/19/error-accumulating-composable-assertions-in-c">Error-accumulating composable assertions in C#</a></li>
<li><a href="/2023/01/30/built-in-alternatives-to-applicative-assertions">Built-in alternatives to applicative assertions</a></li>
</ul>
<p>
A preliminary summary is in order. Based on the first two articles, applicative assertions look like overkill. I think, however, that it's because of the degenerate nature of the example. Some assertions are essentially one-stop verifications: Evaluate a predicate, and throw an exception if the result is <em>false</em>. These assertions return <a href="/2018/01/15/unit-isomorphisms">unit or void</a>. Examples from <a href="https://xunit.net/">xUnit</a> include <code>Assert.Equal</code>, <code>Assert.True</code>, <code>Assert.False</code>, <code>Assert.All</code>, and <code>Assert.DoesNotContain</code>.
</p>
<p>
These are the kinds of assertions that the initial two articles explore.
</p>
<p>
There are other kinds of assertions that return a value in case of success. xUnit.net examples include <code>Assert.Throws</code>, <code>Assert.Single</code>, <code>Assert.IsAssignableFrom</code>, and some overloads of <code>Assert.Contains</code>. <code>Assert.Single</code>, for example, verifies that a collection contains only a single element. While it throws an exception if the collection is either empty or has more than one element, in the success case it returns the single value. This can be useful if you want to add more assertions based on that value.
</p>
<p>
I haven't experimented with this yet, but as far as can tell, you'll run into the following problem: If you make such an assertion return an <a href="/2018/10/01/applicative-functors">applicative functor</a>, you'll need some way to handle the success case. Combining it with another assertion-producing function, such as <code>a -> Asserted e b</code> (pseudocode) is possible with <a href="/2018/03/22/functors">functor</a> mapping, but will leave you with a nested functor.
</p>
<p>
You'll probably want to flatten the nested functor, which is exactly what <a href="/2022/03/28/monads">monads</a> do. Monads, on the other hand, short circuit, so you don't want to make your applicative assertion type a monad. Instead, you'll need to use an isomorphic monad container (<a href="/2022/05/09/an-either-monad">Either</a> should do) to move in and out of. Doable, but is the complexity warranted?
</p>
<p>
I realise that the above musings are abstract, and that I really should show rather than tell. I'll add some more content here if I ever collect something worthy of an article. if you ask me now, though, I consider that a bit of a toss-up.
</p>
<p>
The first two examples also suffer from being written in C#, which doesn't have good syntactic support for applicative functors. Perhaps I'll add some articles that use <a href="https://fsharp.org/">F#</a> or Haskell.
</p>
<h3 id="676b3bf45f0841bc9a51d3510d917a6a">
Conclusion <a href="#676b3bf45f0841bc9a51d3510d917a6a" title="permalink">#</a>
</h3>
<p>
There's the occasional need for composable assertions. You can achieve that with an applicative functor, but the question is whether it's warranted. Could you make something simpler based on the <a href="/2022/04/19/the-list-monad">list monad</a>?
</p>
<p>
As I'm writing this, I don't consider that question settled. Even so, you may want to read on.
</p>
<p>
<strong>Next:</strong> <a href="/2022/11/28/an-initial-proof-of-concept-of-applicative-assertions-in-c">An initial proof of concept of applicative assertions in C#</a>.
</p>
</div>
<div id="comments">
<hr>
<h2 id="comments-header">
Comments
</h2>
<div class="comment" id="e3269279056146f985c8405f6d3ad286">
<div class="comment-author"><a href="https://about.me/tysonwilliams">Tyson Williams</a></div>
<div class="comment-content">
<blockquote>
Monads, on the other hand, short circuit, so you don't want to make your applicative assertion type a monad.
</blockquote>
<p>
I want my assertion type to be both applicative and monadic.
So does Paul Loath, the creator of Language Ext,
which is most clearly seen via <a href="https://github.com/louthy/language-ext/blob/main/LanguageExt.Tests/ValidationTests.cs#L267-L277">this Validation test code</a>.
So does Alexis King (as you pointed out to me) in her Haskell Validation package,
which violiates Hakell's monad type class,
and which she defends <a href="https://hackage.haskell.org/package/monad-validate-1.2.0.1/docs/Control-Monad-Validate.html#:~:text=ValidateT%20and%20the%20Monad%20laws">here</a>.
</p>
<p>
When I want (or typically need) short-circuiting behavior,
then I use the type's monadic API.
When I want "error-collecting behavior",
then I use the type's applicative API.
</p>
<blockquote>
The first two examples also suffer from being written in C#, which doesn't have good syntactic support for applicative functors.
</blockquote>
<p>
The best syntactic support for applicative functors in C# that I have seen is in Langauge Ext.
<a href="https://github.com/louthy/language-ext/blob/15cd875ea40925e2ca9cd702c84f9142918dbb77/LanguageExt.Tests/ValidationTests.cs#L272-L277">A comment explains</a>
in that same Validation test how it works,
and the line after the comment shows it in action.
</p>
</div>
<div class="comment-date">2023-01-16 21:13 UTC</div>
</div>
<div class="comment" id="a1516515c1b84cb2b8473f2c0321562e">
<div class="comment-author"><a href="/">Mark Seemann</a></div>
<div class="comment-content">
<p>
Tyson, thank you for writing. Whether or not you want to enable monadic short-circuiting for assertions or validations depends, I think, on 'developer ergonomics'. It's a trade-off mainly between <em>ease</em> and <em>simplicity</em> as <a href="https://www.infoq.com/presentations/Simple-Made-Easy/">outlined by Rich Hickey</a>. Enabling a monadic API for something that isn't naturally monadic does indeed provide ease of use, in that the compositional capabilities of a monad are readily 'at hand'.
</p>
<p>
If you don't have that capability you'll have to map back and forth between, say, <code>Validation</code> and <code>Either</code> (if using the <a href="https://hackage.haskell.org/package/validation">validation</a> package). This is tedious, but <a href="https://peps.python.org/pep-0020/">explicit</a>.
</p>
<p>
Making validation or assertions monadic makes it easier to compose nested values, but also (in my experience) makes it easier to make mistakes, in the sense that you (or a colleague) may <em>think</em> that the behaviour is error-collecting, whereas in reality it's short-circuiting.
</p>
<p>
In the end, the trade-off may reduce to how much you trust yourself (and co-workers) to steer clear of mistakes, and how important it is to avoid errors. In this case, how important is it to collect the errors, rather than short-circuiting?
</p>
<p>
You can choose one alternative or the other by weighing such concerns.
</p>
</div>
<div class="comment-date">2023-01-19 8:30 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>.A regular grid emergeshttps://blog.ploeh.dk/2022/10/31/a-regular-grid-emerges2022-10-31T06:44:00+00:00Mark Seemann
<div id="post">
<p>
<em>The code behind a lecture animation.</em>
</p>
<p>
If you've seen my presentation <a href="https://youtu.be/FPEEiX5unWI">Fractal Architecture</a>, you may have wondered how I made the animation where a regular(ish) hexagonal grid emerges from adding more and more blobs to an area.
</p>
<p>
<img src="/content/binary/a-regular-grid-emerges.png" alt="A grid-like structure starting to emerge from tightly packing blobs.">
</p>
<p>
Like <a href="/2021/04/05/mazes-on-voronoi-tesselations">a few</a> <a href="/2021/07/05/fractal-hex-flowers">previous</a> blog posts, today's article appears on <a href="https://observablehq.com">Observable</a>, which is where the animation and the code that creates it lives. <a href="https://observablehq.com/@ploeh/a-regular-grid-emerges">Go there to read it</a>.
</p>
<p>
If you have time, watch the animation evolve. Personally I find it quite mesmerising.
</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>.Encapsulation in Functional Programminghttps://blog.ploeh.dk/2022/10/24/encapsulation-in-functional-programming2022-10-24T05:54:00+00:00Mark Seemann
<div id="post">
<p>
<em>Encapsulation is only relevant for object-oriented programming, right?</em>
</p>
<p>
The concept of <em>encapsulation</em> is closely related to object-oriented programming (OOP), and you rarely hear the word in discussions about (statically-typed) functional programming (FP). I will argue, however, that the notion is relevant in FP as well. Typically, it just appears with a different catchphrase.
</p>
<h3 id="f0f64bfaaa6f4d22b990fae4775a8b89">
Contracts <a href="#f0f64bfaaa6f4d22b990fae4775a8b89" title="permalink">#</a>
</h3>
<p>
I base my understanding of encapsulation on <a href="/ref/oosc">Object-Oriented Software Construction</a>. I've tried to distil it in my Pluralsight course <a href="/encapsulation-and-solid">Encapsulation and SOLID</a>.
</p>
<p>
In short, encapsulation denotes the distinction between an object's contract and its implementation. An object should fulfil its contract in such a way that client code doesn't need to know about its implementation.
</p>
<p>
Contracts, according to <a href="https://en.wikipedia.org/wiki/Bertrand_Meyer">Bertrand Meyer</a>, describe three properties of objects:
</p>
<ul>
<li>Preconditions: What client code must fulfil in order to successfully interact with the object.</li>
<li>Invariants: Statements about the object that are always true.</li>
<li>Postconditions: Statements that are guaranteed to be true after a successful interaction between client code and object.</li>
</ul>
<p>
You can replace <em>object</em> with <em>value</em> and I'd argue that the same concerns are relevant in FP.
</p>
<p>
In OOP <em>invariants</em> often point to the properties of an object that are guaranteed to remain even in the face of state mutation. As you change the state of an object, the object should guarantee that its state remains valid. These are the properties (i.e. <em>qualities</em>, <em>traits</em>, <em>attributes</em>) that don't vary - i.e. are <em>invariant</em>.
</p>
<p>
An example would be helpful around here.
</p>
<h3 id="72a37691c0c14d4a8673d52f25e7c3e2">
Table mutation <a href="#72a37691c0c14d4a8673d52f25e7c3e2" title="permalink">#</a>
</h3>
<p>
Consider an object that models a table in a restaurant. You may, for example, be working on <a href="/2020/01/27/the-maitre-d-kata">the Maître d' kata</a>. In short, you may decide to model a table as being one of two kinds: Standard tables and communal tables. You can reserve seats at communal tables, but you still share the table with other people.
</p>
<p>
You may decide to model the problem in such a way that when you reserve the table, you change the state of the object. You may decide to describe the contract of <code>Table</code> objects like this:
</p>
<ul>
<li>Preconditions
<ul>
<li>To create a <code>Table</code> object, you must supply a type (standard or communal).</li>
<li>To create a <code>Table</code> object, you must supply the size of the table, which is a measure of its capacity; i.e. how many people can sit at it.</li>
<li>The capacity must be a natural number. <em>One</em> (1) is the smallest valid capacity.</li>
<li>When reserving a table, you must supply a valid reservation.</li>
<li>When reserving a table, the reservation quantity must be less than or equal to the table's remaining capacity.</li>
</ul>
</li>
<li>Invariants
<ul>
<li>The table capacity doesn't change.</li>
<li>The table type doesn't change.</li>
<li>The number of remaining seats is never negative.</li>
<li>The number of remaining seats is never greater than the table's capacity.</li>
</ul>
</li>
<li>Postconditions
<ul>
<li>After reserving a table, the number of remaining seats can't be greater than the previous number of remaining seats minus the reservation quantity.</li>
</ul>
</li>
</ul>
<p>
This list may be incomplete, and if you add more operations, you may have to elaborate on what that means to the contract.
</p>
<p>
In C# you may implement a <code>Table</code> class like this:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">sealed</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">Table</span>
{
<span style="color:blue;">private</span> <span style="color:blue;">readonly</span> List<Reservation> reservations;
<span style="color:blue;">public</span> <span style="color:#2b91af;">Table</span>(<span style="color:blue;">int</span> capacity, TableType type)
{
<span style="color:blue;">if</span> (capacity < 1)
<span style="color:blue;">throw</span> <span style="color:blue;">new</span> ArgumentOutOfRangeException(
nameof(capacity),
<span style="color:#a31515;">$"Capacity must be greater than zero, but was: </span>{capacity}<span style="color:#a31515;">."</span>);
reservations = <span style="color:blue;">new</span> List<Reservation>();
Capacity = capacity;
Type = type;
RemaingSeats = capacity;
}
<span style="color:blue;">public</span> <span style="color:blue;">int</span> Capacity { <span style="color:blue;">get</span>; }
<span style="color:blue;">public</span> TableType Type { <span style="color:blue;">get</span>; }
<span style="color:blue;">public</span> <span style="color:blue;">int</span> RemaingSeats { <span style="color:blue;">get</span>; <span style="color:blue;">private</span> <span style="color:blue;">set</span>; }
<span style="color:blue;">public</span> <span style="color:blue;">void</span> Reserve(Reservation reservation)
{
<span style="color:blue;">if</span> (RemaingSeats < reservation.Quantity)
<span style="color:blue;">throw</span> <span style="color:blue;">new</span> InvalidOperationException(
<span style="color:#a31515;">"The table has no remaining seats."</span>);
<span style="color:blue;">if</span> (Type == TableType.Communal)
RemaingSeats -= reservation.Quantity;
<span style="color:blue;">else</span>
RemaingSeats = 0;
reservations.Add(reservation);
}
}</pre>
</p>
<p>
This class has good encapsulation because it makes sure to fulfil the contract. You can't put it in an invalid state.
</p>
<h3 id="b37e173371f249d99f80d12d64b2bee2">
Immutable Table <a href="#b37e173371f249d99f80d12d64b2bee2" title="permalink">#</a>
</h3>
<p>
Notice that two of the invariants for the above <code>Table</code> class is that the table can't change type or capacity. While OOP often revolves around state mutation, it seems reasonable that some data is immutable. A table doesn't all of a sudden change size.
</p>
<p>
In FP data is immutable. Data doesn't change. Thus, data has that invariant property.
</p>
<p>
If you consider the above contract, it still applies to FP. The specifics change, though. You'll no longer be dealing with <code>Table</code> objects, but rather <code>Table</code> data, and to make reservations, you call a function that returns a new <code>Table</code> value.
</p>
<p>
In <a href="https://fsharp.org/">F#</a> you could model a <code>Table</code> like this:
</p>
<p>
<pre><span style="color:blue;">type</span> Table = <span style="color:blue;">private</span> Standard <span style="color:blue;">of</span> int * Reservation list | Communal <span style="color:blue;">of</span> int * Reservation list
<span style="color:blue;">module</span> Table =
<span style="color:blue;">let</span> standard capacity =
<span style="color:blue;">if</span> 0 < capacity
<span style="color:blue;">then</span> Some (Standard (capacity, []))
<span style="color:blue;">else</span> None
<span style="color:blue;">let</span> communal capacity =
<span style="color:blue;">if</span> 0 < capacity
<span style="color:blue;">then</span> Some (Communal (capacity, []))
<span style="color:blue;">else</span> None
<span style="color:blue;">let</span> remainingSeats = <span style="color:blue;">function</span>
| Standard (capacity, []) <span style="color:blue;">-></span> capacity
| Standard _ <span style="color:blue;">-></span> 0
| Communal (capacity, rs) <span style="color:blue;">-></span> capacity - List.sumBy (<span style="color:blue;">fun</span> r <span style="color:blue;">-></span> r.Quantity) rs
<span style="color:blue;">let</span> reserve r t =
<span style="color:blue;">match</span> t <span style="color:blue;">with</span>
| Standard (capacity, []) <span style="color:blue;">when</span> r.Quantity <= remainingSeats t <span style="color:blue;">-></span>
Some (Standard (capacity, [r]))
| Communal (capacity, rs) <span style="color:blue;">when</span> r.Quantity <= remainingSeats t <span style="color:blue;">-></span>
Some (Communal (capacity, r :: rs))
| _ <span style="color:blue;">-></span> None</pre>
</p>
<p>
While you'll often hear fsharpers say that one should <a href="https://blog.janestreet.com/effective-ml-video/">make illegal states unrepresentable</a>, in practice you often have to rely on <a href="https://www.hillelwayne.com/post/constructive/">predicative</a> data to enforce contracts. I've done this here by making the <code>Table</code> cases <code>private</code>. Code outside the module can't directly create <code>Table</code> data. Instead, it'll have to use one of two functions: <code>Table.standard</code> or <code>Table.communal</code>. These are functions that return <code>Table option</code> values.
</p>
<p>
That's the idiomatic way to model predicative data in statically typed FP. In <a href="https://www.haskell.org/">Haskell</a> such functions are called <a href="https://wiki.haskell.org/Smart_constructors">smart constructors</a>.
</p>
<p>
Statically typed FP typically use <a href="/2022/04/25/the-maybe-monad">Maybe</a> (<code>Option</code>) or <a href="/2022/05/09/an-either-monad">Either</a> (<code>Result</code>) values to communicate failure, rather than throwing exceptions, but apart from that a smart constructor is just an object constructor.
</p>
<p>
The above F# <code>Table</code> API implements the same contract as the OOP version.
</p>
<p>
If you want to see a more elaborate example of modelling table and reservations in F#, see <a href="/2020/04/27/an-f-implementation-of-the-maitre-d-kata">An F# implementation of the Maître d' kata</a>.
</p>
<h3 id="78027bc1d1414c2fa3604a68c9df6418">
Functional contracts in OOP languages <a href="#78027bc1d1414c2fa3604a68c9df6418" title="permalink">#</a>
</h3>
<p>
You can adopt many FP concepts in OOP languages. My book <a href="/2021/06/14/new-book-code-that-fits-in-your-head">Code That Fits in Your Head</a> contains sample code in C# that implements an online restaurant reservation system. It includes a <code>Table</code> class that, at first glance, looks like the above C# class.
</p>
<p>
While it has the same contract, the book's <code>Table</code> class is implemented with the FP design principles in mind. Thus, it's an immutable class with this API:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">sealed</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">Table</span>
{
<span style="color:blue;">public</span> <span style="color:blue;">static</span> Table Standard(<span style="color:blue;">int</span> seats)
<span style="color:blue;">public</span> <span style="color:blue;">static</span> Table Communal(<span style="color:blue;">int</span> seats)
<span style="color:blue;">public</span> <span style="color:blue;">int</span> Capacity { <span style="color:blue;">get</span>; }
<span style="color:blue;">public</span> <span style="color:blue;">int</span> RemainingSeats { <span style="color:blue;">get</span>; }
<span style="color:blue;">public</span> Table Reserve(Reservation reservation)
<span style="color:blue;">public</span> T Accept<<span style="color:#2b91af;">T</span>>(ITableVisitor<T> visitor)
<span style="color:blue;">public</span> <span style="color:blue;">override</span> <span style="color:blue;">bool</span> Equals(<span style="color:blue;">object</span>? obj)
<span style="color:blue;">public</span> <span style="color:blue;">override</span> <span style="color:blue;">int</span> GetHashCode()
}</pre>
</p>
<p>
Notice that the <code>Reserve</code> method returns a <code>Table</code> object. That's the table with the reservation associated. The original <code>Table</code> instance remains unchanged.
</p>
<p>
The entire book is written in the <a href="https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell">Functional Core, Imperative Shell</a> architecture, so all domain models are immutable objects with <a href="https://en.wikipedia.org/wiki/Pure_function">pure functions</a> as methods.
</p>
<p>
The objects still have contracts. They have proper encapsulation.
</p>
<h3 id="ca2409555a5b4efe9b98e1c65e77256d">
Conclusion <a href="#ca2409555a5b4efe9b98e1c65e77256d" title="permalink">#</a>
</h3>
<p>
Functional programmers may not use the term <em>encapsulation</em> much, but that doesn't mean that they don't share that kind of concern. They often throw around the phrase <em>make illegal states unrepresentable</em> or talk about smart constructors or <a href="https://en.wikipedia.org/wiki/Partial_function">partial versus total functions</a>. It's clear that they care about data modelling that prevents mistakes.
</p>
<p>
The object-oriented notion of <em>encapsulation</em> is ultimately about separating the affordances of an API from its implementation details. An object's contract is an abstract description of the properties (i.e. <em>qualities</em>, <em>traits</em>, or <em>attributes</em>) of the object.
</p>
<p>
Functional programmers care so much about the properties of data and functions that <em>property-based testing</em> is often the preferred way to perform automated testing.
</p>
<p>
Perhaps you can find a functional programmer who might be slightly offended if you suggest that he or she should consider encapsulation. If so, suggest instead that he or she considers the properties of functions and data.
</p>
</div>
<div id="comments">
<hr>
<h2 id="comments-header">
Comments
</h2>
<div class="comment" id="bb616acbc1ac41cb8f937fe7175ce061">
<div class="comment-author"><a href="http://www.raboof.com/">Atif Aziz</a></div>
<div class="comment-content">
<p>
I wonder what's the goal of illustrating OOP-ish examples exclusively in C# and FP-ish ones in F# when you could stick to just one language for the reader. It might not always be as effective depending on the topic, but for encapsulation and the examples shown in this article, a C# version would read just as effective as an F# one. I mean when you get round to making your points in the <strong>Immutable Table</strong> section of your article, you could demonstrate the ideas with a C# version that's nearly identical to and reads as succinct as the F# version:
</p>
<pre><span style="color:gray;">#nullable</span> <span style="color:gray;">enable</span>
<span style="color:blue;">readonly</span> <span style="color:blue;">record</span> <span style="color:blue;">struct</span> <span style="color:darkblue;">Reservation</span>(<span style="color:blue;">int</span> <span style="color:#1f377f;">Quantity</span>);
<span style="color:blue;">abstract</span> <span style="color:blue;">record</span> <span style="color:darkblue;">Table</span>;
<span style="color:blue;">record</span> <span style="color:darkblue;">StandardTable</span>(<span style="color:blue;">int</span> <span style="color:#1f377f;">Capacity</span>, <span style="color:darkblue;">Reservation</span>? <span style="color:#1f377f;">Reservation</span>): <span style="color:darkblue;">Table</span>;
<span style="color:blue;">record</span> <span style="color:darkblue;">CommunalTable</span>(<span style="color:blue;">int</span> <span style="color:#1f377f;">Capacity</span>, <span style="color:darkblue;">ImmutableArray</span><<span style="color:darkblue;">Reservation</span>> <span style="color:#1f377f;">Reservations</span>): <span style="color:darkblue;">Table</span>;
<span style="color:blue;">static</span> <span style="color:blue;">class</span> <span style="color:darkblue;">TableModule</span>
{
<span style="color:blue;">public</span> <span style="color:blue;">static</span> <span style="color:darkblue;">StandardTable</span>? <span style="color:darkcyan;">Standard</span>(<span style="color:blue;">int</span> <span style="color:#1f377f;">capacity</span>) =>
0 < capacity ? <span style="color:blue;">new</span> <span style="color:darkblue;">StandardTable</span>(capacity, <span style="color:blue;">null</span>) : <span style="color:blue;">null</span>;
<span style="color:blue;">public</span> <span style="color:blue;">static</span> <span style="color:darkblue;">CommunalTable</span>? <span style="color:darkcyan;">Communal</span>(<span style="color:blue;">int</span> <span style="color:#1f377f;">capacity</span>) =>
0 < capacity ? <span style="color:blue;">new</span> <span style="color:darkblue;">CommunalTable</span>(capacity, <span style="color:darkblue;">ImmutableArray</span><<span style="color:darkblue;">Reservation</span>>.Empty) : <span style="color:blue;">null</span>;
<span style="color:blue;">public</span> <span style="color:blue;">static</span> <span style="color:blue;">int</span> <span style="color:darkcyan;">RemainingSeats</span>(<span style="color:blue;">this</span> <span style="color:darkblue;">Table</span> <span style="color:#1f377f;">table</span>) => table <span style="color:#8f08c4;">switch</span>
{
<span style="color:darkblue;">StandardTable</span> { <span style="color:purple;">Reservation</span>: <span style="color:blue;">null</span> } t => t.<span style="color:purple;">Capacity</span>,
<span style="color:darkblue;">StandardTable</span> => 0,
<span style="color:darkblue;">CommunalTable</span> <span style="color:#1f377f;">t</span> => t.<span style="color:purple;">Capacity</span> - t.<span style="color:purple;">Reservations</span>.Sum(<span style="color:#1f377f;">r</span> => r.Quantity)
};
<span style="color:blue;">public</span> <span style="color:blue;">static</span> <span style="color:darkblue;">Table</span>? <span style="color:darkcyan;">Reserve</span>(<span style="color:blue;">this</span> <span style="color:darkblue;">Table</span> <span style="color:#1f377f;">table</span>, <span style="color:darkblue;">Reservation</span> <span style="color:#1f377f;">r</span>) => table <span style="color:#8f08c4;">switch</span>
{
<span style="color:darkblue;">StandardTable</span> <span style="color:#1f377f;">t</span> <span style="color:#8f08c4;">when</span> r.<span style="color:purple;">Quantity</span> <= t.<span style="color:darkcyan;">RemainingSeats</span>() => t <span style="color:blue;">with</span> { <span style="color:purple;">Reservation</span> = r },
<span style="color:darkblue;">CommunalTable</span> <span style="color:#1f377f;">t</span> <span style="color:#8f08c4;">when</span> r.<span style="color:purple;">Quantity</span> <= t.<span style="color:darkcyan;">RemainingSeats</span>() => t <span style="color:blue;">with</span> { <span style="color:purple;">Reservations</span> = t.<span style="color:purple;">Reservations</span>.Add(r) },
<span style="color:blue;">_</span> => <span style="color:blue;">null</span>,
};
}
</pre>
<p>
This way, I can just point someone to your article for enlightenment, 😉 but not leave them feeling frustrated that they need F# to (practice and) model around data instead of state mutating objects. It might still be worthwhile to show an F# version to draw the similarities and also call out some differences; like <code>Table</code> being a true discriminated union in F#, and while it appears to be emulated in C#, they desugar to the same thing in terms of CLR types and hierarchies.
</p>
<p>
By the way, in the C# example above, I modeled the standard table variant differently because if it can hold only one reservation at a time then the model should reflect that.
</p>
</div>
<div class="comment-date">2022-10-27 16:09 UTC</div>
</div>
<div class="comment" id="7069ea2b33a64a1caf7247c3a1543bac">
<div class="comment-author"><a href="/">Mark Seemann</a></div>
<div class="comment-content">
<p>
Atif, thank you for supplying and example of an immutable C# implementation.
</p>
<p>
I already have an example of an immutable, functional C# implementation in <a href="/2021/06/14/new-book-code-that-fits-in-your-head">Code That Fits in Your Head</a>, so I wanted to supply something else here. I also tend to find it interesting to compare how to model similar ideas in different languages, and it felt natural to supply an F# example to show how a 'natural' FP implementation might look.
</p>
<p>
Your point is valid, though, so I'm not insisting that this was the right decision.
</p>
</div>
<div class="comment-date">2022-10-28 8:50 UTC</div>
</div>
<div class="comment" id="a7b4d4d0dcc8432fb3b49cb7189d8123">
<div class="comment-author"><a href="https://github.com/sebastianfrelle">Sebastian Frelle Koch</a></div>
<div class="comment-content">
<p>I took your idea, Atif, and wrote something that I think is more congruent with the example <a href="#78027bc1d1414c2fa3604a68c9df6418">here</a>. In short, I’m</p>
<ul>
<li>using polymorphism to avoid having to switch over the Table type</li>
<li>hiding subtypes of Table to simplify the interface.</li>
</ul>
<p>Here's the code:</p>
<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">#</span><span class="n">nullable</span> <span class="n">enable</span>
<span class="k">using</span> <span class="nn">System.Collections.Immutable</span><span class="p">;</span>
<span class="k">readonly</span> <span class="n">record</span> <span class="k">struct</span> <span class="nc">Reservation</span><span class="p">(</span><span class="kt">int</span> <span class="n">Quantity</span><span class="p">);</span>
<span class="k">abstract</span> <span class="n">record</span> <span class="n">Table</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">abstract</span> <span class="n">Table</span><span class="p">?</span> <span class="nf">Reserve</span><span class="p">(</span><span class="n">Reservation</span> <span class="n">r</span><span class="p">);</span>
<span class="k">public</span> <span class="k">abstract</span> <span class="kt">int</span> <span class="nf">RemainingSeats</span><span class="p">();</span>
<span class="k">public</span> <span class="k">static</span> <span class="n">Table</span><span class="p">?</span> <span class="nf">Standard</span><span class="p">(</span><span class="kt">int</span> <span class="n">capacity</span><span class="p">)</span> <span class="p">=></span>
<span class="n">capacity</span> <span class="p">></span> <span class="m">0</span> <span class="p">?</span> <span class="k">new</span> <span class="nf">StandardTable</span><span class="p">(</span><span class="n">capacity</span><span class="p">,</span> <span class="k">null</span><span class="p">)</span> <span class="p">:</span> <span class="k">null</span><span class="p">;</span>
<span class="k">public</span> <span class="k">static</span> <span class="n">Table</span><span class="p">?</span> <span class="nf">Communal</span><span class="p">(</span><span class="kt">int</span> <span class="n">capacity</span><span class="p">)</span> <span class="p">=></span>
<span class="n">capacity</span> <span class="p">></span> <span class="m">0</span> <span class="p">?</span> <span class="k">new</span> <span class="nf">CommunalTable</span><span class="p">(</span>
<span class="n">capacity</span><span class="p">,</span>
<span class="n">ImmutableArray</span><span class="p"><</span><span class="n">Reservation</span><span class="p">>.</span><span class="n">Empty</span><span class="p">)</span> <span class="p">:</span> <span class="k">null</span><span class="p">;</span>
<span class="k">private</span> <span class="n">record</span> <span class="nf">StandardTable</span><span class="p">(</span><span class="kt">int</span> <span class="n">Capacity</span><span class="p">,</span> <span class="n">Reservation</span><span class="p">?</span> <span class="n">Reservation</span><span class="p">)</span> <span class="p">:</span> <span class="n">Table</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">override</span> <span class="n">Table</span><span class="p">?</span> <span class="nf">Reserve</span><span class="p">(</span><span class="n">Reservation</span> <span class="n">r</span><span class="p">)</span> <span class="p">=></span> <span class="nf">RemainingSeats</span><span class="p">()</span> <span class="k">switch</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">seats</span> <span class="n">when</span> <span class="n">seats</span> <span class="p">>=</span> <span class="n">r</span><span class="p">.</span><span class="n">Quantity</span> <span class="p">=></span> <span class="k">this</span> <span class="n">with</span> <span class="p">{</span> <span class="n">Reservation</span> <span class="p">=</span> <span class="n">r</span> <span class="p">},</span>
<span class="n">_</span> <span class="p">=></span> <span class="k">null</span><span class="p">,</span>
<span class="p">};</span>
<span class="k">public</span> <span class="k">override</span> <span class="kt">int</span> <span class="nf">RemainingSeats</span><span class="p">()</span> <span class="p">=></span> <span class="n">Reservation</span> <span class="k">switch</span>
<span class="p">{</span>
<span class="k">null</span> <span class="p">=></span> <span class="n">Capacity</span><span class="p">,</span>
<span class="n">_</span> <span class="p">=></span> <span class="m">0</span><span class="p">,</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="k">private</span> <span class="n">record</span> <span class="nf">CommunalTable</span><span class="p">(</span>
<span class="kt">int</span> <span class="n">Capacity</span><span class="p">,</span>
<span class="n">ImmutableArray</span><span class="p"><</span><span class="n">Reservation</span><span class="p">></span> <span class="n">Reservations</span><span class="p">)</span> <span class="p">:</span> <span class="n">Table</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">override</span> <span class="n">Table</span><span class="p">?</span> <span class="nf">Reserve</span><span class="p">(</span><span class="n">Reservation</span> <span class="n">r</span><span class="p">)</span> <span class="p">=></span> <span class="nf">RemainingSeats</span><span class="p">()</span> <span class="k">switch</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">seats</span> <span class="n">when</span> <span class="n">seats</span> <span class="p">>=</span> <span class="n">r</span><span class="p">.</span><span class="n">Quantity</span> <span class="p">=></span>
<span class="k">this</span> <span class="n">with</span> <span class="p">{</span> <span class="n">Reservations</span> <span class="p">=</span> <span class="n">Reservations</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">r</span><span class="p">)</span> <span class="p">},</span>
<span class="n">_</span> <span class="p">=></span> <span class="k">null</span><span class="p">,</span>
<span class="p">};</span>
<span class="k">public</span> <span class="k">override</span> <span class="kt">int</span> <span class="nf">RemainingSeats</span><span class="p">()</span> <span class="p">=></span>
<span class="n">Capacity</span> <span class="p">-</span> <span class="n">Reservations</span><span class="p">.</span><span class="nf">Sum</span><span class="p">(</span><span class="n">r</span> <span class="p">=></span> <span class="n">r</span><span class="p">.</span><span class="n">Quantity</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>I’d love to hear your thoughts on this approach. I think that one of its weaknesses is that calls to <code class="language-plaintext highlighter-rouge">Table.Standard()</code> and <code class="language-plaintext highlighter-rouge">Table.Communal()</code> will yield two instances of <code class="language-plaintext highlighter-rouge">Table</code> that can never be equal. For instance, <code class="language-plaintext highlighter-rouge">Table.Standard(4) != Table.Communal(4)</code>, even though they’re both of type <code class="language-plaintext highlighter-rouge">Table?</code> and have the same number of seats.
</p>
<p>
Calling <code class="language-plaintext highlighter-rouge">GetType()</code> on each of the instances reveals that their types are actually <code class="language-plaintext highlighter-rouge">Table+StandardTable</code> and <code class="language-plaintext highlighter-rouge">Table+CommunalTable</code> respectively; however, this isn't transparent to callers. Another solution might be to expose the <code class="language-plaintext highlighter-rouge">Table</code> subtypes and give them private constructors – I just like the simplicity of not exposing the individual types of tables the same way you’re doing <a href="#b37e173371f249d99f80d12d64b2bee2">here</a>, Mark.</p>
</div>
<div class="comment-date">2022-11-29 11:28 UTC</div>
</div>
<div class="comment" id="f925c18ec3a746c393cfae319200baac">
<div class="comment-author"><a href="https://github.com/alexmurari">Alexandre Murari Jr</a></div>
<div class="comment-content">
<p>
Mark,
<p>
How do you differentiate encapsulation from abstraction?
</p>
<p>
Here's an excerpt from your book Dependency Injection: Principles, Practices, and Patterns.
</p>
<p>
Section: 1.3 - What to inject and what not to inject
Subsection: 1.3.1 - Stable Dependencies
</p>
<blockquote>
"Other examples [of libraries that do not require to be injected] may include specialized libraries that encapsulate alogorithms relevant to your application".
</blockquote>
<p>
In that section, you and Steven were giving examples of stable dependencies that do not require to be injected to keep modularity.
You define a library that "encapsulates an algorithm" as an example.
</p>
<p>
Now, to me, encapsulation is "protecting data integrity", plain and simple.
A class is encapsulated as long as it's impossible or nearly impossible to bring it to an invalid or inconsistent state.
</p>
<p>
Protection of invariants, implementation hiding, bundling data and operations together, pre- and postconditions, Postel's Law all come into play to achieve this goal.
</p>
<p>
Thus, a class, to be "encapsulatable", has to have a state that can be initialized and/or modified by the client code.
</p>
<p>
Now I ask: most of the time when we say that something is encapsulating another, don't we really mean abstracting?
</p>
<p>
Why is it relevant to know that the hypothetical algorithm library protects it's invariants by using the term "encapsulate"?
</p>
<p>
Abstraction, under the light of Robert C. Martin's definition of it, makes much more sense in that context: "a specialized library that abstracts algorithms relevant to your application".
It amplifies the essential (by providing a clear API), but eliminates the irrelevant (by hiding the alogirthm's implementation details).
</p>
<p>
Granted, there is some overlap between encapsulation and abstraction, specially when you bundle data and operations together (rich domain models), but they are not the same thing, you just use one to achieve another sometimes.
</p>
<p>
Would it be correct to say that the .NET Framework encapsulates math algorithms in the System.Math class? Is there any state there to be preserved? They're all static methods and constants.
On the other hand, they're surely eliminating some pretty irrelevant (from a consumer POV) trigonometric algorithms.
</p>
<p>
Thanks.
</p>
</div>
<div class="comment-date">2022-12-04 02:35 UTC</div>
</div>
<div class="comment" id="5af1535933bf4b28bb5c2fc14ce0a01a">
<div class="comment-author"><a href="/">Mark Seemann</a></div>
<div class="comment-content">
<p>
Alexandre, thank you for writing. How do I distinguish between abstraction and encapsulation?
</p>
<p>
There's much overlap, to be sure.
</p>
<p>
As I write, my view on encapsulation is influenced by Bertrand Meyer's notion of contract. Likewise, I do use Robert C. Martin's notion of amplifying the essentials while hiding the irrelevant details as a guiding light when discussing abstraction.
</p>
<p>
While these concepts may seem synonymous, they're not quite the same. I can't say that I've spent too much time considering how these two words relate, but shooting from the hip I think that <em>abstraction</em> is a wider concept.
</p>
<p>
You don't need to read much of Robert C. Martin before he'll tell you that the <a href="https://en.wikipedia.org/wiki/Dependency_inversion_principle">Dependency Inversion Principle</a> is an important part of abstraction:
</p>
<blockquote>
<p>
"Abstractions should not depend on details. Details should depend on abstractions."
</p>
<footer><cite>Robert C. Martin, <a href="/ref/appp">Agile Principles, Patterns, and Practices in C#</a></cite></footer>
</blockquote>
<p>
It's possible to implement a code base where this isn't true, even if classes have good encapsulation. You could imagine a domain model that depends on database details like a particular ORM. I've seen plenty of those in my career, although I grant that most of them have had poor encapsulation as well. It is not, however, impossible to imagine such a system with good encapsulation, but suboptimal abstraction.
</p>
<p>
Does it go the other way as well? Can we have good abstraction, but poor encapsulation?
</p>
<p>
An example doesn't come immediately to mind, but as I wrote, it's not an ontology that I've given much thought.
</p>
</div>
<div class="comment-date">2022-12-06 22:11 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>.Stubs and mocks break encapsulationhttps://blog.ploeh.dk/2022/10/17/stubs-and-mocks-break-encapsulation2022-10-17T08:47:00+00:00Mark Seemann
<div id="post">
<p>
<em>Favour Fakes over dynamic mocks.</em>
</p>
<p>
For a while now, I've <a href="/2019/02/18/from-interaction-based-to-state-based-testing">favoured Fakes over Stubs and Mocks</a>. Using <a href="http://xunitpatterns.com/Fake%20Object.html">Fake Objects</a> over other <a href="https://martinfowler.com/bliki/TestDouble.html">Test Doubles</a> makes test suites more robust. I wrote the code base for my book <a href="/2021/06/14/new-book-code-that-fits-in-your-head">Code That Fits in Your Head</a> entirely with Fakes and the occasional <a href="http://xunitpatterns.com/Test%20Spy.html">Test Spy</a>, and I rarely had to fix broken tests. No <a href="https://moq.github.io/moq4/">Moq</a>, <a href="https://fakeiteasy.github.io/">FakeItEasy</a>, <a href="https://nsubstitute.github.io/">NSubstitute</a>, nor <a href="https://hibernatingrhinos.com/oss/rhino-mocks">Rhino Mocks</a>. Just hand-written Test Doubles.
</p>
<p>
It recently occurred to me that a way to explain the problem with <a href="http://xunitpatterns.com/Mock%20Object.html">Mocks</a> and <a href="http://xunitpatterns.com/Test%20Stub.html">Stubs</a> is that they break encapsulation.
</p>
<p>
You'll see some examples soon, but first it's important to be explicit about terminology.
</p>
<h3 id="bde25ebecc664e99b529755c3f0829fb">
Terminology <a href="#bde25ebecc664e99b529755c3f0829fb" title="permalink">#</a>
</h3>
<p>
Words like <em>Mocks</em>, <em>Stubs</em>, as well as <em>encapsulation</em>, have different meanings to different people. They've fallen victim to <a href="https://martinfowler.com/bliki/SemanticDiffusion.html">semantic diffusion</a>, if ever they were well-defined to begin with.
</p>
<p>
When I use the words <em>Test Double</em>, <em>Fake</em>, <em>Mock</em>, and <em>Stub</em>, I use them as they are defined in <a href="/ref/xunit-patterns">xUnit Test Patterns</a>. I usually try to avoid the terms <em>Mock</em> and <em>Stub</em> since people use them vaguely and inconsistently. The terms <em>Test Double</em> and <em>Fake</em> fare better.
</p>
<p>
We do need, however, a name for those libraries that generate Test Doubles on the fly. In .NET, they are libraries like Moq, FakeItEasy, and so on, as listed above. Java has <a href="https://site.mockito.org/">Mockito</a>, <a href="https://easymock.org/">EasyMock</a>, <a href="https://jmockit.github.io/">JMockit</a>, and possibly more like that.
</p>
<p>
What do we call such libraries? Most people call them <em>mock libraries</em> or <em>dynamic mock libraries</em>. Perhaps <em>dynamic Test Double library</em> would be more consistent with the <em>xUnit Test Patterns</em> vocabulary, but nobody calls them that. I'll call them <em>dynamic mock libraries</em> to at least emphasise the dynamic, on-the-fly object generation these libraries typically use.
</p>
<p>
Finally, it's important to define <em>encapsulation</em>. This is another concept where people may use the same word and yet mean different things.
</p>
<p>
I base my understanding of encapsulation on <a href="/ref/oosc">Object-Oriented Software Construction</a>. I've tried to distil it in my Pluralsight course <a href="/encapsulation-and-solid">Encapsulation and SOLID</a>.
</p>
<p>
In short, encapsulation denotes the distinction between an object's contract and its implementation. An object should fulfil its contract in such a way that client code doesn't need to know about its implementation.
</p>
<p>
Contracts, according to Meyer, describe three properties of objects:
</p>
<ul>
<li>Preconditions: What client code must fulfil in order to successfully interact with the object.</li>
<li>Invariants: Statements about the object that are always true.</li>
<li>Postconditions: Statements that are guaranteed to be true after a successful interaction between client code and object.</li>
</ul>
<p>
As I'll demonstrate in this article, objects generated by dynamic mock libraries often break their contracts.
</p>
<h3 id="2d05b5926474448589c3953f6796c2a9">
Create-and-read round-trip <a href="#2d05b5926474448589c3953f6796c2a9" title="permalink">#</a>
</h3>
<p>
Consider the <code>IReservationsRepository</code> interface from <a href="/code-that-fits-in-your-head">Code That Fits in Your Head</a>:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">interface</span> <span style="color:#2b91af;">IReservationsRepository</span>
{
Task Create(<span style="color:blue;">int</span> restaurantId, Reservation reservation);
Task<IReadOnlyCollection<Reservation>> ReadReservations(
<span style="color:blue;">int</span> restaurantId, DateTime min, DateTime max);
Task<Reservation?> ReadReservation(<span style="color:blue;">int</span> restaurantId, Guid id);
Task Update(<span style="color:blue;">int</span> restaurantId, Reservation reservation);
Task Delete(<span style="color:blue;">int</span> restaurantId, Guid id);
}</pre>
</p>
<p>
I already discussed some of the contract properties of this interface in <a href="/2021/12/06/the-liskov-substitution-principle-as-a-profunctor">an earlier article</a>. Here, I want to highlight a certain interaction.
</p>
<p>
What is the contract of the <code>Create</code> method?
</p>
<p>
There are a few preconditions:
</p>
<ul>
<li>The client must have a properly initialised <code>IReservationsRepository</code> object.</li>
<li>The client must have a valid <code>restaurantId</code>.</li>
<li>The client must have a valid <code>reservation</code>.</li>
</ul>
<p>
A client that fulfils these preconditions can successfully call and await the <code>Create</code> method. What are the invariants and postconditions?
</p>
<p>
I'll skip the invariants because they aren't relevant to the line of reasoning that I'm pursuing. One postcondition, however, is that the <code>reservation</code> passed to <code>Create</code> must now be 'in' the repository.
</p>
<p>
How does that manifest as part of the object's contract?
</p>
<p>
This implies that a client should be able to retrieve the <code>reservation</code>, either with <code>ReadReservation</code> or <code>ReadReservations</code>. This suggests a kind of property that Scott Wlaschin calls <a href="https://fsharpforfunandprofit.com/posts/property-based-testing-2/">There and back again</a>.
</p>
<p>
Picking <code>ReadReservation</code> for the verification step we now have a property: If client code successfully calls and awaits <code>Create</code> it should be able to use <code>ReadReservation</code> to retrieve the reservation it just saved. That's implied by the <code>IReservationsRepository</code> contract.
</p>
<h3 id="f787d89599a04573a2c9b7afc28b2315">
SQL implementation <a href="#f787d89599a04573a2c9b7afc28b2315" title="permalink">#</a>
</h3>
<p>
The 'real' implementation of <code>IReservationsRepository</code> used in production is an implementation that stores reservations in SQL Server. This class should obey the contract.
</p>
<p>
While it might be possible to write a true property-based test, running hundreds of randomly generated test cases against a real database is going to take time. Instead, I chose to only write a parametrised test:
</p>
<p>
<pre>[Theory]
[InlineData(Grandfather.Id, <span style="color:#a31515;">"2022-06-29 12:00"</span>, <span style="color:#a31515;">"e@example.gov"</span>, <span style="color:#a31515;">"Enigma"</span>, 1)]
[InlineData(Grandfather.Id, <span style="color:#a31515;">"2022-07-27 11:40"</span>, <span style="color:#a31515;">"c@example.com"</span>, <span style="color:#a31515;">"Carlie"</span>, 2)]
[InlineData(2, <span style="color:#a31515;">"2021-09-03 14:32"</span>, <span style="color:#a31515;">"bon@example.edu"</span>, <span style="color:#a31515;">"Jovi"</span>, 4)]
<span style="color:blue;">public</span> <span style="color:blue;">async</span> Task CreateAndReadRoundTrip(
<span style="color:blue;">int</span> restaurantId,
<span style="color:blue;">string</span> at,
<span style="color:blue;">string</span> email,
<span style="color:blue;">string</span> name,
<span style="color:blue;">int</span> quantity)
{
<span style="color:blue;">var</span> expected = <span style="color:blue;">new</span> Reservation(
Guid.NewGuid(),
DateTime.Parse(at, CultureInfo.InvariantCulture),
<span style="color:blue;">new</span> Email(email),
<span style="color:blue;">new</span> Name(name),
quantity);
<span style="color:blue;">var</span> connectionString = ConnectionStrings.Reservations;
<span style="color:blue;">var</span> sut = <span style="color:blue;">new</span> SqlReservationsRepository(connectionString);
<span style="color:blue;">await</span> sut.Create(restaurantId, expected);
<span style="color:blue;">var</span> actual = <span style="color:blue;">await</span> sut.ReadReservation(restaurantId, expected.Id);
Assert.Equal(expected, actual);
}</pre>
</p>
<p>
The part that we care about is the three last lines:
</p>
<p>
<pre><span style="color:blue;">await</span> sut.Create(restaurantId, expected);
<span style="color:blue;">var</span> actual = <span style="color:blue;">await</span> sut.ReadReservation(restaurantId, expected.Id);
Assert.Equal(expected, actual);</pre>
</p>
<p>
First call <code>Create</code> and subsequently <code>ReadReservation</code>. The value created should equal the value retrieved, which is also the case. All tests pass.
</p>
<h3 id="dc7d9e2730364cf8895d73d2adcd37b0">
Fake <a href="#dc7d9e2730364cf8895d73d2adcd37b0" title="permalink">#</a>
</h3>
<p>
The Fake implementation is effectively an in-memory database, so we expect it to also fulfil the same contract. We can test it with an almost identical test:
</p>
<p>
<pre>[Theory]
[InlineData(RestApi.Grandfather.Id, <span style="color:#a31515;">"2022-06-29 12:00"</span>, <span style="color:#a31515;">"e@example.gov"</span>, <span style="color:#a31515;">"Enigma"</span>, 1)]
[InlineData(RestApi.Grandfather.Id, <span style="color:#a31515;">"2022-07-27 11:40"</span>, <span style="color:#a31515;">"c@example.com"</span>, <span style="color:#a31515;">"Carlie"</span>, 2)]
[InlineData(2, <span style="color:#a31515;">"2021-09-03 14:32"</span>, <span style="color:#a31515;">"bon@example.edu"</span>, <span style="color:#a31515;">"Jovi"</span>, 4)]
<span style="color:blue;">public</span> <span style="color:blue;">async</span> Task CreateAndReadRoundTrip(
<span style="color:blue;">int</span> restaurantId,
<span style="color:blue;">string</span> at,
<span style="color:blue;">string</span> email,
<span style="color:blue;">string</span> name,
<span style="color:blue;">int</span> quantity)
{
<span style="color:blue;">var</span> expected = <span style="color:blue;">new</span> Reservation(
Guid.NewGuid(),
DateTime.Parse(at, CultureInfo.InvariantCulture),
<span style="color:blue;">new</span> Email(email),
<span style="color:blue;">new</span> Name(name),
quantity);
<span style="color:blue;">var</span> sut = <span style="color:blue;">new</span> FakeDatabase();
<span style="color:blue;">await</span> sut.Create(restaurantId, expected);
<span style="color:blue;">var</span> actual = <span style="color:blue;">await</span> sut.ReadReservation(restaurantId, expected.Id);
Assert.Equal(expected, actual);
}</pre>
</p>
<p>
The only difference is that the <code>sut</code> is a different class instance. These test cases also all pass.
</p>
<p>
How is <code>FakeDatabase</code> implemented? That's not important, because it obeys the contract. <code>FakeDatabase</code> has good encapsulation, which makes it possible to use it without knowing anything about its internal implementation details. That, after all, is the point of encapsulation.
</p>
<h3 id="a13bc3a894914ce59b1c11ea9702b3f8">
Dynamic mock <a href="#a13bc3a894914ce59b1c11ea9702b3f8" title="permalink">#</a>
</h3>
<p>
How does a dynamic mock fare if subjected to the same test? Let's try with Moq 4.18.2 (and I'm not choosing Moq to single it out - I chose Moq because it's the dynamic mock library I used to love the most):
</p>
<p>
<pre>[Theory]
[InlineData(RestApi.Grandfather.Id, <span style="color:#a31515;">"2022-06-29 12:00"</span>, <span style="color:#a31515;">"e@example.gov"</span>, <span style="color:#a31515;">"Enigma"</span>, 1)]
[InlineData(RestApi.Grandfather.Id, <span style="color:#a31515;">"2022-07-27 11:40"</span>, <span style="color:#a31515;">"c@example.com"</span>, <span style="color:#a31515;">"Carlie"</span>, 2)]
[InlineData(2, <span style="color:#a31515;">"2021-09-03 14:32"</span>, <span style="color:#a31515;">"bon@example.edu"</span>, <span style="color:#a31515;">"Jovi"</span>, 4)]
<span style="color:blue;">public</span> <span style="color:blue;">async</span> Task CreateAndReadRoundTrip(
<span style="color:blue;">int</span> restaurantId,
<span style="color:blue;">string</span> at,
<span style="color:blue;">string</span> email,
<span style="color:blue;">string</span> name,
<span style="color:blue;">int</span> quantity)
{
<span style="color:blue;">var</span> expected = <span style="color:blue;">new</span> Reservation(
Guid.NewGuid(),
DateTime.Parse(at, CultureInfo.InvariantCulture),
<span style="color:blue;">new</span> Email(email),
<span style="color:blue;">new</span> Name(name),
quantity);
<span style="color:blue;">var</span> sut = <span style="color:blue;">new</span> Mock<IReservationsRepository>().Object;
<span style="color:blue;">await</span> sut.Create(restaurantId, expected);
<span style="color:blue;">var</span> actual = <span style="color:blue;">await</span> sut.ReadReservation(restaurantId, expected.Id);
Assert.Equal(expected, actual);
}</pre>
</p>
<p>
If you've worked a little with dynamic mock libraries, you will not be surprised to learn that all three tests fail. Here's one of the failure messages:
</p>
<p>
<pre>Ploeh.Samples.Restaurants.RestApi.Tests.MoqRepositoryTests.CreateAndReadRoundTrip(↩
restaurantId: 1, at: "2022-06-29 12:00", email: "e@example.gov", name: "Enigma", quantity: 1)
Source: <span style="color:blue;">MoqRepositoryTests.cs</span> line 17
Duration: 1 ms
Message:
Assert.Equal() Failure
Expected: Reservation↩
{↩
At = 2022-06-29T12:00:00.0000000,↩
Email = e@example.gov,↩
Id = c9de4f95-3255-4e1f-a1d6-63591b58ff0c,↩
Name = Enigma,↩
Quantity = 1↩
}
Actual: (null)
Stack Trace:
<span style="color:red;">MoqRepositoryTests.CreateAndReadRoundTrip(↩
Int32 restaurantId, String at, String email, String name, Int32 quantity)</span> line 35
--- End of stack trace from previous location where exception was thrown ---</pre>
</p>
<p>
(I've introduced line breaks and indicated them with the ↩ symbol to make the output more readable. I'll do that again later in the article.)
</p>
<p>
Not surprisingly, the return value of <code>Create</code> is null. You typically have to configure a dynamic mock in order to give it any sort of behaviour, and I didn't do that here. In that case, the dynamic mock returns the default value for the return type, which in this case correctly is null.
</p>
<p>
You may object that the above example is unfair. How can a dynamic mock know what to do? You have to configure it. That's the whole point of it.
</p>
<h3 id="307eb992e4c54aae8a2f331c05d9d7e4">
Retrieval without creation <a href="#307eb992e4c54aae8a2f331c05d9d7e4" title="permalink">#</a>
</h3>
<p>
Okay, let's set up the dynamic mock:
</p>
<p>
<pre><span style="color:blue;">var</span> dm = <span style="color:blue;">new</span> Mock<IReservationsRepository>();
dm.Setup(r => r.ReadReservation(restaurantId, expected.Id)).ReturnsAsync(expected);
<span style="color:blue;">var</span> sut = dm.Object;</pre>
</p>
<p>
These are the only lines I've changed from the previous listing of the test, which now passes.
</p>
<p>
A common criticism of dynamic-mock-heavy tests is that they mostly 'just test the mocks', and this is exactly what happens here.
</p>
<p>
You can make that more explicit by deleting the <code>Create</code> method call:
</p>
<p>
<pre><span style="color:blue;">var</span> dm = <span style="color:blue;">new</span> Mock<IReservationsRepository>();
dm.Setup(r => r.ReadReservation(restaurantId, expected.Id)).ReturnsAsync(expected);
<span style="color:blue;">var</span> sut = dm.Object;
<span style="color:blue;">var</span> actual = <span style="color:blue;">await</span> sut.ReadReservation(restaurantId, expected.Id);
Assert.Equal(expected, actual);</pre>
</p>
<p>
The test still passes. Clearly it only tests the dynamic mock.
</p>
<p>
You may, again, demur that this is expected, and it doesn't demonstrate that dynamic mocks break encapsulation. Keep in mind, however, the nature of the contract: Upon successful completion of <code>Create</code>, the reservation is 'in' the repository and can later be retrieved, either with <code>ReadReservation</code> or <code>ReadReservations</code>.
</p>
<p>
This variation of the test no longer calls <code>Create</code>, yet <code>ReadReservation</code> still returns the <code>expected</code> value.
</p>
<p>
Do <code>SqlReservationsRepository</code> or <code>FakeDatabase</code> behave like that? No, they don't.
</p>
<p>
Try to delete the <code>Create</code> call from the test that exercises <code>SqlReservationsRepository</code>:
</p>
<p>
<pre><span style="color:blue;">var</span> sut = <span style="color:blue;">new</span> SqlReservationsRepository(connectionString);
<span style="color:blue;">var</span> actual = <span style="color:blue;">await</span> sut.ReadReservation(restaurantId, expected.Id);
Assert.Equal(expected, actual);</pre>
</p>
<p>
Hardly surprising, the test now fails because <code>actual</code> is null. The same happens if you delete the <code>Create</code> call from the test that exercises <code>FakeDatabase</code>:
</p>
<p>
<pre><span style="color:blue;">var</span> sut = <span style="color:blue;">new</span> FakeDatabase();
<span style="color:blue;">var</span> actual = <span style="color:blue;">await</span> sut.ReadReservation(restaurantId, expected.Id);
Assert.Equal(expected, actual);</pre>
</p>
<p>
Again, the assertion fails because <code>actual</code> is null.
</p>
<p>
The classes <code>SqlReservationsRepository</code> and <code>FakeDatabase</code> behave according to contract, while the dynamic mock doesn't.
</p>
<h3 id="81c7041024ad4c5d99055494c5b0bdf0">
Alternative retrieval <a href="#81c7041024ad4c5d99055494c5b0bdf0" title="permalink">#</a>
</h3>
<p>
There's another way in which the dynamic mock breaks encapsulation. Recall what the contract states: Upon successful completion of <code>Create</code>, the reservation is 'in' the repository and can later be retrieved, either with <code>ReadReservation</code> or <code>ReadReservations</code>.
</p>
<p>
In other words, it should be possible to change the interaction from <code>Create</code> followed by <code>ReadReservation</code> to <code>Create</code> followed by <code>ReadReservations</code>.
</p>
<p>
First, try it with <code>SqlReservationsRepository</code>:
</p>
<p>
<pre><span style="color:blue;">await</span> sut.Create(restaurantId, expected);
<span style="color:blue;">var</span> min = expected.At.Date;
<span style="color:blue;">var</span> max = min.AddDays(1);
<span style="color:blue;">var</span> actual = <span style="color:blue;">await</span> sut.ReadReservations(restaurantId, min, max);
Assert.Contains(expected, actual);</pre>
</p>
<p>
The test still passes, as expected.
</p>
<p>
Second, try the same change with <code>FakeDatabase</code>:
</p>
<p>
<pre><span style="color:blue;">await</span> sut.Create(restaurantId, expected);
<span style="color:blue;">var</span> min = expected.At.Date;
<span style="color:blue;">var</span> max = min.AddDays(1);
<span style="color:blue;">var</span> actual = <span style="color:blue;">await</span> sut.ReadReservations(restaurantId, min, max);
Assert.Contains(expected, actual);</pre>
</p>
<p>
Notice that this is the exact same code as in the <code>SqlReservationsRepository</code> test. That test also passes, as expected.
</p>
<p>
Third, try it with the dynamic mock:
</p>
<p>
<pre><span style="color:blue;">await</span> sut.Create(restaurantId, expected);
<span style="color:blue;">var</span> min = expected.At.Date;
<span style="color:blue;">var</span> max = min.AddDays(1);
<span style="color:blue;">var</span> actual = <span style="color:blue;">await</span> sut.ReadReservations(restaurantId, min, max);
Assert.Contains(expected, actual);</pre>
</p>
<p>
Same code, different <code>sut</code>, and the test fails. The dynamic mock breaks encapsulation. You'll have to go and fix the <code>Setup</code> of it to make the test pass again. That's not the case with <code>SqlReservationsRepository</code> or <code>FakeDatabase</code>.
</p>
<h3 id="09410dcfb758412d991a47f08be885b5">
Dynamic mocks break the SUT, not the tests <a href="#09410dcfb758412d991a47f08be885b5" title="permalink">#</a>
</h3>
<p>
Perhaps you're still not convinced that this is of practical interest. After all, <a href="https://en.wikipedia.org/wiki/Bertrand_Meyer">Bertrand Meyer</a> had limited success getting mainstream adoption of his thought on contract-based programming.
</p>
<p>
That dynamic mocks break encapsulation does, however, have real implications.
</p>
<p>
What if, instead of using <code>FakeDatabase</code>, I'd used dynamic mocks when testing my online restaurant reservation system? A test might have looked like this:
</p>
<p>
<pre>[Theory]
[InlineData(1049, 19, 00, <span style="color:#a31515;">"juliad@example.net"</span>, <span style="color:#a31515;">"Julia Domna"</span>, 5)]
[InlineData(1130, 18, 15, <span style="color:#a31515;">"x@example.com"</span>, <span style="color:#a31515;">"Xenia Ng"</span>, 9)]
[InlineData( 956, 16, 55, <span style="color:#a31515;">"kite@example.edu"</span>, <span style="color:blue;">null</span>, 2)]
[InlineData( 433, 17, 30, <span style="color:#a31515;">"shli@example.org"</span>, <span style="color:#a31515;">"Shanghai Li"</span>, 5)]
<span style="color:blue;">public</span> <span style="color:blue;">async</span> Task PostValidReservationWhenDatabaseIsEmpty(
<span style="color:blue;">int</span> days,
<span style="color:blue;">int</span> hours,
<span style="color:blue;">int</span> minutes,
<span style="color:blue;">string</span> email,
<span style="color:blue;">string</span> name,
<span style="color:blue;">int</span> quantity)
{
<span style="color:blue;">var</span> at = DateTime.Now.Date + <span style="color:blue;">new</span> TimeSpan(days, hours, minutes, 0);
<span style="color:blue;">var</span> dm = <span style="color:blue;">new</span> Mock<IReservationsRepository>();
dm.Setup(r => r.ReadReservations(Grandfather.Id, at.Date, at.Date.AddDays(1).AddTicks(-1)))
.ReturnsAsync(Array.Empty<Reservation>());
<span style="color:blue;">var</span> sut = <span style="color:blue;">new</span> ReservationsController(
<span style="color:blue;">new</span> SystemClock(),
<span style="color:blue;">new</span> InMemoryRestaurantDatabase(Grandfather.Restaurant),
dm.Object);
<span style="color:blue;">var</span> expected = <span style="color:blue;">new</span> Reservation(
<span style="color:blue;">new</span> Guid(<span style="color:#a31515;">"B50DF5B1-F484-4D99-88F9-1915087AF568"</span>),
at,
<span style="color:blue;">new</span> Email(email),
<span style="color:blue;">new</span> Name(name ?? <span style="color:#a31515;">""</span>),
quantity);
<span style="color:blue;">await</span> sut.Post(expected.ToDto());
dm.Verify(r => r.Create(Grandfather.Id, expected));
}</pre>
</p>
<p>
This is yet another riff on the <code>PostValidReservationWhenDatabaseIsEmpty</code> test - the gift that keeps giving. I've previously discussed this test in other articles:
</p>
<ul>
<li><a href="/2020/12/07/branching-tests">Branching tests</a></li>
<li><a href="/2021/01/11/waiting-to-happen">Waiting to happen</a></li>
<li><a href="/2021/01/18/parametrised-test-primitive-obsession-code-smell">Parametrised test primitive obsession code smell</a></li>
<li><a href="/2021/09/27/the-equivalence-contravariant-functor">The Equivalence contravariant functor</a></li>
</ul>
<p>
Here I've replaced the <code>FakeDatabase</code> Test Double with a dynamic mock. (I am, again, using Moq, but keep in mind that the fallout of using a dynamic mock is unrelated to specific libraries.)
</p>
<p>
To go 'full dynamic mock' I should also have replaced <code>SystemClock</code> and <code>InMemoryRestaurantDatabase</code> with dynamic mocks, but that's not necessary to illustrate the point I wish to make.
</p>
<p>
This, and other tests, describe the desired outcome of making a reservation against the REST API. It's an interaction that looks like this:
</p>
<p>
<pre>POST /restaurants/90125/reservations?sig=aco7VV%2Bh5sA3RBtrN8zI8Y9kLKGC60Gm3SioZGosXVE%3D HTTP/1.1
content-type: application/json
{
<span style="color:#2e75b6;">"at"</span>: <span style="color:#a31515;">"2022-12-12T20:00"</span>,
<span style="color:#2e75b6;">"name"</span>: <span style="color:#a31515;">"Pearl Yvonne Gates"</span>,
<span style="color:#2e75b6;">"email"</span>: <span style="color:#a31515;">"pearlygates@example.net"</span>,
<span style="color:#2e75b6;">"quantity"</span>: 4
}
HTTP/1.1 201 Created
Content-Length: 151
Content-Type: application/json; charset=utf-8
Location: [...]/restaurants/90125/reservations/82e550b1690742368ea62d76e103b232?sig=fPY1fSr[...]
{
<span style="color:#2e75b6;">"id"</span>: <span style="color:#a31515;">"82e550b1690742368ea62d76e103b232"</span>,
<span style="color:#2e75b6;">"at"</span>: <span style="color:#a31515;">"2022-12-12T20:00:00.0000000"</span>,
<span style="color:#2e75b6;">"email"</span>: <span style="color:#a31515;">"pearlygates@example.net"</span>,
<span style="color:#2e75b6;">"name"</span>: <span style="color:#a31515;">"Pearl Yvonne Gates"</span>,
<span style="color:#2e75b6;">"quantity"</span>: 4
}</pre>
</p>
<p>
What's of interest here is that the response includes the JSON representation of the resource that the interaction created. It's mostly a copy of the posted data, but enriched with a server-generated ID.
</p>
<p>
The code responsible for the database interaction looks like this:
</p>
<p>
<pre><span style="color:blue;">private</span> <span style="color:blue;">async</span> Task<ActionResult> TryCreate(Restaurant restaurant, Reservation reservation)
{
<span style="color:blue;">using</span> <span style="color:blue;">var</span> scope = <span style="color:blue;">new</span> TransactionScope(TransactionScopeAsyncFlowOption.Enabled);
<span style="color:blue;">var</span> reservations = <span style="color:blue;">await</span> Repository
.ReadReservations(restaurant.Id, reservation.At)
.ConfigureAwait(<span style="color:blue;">false</span>);
<span style="color:blue;">var</span> now = Clock.GetCurrentDateTime();
<span style="color:blue;">if</span> (!restaurant.MaitreD.WillAccept(now, reservations, reservation))
<span style="color:blue;">return</span> NoTables500InternalServerError();
<span style="color:blue;">await</span> Repository.Create(restaurant.Id, reservation).ConfigureAwait(<span style="color:blue;">false</span>);
scope.Complete();
<span style="color:blue;">return</span> Reservation201Created(restaurant.Id, reservation);
}</pre>
</p>
<p>
The last line of code creates a <code>201 Created</code> response with the <code>reservation</code> as content. Not shown in this snippet is the origin of the <code>reservation</code> parameter, but it's <a href="/2022/07/25/an-applicative-reservation-validation-example-in-c">the input JSON document parsed to a <code>Reservation</code> object</a>. Each <code>Reservation</code> object has <a href="/2022/09/12/coalescing-dtos">an ID that the server creates when it's not supplied by the client</a>.
</p>
<p>
The above <code>TryCreate</code> helper method contains all the database interaction code related to creating a new reservation. It first calls <code>ReadReservations</code> to retrieve the existing reservations. Subsequently, it calls <code>Create</code> if it decides to accept the reservation. The <code>ReadReservations</code> method is actually an <code>internal</code> extension method:
</p>
<p>
<pre><span style="color:blue;">internal</span> <span style="color:blue;">static</span> Task<IReadOnlyCollection<Reservation>> ReadReservations(
<span style="color:blue;">this</span> IReservationsRepository repository,
<span style="color:blue;">int</span> restaurantId,
DateTime date)
{
<span style="color:blue;">var</span> min = date.Date;
<span style="color:blue;">var</span> max = min.AddDays(1).AddTicks(-1);
<span style="color:blue;">return</span> repository.ReadReservations(restaurantId, min, max);
}</pre>
</p>
<p>
Notice how the dynamic-mock-based test has to replicate this <code>internal</code> implementation detail to the <a href="https://docs.microsoft.com/dotnet/api/system.datetime.ticks">tick</a>. If I ever decide to change this just one tick, the test is going to fail. That's already bad enough (and something that <code>FakeDatabase</code> gracefully handles), but not what I'm driving towards.
</p>
<p>
At the moment the <code>TryCreate</code> method echoes back the <code>reservation</code>. What if, however, you instead want to query the database and return the record that you got from the database? In this particular case, there's no reason to do that, but perhaps in other cases, something happens in the data layer that either enriches or normalises the data. So you make an innocuous change:
</p>
<p>
<pre><span style="color:blue;">private</span> <span style="color:blue;">async</span> Task<ActionResult> TryCreate(Restaurant restaurant, Reservation reservation)
{
<span style="color:blue;">using</span> <span style="color:blue;">var</span> scope = <span style="color:blue;">new</span> TransactionScope(TransactionScopeAsyncFlowOption.Enabled);
<span style="color:blue;">var</span> reservations = <span style="color:blue;">await</span> Repository
.ReadReservations(restaurant.Id, reservation.At)
.ConfigureAwait(<span style="color:blue;">false</span>);
<span style="color:blue;">var</span> now = Clock.GetCurrentDateTime();
<span style="color:blue;">if</span> (!restaurant.MaitreD.WillAccept(now, reservations, reservation))
<span style="color:blue;">return</span> NoTables500InternalServerError();
<span style="color:blue;">await</span> Repository.Create(restaurant.Id, reservation).ConfigureAwait(<span style="color:blue;">false</span>);
<span style="color:blue;">var</span> storedReservation = <span style="color:blue;">await</span> Repository
.ReadReservation(restaurant.Id, reservation.Id)
.ConfigureAwait(<span style="color:blue;">false</span>);
scope.Complete();
<span style="color:blue;">return</span> Reservation201Created(restaurant.Id, storedReservation!);
}</pre>
</p>
<p>
Now, instead of echoing back <code>reservation</code>, the method calls <code>ReadReservation</code> to retrieve the (possibly enriched or normalised) <code>storedReservation</code> and returns that value. Since this value could, conceivably, be null, for now the method uses the <code>!</code> operator to insist that this is not the case. A new test case might be warranted to cover the scenario where the query returns null.
</p>
<p>
This is perhaps a little less efficient because it implies an extra round-trip to the database, but <em>it shouldn't change the behaviour of the system!</em>
</p>
<p>
But when you run the test suite, that <code>PostValidReservationWhenDatabaseIsEmpty</code> test fails:
</p>
<p>
<pre>Ploeh.Samples.Restaurants.RestApi.Tests.ReservationsTests.PostValidReservationWhenDatabaseIsEmpty(↩
days: 433, hours: 17, minutes: 30, email: "shli@example.org", name: "Shanghai Li", quantity: 5)↩
[FAIL]
System.NullReferenceException : Object reference not set to an instance of an object.
Stack Trace:
[...]\Restaurant.RestApi\ReservationsController.cs(94,0): at↩
[...].RestApi.ReservationsController.Reservation201Created↩
(Int32 restaurantId, Reservation r)
[...]\Restaurant.RestApi\ReservationsController.cs(79,0): at↩
[...].RestApi.ReservationsController.TryCreate↩
(Restaurant restaurant, Reservation reservation)
[...]\Restaurant.RestApi\ReservationsController.cs(57,0): at↩
[...].RestApi.ReservationsController.Post↩
(Int32 restaurantId, ReservationDto dto)
[...]\Restaurant.RestApi.Tests\ReservationsTests.cs(73,0): at↩
[...].RestApi.Tests.ReservationsTests.PostValidReservationWhenDatabaseIsEmpty↩
(Int32 days, Int32 hours, Int32 minutes, String email, String name, Int32 quantity)
--- End of stack trace from previous location where exception was thrown ---</pre>
</p>
<p>
Oh, the dreaded <code>NullReferenceException</code>! This happens because <code>ReadReservation</code> returns null, since the dynamic mock isn't configured.
</p>
<p>
The typical reaction that most people have is: <em>Oh no, the tests broke!</em>
</p>
<p>
I think, though, that this is the wrong perspective. The dynamic mock broke the System Under Test (SUT) because it passed an implementation of <code>IReservationsRepository</code> that breaks the contract. The test didn't 'break', because it was never correct from the outset.
</p>
<h3 id="f720608a0e3b45aa88f1831a4bb1f4e8">
Shotgun surgery <a href="#f720608a0e3b45aa88f1831a4bb1f4e8" title="permalink">#</a>
</h3>
<p>
When a test code base uses dynamic mocks, it tends to do so pervasively. Most tests create one or more dynamic mocks that they pass to their SUT. Most of these dynamic mocks break encapsulation, so when you refactor, the dynamic mocks break the SUT.
</p>
<p>
You'll typically need to revisit and 'fix' all the failing tests to accommodate the refactoring:
</p>
<p>
<pre>[Theory]
[InlineData(1049, 19, 00, <span style="color:#a31515;">"juliad@example.net"</span>, <span style="color:#a31515;">"Julia Domna"</span>, 5)]
[InlineData(1130, 18, 15, <span style="color:#a31515;">"x@example.com"</span>, <span style="color:#a31515;">"Xenia Ng"</span>, 9)]
[InlineData( 956, 16, 55, <span style="color:#a31515;">"kite@example.edu"</span>, <span style="color:blue;">null</span>, 2)]
[InlineData( 433, 17, 30, <span style="color:#a31515;">"shli@example.org"</span>, <span style="color:#a31515;">"Shanghai Li"</span>, 5)]
<span style="color:blue;">public</span> <span style="color:blue;">async</span> Task PostValidReservationWhenDatabaseIsEmpty(
<span style="color:blue;">int</span> days,
<span style="color:blue;">int</span> hours,
<span style="color:blue;">int</span> minutes,
<span style="color:blue;">string</span> email,
<span style="color:blue;">string</span> name,
<span style="color:blue;">int</span> quantity)
{
<span style="color:blue;">var</span> at = DateTime.Now.Date + <span style="color:blue;">new</span> TimeSpan(days, hours, minutes, 0);
<span style="color:blue;">var</span> expected = <span style="color:blue;">new</span> Reservation(
<span style="color:blue;">new</span> Guid(<span style="color:#a31515;">"B50DF5B1-F484-4D99-88F9-1915087AF568"</span>),
at,
<span style="color:blue;">new</span> Email(email),
<span style="color:blue;">new</span> Name(name ?? <span style="color:#a31515;">""</span>),
quantity);
<span style="color:blue;">var</span> dm = <span style="color:blue;">new</span> Mock<IReservationsRepository>();
dm.Setup(r => r.ReadReservations(Grandfather.Id, at.Date, at.Date.AddDays(1).AddTicks(-1)))
.ReturnsAsync(Array.Empty<Reservation>());
dm.Setup(r => r.ReadReservation(Grandfather.Id, expected.Id)).ReturnsAsync(expected);
<span style="color:blue;">var</span> sut = <span style="color:blue;">new</span> ReservationsController(
<span style="color:blue;">new</span> SystemClock(),
<span style="color:blue;">new</span> InMemoryRestaurantDatabase(Grandfather.Restaurant),
dm.Object);
<span style="color:blue;">await</span> sut.Post(expected.ToDto());
dm.Verify(r => r.Create(Grandfather.Id, expected));
}</pre>
</p>
<p>
The test now passes (until the next change in the SUT), but notice how top-heavy it becomes. That's a test code smell when using dynamic mocks. Everything has to happen in <a href="/2013/06/24/a-heuristic-for-formatting-code-according-to-the-aaa-pattern">the Arrange phase</a>.
</p>
<p>
You typically have many such tests that you need to edit. The name of this antipattern is <a href="https://en.wikipedia.org/wiki/Shotgun_surgery">Shotgun Surgery</a>.
</p>
<p>
The implication is that <em>refactoring</em> by definition is impossible:
</p>
<blockquote>
<p>
"to refactor, the essential precondition is [...] solid tests"
</p>
<footer><cite>Martin Fowler, <a href="/ref/refactoring">Refactoring</a></cite></footer>
</blockquote>
<p>
You need tests that don't break when you refactor. When you use dynamic mocks, tests tend to fail whenever you make changes in SUTs. Even though you have tests, they don't enable refactoring.
</p>
<p>
To add spite to injury, <a href="/2013/04/02/why-trust-tests">every time you edit existing tests, they become less trustworthy</a>.
</p>
<p>
To address these problems, use Fakes instead of Mocks and Stubs. With the <code>FakeDatabase</code> the entire sample test suite for the online restaurant reservation system gracefully handles the change described above. No tests fail.
</p>
<h3 id="8b30b068b4a4412ca3a797de2760b2be">
Spies <a href="#8b30b068b4a4412ca3a797de2760b2be" title="permalink">#</a>
</h3>
<p>
If you spelunk the test code base for the book, you may also find this Test Double:
</p>
<p>
<pre><span style="color:blue;">internal</span> <span style="color:blue;">sealed</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">SpyPostOffice</span> :
Collection<SpyPostOffice.Observation>, IPostOffice
{
<span style="color:blue;">public</span> Task EmailReservationCreated(
<span style="color:blue;">int</span> restaurantId,
Reservation reservation)
{
Add(<span style="color:blue;">new</span> Observation(Event.Created, restaurantId, reservation));
<span style="color:blue;">return</span> Task.CompletedTask;
}
<span style="color:blue;">public</span> Task EmailReservationDeleted(
<span style="color:blue;">int</span> restaurantId,
Reservation reservation)
{
Add(<span style="color:blue;">new</span> Observation(Event.Deleted, restaurantId, reservation));
<span style="color:blue;">return</span> Task.CompletedTask;
}
<span style="color:blue;">public</span> Task EmailReservationUpdating(
<span style="color:blue;">int</span> restaurantId,
Reservation reservation)
{
Add(<span style="color:blue;">new</span> Observation(Event.Updating, restaurantId, reservation));
<span style="color:blue;">return</span> Task.CompletedTask;
}
<span style="color:blue;">public</span> Task EmailReservationUpdated(
<span style="color:blue;">int</span> restaurantId,
Reservation reservation)
{
Add(<span style="color:blue;">new</span> Observation(Event.Updated, restaurantId, reservation));
<span style="color:blue;">return</span> Task.CompletedTask;
}
<span style="color:blue;">internal</span> <span style="color:blue;">enum</span> <span style="color:#2b91af;">Event</span>
{
Created = 0,
Updating,
Updated,
Deleted
}
<span style="color:blue;">internal</span> <span style="color:blue;">sealed</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">Observation</span>
{
<span style="color:blue;">public</span> <span style="color:#2b91af;">Observation</span>(
Event @event,
<span style="color:blue;">int</span> restaurantId,
Reservation reservation)
{
Event = @event;
RestaurantId = restaurantId;
Reservation = reservation;
}
<span style="color:blue;">public</span> Event Event { <span style="color:blue;">get</span>; }
<span style="color:blue;">public</span> <span style="color:blue;">int</span> RestaurantId { <span style="color:blue;">get</span>; }
<span style="color:blue;">public</span> Reservation Reservation { <span style="color:blue;">get</span>; }
<span style="color:blue;">public</span> <span style="color:blue;">override</span> <span style="color:blue;">bool</span> Equals(<span style="color:blue;">object</span>? obj)
{
<span style="color:blue;">return</span> obj <span style="color:blue;">is</span> Observation observation &&
Event == observation.Event &&
RestaurantId == observation.RestaurantId &&
EqualityComparer<Reservation>.Default.Equals(Reservation, observation.Reservation);
}
<span style="color:blue;">public</span> <span style="color:blue;">override</span> <span style="color:blue;">int</span> GetHashCode()
{
<span style="color:blue;">return</span> HashCode.Combine(Event, RestaurantId, Reservation);
}
}
}</pre>
</p>
<p>
As you can see, I've chosen to name this class with the <em>Spy</em> prefix, indicating that this is a Test Spy rather than a Fake Object. A Spy is a Test Double whose main purpose is to observe and record interactions. Does that break or realise encapsulation?
</p>
<p>
While I favour Fakes whenever possible, consider the interface that <code>SpyPostOffice</code> implements:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">interface</span> <span style="color:#2b91af;">IPostOffice</span>
{
Task EmailReservationCreated(<span style="color:blue;">int</span> restaurantId, Reservation reservation);
Task EmailReservationDeleted(<span style="color:blue;">int</span> restaurantId, Reservation reservation);
Task EmailReservationUpdating(<span style="color:blue;">int</span> restaurantId, Reservation reservation);
Task EmailReservationUpdated(<span style="color:blue;">int</span> restaurantId, Reservation reservation);
}</pre>
</p>
<p>
This interface consist entirely of <a href="https://en.wikipedia.org/wiki/Command%E2%80%93query_separation">Commands</a>. There's no way to query the interface to examine the state of the object. Thus, you can't check that postconditions hold <em>exclusively via the interface</em>. Instead, you need an additional <a href="http://xunitpatterns.com/Test%20Spy.html">retrieval interface</a> to examine the posterior state of the object. The <code>SpyPostOffice</code> concrete class exposes such an interface.
</p>
<p>
In a sense, you can view <code>SpyPostOffice</code> as an in-memory message sink. It fulfils the contract.
</p>
<h3 id="b36b228b2b4f4187918c8c224c9aed04">
Concurrency <a href="#b36b228b2b4f4187918c8c224c9aed04" title="permalink">#</a>
</h3>
<p>
Perhaps you're still not convinced. You may argue, for example, that the (partial) contract that I stated is naive. Consider, again, the implications expressed as code:
</p>
<p>
<pre><span style="color:blue;">await</span> sut.Create(restaurantId, expected);
<span style="color:blue;">var</span> actual = <span style="color:blue;">await</span> sut.ReadReservation(restaurantId, expected.Id);
Assert.Equal(expected, actual);</pre>
</p>
<p>
You may argue that in the face of concurrency, another thread or process could be making changes to the reservation <em>after</em> <code>Create</code>, but <em>before</em> <code>ReadReservation</code>. Thus, you may argue, the contract I've stipulated is false. In a real system, we can't expect that to be the case.
</p>
<p>
I agree.
</p>
<p>
Concurrency makes things much harder. Even in that light, I think the above line of reasoning is appropriate, for two reasons.
</p>
<p>
First, I chose to model <code>IReservationsRepository</code> like I did because I didn't expect high contention on individual reservations. In other words, I don't expect two or more concurrent processes to attempt to modify <em>the same reservation</em> at the same time. Thus, I found it appropriate to model the Repository as
</p>
<blockquote>
<p>
"a collection-like interface for accessing domain objects."
</p>
<footer><cite>Edward Hieatt and Rob Mee, in Martin Fowler, <a href="/ref/peaa">Patterns of Enterprise Application Architecture</a>, <em>Repository</em> pattern</cite></footer>
</blockquote>
<p>
A <em>collection-like interface</em> implies both data retrieval and collection manipulation members. In low-contention scenarios like the reservation system, this turns out to be a useful model. As the aphorism goes, <a href="https://en.wikipedia.org/wiki/All_models_are_wrong">all models are wrong, but some models are useful</a>. Treating <code>IReservationsRepository</code> as a collection accessed in a non-concurrent manner turned out to be useful in this code base.
</p>
<p>
Had I been more worried about data contention, a move towards <a href="https://martinfowler.com/bliki/CQRS.html">CQRS</a> seems promising. This leads to another object model, with different contracts.
</p>
<p>
Second, even in the face of concurrency, most unit test cases are implicitly running on a single thread. While they may run in parallel, each unit test exercises the SUT on a single thread. This implies that reads and writes against Test Doubles are serialised.
</p>
<p>
Even if concurrency is a real concern, you'd still expect that <em>if only one thread is manipulating the Repository object</em>, then what you <code>Create</code> you should be able to retrieve. The contract may be a little looser, but it'd still be a violation of the <a href="https://en.wikipedia.org/wiki/Principle_of_least_astonishment">principle of least surprise</a> if it was any different.
</p>
<h3 id="7db1c826945e417db7eacf65ac5207bb">
Conclusion <a href="#7db1c826945e417db7eacf65ac5207bb" title="permalink">#</a>
</h3>
<p>
In object-oriented programming, encapsulation is the notion of separating the affordances of an object from its implementation details. I find it most practical to think about this in terms of contracts, which again can be subdivided into sets of preconditions, invariants, and postconditions.
</p>
<p>
Polymorphic objects (like interfaces and base classes) come with contracts as well. When you replace 'real' implementations with Test Doubles, the Test Doubles should also fulfil the contracts. Fake objects do that; Test Spies may also fit that description.
</p>
<p>
When Test Doubles obey their contracts, you can refactor your SUT without breaking your test suite.
</p>
<p>
By default, however, dynamic mocks break encapsulation because they don't fulfil the objects' contracts. This leads to fragile tests.
</p>
<p>
Favour Fakes over dynamic mocks. You can read more about this way to write tests by following many of the links in this article, or by reading my book <a href="/code-that-fits-in-your-head">Code That Fits in Your Head</a>.
</p>
</div>
<div id="comments">
<hr>
<h2 id="comments-header">
Comments
</h2>
<div class="comment" id="6b55998427954772bed6da4ed8be8694">
<div class="comment-author">Matthew Wiemer</div>
<div class="comment-content">
<p>
Excellent article exploring the nuances of encapsulation as it relates to testing. That said, the examples here left me with one big question: what exactly is covered by the tests using `FakeDatabase`?
</p>
<p>This line in particular is confusing me (as to its practical use in a "real-world" setting): `var sut = new FakeDatabase();`</p>
<p>
How can I claim to have tested the real system's implementation when the "system under test" is, in this approach, explicitly _not_ my real system? It appears the same criticism of dynamic mocks surfaces: "you're only testing the fake database". Does this approach align with any claim you are testing the "real database"?
</p>
<p>
When testing the data-layer, I have historically written (heavier) tests that integrate with a real database to exercise a system's data-layer (as you describe with `SqlReservationsRepository`). I find myself reaching for dynamic mocks in the context of exercising an application's domain layer -- where the data-layer is a dependency providing indirect input/output. Does this use of mocks violate encapsulation in the way this article describes? I _think_ not, because in that case a dynamic mock is used to represent states that are valid "according to the contract", but I'm hoping you could shed a bit more light on the topic. Am I putting the pieces together correctly?
</p>
<p>
Rephrasing the question using your Reservations example code, I would typically inject `IReservationsRepository` into `MaitreD` (which you opt not to do) and outline the posssible database return values (or commands) using dynamic mocks in a test suite of `MaitreD`. What drawbacks, if any, would that approach lead to with respect to encapsulation and test fragility?
</p>
</div>
<div class="comment-date">2022-11-02 20:11 UTC</div>
</div>
<div class="comment" id="98ef29aec08e408382205b49bea697b6">
<div class="comment-author"><a href="/">Mark Seemann</a></div>
<div class="comment-content">
<p>
Matthew, thank you for writing. I apologise if the article is unclear about this, but nowhere in the <em>real</em> code base do I have a test of <code>FakeDatabase</code>. I only wrote the tests that exercise the Test Doubles to illustrate the point I was trying to make. These tests only exist for the benefit of this article.
</p>
<p>
The first <code>CreateAndReadRoundTrip</code> test in the article shows a real integration test. The System Under Test (SUT) is the <code>SqlReservationsRepository</code> class, which is part of the production code - not a Test Double.
</p>
<p>
That class implements the <code>IReservationsRepository</code> interface. The point I was trying to make is that the <code>CreateAndReadRoundTrip</code> test already exercises a particular subset of the contract of the interface. Thus, if one replaces one implementation of the interface with another implementation, according to the <a href="https://en.wikipedia.org/wiki/Liskov_substitution_principle">Liskov Substitution Principle</a> (LSP) the test should still pass.
</p>
<p>
This is true for <code>FakeDatabase</code>. While the behaviour is different (it doesn't persist data), it still fulfils the contract. Dynamic mocks, on the other hand, don't automatically follow the LSP. Unless one is careful and explicit, dynamic mocks tend to weaken postconditions. For example, a dynamic mock doesn't automatically return the added reservation when you call <code>ReadReservation</code>.
</p>
<p>
This is an essential flaw of dynamic mock objects that is independent of where you use them. My article <a href="#09410dcfb758412d991a47f08be885b5">already describes</a> how a fairly innocuous change in the production code will cause a dynamic mock to break the test.
</p>
<p>
I no longer inject dependencies into domain models, since doing so <a href="/2017/01/27/from-dependency-injection-to-dependency-rejection">makes the domain model impure</a>. Even if I did, however, I'd still have the same problem with dynamic mocks breaking encapsulation.
</p>
</div>
<div class="comment-date">2022-11-04 7:06 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>.Refactoring a saga from the State pattern to the State monadhttps://blog.ploeh.dk/2022/10/10/refactoring-a-saga-from-the-state-pattern-to-the-state-monad2022-10-10T06:27:00+00:00Mark Seemann
<div id="post">
<p>
<em>A slightly less unrealistic example in C#.</em>
</p>
<p>
This article is one of the examples that I promised in the earlier article <a href="/2022/09/05/the-state-pattern-and-the-state-monad">The State pattern and the State monad</a>. That article examines the relationship between the <a href="https://en.wikipedia.org/wiki/State_pattern">State design pattern</a> and the <a href="/2022/06/20/the-state-monad">State monad</a>. It's deliberately abstract, so one or more examples are in order.
</p>
<p>
In the <a href="/2022/09/26/refactoring-the-tcp-state-pattern-example-to-pure-functions">previous example</a> you saw how to refactor <a href="/ref/dp">Design Patterns</a>' <em>TCP connection</em> example. That example is, unfortunately, hardly illuminating due to its nature, so a second example is warranted.
</p>
<p>
This second example shows how to refactor a stateful asynchronous message handler from the State pattern to the State monad.
</p>
<h3 id="20b0274c10b14a84a07ebd2086ab1fa0">
Shipping policy <a href="#20b0274c10b14a84a07ebd2086ab1fa0" title="permalink">#</a>
</h3>
<p>
Instead of inventing an example from scratch, I decided to use <a href="https://docs.particular.net/tutorials/nservicebus-sagas/1-saga-basics/">an NServiceBus saga tutorial</a> as a foundation. Read on even if you don't know <a href="https://particular.net/nservicebus">NServiceBus</a>. You don't have to know anything about NServiceBus in order to follow along. I just thought that I'd embed the example code in a context that actually executes and does something, instead of faking it with a bunch of unit tests. Hopefully this will help make the example a bit more realistic and relatable.
</p>
<p>
The example is a simple demo of asynchronous message handling. In a web store shipping department, you should only ship an item once you've received the order and a billing confirmation. When working with asynchronous messaging, you can't, however, rely on message ordering, so perhaps the <code>OrderBilled</code> message arrives before the <code>OrderPlaced</code> message, and sometimes it's the other way around.
</p>
<p>
<img src="/content/binary/shipping-policy-state-diagram.png" alt="Shipping policy state diagram.">
</p>
<p>
Only when you've received both messages may you ship the item.
</p>
<p>
It's a simple workflow, and you don't <em>really</em> need the State pattern. So much is clear from the sample code implementation:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">ShippingPolicy</span> : Saga<ShippingPolicyData>,
IAmStartedByMessages<OrderBilled>,
IAmStartedByMessages<OrderPlaced>
{
<span style="color:blue;">static</span> ILog log = LogManager.GetLogger<ShippingPolicy>();
<span style="color:blue;">protected</span> <span style="color:blue;">override</span> <span style="color:blue;">void</span> ConfigureHowToFindSaga(SagaPropertyMapper<ShippingPolicyData> mapper)
{
mapper.MapSaga(sagaData => sagaData.OrderId)
.ToMessage<OrderPlaced>(message => message.OrderId)
.ToMessage<OrderBilled>(message => message.OrderId);
}
<span style="color:blue;">public</span> Task Handle(OrderPlaced message, IMessageHandlerContext context)
{
log.Info(<span style="color:#a31515;">$"OrderPlaced message received."</span>);
Data.IsOrderPlaced = <span style="color:blue;">true</span>;
<span style="color:blue;">return</span> ProcessOrder(context);
}
<span style="color:blue;">public</span> Task Handle(OrderBilled message, IMessageHandlerContext context)
{
log.Info(<span style="color:#a31515;">$"OrderBilled message received."</span>);
Data.IsOrderBilled = <span style="color:blue;">true</span>;
<span style="color:blue;">return</span> ProcessOrder(context);
}
<span style="color:blue;">private</span> <span style="color:blue;">async</span> Task ProcessOrder(IMessageHandlerContext context)
{
<span style="color:blue;">if</span> (Data.IsOrderPlaced && Data.IsOrderBilled)
{
<span style="color:blue;">await</span> context.SendLocal(<span style="color:blue;">new</span> ShipOrder() { OrderId = Data.OrderId });
MarkAsComplete();
}
}
}</pre>
</p>
<p>
I don't expect you to be familiar with the NServiceBus API, so don't worry about the base class, the interfaces, or the <code>ConfigureHowToFindSaga</code> method. What you need to know is that this class handles two types of messages: <code>OrderPlaced</code> and <code>OrderBilled</code>. What the base class and the framework does is handling message correlation, hydration and dehydration, and so on.
</p>
<p>
For the purposes of this demo, all you need to know about the <code>context</code> object is that it enables you to send and publish messages. The code sample uses <code>context.SendLocal</code> to send a new <code>ShipOrder</code> Command.
</p>
<p>
Messages arrive asynchronously and conceptually with long wait times between them. You can't just rely on in-memory object state because a <code>ShippingPolicy</code> instance may receive one message and then risk that the server it's running on shuts down before the next message arrives. The NServiceBus framework handles message correlation and hydration and dehydration of state data. The latter is modelled by the <code>ShippingPolicyData</code> class:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">ShippingPolicyData</span> : ContainSagaData
{
<span style="color:blue;">public</span> <span style="color:blue;">string</span> OrderId { <span style="color:blue;">get</span>; <span style="color:blue;">set</span>; }
<span style="color:blue;">public</span> <span style="color:blue;">bool</span> IsOrderPlaced { <span style="color:blue;">get</span>; <span style="color:blue;">set</span>; }
<span style="color:blue;">public</span> <span style="color:blue;">bool</span> IsOrderBilled { <span style="color:blue;">get</span>; <span style="color:blue;">set</span>; }
}</pre>
</p>
<p>
Notice that the above sample code inspects and manipulates the <code>Data</code> property defined by the <code>Saga<ShippingPolicyData></code> base class.
</p>
<p>
When the <code>ShippingPolicy</code> methods are called by the NServiceBus framework, the <code>Data</code> is automatically populated. When you modify the <code>Data</code>, the state data is automatically persisted when the message handler shuts down to wait for the next message.
</p>
<h3 id="0edda65734e64a6a99a865c43d6de5be">
Characterisation tests <a href="#0edda65734e64a6a99a865c43d6de5be" title="permalink">#</a>
</h3>
<p>
While you can draw an explicit state diagram like the one above, the sample code doesn't explicitly model the various states as objects. Instead, it relies on reading and writing two Boolean values.
</p>
<p>
There's nothing wrong with this implementation. It's the simplest thing that could possibly work, so why make it more complicated?
</p>
<p>
In this article, I <em>am</em> going to make it more complicated. First, I'm going to refactor the above sample code to use the State design pattern, and then I'm going to refactor that code to use the State monad. From a perspective of maintainability, this isn't warranted, but on the other hand, I hope it's educational. The sample code is just complex enough to showcase the structures of the State pattern and the State monad, yet simple enough that the implementation logic doesn't get in the way.
</p>
<p>
Simplicity can be deceiving, however, and no refactoring is without risk.
</p>
<blockquote>
<p>
"to refactor, the essential precondition is [...] solid tests"
</p>
<footer><cite><a href="https://martinfowler.com/">Martin Fowler</a>, <a href="/ref/refactoring">Refactoring</a></cite></footer>
</blockquote>
<p>
I found it safest to first add a few <a href="https://en.wikipedia.org/wiki/Characterization_test">Characterisation Tests</a> to make sure I didn't introduce any errors as I changed the code. It did catch a few copy-paste goofs that I made, so adding tests turned out to be a good idea.
</p>
<p>
Testing NServiceBus message handlers isn't too hard. All the tests I wrote look similar, so one should be enough to give you an idea.
</p>
<p>
<pre>[Theory]
[InlineData(<span style="color:#a31515;">"1337"</span>)]
[InlineData(<span style="color:#a31515;">"baz"</span>)]
<span style="color:blue;">public</span> <span style="color:blue;">async</span> Task OrderPlacedAndBilled(<span style="color:blue;">string</span> orderId)
{
<span style="color:blue;">var</span> sut =
<span style="color:blue;">new</span> ShippingPolicy
{
Data = <span style="color:blue;">new</span> ShippingPolicyData { OrderId = orderId }
};
<span style="color:blue;">var</span> ctx = <span style="color:blue;">new</span> TestableMessageHandlerContext();
<span style="color:blue;">await</span> sut.Handle(<span style="color:blue;">new</span> OrderPlaced { OrderId = orderId }, ctx);
<span style="color:blue;">await</span> sut.Handle(<span style="color:blue;">new</span> OrderBilled { OrderId = orderId }, ctx);
Assert.True(sut.Completed);
<span style="color:blue;">var</span> msg = Assert.Single(ctx.SentMessages.Containing<ShipOrder>());
Assert.Equal(orderId, msg.Message.OrderId);
}</pre>
</p>
<p>
The tests use <a href="https://xunit.net/">xUnit.net</a> 2.4.2. When I downloaded the <a href="https://docs.particular.net/tutorials/nservicebus-sagas/1-saga-basics/">NServiceBus saga sample code</a> it targeted .NET Framework 4.8, and I didn't bother to change the version.
</p>
<p>
While the NServiceBus framework will automatically hydrate and populate <code>Data</code>, in a unit test you have to remember to explicitly populate it. The <code>TestableMessageHandlerContext</code> class is a <a href="http://xunitpatterns.com/Test%20Spy.html">Test Spy</a> that is part of <a href="https://docs.particular.net/nservicebus/testing/">NServiceBus testing API</a>.
</p>
<p>
You'd think I was paid by <a href="https://particular.net/">Particular Software</a> to write this article, but I'm not. All this is really just the introduction. You're excused if you've forgotten the topic of this article, but my goal is to show a State pattern example. Only now can we begin in earnest.
</p>
<h3 id="7b1878c85e134ac5a24e9ce13ba064d2">
State pattern implementation <a href="#7b1878c85e134ac5a24e9ce13ba064d2" title="permalink">#</a>
</h3>
<p>
Refactoring to the State pattern, I chose to let the <code>ShippingPolicy</code> class fill the role of the pattern's <code>Context</code>. Instead of a base class with virtual method, I used an interface to define the <code>State</code> object, as that's more <a href="/2015/08/03/idiomatic-or-idiosyncratic">Idiomatic</a> in C#:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">interface</span> <span style="color:#2b91af;">IShippingState</span>
{
Task OrderPlaced(OrderPlaced message, IMessageHandlerContext context, ShippingPolicy policy);
Task OrderBilled(OrderBilled message, IMessageHandlerContext context, ShippingPolicy policy);
}</pre>
</p>
<p>
The State pattern only shows examples where the <code>State</code> methods take a single argument: The <code>Context</code>. In this case, that's the <code>ShippingPolicy</code>. Careful! There's also a parameter called <code>context</code>! That's the NServiceBus context, and is an artefact of the original example. The two other parameters, <code>message</code> and <code>context</code>, are run-time values passed on from the <code>ShippingPolicy</code>'s <code>Handle</code> methods:
</p>
<p>
<pre><span style="color:blue;">public</span> IShippingState State { <span style="color:blue;">get</span>; <span style="color:blue;">internal</span> <span style="color:blue;">set</span>; }
<span style="color:blue;">public</span> <span style="color:blue;">async</span> Task Handle(OrderPlaced message, IMessageHandlerContext context)
{
log.Info(<span style="color:#a31515;">$"OrderPlaced message received."</span>);
Hydrate();
<span style="color:blue;">await</span> State.OrderPlaced(message, context, <span style="color:blue;">this</span>);
Dehydrate();
}
<span style="color:blue;">public</span> <span style="color:blue;">async</span> Task Handle(OrderBilled message, IMessageHandlerContext context)
{
log.Info(<span style="color:#a31515;">$"OrderBilled message received."</span>);
Hydrate();
<span style="color:blue;">await</span> State.OrderBilled(message, context, <span style="color:blue;">this</span>);
Dehydrate();
}</pre>
</p>
<p>
The <code>Hydrate</code> method isn't part of the State pattern, but finds an appropriate state based on <code>Data</code>:
</p>
<p>
<pre><span style="color:blue;">private</span> <span style="color:blue;">void</span> Hydrate()
{
<span style="color:blue;">if</span> (!Data.IsOrderPlaced && !Data.IsOrderBilled)
State = InitialShippingState.Instance;
<span style="color:blue;">else</span> <span style="color:blue;">if</span> (Data.IsOrderPlaced && !Data.IsOrderBilled)
State = AwaitingBillingState.Instance;
<span style="color:blue;">else</span> <span style="color:blue;">if</span> (!Data.IsOrderPlaced && Data.IsOrderBilled)
State = AwaitingPlacementState.Instance;
<span style="color:blue;">else</span>
State = CompletedShippingState.Instance;
}</pre>
</p>
<p>
In more recent versions of C# you'd be able to use more succinct pattern matching, but since this code base is on .NET Framework 4.8 I'm constrained to C# 7.3 and this is as good as I cared to make it. It's not important to the topic of the State pattern, but I'm showing it in case you where wondering. It's typical that you need to translate between data that exists in the 'external world' and your object-oriented, polymorphic code, since <a href="/2011/05/31/AttheBoundaries,ApplicationsareNotObject-Oriented">at the boundaries, applications aren't object-oriented</a>.
</p>
<p>
Likewise, the <code>Dehydrate</code> method translates the other way:
</p>
<p>
<pre><span style="color:blue;">private</span> <span style="color:blue;">void</span> Dehydrate()
{
<span style="color:blue;">if</span> (State <span style="color:blue;">is</span> AwaitingBillingState)
{
Data.IsOrderPlaced = <span style="color:blue;">true</span>;
Data.IsOrderBilled = <span style="color:blue;">false</span>;
<span style="color:blue;">return</span>;
}
<span style="color:blue;">if</span> (State <span style="color:blue;">is</span> AwaitingPlacementState)
{
Data.IsOrderPlaced = <span style="color:blue;">false</span>;
Data.IsOrderBilled = <span style="color:blue;">true</span>;
<span style="color:blue;">return</span>;
}
<span style="color:blue;">if</span> (State <span style="color:blue;">is</span> CompletedShippingState)
{
Data.IsOrderPlaced = <span style="color:blue;">true</span>;
Data.IsOrderBilled = <span style="color:blue;">true</span>;
<span style="color:blue;">return</span>;
}
Data.IsOrderPlaced = <span style="color:blue;">false</span>;
Data.IsOrderBilled = <span style="color:blue;">false</span>;
}</pre>
</p>
<p>
In any case, <code>Hydrate</code> and <code>Dehydrate</code> are distractions. The important part is that the <code>ShippingPolicy</code> (the State <em>Context</em>) now delegates execution to its <code>State</code>, which performs the actual work and updates the <code>State</code>.
</p>
<h3 id="0ad9f36d329d45cda95fc92630e65eed">
Initial state <a href="#0ad9f36d329d45cda95fc92630e65eed" title="permalink">#</a>
</h3>
<p>
The first time the saga runs, both <code>Data.IsOrderPlaced</code> and <code>Data.IsOrderBilled</code> are <code>false</code>, which means that the <code>State</code> is <code>InitialShippingState</code>:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">sealed</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">InitialShippingState</span> : IShippingState
{
<span style="color:blue;">public</span> <span style="color:blue;">readonly</span> <span style="color:blue;">static</span> InitialShippingState Instance =
<span style="color:blue;">new</span> InitialShippingState();
<span style="color:blue;">private</span> <span style="color:#2b91af;">InitialShippingState</span>()
{
}
<span style="color:blue;">public</span> Task OrderPlaced(
OrderPlaced message,
IMessageHandlerContext context,
ShippingPolicy policy)
{
policy.State = AwaitingBillingState.Instance;
<span style="color:blue;">return</span> Task.CompletedTask;
}
<span style="color:blue;">public</span> Task OrderBilled(
OrderBilled message,
IMessageHandlerContext context,
ShippingPolicy policy)
{
policy.State = AwaitingPlacementState.Instance;
<span style="color:blue;">return</span> Task.CompletedTask;
}
}</pre>
</p>
<p>
As the above state transition diagram indicates, the only thing that each of the methods do is that they transition to the next appropriate state: <code>AwaitingBillingState</code> if the first event was <code>OrderPlaced</code>, and <code>AwaitingPlacementState</code> when the event was <code>OrderBilled</code>.
</p>
<blockquote>
<p>
"State object are often Singletons"
</p>
<footer><cite><a href="/ref/dp">Design Patterns</a></cite></footer>
</blockquote>
<p>
Like in the <a href="/2022/09/26/refactoring-the-tcp-state-pattern-example-to-pure-functions">previous example</a> I've made all the State objects <a href="https://en.wikipedia.org/wiki/Singleton_pattern">Singletons</a>. It's not that important, but since they are all stateless, we might as well. At least, it's in the spirit of the book.
</p>
<h3 id="1a3c6882c82d444fb4dff0cb9ffee2e5">
Awaiting billing <a href="#1a3c6882c82d444fb4dff0cb9ffee2e5" title="permalink">#</a>
</h3>
<p>
<code>AwaitingBillingState</code> is another <code>IShippingState</code> implementation:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">sealed</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">AwaitingBillingState</span> : IShippingState
{
<span style="color:blue;">public</span> <span style="color:blue;">readonly</span> <span style="color:blue;">static</span> IShippingState Instance =
<span style="color:blue;">new</span> AwaitingBillingState();
<span style="color:blue;">private</span> <span style="color:#2b91af;">AwaitingBillingState</span>()
{
}
<span style="color:blue;">public</span> Task OrderPlaced(
OrderPlaced message,
IMessageHandlerContext context,
ShippingPolicy policy)
{
<span style="color:blue;">return</span> Task.CompletedTask;
}
<span style="color:blue;">public</span> <span style="color:blue;">async</span> Task OrderBilled(
OrderBilled message,
IMessageHandlerContext context,
ShippingPolicy policy)
{
<span style="color:blue;">await</span> context.SendLocal(
<span style="color:blue;">new</span> ShipOrder() { OrderId = policy.Data.OrderId });
policy.Complete();
policy.State = CompletedShippingState.Instance;
}
}</pre>
</p>
<p>
This State doesn't react to <code>OrderPlaced</code> because it assumes that an order has already been placed. It only reacts to an <code>OrderBilled</code> event. When that happens, all requirements have been fulfilled to ship the item, so it sends a <code>ShipOrder</code> Command, marks the saga as completed, and changes the <code>State</code> to <code>CompletedShippingState</code>.
</p>
<p>
The <code>Complete</code> method is a little wrapper method I had to add to the <code>ShippingPolicy</code> class, since <code>MarkAsComplete</code> is a <code>protected</code> method:
</p>
<p>
<pre><span style="color:blue;">internal</span> <span style="color:blue;">void</span> Complete()
{
MarkAsComplete();
}</pre>
</p>
<p>
The <code>AwaitingPlacementState</code> class is similar to <code>AwaitingBillingState</code>, except that it reacts to <code>OrderPlaced</code> rather than <code>OrderBilled</code>.
</p>
<h3 id="503262f1d69a4042bb3f93b16aa04d44">
Terminal state <a href="#503262f1d69a4042bb3f93b16aa04d44" title="permalink">#</a>
</h3>
<p>
The fourth and final state is the <code>CompletedShippingState</code>:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">sealed</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">CompletedShippingState</span> : IShippingState
{
<span style="color:blue;">public</span> <span style="color:blue;">readonly</span> <span style="color:blue;">static</span> IShippingState Instance =
<span style="color:blue;">new</span> CompletedShippingState();
<span style="color:blue;">private</span> <span style="color:#2b91af;">CompletedShippingState</span>()
{
}
<span style="color:blue;">public</span> Task OrderPlaced(
OrderPlaced message,
IMessageHandlerContext context,
ShippingPolicy policy)
{
<span style="color:blue;">return</span> Task.CompletedTask;
}
<span style="color:blue;">public</span> Task OrderBilled(
OrderBilled message,
IMessageHandlerContext context,
ShippingPolicy policy)
{
<span style="color:blue;">return</span> Task.CompletedTask;
}
}</pre>
</p>
<p>
In this state, the saga is completed, so it ignores both events.
</p>
<h3 id="3769c2c7504548c884cdc38d788a8f46">
Move Commands to output <a href="#3769c2c7504548c884cdc38d788a8f46" title="permalink">#</a>
</h3>
<p>
The saga now uses the State pattern to manage state-specific behaviour as well as state transitions. To be clear, this complexity isn't warranted for the simple requirements. This is, after all, an example. All tests still pass, and smoke testing also indicates that everything still works as it's supposed to.
</p>
<p>
The goal of this article is now to refactor the State pattern implementation to <a href="https://en.wikipedia.org/wiki/Pure_function">pure functions</a>. When the saga runs it has an observable side effect: It eventually sends a <code>ShipOrder</code> Command. During processing it also updates its internal state. Both of these are sources of impurity that we have to <a href="/2016/09/26/decoupling-decisions-from-effects">decouple from the decision logic</a>.
</p>
<p>
I'll do this in several steps. The first impure action I'll address is the externally observable message transmission. A common functional-programming trick is to turn a side effect into a return value. So far, the <code>IShippingState</code> methods don't return anything. (This is strictly not true; they each return <a href="https://docs.microsoft.com/dotnet/api/system.threading.tasks.task">Task</a>, but we can regard <code>Task</code> as 'asynchronous <code>void</code>'.) Thus, return values are still available as a communications channel.
</p>
<p>
Refactor the <code>IShippingState</code> methods to return Commands instead of actually sending them. Each method may send an arbitrary number of Commands, including none, so the return type has to be a collection:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">interface</span> <span style="color:#2b91af;">IShippingState</span>
{
IReadOnlyCollection<ICommand> OrderPlaced(
OrderPlaced message,
IMessageHandlerContext context,
ShippingPolicy policy);
IReadOnlyCollection<ICommand> OrderBilled(
OrderBilled message,
IMessageHandlerContext context,
ShippingPolicy policy);
}</pre>
</p>
<p>
When you change the interface you also have to change all the implementing classes, including <code>AwaitingBillingState</code>:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">sealed</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">AwaitingBillingState</span> : IShippingState
{
<span style="color:blue;">public</span> <span style="color:blue;">readonly</span> <span style="color:blue;">static</span> IShippingState Instance = <span style="color:blue;">new</span> AwaitingBillingState();
<span style="color:blue;">private</span> <span style="color:#2b91af;">AwaitingBillingState</span>()
{
}
<span style="color:blue;">public</span> IReadOnlyCollection<ICommand> OrderPlaced(
OrderPlaced message,
IMessageHandlerContext context,
ShippingPolicy policy)
{
<span style="color:blue;">return</span> Array.Empty<ICommand>();
}
<span style="color:blue;">public</span> IReadOnlyCollection<ICommand> OrderBilled(
OrderBilled message,
IMessageHandlerContext context,
ShippingPolicy policy)
{
policy.Complete();
policy.State = CompletedShippingState.Instance;
<span style="color:blue;">return</span> <span style="color:blue;">new</span>[] { <span style="color:blue;">new</span> ShipOrder() { OrderId = policy.Data.OrderId } };
}
}</pre>
</p>
<p>
In order to do nothing a method like <code>OrderPlaced</code> now has to return an empty collection of Commands. In order to 'send' a Command, <code>OrderBilled</code> now returns it instead of using the <code>context</code> to send it. The <code>context</code> is already redundant, but since I prefer to <a href="https://stackoverflow.blog/2022/04/06/use-git-tactically/">move in small steps</a>, I'll remove it in a separate step.
</p>
<p>
It's now the responsibility of the <code>ShippingPolicy</code> class to do something with the Commands returned by the <code>State</code>:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">async</span> Task Handle(OrderBilled message, IMessageHandlerContext context)
{
log.Info(<span style="color:#a31515;">$"OrderBilled message received."</span>);
Hydrate();
<span style="color:blue;">var</span> result = State.OrderBilled(message, context, <span style="color:blue;">this</span>);
<span style="color:blue;">await</span> Interpret(result, context);
Dehydrate();
}
<span style="color:blue;">private</span> <span style="color:blue;">async</span> Task Interpret(
IReadOnlyCollection<ICommand> commands,
IMessageHandlerContext context)
{
<span style="color:blue;">foreach</span> (var cmd <span style="color:blue;">in</span> commands)
<span style="color:blue;">await</span> context.SendLocal(cmd);
}</pre>
</p>
<p>
In functional programming, you often run an interpreter over the instructions returned by a pure function. Here the interpreter is just a private helper method.
</p>
<p>
The <code>IShippingState</code> methods are no longer asynchronous. Now they just return collections. I consider that a simplification.
</p>
<h3 id="31ef1f01413143359d91e067da9d9a35">
Remove context parameter <a href="#31ef1f01413143359d91e067da9d9a35" title="permalink">#</a>
</h3>
<p>
The <code>context</code> parameter is now redundant, so remove it from the <code>IShippingState</code> interface:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">interface</span> <span style="color:#2b91af;">IShippingState</span>
{
IReadOnlyCollection<ICommand> OrderPlaced(OrderPlaced message, ShippingPolicy policy);
IReadOnlyCollection<ICommand> OrderBilled(OrderBilled message, ShippingPolicy policy);
}</pre>
</p>
<p>
I used Visual Studio's built-in refactoring tools to remove the parameter, which automatically removed it from all the call sites and implementations.
</p>
<p>
This takes us part of the way towards implementing the states as pure functions, but there's still work to be done.
</p>
<p>
<pre><span style="color:blue;">public</span> IReadOnlyCollection<ICommand> OrderBilled(OrderBilled message, ShippingPolicy policy)
{
policy.Complete();
policy.State = CompletedShippingState.Instance;
<span style="color:blue;">return</span> <span style="color:blue;">new</span>[] { <span style="color:blue;">new</span> ShipOrder() { OrderId = policy.Data.OrderId } };
}</pre>
</p>
<p>
The above <code>OrderBilled</code> implementation calls <code>policy.Complete</code> to indicate that the saga has completed. That's another state mutation that must be eliminated to make this a pure function.
</p>
<h3 id="51ae5d89697b47fe8611b58b4540163e">
Return complex result <a href="#51ae5d89697b47fe8611b58b4540163e" title="permalink">#</a>
</h3>
<p>
How do you refactor from state mutation to pure function? You turn the mutation statement into an instruction, which is a value that you return. In this case you might want to return a Boolean value: True to complete the saga. False otherwise.
</p>
<p>
There seems to be a problem, though. The <code>IShippingState</code> methods already return data: They return a collection of Commands. How do we get around this conundrum?
</p>
<p>
Introduce a complex object:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">sealed</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">ShippingStateResult</span>
{
<span style="color:blue;">public</span> <span style="color:#2b91af;">ShippingStateResult</span>(
IReadOnlyCollection<ICommand> commands,
<span style="color:blue;">bool</span> completeSaga)
{
Commands = commands;
CompleteSaga = completeSaga;
}
<span style="color:blue;">public</span> IReadOnlyCollection<ICommand> Commands { <span style="color:blue;">get</span>; }
<span style="color:blue;">public</span> <span style="color:blue;">bool</span> CompleteSaga { <span style="color:blue;">get</span>; }
<span style="color:blue;">public</span> <span style="color:blue;">override</span> <span style="color:blue;">bool</span> Equals(<span style="color:blue;">object</span> obj)
{
<span style="color:blue;">return</span> obj <span style="color:blue;">is</span> ShippingStateResult result &&
EqualityComparer<IReadOnlyCollection<ICommand>>.Default
.Equals(Commands, result.Commands) &&
CompleteSaga == result.CompleteSaga;
}
<span style="color:blue;">public</span> <span style="color:blue;">override</span> <span style="color:blue;">int</span> GetHashCode()
{
<span style="color:blue;">int</span> hashCode = -1668187231;
hashCode = hashCode * -1521134295 + EqualityComparer<IReadOnlyCollection<ICommand>>
.Default.GetHashCode(Commands);
hashCode = hashCode * -1521134295 + CompleteSaga.GetHashCode();
<span style="color:blue;">return</span> hashCode;
}
}</pre>
</p>
<p>
That looks rather horrible, but most of the code is generated by Visual Studio. The only thing I wrote myself was the class declaration and the two read-only properties. I then used Visual Studio's <em>Generate constructor</em> and <em>Generate Equals and GetHashCode</em> Quick Actions to produce the rest of the code.
</p>
<p>
With more modern versions of C# I could have used a <a href="https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/record">record</a>, but as I've already mentioned, I'm on C# 7.3 here.
</p>
<p>
The <code>IShippingState</code> interface can now define its methods with this new return type:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">interface</span> <span style="color:#2b91af;">IShippingState</span>
{
ShippingStateResult OrderPlaced(OrderPlaced message, ShippingPolicy policy);
ShippingStateResult OrderBilled(OrderBilled message, ShippingPolicy policy);
}</pre>
</p>
<p>
This change reminds me of the <a href="https://refactoring.com/catalog/introduceParameterObject.html">Introduce Parameter Object</a> refactoring, but instead applied to the return value instead of input.
</p>
<p>
Implementers now have to return values of this new type:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">sealed</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">AwaitingBillingState</span> : IShippingState
{
<span style="color:blue;">public</span> <span style="color:blue;">readonly</span> <span style="color:blue;">static</span> IShippingState Instance = <span style="color:blue;">new</span> AwaitingBillingState();
<span style="color:blue;">private</span> <span style="color:#2b91af;">AwaitingBillingState</span>()
{
}
<span style="color:blue;">public</span> ShippingStateResult OrderPlaced(OrderPlaced message, ShippingPolicy policy)
{
<span style="color:blue;">return</span> <span style="color:blue;">new</span> ShippingStateResult(Array.Empty<ICommand>(), <span style="color:blue;">false</span>);
}
<span style="color:blue;">public</span> ShippingStateResult OrderBilled(OrderBilled message, ShippingPolicy policy)
{
policy.State = CompletedShippingState.Instance;
<span style="color:blue;">return</span> <span style="color:blue;">new</span> ShippingStateResult(
<span style="color:blue;">new</span>[] { <span style="color:blue;">new</span> ShipOrder() { OrderId = policy.Data.OrderId } },
<span style="color:blue;">true</span>);
}
}</pre>
</p>
<p>
Moving a statement to an output value implies that the effect must happen somewhere else. It seems natural to put it in the <code>ShippingPolicy</code> class' <code>Interpret</code> method:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">async</span> Task Handle(OrderBilled message, IMessageHandlerContext context)
{
log.Info(<span style="color:#a31515;">$"OrderBilled message received."</span>);
Hydrate();
<span style="color:blue;">var</span> result = State.OrderBilled(message, <span style="color:blue;">this</span>);
<span style="color:blue;">await</span> Interpret(result, context);
Dehydrate();
}
<span style="color:blue;">private</span> <span style="color:blue;">async</span> Task Interpret(ShippingStateResult result, IMessageHandlerContext context)
{
<span style="color:blue;">foreach</span> (var cmd <span style="color:blue;">in</span> result.Commands)
<span style="color:blue;">await</span> context.SendLocal(cmd);
<span style="color:blue;">if</span> (result.CompleteSaga)
MarkAsComplete();
}</pre>
</p>
<p>
Since <code>Interpret</code> is an instance method on the <code>ShippingPolicy</code> class I can now also delete the internal <code>Complete</code> method, since <code>MarkAsComplete</code> is already callable (it's a <code>protected</code> method defined by the <code>Saga</code> base class).
</p>
<h3 id="ce2f9545c94b4c6ab9536050ed030b8b">
Use message data <a href="#ce2f9545c94b4c6ab9536050ed030b8b" title="permalink">#</a>
</h3>
<p>
Have you noticed an odd thing about the code so far? It doesn't use any of the <code>message</code> data!
</p>
<p>
This is an artefact of the original code example. Refer back to the original <code>ProcessOrder</code> helper method. It uses neither <code>OrderPlaced</code> nor <code>OrderBilled</code> for anything. Instead, it pulls the <code>OrderId</code> from the saga's <code>Data</code> property. It can do that because NServiceBus makes sure that all <code>OrderId</code> values are correlated. It'll only instantiate a saga for which <code>Data.OrderId</code> matches <code>OrderPlaced.OrderId</code> or <code>OrderBilled.OrderId</code>. Thus, these values are guaranteed to be the same, and that's why <code>ProcessOrder</code> can get away with using <code>Data.OrderId</code> instead of the <code>message</code> data.
</p>
<p>
So far, through all refactorings, I've retained this detail, but it seems odd. It also couples the implementation methods to the <code>ShippingPolicy</code> class rather than the message classes. For these reasons, refactor the methods to use the message data instead. Here's the <code>AwaitingBillingState</code> implementation:
</p>
<p>
<pre><span style="color:blue;">public</span> ShippingStateResult OrderBilled(OrderBilled message, ShippingPolicy policy)
{
policy.State = CompletedShippingState.Instance;
<span style="color:blue;">return</span> <span style="color:blue;">new</span> ShippingStateResult(
<span style="color:blue;">new</span>[] { <span style="color:blue;">new</span> ShipOrder() { OrderId = message.OrderId } },
<span style="color:blue;">true</span>);
}</pre>
</p>
<p>
Compare this version with the previous iteration, where it used <code>policy.Data.OrderId</code> instead of <code>message.OrderId</code>.
</p>
<p>
Now, the only reason to pass <code>ShippingPolicy</code> as a method parameter is to mutate <code>policy.State</code>. We'll get to that in due time, but first, there's another issue I'd like to address.
</p>
<h3 id="800453851c1944e3835a05f8ff2e3272">
Immutable arguments <a href="#800453851c1944e3835a05f8ff2e3272" title="permalink">#</a>
</h3>
<p>
Keep in mind that the overall goal of the exercise is to refactor the state machine to pure functions. For good measure, method parameters should be immutable as well. Consider a method like <code>OrderBilled</code> shown above in its most recent iteration. It mutates <code>policy</code> by setting <code>policy.State</code>. The long-term goal is to get rid of that statement.
</p>
<p>
The method doesn't mutate the other argument, <code>message</code>, but the <code>OrderBilled</code> class is actually mutable:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">OrderBilled</span> : IEvent
{
<span style="color:blue;">public</span> <span style="color:blue;">string</span> OrderId { <span style="color:blue;">get</span>; <span style="color:blue;">set</span>; }
}</pre>
</p>
<p>
The same is true for the other message type, <code>OrderPlaced</code>.
</p>
<p>
For good measure, pure functions shouldn't take mutable arguments. You could argue that, since none of the implementation methods actually mutate the messages, it doesn't really matter. I am, however, enough of a neat freak that I don't like to leave such a loose strand dangling. I'd like to refactor the <code>IShippingState</code> API so that only immutable message data is passed as arguments.
</p>
<p>
In a situation like this, there are (at least) three options:
</p>
<ul>
<li>
Make the message types immutable. This would mean making <code>OrderBilled</code> and <code>OrderPlaced</code> immutable. These message types are by default mutable <a href="https://en.wikipedia.org/wiki/Data_transfer_object">Data Transfer Objects</a> (DTO), because NServiceBus needs to serialise and deserialise them to transmit them over durable queues. There are ways you can configure NServiceBus to use serialisation mechanisms that enable immutable records as messages, but for an example code base like this, I might be inclined to reach for an easier solution if one presents itself.
</li>
<li>
Add an immutable 'mirror' class. This may often be a good idea if you have a rich domain model that you'd like to represent. You can see an example of that in <a href="/code-that-fits-in-your-head">Code That Fits in Your Head</a>, where there's both a mutable <code>ReservationDto</code> class and an immutable <code>Reservation</code> <a href="https://www.martinfowler.com/bliki/ValueObject.html">Value Object</a>. This makes sense if the invariants of the domain model are sufficiently stronger than the DTO. That hardly seems to be the case here, since both messages only contain an <code>OrderId</code>.
</li>
<li>
Dissolve the DTO into its constituents and pass each as an argument. This doesn't work if the DTO is complex and nested, but here there's only a single constituent element, and that's the <code>OrderId</code> property.
</li>
</ul>
<p>
The third option seems like the simplest solution, so refactor the <code>IShippingState</code> methods to take an <code>orderId</code> parameter instead of a message:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">interface</span> <span style="color:#2b91af;">IShippingState</span>
{
ShippingStateResult OrderPlaced(<span style="color:blue;">string</span> orderId, ShippingPolicy policy);
ShippingStateResult OrderBilled(<span style="color:blue;">string</span> orderId, ShippingPolicy policy);
}</pre>
</p>
<p>
While this is the easiest of the three options given above, the refactoring doesn't hinge on this. It would work just as well with one of the two other options.
</p>
<p>
Implementations now look like this:
</p>
<p>
<pre><span style="color:blue;">public</span> ShippingStateResult OrderBilled(<span style="color:blue;">string</span> orderId, ShippingPolicy policy)
{
policy.State = CompletedShippingState.Instance;
<span style="color:blue;">return</span> <span style="color:blue;">new</span> ShippingStateResult(
<span style="color:blue;">new</span>[] { <span style="color:blue;">new</span> ShipOrder() { OrderId = orderId } },
<span style="color:blue;">true</span>);
}</pre>
</p>
<p>
The only impure action still lingering is the mutation of <code>policy.State</code>. Once we're rid of that, the API consists of pure functions.
</p>
<h3 id="1034a4283bb44e639805778d5ae4504a">
Return state <a href="#1034a4283bb44e639805778d5ae4504a" title="permalink">#</a>
</h3>
<p>
As outlined by the <a href="/2022/09/05/the-state-pattern-and-the-state-monad">parent article</a>, instead of mutating the caller's state, you can return the state as part of a tuple. This means that you no longer need to pass <code>ShippingPolicy </code> as a parameter:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">interface</span> <span style="color:#2b91af;">IShippingState</span>
{
Tuple<ShippingStateResult, IShippingState> OrderPlaced(<span style="color:blue;">string</span> orderId);
Tuple<ShippingStateResult, IShippingState> OrderBilled(<span style="color:blue;">string</span> orderId);
}</pre>
</p>
<p>
Why not expand the <code>ShippingStateResult</code> class, or conversely, dissolve that class and instead return a triple (a three-tuple)? All of these are possible as alternatives, as they'd be isomorphic to this particular design. The reason I've chosen this particular return type is that it's the idiomatic implementation of the State monad: The result is the first element of a tuple, and the state is the second element. This means that you can use a standard, reusable State monad library to manipulate the values, as you'll see later.
</p>
<p>
An implementation now looks like this:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">sealed</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">AwaitingBillingState</span> : IShippingState
{
<span style="color:blue;">public</span> <span style="color:blue;">readonly</span> <span style="color:blue;">static</span> IShippingState Instance = <span style="color:blue;">new</span> AwaitingBillingState();
<span style="color:blue;">private</span> <span style="color:#2b91af;">AwaitingBillingState</span>()
{
}
<span style="color:blue;">public</span> Tuple<ShippingStateResult, IShippingState> OrderPlaced(<span style="color:blue;">string</span> orderId)
{
<span style="color:blue;">return</span> Tuple.Create(
<span style="color:blue;">new</span> ShippingStateResult(Array.Empty<ICommand>(), <span style="color:blue;">false</span>),
(IShippingState)<span style="color:blue;">this</span>);
}
<span style="color:blue;">public</span> Tuple<ShippingStateResult, IShippingState> OrderBilled(<span style="color:blue;">string</span> orderId)
{
<span style="color:blue;">return</span> Tuple.Create(
<span style="color:blue;">new</span> ShippingStateResult(
<span style="color:blue;">new</span>[] { <span style="color:blue;">new</span> ShipOrder() { OrderId = orderId } },
<span style="color:blue;">true</span>),
CompletedShippingState.Instance);
}
}</pre>
</p>
<p>
Since the <code>ShippingPolicy</code> class that calls these methods now directly receives the state as part of the output, it no longer needs a mutable <code>State</code> property. Instead, it immediately handles the return value:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">async</span> Task Handle(OrderPlaced message, IMessageHandlerContext context)
{
log.Info(<span style="color:#a31515;">$"OrderPlaced message received."</span>);
<span style="color:blue;">var</span> state = Hydrate();
<span style="color:blue;">var</span> result = state.OrderPlaced(message.OrderId);
<span style="color:blue;">await</span> Interpret(result.Item1, context);
Dehydrate(result.Item2);
}
<span style="color:blue;">public</span> <span style="color:blue;">async</span> Task Handle(OrderBilled message, IMessageHandlerContext context)
{
log.Info(<span style="color:#a31515;">$"OrderBilled message received."</span>);
<span style="color:blue;">var</span> state = Hydrate();
<span style="color:blue;">var</span> result = state.OrderBilled(message.OrderId);
<span style="color:blue;">await</span> Interpret(result.Item1, context);
Dehydrate(result.Item2);
}</pre>
</p>
<p>
Each <code>Handle</code> method is now an <a href="/2020/03/02/impureim-sandwich">impureim sandwich</a>.
</p>
<p>
Since the <code>result</code> is now a tuple, the <code>Handle</code> methods now have to pass the first element (<code>result.Item1</code>) to the <code>Interpret</code> helper method, and the second element (<code>result.Item2</code>) - the state - to <code>Dehydrate</code>. It's also possible to pattern match (or <em>destructure</em>) each of the elements directly; you'll see an example of that later.
</p>
<p>
Since the mutable <code>State</code> property is now gone, the <code>Hydrate</code> method returns the hydrated state:
</p>
<p>
<pre><span style="color:blue;">private</span> IShippingState Hydrate()
{
<span style="color:blue;">if</span> (!Data.IsOrderPlaced && !Data.IsOrderBilled)
<span style="color:blue;">return</span> InitialShippingState.Instance;
<span style="color:blue;">else</span> <span style="color:blue;">if</span> (Data.IsOrderPlaced && !Data.IsOrderBilled)
<span style="color:blue;">return</span> AwaitingBillingState.Instance;
<span style="color:blue;">else</span> <span style="color:blue;">if</span> (!Data.IsOrderPlaced && Data.IsOrderBilled)
<span style="color:blue;">return</span> AwaitingPlacementState.Instance;
<span style="color:blue;">else</span>
<span style="color:blue;">return</span> CompletedShippingState.Instance;
}</pre>
</p>
<p>
Likewise, the <code>Dehydrate</code> method takes the new state as an input parameter:
</p>
<p>
<pre><span style="color:blue;">private</span> <span style="color:blue;">void</span> Dehydrate(IShippingState state)
{
<span style="color:blue;">if</span> (state <span style="color:blue;">is</span> AwaitingBillingState)
{
Data.IsOrderPlaced = <span style="color:blue;">true</span>;
Data.IsOrderBilled = <span style="color:blue;">false</span>;
<span style="color:blue;">return</span>;
}
<span style="color:blue;">if</span> (state <span style="color:blue;">is</span> AwaitingPlacementState)
{
Data.IsOrderPlaced = <span style="color:blue;">false</span>;
Data.IsOrderBilled = <span style="color:blue;">true</span>;
<span style="color:blue;">return</span>;
}
<span style="color:blue;">if</span> (state <span style="color:blue;">is</span> CompletedShippingState)
{
Data.IsOrderPlaced = <span style="color:blue;">true</span>;
Data.IsOrderBilled = <span style="color:blue;">true</span>;
<span style="color:blue;">return</span>;
}
Data.IsOrderPlaced = <span style="color:blue;">false</span>;
Data.IsOrderBilled = <span style="color:blue;">false</span>;
}</pre>
</p>
<p>
Since each <code>Handle</code> method only calls a single State-valued method, they don't need the State monad machinery. This only becomes useful when you need to compose multiple State-based operations.
</p>
<p>
This might be useful in unit tests, so let's examine that next.
</p>
<h3 id="8559bfcefc6e49459fa16fce5977cc58">
State monad <a href="#8559bfcefc6e49459fa16fce5977cc58" title="permalink">#</a>
</h3>
<p>
In <a href="/2022/06/20/the-state-monad">previous articles about the State monad</a> you've seen it implemented based on an <code>IState</code> interface. I've also dropped hints here and there that you don't <em>need</em> the interface. Instead, you can implement the monad functions directly on State-valued functions. That's what I'm going to do here:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> Func<S, Tuple<T1, S>> SelectMany<<span style="color:#2b91af;">S</span>, <span style="color:#2b91af;">T</span>, <span style="color:#2b91af;">T1</span>>(
<span style="color:blue;">this</span> Func<S, Tuple<T, S>> source,
Func<T, Func<S, Tuple<T1, S>>> selector)
{
<span style="color:blue;">return</span> s =>
{
<span style="color:blue;">var</span> tuple = source(s);
<span style="color:blue;">var</span> f = selector(tuple.Item1);
<span style="color:blue;">return</span> f(tuple.Item2);
};
}</pre>
</p>
<p>
This <code>SelectMany</code> implementation works directly on another function, <code>source</code>. This function takes a state of type <code>S</code> as input and returns a tuple as a result. The first element is the result of type <code>T</code>, and the second element is the new state, still of type <code>S</code>. Compare that to <a href="/2021/07/19/the-state-functor">the IState interface</a> to convince yourself that these are just two representations of the same idea.
</p>
<p>
The return value is a new function with the same shape, but where the result type is <code>T1</code> rather than <code>T</code>.
</p>
<p>
You can implement the special <code>SelectMany</code> overload that enables query syntax in <a href="/2022/03/28/monads">the standard way</a>.
</p>
<p>
The <em>return</em> function also mirrors the previous interface-based implementation:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> Func<S, Tuple<T, S>> Return<<span style="color:#2b91af;">S</span>, <span style="color:#2b91af;">T</span>>(T x)
{
<span style="color:blue;">return</span> s => Tuple.Create(x, s);
}</pre>
</p>
<p>
You can also implement <a href="/2022/07/04/get-and-put-state">the standard Get, Put, and Modify functions</a>, but we are not going to need them here. Try it as an exercise.
</p>
<h3 id="4fe0da2976e34c8eaf8490186f7d022a">
State-valued event handlers <a href="#4fe0da2976e34c8eaf8490186f7d022a" title="permalink">#</a>
</h3>
<p>
The <code>IShippingState</code> methods almost look like State values, but the arguments are in the wrong order. A State value is a function that takes state as input and returns a tuple. The methods on <code>IShippingState</code>, however, take <code>orderId</code> as input and return a tuple. The state is also present, but as the instance that exposes the methods. We have to flip the arguments:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">static</span> Func<IShippingState, Tuple<ShippingStateResult, IShippingState>> Billed(
<span style="color:blue;">this</span> <span style="color:blue;">string</span> orderId)
{
<span style="color:blue;">return</span> s => s.OrderBilled(orderId);
}
<span style="color:blue;">public</span> <span style="color:blue;">static</span> Func<IShippingState, Tuple<ShippingStateResult, IShippingState>> Placed(
<span style="color:blue;">this</span> <span style="color:blue;">string</span> orderId)
{
<span style="color:blue;">return</span> s => s.OrderPlaced(orderId);
}</pre>
</p>
<p>
This is a typical example of how you have to turn things on their heads in functional programming, compared to object-oriented programming. These two methods convert <code>OrderBilled</code> and <code>OrderPlaced</code> to State monad values.
</p>
<h3 id="2aa26c7863bc47f6a37ad50f54d97d24">
Testing state results <a href="#2aa26c7863bc47f6a37ad50f54d97d24" title="permalink">#</a>
</h3>
<p>
A unit test demonstrates how this enables you to compose multiple stateful operations using query syntax:
</p>
<p>
<pre>[Theory]
[InlineData(<span style="color:#a31515;">"90125"</span>)]
[InlineData(<span style="color:#a31515;">"quux"</span>)]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> StateResultExample(<span style="color:blue;">string</span> orderId)
{
<span style="color:blue;">var</span> sf = <span style="color:blue;">from</span> x <span style="color:blue;">in</span> orderId.Placed()
<span style="color:blue;">from</span> y <span style="color:blue;">in</span> orderId.Billed()
<span style="color:blue;">select</span> <span style="color:blue;">new</span>[] { x, y };
var (results, finalState) = sf(InitialShippingState.Instance);
Assert.Equal(
<span style="color:blue;">new</span>[] { <span style="color:blue;">false</span>, <span style="color:blue;">true</span> },
results.Select(r => r.CompleteSaga));
Assert.Single(
results
.SelectMany(r => r.Commands)
.OfType<ShipOrder>()
.Select(msg => msg.OrderId),
orderId);
Assert.Equal(CompletedShippingState.Instance, finalState);
}</pre>
</p>
<p>
Keep in mind that a State monad value is a function. That's the reason I called the composition <code>sf</code> - for <em>State Function</em>. When you execute it with <code>InitialShippingState</code> as input it returns a tuple that the test immediately pattern matches (destructures) into its constituent elements.
</p>
<p>
The test then asserts that the <code>results</code> and <code>finalState</code> are as expected. The assertions against <code>results</code> are a bit awkward, since C# collections don't have structural equality. These assertions would have been simpler in <a href="https://fsharp.org/">F#</a> or <a href="https://www.haskell.org/">Haskell</a>.
</p>
<h3 id="c899bd7d1b8f4bcea29a5ad946b0f3b8">
Testing with an interpreter <a href="#c899bd7d1b8f4bcea29a5ad946b0f3b8" title="permalink">#</a>
</h3>
<p>
While <a href="/2013/06/24/a-heuristic-for-formatting-code-according-to-the-aaa-pattern">the Arrange and Act phases of the above test</a> are simple, the Assertion phase seems awkward. Another testing strategy is to run a test-specific interpreter over the instructions returned as the State computation result:
</p>
<p>
<pre>[Theory]
[InlineData(<span style="color:#a31515;">"1984"</span>)]
[InlineData(<span style="color:#a31515;">"quuz"</span>)]
<span style="color:blue;">public</span> <span style="color:blue;">void</span> StateInterpretationExample(<span style="color:blue;">string</span> orderId)
{
<span style="color:blue;">var</span> sf = <span style="color:blue;">from</span> x <span style="color:blue;">in</span> orderId.Placed()
<span style="color:blue;">from</span> y <span style="color:blue;">in</span> orderId.Billed()
<span style="color:blue;">select</span> <span style="color:blue;">new</span>[] { x, y };
var (results, finalState) = sf(InitialShippingState.Instance);
Assert.Equal(CompletedShippingState.Instance, finalState);
<span style="color:blue;">var</span> result = Interpret(results);
Assert.True(result.CompleteSaga);
Assert.Single(
result.Commands.OfType<ShipOrder>().Select(msg => msg.OrderId),
orderId);
}</pre>
</p>
<p>
It helps a little, but the assertions still have to work around the lack of structural equality of <code>result.Commands</code>.
</p>
<h3 id="80405400d4ed4cfd9c89bf539df21b3b">
Monoid <a href="#80405400d4ed4cfd9c89bf539df21b3b" title="permalink">#</a>
</h3>
<p>
The test-specific <code>Interpret</code> helper method is interesting in its own right, though:
</p>
<p>
<pre><span style="color:blue;">private</span> ShippingStateResult Interpret(IEnumerable<ShippingStateResult> results)
{
<span style="color:blue;">var</span> identity = <span style="color:blue;">new</span> ShippingStateResult(Array.Empty<ICommand>(), <span style="color:blue;">false</span>);
ShippingStateResult Combine(ShippingStateResult x, ShippingStateResult y)
{
<span style="color:blue;">return</span> <span style="color:blue;">new</span> ShippingStateResult(
x.Commands.Concat(y.Commands).ToArray(),
x.CompleteSaga || y.CompleteSaga);
}
<span style="color:blue;">return</span> results.Aggregate(identity, Combine);
}</pre>
</p>
<p>
It wasn't until I started implementing this helper method that I realised that <code>ShippingStateResult</code> gives rise to a <a href="/2017/10/06/monoids">monoid</a>! Since <a href="/2017/11/20/monoids-accumulate">monoids accumulate</a>, you can start with the <code>identity</code> and use the binary operation (here called <code>Combine</code>) to <code>Aggregate</code> an arbitrary number of <code>ShippingStateResult</code> values into one.
</p>
<p>
The <code>ShippingStateResult</code> class is composed of two constituent values (a collection and a Boolean value), and since both of these give rise to one or more monoids, a <a href="/2017/10/30/tuple-monoids">tuple of those monoids itself gives rise to one or more monoids</a>. The <code>ShippingStateResult</code> is isomorphic to a tuple, so this result carries over.
</p>
<p>
Should you move the <code>Combine</code> method and the <code>identity</code> value to the <code>ShippingStateResult</code> class itself. After all, putting them in a test-specific helper method smells a bit of <a href="https://wiki.c2.com/?FeatureEnvySmell">Feature Envy</a>.
</p>
<p>
This seems compelling, but it's not clear that arbitrary client code might need this particular monoid. After all, there are four monoids over Boolean values, and at least two over collections. That's eight possible combinations. Which one should <code>ShippingStateResult</code> expose as members?
</p>
<p>
The monoid used in <code>Interpret</code> combines the normal <a href="/2017/10/10/strings-lists-and-sequences-as-a-monoid">collection monoid</a> with the <em>any</em> monoid. That seems appropriate in this case, but other clients might rather need the <em>all</em> monoid.
</p>
<p>
Without more usage examples, I decided to leave the code as an <code>Interpret</code> implementation detail for now.
</p>
<p>
In any case, I find it worth noting that by decoupling the state logic from the NServiceBus framework, it's possible to test it <a href="/2019/02/11/asynchronous-injection">without running asynchronous workflows</a>.
</p>
<h3 id="a1bc6585723044a9b795aa23099d9d36">
Conclusion <a href="#a1bc6585723044a9b795aa23099d9d36" title="permalink">#</a>
</h3>
<p>
In this article you saw how to implement an asynchronous messaging saga in three different ways. First, as a simple ad-hoc solution, second using the State pattern, and third implemented with the State monad. Both the State pattern and State monad implementations are meant exclusively to showcase these two techniques. The first solution using two Boolean flags is by far the simplest solution, and the one I'd use in a production system.
</p>
<p>
The point is that you can use the State monad if you need to write stateful computations. This may include finite state machines, as otherwise addressed by the State design pattern, but could also include other algorithms where you need to keep track of state.
</p>
<p>
<strong>Next:</strong> <a href="/2021/11/29/postels-law-as-a-profunctor">Postel's law as a profunctor</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>.Some thoughts on the economics of programminghttps://blog.ploeh.dk/2022/10/03/some-thoughts-on-the-economics-of-programming2022-10-03T05:53:00+00:00Mark Seemann
<div id="post">
<p>
<em>On the net value of process and code quality.</em>
</p>
<p>
Once upon a time there was a software company that had a special way of doing things. No other company had ever done things quite like that before, but the company had much success. In short time it rose to dominance in the market, outcompeting all serious competition. Some people disliked the company because of its business tactics and sheer size, but others admired it.
</p>
<p>
Even more wanted to be like it.
</p>
<p>
How did the company achieve its indisputable success? It looked as though it was really, really good at making software. How did they write such good software?
</p>
<p>
It turned out that the company had a special software development process.
</p>
<p>
Other software organisations, hoping to be able to be as successful, tried to copy the special process. The company was willing to share. Its employees wrote about the process. They gave conference presentations on their special sauce.
</p>
<p>
Which company do I have in mind, and what was the trick that made it so much better than its competition? Was it <a href="https://en.wikipedia.org/wiki/Microservices">microservices</a>? <a href="https://en.wikipedia.org/wiki/Monorepo">Monorepos</a>? <a href="https://en.wikipedia.org/wiki/Kubernetes">Kubernetes</a>? <a href="https://en.wikipedia.org/wiki/DevOps">DevOps</a>? <a href="https://en.wikipedia.org/wiki/Serverless_computing">Serverless</a>?
</p>
<p>
No, the company was <a href="https://microsoft.com">Microsoft</a> and the development process was called <a href="https://en.wikipedia.org/wiki/Microsoft_Solutions_Framework">Microsoft Solutions Framework</a> (MSF).
</p>
<p>
<em>What?!</em> do you say.
</p>
<p>
You've never heard of MSF?
</p>
<p>
That's hardly surprising. I doubt that MSF was in any way related to Microsoft's success.
</p>
<h3 id="9333d3993dbb4125a7d40faf5221ea02">
Net profits <a href="#9333d3993dbb4125a7d40faf5221ea02" title="permalink">#</a>
</h3>
<p>
These days, many people in technology consider Microsoft an embarrassing dinosaur. While you know that it's still around, does it really <em>matter</em>, these days?
</p>
<p>
You can't deny, however, that Microsoft made a lot of money in the Nineties. They still do.
</p>
<p>
What's the key to making a lot of money? Have a revenue larger than your costs.
</p>
<p>
I'm too lazy to look up the actual numbers, but clearly Microsoft had (and still has) a revenue vastly larger than its costs:
</p>
<p>
<img src="/content/binary/great-net-value-chart.png" alt="Revenue and cost line chart. The revenue is visibly and significantly greater than the cost over the entire time line.">
</p>
<p>
Compared to real, historic numbers, this may be exaggerated, but I'm trying to make a general point - not one that hinges on actual profit numbers of Microsoft, <a href="https://apple.com">Apple</a>, <a href="https://amzn.to/3QLHkly">Amazon</a>, <a href="http://google.com">Google</a>, or any other tremendously profitable company. I'm also aware that real companies have costs that aren't directly related to software development: Marketing, operations, buildings, sales, etcetera. They also make money in other ways than from their software, mainly from investments of the profits.
</p>
<p>
The difference between the revenue and the cost is the profit or net value.
</p>
<p>
If the graph looks like the above, is <em>managing cost</em> the main cause of success? Hardly. The cost is almost a rounding error on the profits.
</p>
<p>
If so, is the technology or process key to such a company's success? Was it MSF that made Microsoft the wealthiest company in the world? Are two-pizza teams the only explanation of Amazon's success? Is Google the dominant search engine because the source code is organised in a monorepo?
</p>
<p>
I'd be surprised were that the case. Rather, I think that these companies were at the right place at the right time. While there were search engines before Google, Google was so much better that users quickly migrated. Google was also better at making money than earlier search engines like <a href="https://en.wikipedia.org/wiki/AltaVista">AltaVista</a> or <a href="https://en.wikipedia.org/wiki/Yahoo!">Yahoo!</a> Likewise, Microsoft made more successful PC operating systems than the competition (which in the early Windows era consisted exclusively of <a href="https://en.wikipedia.org/wiki/OS/2">OS/2</a>) and better professional software (word processor, spreadsheet, etcetera). Amazon made a large-scale international web shop before anyone else. Apple made affordable computers with graphical user interfaces before other companies. Later, they introduced a smartphone at the right time.
</p>
<p>
All of this is simplified. For example, it's not really true that Apple made the first smartphone. When the iPhone was introduced, I already carried a <a href="https://en.wikipedia.org/wiki/Pocket_PC">Pocket PC Phone Edition</a> device that could browse the internet, had email, phone, SMS, and so on. There were other precursors even earlier.
</p>
<p>
I'm not trying to explain away <em>excellence of execution</em>. These companies succeeded for a variety of reasons, including that they were good at what they were doing. Lots of companies, however, are good at what they are doing, and still they fail. Being at the right place at the right time matters. Once in a while, a company finds itself in such favourable circumstances that success is served on a silver platter. While good execution is important, it doesn't explain the magnitude of the success.
</p>
<p>
Bad execution is likely to eliminate you in the long run, but it doesn't follow logically that good execution guarantees success.
</p>
<p>
Perhaps the successful companies succeeded because of circumstances, and <em>despite</em> mediocre execution. As usual, you should be wary not to mistake correlation for causation.
</p>
<h3 id="d1ab697df716465ab7eb8c841d3a1615">
Legacy code <a href="#d1ab697df716465ab7eb8c841d3a1615" title="permalink">#</a>
</h3>
<p>
You should be sceptical of adopting processes or technology just because a <a href="https://en.wikipedia.org/wiki/Big_Tech">Big Tech</a> company uses it. Still, if that was all I had in mind, I could probably had said that shorter. I have another point to make.
</p>
<p>
I often encounter resistance to ideas about better software development on the grounds that the status quo is good enough. Put bluntly,
</p>
<blockquote>
<p>""legacy," [...] is condescending-engineer-speak for "actually makes money.""</p>
<footer><cite><a href="https://www.lastweekinaws.com/blog/right-sizing-your-instances-is-nonsense">Corey Quinn</a></cite></footer>
</blockquote>
<p>
To be clear, I have nothing against the author or the cited article, which discusses something (right-sizing VMs) that I know nothing about. The phrase, or variations thereof, however, is such a fit <a href="https://en.wikipedia.org/wiki/Meme">meme</a> that it spreads. It strongly indicates that people who discuss code quality are wankers, while 'real programmers' produce code that makes money. I consider that a <a href="https://en.wikipedia.org/wiki/False_dilemma">false dichotomy</a>.
</p>
<p>
Most software organisations aren't in the fortunate situation that revenues are orders of magnitude greater than costs. Most software organisations can make a decent profit if they find a market and execute on a good idea. Perhaps the revenue starts at 'only' double the cost.
</p>
<p>
<img src="/content/binary/decreasing-profit-margin-from-increased-cost.png" alt="Revenue and cost line chart. The revenue starts at about double that of the cost. The cost line, however, grows by a steeper rater and eventually overtakes the revenue.">
</p>
<p>
If you can consistently make the double of your costs, you'll be in business for a long time. As the above line chart indicates, however, is that if the costs rise faster than the revenue, you'll eventually hit a point when you start losing money.
</p>
<p>
The Big Tech companies aren't likely to run into that situation because their profit margins are so great, but normal companies are very much at risk.
</p>
<p>
The area between the revenue and the cost represents the profit. Thus, looking back, it may be true that a software system has been making money. This doesn't mean, however, that it will keep making money.
</p>
<p>
In the above chart, the cost eventually exceeds the revenue. If this cost is mainly driven by rising software development costs, then the company is in deep trouble.
</p>
<p>
I've worked with such a company. When I started with it, it was a thriving company with many employees, most of them developers or IT professionals. In the previous decade, it had turned a nice profit every year.
</p>
<p>
This all started to change around the time that I arrived. (I will, again, remind the reader that correlation does not imply causation.) One reason I was engaged was that the developers were stuck. Due to external market pressures they had to deliver a tremendous amount of new features, and they were stuck in <a href="https://en.wikipedia.org/wiki/Analysis_paralysis">analysis paralysis</a>.
</p>
<p>
I helped them get unstuck, but as we started working on the new features, we discovered the size of the mess of the legacy code base.
</p>
<p>
I recall a conversation I later had with the CEO. He told me, after having discussed the situation with several key people: <em>"I knew that we had a legacy code base... but I didn't know it was </em>this<em> bad!"</em>
</p>
<p>
Revenue remained constant, but costs kept rising. Today, the company is no longer around.
</p>
<p>
This was a 100% digital service company. All revenue was ultimately based on software. The business idea was good, but the company couldn't keep up with competitors. As far as I can tell, it was undone by its legacy code base.
</p>
<h3 id="33ded378d771431fa00f37c8b3e85bfc">
Conclusion <a href="#33ded378d771431fa00f37c8b3e85bfc" title="permalink">#</a>
</h3>
<p>
Software should provide some kind of value. Usually profits, but sometimes savings, and occasionally wider concerns are in scope. It's reasonable and professional to consider value as you produce software. You should, however, be aware of a too myopic focus on immediate and past value.
</p>
<p>
Finding safety in past value is indulging in complacency. Legacy software can make money from day one, but that doesn't mean that it'll keep making money. The main problem with legacy code is that costs keep rising. When non-technical business stakeholders start to notice this, it may be too late.
</p>
<p>
The is one of many reasons I believe that we, software developers, have a <em>responsibility</em> to combat the mess. I don't think there's anything condescending about that attitude.
</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>.Refactoring the TCP State pattern example to pure functionshttps://blog.ploeh.dk/2022/09/26/refactoring-the-tcp-state-pattern-example-to-pure-functions2022-09-26T05:50:00+00:00Mark Seemann
<div id="post">
<p>
<em>A C# example.</em>
</p>
<p>
This article is one of the examples that I promised in the earlier article <a href="/2022/09/05/the-state-pattern-and-the-state-monad">The State pattern and the State monad</a>. That article examines the relationship between the <a href="https://en.wikipedia.org/wiki/State_pattern">State design pattern</a> and the <a href="/2022/06/20/the-state-monad">State monad</a>. That article is deliberately abstract, so one or more examples are in order.
</p>
<p>
In this article, I show you how to start with the example from <a href="/ref/dp">Design Patterns</a> and refactor it to an immutable solution using <a href="https://en.wikipedia.org/wiki/Pure_function">pure functions</a>.
</p>
<p>
The code shown here is <a href="https://github.com/ploeh/TCPStateCSharp">available on GitHub</a>.
</p>
<h3 id="f70ca28a361241e5a352399f8cf912d7">
TCP connection <a href="#f70ca28a361241e5a352399f8cf912d7" title="permalink">#</a>
</h3>
<p>
The example is a class that handles <a href="https://en.wikipedia.org/wiki/Transmission_Control_Protocol">TCP</a> connections. The book's example is in C++, while I'll show my C# interpretation.
</p>
<p>
A TCP connection can be in one of several states, so the <code>TcpConnection</code> class keeps an instance of the polymorphic <code>TcpState</code>, which implements the state and transitions between them.
</p>
<p>
<code>TcpConnection</code> plays the role of the State pattern's <code>Context</code>, and <code>TcpState</code> of the <code>State</code>.
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">TcpConnection</span>
{
<span style="color:blue;">public</span> TcpState State { <span style="color:blue;">get</span>; <span style="color:blue;">internal</span> <span style="color:blue;">set</span>; }
<span style="color:blue;">public</span> <span style="color:#2b91af;">TcpConnection</span>()
{
State = TcpClosed.Instance;
}
<span style="color:blue;">public</span> <span style="color:blue;">void</span> ActiveOpen()
{
State.ActiveOpen(<span style="color:blue;">this</span>);
}
<span style="color:blue;">public</span> <span style="color:blue;">void</span> PassiveOpen()
{
State.PassiveOpen(<span style="color:blue;">this</span>);
}
<span style="color:green;">// More members that delegate to State follows...</span></pre>
</p>
<p>
The <code>TcpConnection</code> class' methods delegate to a corresponding method on <code>TcpState</code>, passing itself an argument. This gives the <code>TcpState</code> implementation an opportunity to change the <code>TcpConnection</code>'s <code>State</code> property, which has an <code>internal</code> setter.
</p>
<h3 id="ffea200499f94145a0686e2481aebf2c">
State <a href="#ffea200499f94145a0686e2481aebf2c" title="permalink">#</a>
</h3>
<p>
This is the <code>TcpState</code> class:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">TcpState</span>
{
<span style="color:blue;">public</span> <span style="color:blue;">virtual</span> <span style="color:blue;">void</span> Transmit(TcpConnection connection, TcpOctetStream stream)
{
}
<span style="color:blue;">public</span> <span style="color:blue;">virtual</span> <span style="color:blue;">void</span> ActiveOpen(TcpConnection connection)
{
}
<span style="color:blue;">public</span> <span style="color:blue;">virtual</span> <span style="color:blue;">void</span> PassiveOpen(TcpConnection connection)
{
}
<span style="color:blue;">public</span> <span style="color:blue;">virtual</span> <span style="color:blue;">void</span> Close(TcpConnection connection)
{
}
<span style="color:blue;">public</span> <span style="color:blue;">virtual</span> <span style="color:blue;">void</span> Synchronize(TcpConnection connection)
{
}
<span style="color:blue;">public</span> <span style="color:blue;">virtual</span> <span style="color:blue;">void</span> Acknowledge(TcpConnection connection)
{
}
<span style="color:blue;">public</span> <span style="color:blue;">virtual</span> <span style="color:blue;">void</span> Send(TcpConnection connection)
{
}
}</pre>
</p>
<p>
I don't consider this entirely <a href="/2015/08/03/idiomatic-or-idiosyncratic">idiomatic</a> C# code, but it seems closer to the book's C++ example. (It's been a couple of decades since I wrote C++, so I could be mistaken.) It doesn't matter in practice, but instead of a concrete class with <a href="https://en.wikipedia.org/wiki/NOP_(code)">no-op</a> <code>virtual</code> methods, I would usually define an interface. I'll do that in the next example article.
</p>
<p>
The methods have the same names as the methods on <code>TcpConnection</code>, but the signatures are different. All the <code>TcpState</code> methods take a <code>TcpConnection</code> parameter, whereas the <code>TcpConnection</code> methods take no arguments.
</p>
<p>
While the <code>TcpState</code> methods don't do anything, various classes can inherit from the class and override some or all of them.
</p>
<h3 id="d68a32e30a314c9ea7f45004482a7d98">
Connection closed <a href="#d68a32e30a314c9ea7f45004482a7d98" title="permalink">#</a>
</h3>
<p>
The book shows implementations of three classes that inherit from <code>TcpState</code>, starting with <code>TcpClosed</code>. Here's my translation to C#:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">TcpClosed</span> : TcpState
{
<span style="color:blue;">public</span> <span style="color:blue;">static</span> TcpState Instance = <span style="color:blue;">new</span> TcpClosed();
<span style="color:blue;">private</span> <span style="color:#2b91af;">TcpClosed</span>()
{
}
<span style="color:blue;">public</span> <span style="color:blue;">override</span> <span style="color:blue;">void</span> ActiveOpen(TcpConnection connection)
{
<span style="color:green;">// Send SYN, receive SYN, Ack, etc.</span>
connection.State = TcpEstablished.Instance;
}
<span style="color:blue;">public</span> <span style="color:blue;">override</span> <span style="color:blue;">void</span> PassiveOpen(TcpConnection connection)
{
connection.State = TcpListen.Instance;
}
}</pre>
</p>
<p>
This implementation overrides <code>ActiveOpen</code> and <code>PassiveOpen</code>. In both cases, after performing some work, they change <code>connection.State</code>.
</p>
<blockquote>
<p>
"<code>TCPState</code> subclasses maintain no local state, so they can be shared, and only one instance of each is required. The unique instance of <code>TCPState</code> subclass is obtained by the static <code>Instance</code> operation. [...]
</p>
<p>
"This make each <code>TCPState</code> subclass a Singleton [...]."
</p>
<footer><cite><a href="/ref/dp">Design Patterns</a></cite></footer>
</blockquote>
<p>
I've maintained that property of each subclass in my C# code, even though it has no impact on the structure of the State pattern.
</p>
<h3 id="8e21a702cffe4ef09455a29c2981ab39">
The other subclasses <a href="#8e21a702cffe4ef09455a29c2981ab39" title="permalink">#</a>
</h3>
<p>
The next subclass, <code>TcpEstablished</code>, is cast in the same mould:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">TcpEstablished</span> : TcpState
{
<span style="color:blue;">public</span> <span style="color:blue;">static</span> TcpState Instance = <span style="color:blue;">new</span> TcpEstablished();
<span style="color:blue;">private</span> <span style="color:#2b91af;">TcpEstablished</span>()
{
}
<span style="color:blue;">public</span> <span style="color:blue;">override</span> <span style="color:blue;">void</span> Close(TcpConnection connection)
{
<span style="color:green;">// send FIN, receive ACK of FIN</span>
connection.State = TcpListen.Instance;
}
<span style="color:blue;">public</span> <span style="color:blue;">override</span> <span style="color:blue;">void</span> Transmit(
TcpConnection connection,
TcpOctetStream stream)
{
connection.ProcessOctet(stream);
}
}</pre>
</p>
<p>
As is <code>TcpListen</code>:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">TcpListen</span> : TcpState
{
<span style="color:blue;">public</span> <span style="color:blue;">static</span> TcpState Instance = <span style="color:blue;">new</span> TcpListen();
<span style="color:blue;">private</span> <span style="color:#2b91af;">TcpListen</span>()
{
}
<span style="color:blue;">public</span> <span style="color:blue;">override</span> <span style="color:blue;">void</span> Send(TcpConnection connection)
{
<span style="color:green;">// Send SYN, receive SYN, ACK, etc.</span>
connection.State = TcpEstablished.Instance;
}
}</pre>
</p>
<p>
I admit that I find these examples a bit anaemic, since there's really no logic going on. None of the overrides change state <em>conditionally</em>, which would be possible and make the examples a little more interesting. If you're interested in an example where this happens, see my article <a href="/2021/05/24/tennis-kata-using-the-state-pattern">Tennis kata using the State pattern</a>.
</p>
<h3 id="68a957ca3dcd40e9986b078223f0763e">
Refactor to pure functions <a href="#68a957ca3dcd40e9986b078223f0763e" title="permalink">#</a>
</h3>
<p>
There's only one obvious source of impurity in the example: The literal <code>State</code> mutation of <code>TcpConnection</code>:
</p>
<p>
<pre><span style="color:blue;">public</span> TcpState State { <span style="color:blue;">get</span>; <span style="color:blue;">internal</span> <span style="color:blue;">set</span>; }</pre>
</p>
<p>
While client code can't <code>set</code> the <code>State</code> property, subclasses can, and they do. After all, it's how the State pattern works.
</p>
<p>
It's quite a stretch to claim that if we can only get rid of that property setter then all else will be pure. After all, who knows what all those comments actually imply:
</p>
<p>
<pre><span style="color:green;">// Send SYN, receive SYN, ACK, etc.</span></pre>
</p>
<p>
To be honest, we must imagine that <a href="https://en.wikipedia.org/wiki/Input/output">I/O</a> takes place here. This means that even though it's possible to refactor away from mutating the <code>State</code> property, these implementations are not really going to be pure functions.
</p>
<p>
I could try to imagine what that <code>SYN</code> and <code>ACK</code> would look like, but it would be unfounded and hypothetical. I'm not going to do that here. Instead, that's the reason I'm going to publish a second article with a more realistic and complex example. When it comes to the present example, I'm going to proceed with the unreasonable assumption that the comments hide no nondeterministic behaviour or side effects.
</p>
<p>
As outlined in the <a href="/2022/09/05/the-state-pattern-and-the-state-monad">article that compares the State pattern and the State monad</a>, you can refactor state mutation to a pure function by instead returning the new state. Usually, you'd have to return a tuple, because you'd also need to return the 'original' return value. Here, however, the 'return type' of all methods is <code>void</code>, so this isn't necessary.
</p>
<p>
<code>void</code> is <a href="/2018/01/15/unit-isomorphisms">isomorphic to unit</a>, so strictly speaking you could refactor to a return type like <code>Tuple<Unit, TcpConnection></code>, but that is isomorphic to <code>TcpConnection</code>. (If you need to understand why that is, try writing two functions: One that converts a <code>Tuple<Unit, TcpConnection></code> to a <code>TcpConnection</code>, and another that converts a <code>TcpConnection</code> to a <code>Tuple<Unit, TcpConnection></code>.)
</p>
<p>
There's no reason to make things more complicated than they have to be, so I'm going to use the simplest representation: <code>TcpConnection</code>. Thus, you can get rid of the <code>State</code> mutation by instead returning a new <code>TcpConnection</code> from all methods:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">TcpConnection</span>
{
<span style="color:blue;">public</span> TcpState State { <span style="color:blue;">get</span>; }
<span style="color:blue;">public</span> <span style="color:#2b91af;">TcpConnection</span>()
{
State = TcpClosed.Instance;
}
<span style="color:blue;">private</span> <span style="color:#2b91af;">TcpConnection</span>(TcpState state)
{
State = state;
}
<span style="color:blue;">public</span> TcpConnection ActiveOpen()
{
<span style="color:blue;">return</span> <span style="color:blue;">new</span> TcpConnection(State.ActiveOpen(<span style="color:blue;">this</span>));
}
<span style="color:blue;">public</span> TcpConnection PassiveOpen()
{
<span style="color:blue;">return</span> <span style="color:blue;">new</span> TcpConnection(State.PassiveOpen(<span style="color:blue;">this</span>));
}
<span style="color:green;">// More members that delegate to State follows...</span></pre>
</p>
<p>
The <code>State</code> property no longer has a setter; there's only a public getter. In order to 'change' the state, code must return a new <code>TcpConnection</code> object with the new state. To facilitate that, you'll need to add a constructor overload that takes the new state as an input. Here I made it <code>private</code>, but making it more accessible is not prohibited.
</p>
<p>
This implies, however, that the <code>TcpState</code> methods <em>also</em> return values instead of mutating state. The base class now looks like this:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">TcpState</span>
{
<span style="color:blue;">public</span> <span style="color:blue;">virtual</span> TcpState Transmit(TcpConnection connection, TcpOctetStream stream)
{
<span style="color:blue;">return</span> <span style="color:blue;">this</span>;
}
<span style="color:blue;">public</span> <span style="color:blue;">virtual</span> TcpState ActiveOpen(TcpConnection connection)
{
<span style="color:blue;">return</span> <span style="color:blue;">this</span>;
}
<span style="color:blue;">public</span> <span style="color:blue;">virtual</span> TcpState PassiveOpen(TcpConnection connection)
{
<span style="color:blue;">return</span> <span style="color:blue;">this</span>;
}
<span style="color:green;">// And so on...</span></pre>
</p>
<p>
Again, all the methods previously 'returned' <code>void</code>, so while, according to the State monad, you should strictly speaking return <code>Tuple<Unit, TcpState></code>, this simplifies to <code>TcpState</code>.
</p>
<p>
Individual subclasses now do their work and return other <code>TcpState</code> implementations. I'm not going to tire you with all the example subclasses, so here's just <code>TcpEstablished</code>:
</p>
<p>
<pre><span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">TcpEstablished</span> : TcpState
{
<span style="color:blue;">public</span> <span style="color:blue;">static</span> TcpState Instance = <span style="color:blue;">new</span> TcpEstablished();
<span style="color:blue;">private</span> <span style="color:#2b91af;">TcpEstablished</span>()
{
}
<span style="color:blue;">public</span> <span style="color:blue;">override</span> TcpState Close(TcpConnection connection)
{
<span style="color:green;">// send FIN, receive ACK of FIN</span>
<span style="color:blue;">return</span> TcpListen.Instance;
}
<span style="color:blue;">public</span> <span style="color:blue;">override</span> TcpState Transmit(
TcpConnection connection,
TcpOctetStream stream)
{
TcpConnection newConnection = connection.ProcessOctet(stream);
<span style="color:blue;">return</span> newConnection.State;
}
}</pre>
</p>
<p>
The trickiest implementation is <code>Transmit</code>, since <code>ProcessOctet</code> returns a <code>TcpConnection</code> while the <code>Transmit</code> method has to return a <code>TcpState</code>. Fortunately, the <code>Transmit</code> method can achieve that goal by returning <code>newConnection.State</code>. It feels a bit roundabout, but highlights a point I made in the <a href="/2022/09/05/the-state-pattern-and-the-state-monad">previous article</a>: The <code>TcpConnection</code> and <code>TcpState</code> classes are isomorphic - or, they would be if we made the <code>TcpConnection</code> constructor overload public. Thus, the <code>TcpConnection</code> class is redundant and might be deleted.
</p>
<h3 id="a94a0e101f6b49d3b4caea30060ae1e1">
Conclusion <a href="#a94a0e101f6b49d3b4caea30060ae1e1" title="permalink">#</a>
</h3>
<p>
This article shows how to refactor the <em>TCP connection</em> sample code from <a href="/ref/dp">Design Patterns</a> to pure functions.
</p>
<p>
If it feels as though something's missing there's a good reason for that. The example, as given, is degenerate because all methods 'return' <code>void</code>, and we don't really know what the actual implementation code (all that <em>Send SYN, receive SYN, ACK, etc.</em>) looks like. This means that we actually don't have to make use of the State monad, because we can get away with <a href="https://en.wikipedia.org/wiki/Endomorphism">endomorphisms</a>. All methods on <code>TcpConnection</code> are really functions that take <code>TcpConnection</code> as input (the instance itself) and return <code>TcpConnection</code>. If you want to see a more realistic example showcasing that perspective, see my article <a href="/2021/05/31/from-state-tennis-to-endomorphism">From State tennis to endomorphism</a>.
</p>
<p>
Even though the example is degenerate, I wanted to show it because otherwise you might wonder how the book's example code fares when exposed to the State monad. To be clear, because of the nature of the example, the State monad never becomes necessary. Thus, we need a second example.
</p>
<p>
<strong>Next:</strong> <a href="/2022/10/10/refactoring-a-saga-from-the-state-pattern-to-the-state-monad">Refactoring a saga from the State pattern to the State monad</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>.When to refactorhttps://blog.ploeh.dk/2022/09/19/when-to-refactor2022-09-19T06:36:00+00:00Mark Seemann
<div id="post">
<p>
<em>FAQ: How do I convince my manager to let me refactor?</em>
</p>
<p>
This question frequently comes up. Developers want to refactor, but are under the impression that managers or other stakeholders will not let them.
</p>
<p>
Sometimes people ask me how to convince their managers to get permission to refactor. I can't answer that. <a href="/2021/03/22/the-dispassionate-developer">I don't know how to convince other people</a>. That's not my métier.
</p>
<p>
I also believe that professional programmers <a href="/2019/03/18/the-programmer-as-decision-maker">should make their own decisions</a>. You don't ask permission to add three lines to a file, or create a new class. Why do you feel that you have to ask permission to refactor?
</p>
<h3 id="4af4356cd706457ebf8968e92850b140">
Does refactoring take time? <a href="#4af4356cd706457ebf8968e92850b140" title="permalink">#</a>
</h3>
<p>
In <a href="/code-that-fits-in-your-head">Code That Fits in Your Head</a> I tell the following story:
</p>
<blockquote>
<p>
"I once led an effort to <a href="/ref/ddd">refactor towards deeper insight</a>. My colleague and I had identified that the key to implementing a new feature would require changing a fundamental class in our code base.
</p>
<p>
"While such an insight rarely arrives at an opportune time, we wanted to make the change, and our manager allowed it.
</p>
<p>
"A week later, our code still didn’t compile.
</p>
<p>
"I’d hoped that I could make the change to the class in question and then <a href="/ref/welc">lean on the compiler</a> to identify the call sites that needed modification. The problem was that there was an abundance of compilation errors, and fixing them wasn’t a simple question of search-and-replace.
</p>
<p>
"My manager finally took me aside to let me know that he wasn’t satisfied with the situation. I could only concur.
</p>
<p>
"After a mild dressing down, he allowed me to continue the work, and a few more days of heroic effort saw the work completed.
</p>
<p>
"That’s a failure I don’t intend to repeat."
</p>
<footer><cite><a href="/code-that-fits-in-your-head">Code That Fits in Your Head</a></cite></footer>
</blockquote>
<p>
There's a couple of points to this story. Yes, I <em>did</em> ask for permission before refactoring. I expected the process to take time, and I felt that making such a choice of prioritisation should involve my manager. While this manager trusted me, I felt a moral obligation to be transparent about the work I was doing. I didn't consider it professional to take a week out of the calendar and work on one thing while the rest of the organisation was expecting me to be working on something else.
</p>
<p>
So I can understand why developers feel that they have to ask permission to refactor. After all, refactoring takes time... Doesn't it?
</p>
<h3 id="ddb8e36130fe475da5ea914ccf06ae45">
Small steps <a href="#ddb8e36130fe475da5ea914ccf06ae45" title="permalink">#</a>
</h3>
<p>
This may unearth the underlying assumption that prevents developers from refactoring: The notion that refactoring takes time.
</p>
<p>
As I wrote in <a href="/code-that-fits-in-your-head">Code That Fits in Y