The idea of an error about the mishandling of an error is novel. It's also an obvious consequence of using the new
async patterns of our
Result type. At this point we've hit the compilation wall: any substantial improvements on the legibility of the code in earlier parts take us outside the realm of code that'll be tolerated by a compiler. But at this point, the compilation wall seems to be easier wall to jump when faced with the 'developer community' wall: none of the code I've written here is ever getting to production.
C# committed early on to "borrowing" an exception handling framework from Java. It also committed from its outset to permitting null values, and a various patchwork of fixes since (nullable reference types, structs, etc) haven't yet removed the problem null values introduced. When C# introduced
await it stumbled across a remarkably powerful language tool — and then limited it just enough to make it useful for
Tasks but not much else: the keyword choices themselves hammer home just how 'hacky' C# thinks it is to roll custom types for emulating even discount "monads".
The consequence of these decisions is that C# has attracted certain conventions that it now cannot overcome. The first and main convention is that functionality should be obvious to anyone reading the code. This sounds good on paper (and encourages many good things like immutability, pure functions, simple inheritance trees, and semantically useful (a phrase which here means 'long') variables names) but it also means that code must remain simple and obvious — burying functionality in an
AsyncMethodBuilder is definitely not allowed.
The second convention is consistency. Again, this does a world of good when it comes to maintaining very large codebases. It also means that any change to the established rulebook has to be agreed at least by a whole team, and normally by the collection of teams that touch shared code. I wouldn't dare claim that this convention should fall for any reason, but I must acknowledge that bad practices linger in code bases considerably longer than they should simply due to the effort required to remove them all in one go.
The third convention is a more general rule of thumb for professional development: don't reinvent anything. If an open-source tool exists, use it. It might be good for a company to roll its own tooling for development (or metrics or orchestration and so on) but that only increases the onboarding time for new starters and introduces another maintenance burden as the custom tooling inevitably rots (despite the nature of its existence, code rots ludicrously quickly). At the scope of C#, if any company-wide decision were taken to adopt a more robust version of the concepts introduced in this series, then suddenly every developer needs retraining, as does every new starter. Further, the skills they adopt aren't transferrable to other companies, so many would be sceptical even of taking the time to learn a new practice.
The less obvious issue is that of accessibility. Most developers would've understood this blog had it been written by someone who could write, but few would've hit the ground running. The time taken to understand complicated concepts in development is dev time: it's worth just as much as the time spent diagnosing issues caused by a stray
null. Maybe we're optimising the wrong thing here, and all of this precision with error types is just a distraction from the more important work of finding out why developers are so reliably unable to write good docs.
So, what does the barely conscious and childishly idealistic developer do in the face of such inertia? I suppose they could write a long blog series about wild code that sits in a personal repo on GitHub because it's not making it past code review for a company codebase. They could abandon ageing languages like C# in favour of the functional paradise offered by languages like Haskell, or could abandon ageing companies in favour of small cliquey groups of the converted who enjoy writing that stuff. Either way, it means leaving the wider developer community behind to go be snobbish somewhere else.
When I started writing this I was already more interested in the code itself than being able to use it (I think the term 'academic' was coined to describe such pursuits) but the motivation was to look into ways to make development easier to help developers. Between then and now, it's become more apparent that problems facing developers go far beyond code, and dealing with the larger cultural problems is, to be frank, so much harder than writing some good error handling code. So, interesting attempt though this was, I think I'll call it quits here, having made a meta-meta-error: to have made the error of focussing exclusively on errors to do with error handling. What a mess.
What to do about the larger cultural issues that we can't solve with a better developement language? I'll call myself unqualified for that one.