Technical debt – the truth


Within software engineering we often talk about Technical Debt. It was defined by elder programmer and agilist Ward Cunningham and likens trade offs made when designing and developing software to credit you can take on, but that has to be repaid eventually. The comparison further correctly implies that you have to service your credit every time you make new changes to the code, and that the interest compounds over time. Some companies literally go bankrupt over unmanageable technical debt – because the cost of development goes up as speed of delivery plummets, and whatever use the software was intended to have is eventually completely covered by a competitor yet unburden by technical debt.

But what do you mean technical debt?

The decision to take a shortcut can be a couple of things. Usually amount of features, or time spent per feature. It could mean postponing required features to meet a deadline/milestone, despite it taking longer to circle back and do the work later in the process. If there is no cost to this scheduling change, it’s just good planning. For it to be defined as technical debt there has to have been a cost associated with the rescheduling.

It is also possible to sacrifice quality to meet a deadline. “Let’s not apply test driven development because it takes longer, we can write tests after the feature code instead”. That would mean that instead of iteratively writing a failing tests first followed by the feature code that makes that test pass, we will get into a state of flow and churn out code as we solve the problem in varying levels of abstraction and retrofit tests as we deem necessary. Feels fast, but the tests get big, incomplete, unwieldy and brittle compared to the plentiful small all-encompassing, and specific tests TDD bring. A debt you are taking on to be paid later.

A third kind of technical debt – which I suspect is the most common – is also the one that fits the comparison to financial debt the least. A common way to cut corners is to not continuously maintain your code as it evolves over time. It’s more akin to the cost of not looking after your house as it is attacked by weather and nature, more dereliction than anything else really.

Let’s say your business had a physical product it would sell back when a certain piece of software was written. Now the product sold is essentially a digital license of some kind, but in the source code you still have inventory, shipping et cetera that has been modified to handle selling a digital product in a way that kind of works, but every time you introduce a new type of digital product you have to write further hacks to make it appear like a physical product as far as the system knows.

The correct way to deal with this would have been to make a more fundamental change the first time digital products were introduced. Maybe copy the physical process at first and cut things out that don’t make sense whilst you determine how digital products work, gradually refactoring the code as you learn.


What does compound interest mean in the context of technical debt? Let’s say you have created a piece of software, your initial tech debt in this story is you are thin on unit tests but have tried to compensate by making more elaborate integration tests. So let’s say the time comes to add an integration, let’s say a json payload needs to be posted to a third party service over HTTP with a bespoke authentication behaviour.

If you had applied TDD, you would most likely have a fairly solid abstraction over the rest payload, so that an integration test could be simple and small.

But in our hypothetical you have less than ideal test coverage, so you need to write a fairly elaborate integration test that needs to verify parts of the surrounding feature along with the integration itself to truly know the integration works.

Like with some credit cards, you have two options on your hypothetical tech debt statement, either build the elaborate new integration test at a significant cost – a day? Three? Or you avert your eyes and choose the second – smaller- amount and increase your tech debt principal by not writing an automated test at all and vow to test this area of code by hand every time you make a change. The technical debt equivalent of a payday loan.


So what’s wrong with this perfect description of engineering trade offs? We addressed above how a common type of debt doesn’t fit the debt model very neatly, which is one issue, but I think the bigger problem is – to the business we just sound like cowboy builders.

Would you accept that a builder under-specified a steel beam for an extension you are having built? “It’s cheaper and although it is not up to code, it’ll still take the weight of the side of the house and your kids and a few of their friends. Don’t worry about it.“ No, right? Or an electrician getting creative with the earthing of the power shower as it’s Friday afternoon, and he had promised to be done by now. Heck no, yes?

The difference of course is that within programming there is no equivalent of a GasSafe registry, no NICEIC et cetera. There are no safety regulations for how you write code, yet.

This means some people will offer harmful ways of cutting corners to people that don’t have the context to know the true cost of the technical debt involved.

We will complain that product owners are unwilling to spend budget on necessary technical work, so as to blame product rather than take some responsibility. The business expects us to flag up if there are problems. Refactoring as we go, upgrading third party dependencies as we go should not be something the business has to care about. Just add it to the tickets, cost of doing business.

Sure there are big singular incidents such as a form of authentication being decommissioned or a framework being sunset that will require big coordinated change involving product, but usually those changes aren’t that hard to sell to the business. It is unpleasant but the business can understand this type of work being necessary.

The stuff that is hard to sell is bunched up refactorings you should have done along the way over time, but you didn’t- and now you want to do them because it’s starting to hurt. Tech debt amortisation is very hard to sell, because things are not totally broken now, why do we have to eat the cost of this massive ticket when everything works and is making money? Are you sure you aren’t just trying to gold plate something just out of vanity? The budget is finite and product has other things on their mind to deal with. Leave it for now, we’ll come back to it (when it’s already fallen over).

The business expects you to write code that is reliable, performant and maintainable. Even if you warn them you are offering to cut corners at the expense of future speed of execution, a non-developer may have no idea of the scale of the implications of what you are offering .

If they spent a big chunk out of their budget one year – the equivalent of a new house in a good neighbourhood – so that a bunch of people could build a piece of software with the hope that this brand new widget in a website or new line-of-business app will bring increased profits over the coming years, they don’t want to hear roughly the same group of people refer to it as “legacy code” already at the end of the following financial year.


Think of your practices as regulations that you simply cannot violate. Stop offering solutions that involve sacrificing quality! Please even.

We are told that making an elaborate big-design-upfront is waterfall and bad – but how about some-design-upfront? Just enough thinking ahead to decide where to extend existing functionality and where to instead put a fork in the road and begin a more separate flow in the code, that you then develop iteratively.

If you have to make the bottom line more appealing to the stakeholders for them to dare invest in making new product through you and not through dubious shadow-IT, try and figure out a way to start smaller and deliver value sooner rather than tricking yourself into accepting work that you cannot possibly deliver safely and responsibly.


Size matters

When I started out, I had no idea about lean, agile or TDD. I did read a lot about Object Oriented Programming. I even thought I was practicing it. My first decade of programming was not what would pass for professional grade by modern standards, but even my poor standard back then was – and still would be – not the worst. Sadly.

Eventually I read some pamphlets about TDD, tried some katas, read books about lean software development and the book the Phoenix Project and was subjected to Fred George‘s Object Bootcamp with my co-workers a couple of employers ago.

Then I understood. All of it. Object oriented programming, TDD, lean. All of it. Because of how steeped in my old bad habits I am it still takes conscious effort to practice all these things, and I fail to enforce it sometimes, but at least at this point I know what good looks like. If I had stronger discipline I could refactor towards it as often as I like.

Like, if you make small enough focused classes, object orientation makes sense and you find yourself binning and replacing classes that are no longer fit-for-purpose rather than rewriting them. Open-Closed principle. There are all of a sudden more value objects and composable domain classes that cleanly describe domain behaviour and you come away from cascading changes that you thought were inherent in OO. But is it easy? No. It requires constant effort to maintain.

The most important thing is size. Make the smallest possible change to make the test go green. People – me, you – we? – overcomplicate things and fail to comprehend just how small small should be and in the refactor step, we rarely refactor enough and leave classes too big. Now I find this really hard, the commit-by-commit design step where you are supposed to refactor code into proper shape, reduce classes down to their most composable form, their bare essence. On the other hand, “It’s your only job, Rachel!” like Jimmy Carr says on Eight out of Ten Cats Does Countdown when she can’t solve a numbers game right away. We are paid not only to sit in front of our computers and type but also to think. If we do a bit more of the thinking and a little bit less of the typing, nobody is going to get upset.

Allen Holub talks about user stories on Twitter, reminding us that a story isn’t a neologism for “requirement” and that a user story literally means that, a software user telling us a story about a domain problem they are having. Not “as a user I want to authenticate so that I can have access to the system” but like actual meat on the bone. “As an underwriter I want to bind a quote as I have agreed terms with the broker”. Requirements for authentication will come as part of some story, but start stupid simple with a .htaccess file or similar. For some subsystems that requirement will never come, or can be trivially covered with infrastructure, and you just saved yourself a bunch of maintenance. Code is not an asset, it’s a liability.

Allen Holub also uses TDD when designing systems, as in uses Java and jUnit to TDD integrations between microservices like a less-trendy jupyter notebook proving his overall system design, even ending up with some code that could describe integration points. Start smaller. No, even smaller than that.

Then we have the No Estimates crowd. Seems insane to people used to the widespread non-story user stories with large blocks of detailed requirements that necessitates complex up-front engineering. How could teams take on these big stories without estimating how much they will take to build – what if we spend three months and we don’t even achieve what we want?!

That’s right. But – do you remember Agile? Yea, see the point was to build the smallest possible implementation that can prove viability. If your stories are sized consistently and correctly – i.e. smaller than you think possible – the consistent implementation work will give you the foresight you need to coordinate and plan as necessary.

We can then add features incrementally as users examine the existing product and realise the potential and get ideas based on their experience as domain experts for what they could do to meet their customers’ needs, or what experiments could be run to determine customer desires. In small increments still.

Even if you insist on keeping creating your estimates, you will find that making stories smaller will improve delivery quality and adherence to timescales. As soon as stories get too big, they are harder to reason about and you may even forget acceptance criteria you thought you had clear in your head. You will never regret making stories smaller.

SD&D 2022

I had the chance to attend the Software Design & Development conference at the Barbican Centre this week. It was my first conference since the plague so it was a new experience. I will here coalesce some of the main points that I gathered. I may go into specifics in a couple of topics that stood out to me, but this is mostly so that I have some notes to aid my memory.


The conference is very well organised, you can tell it’s not their first rodeo. From a practicality point of view the Barbican is equally easy/cumbersome to get to from all directions, which is about as good as you can get in London where usually you will end up favouring proximity to a subset of main line termini, thus making the location cumbersome to get to for at least half the population (since there are airports in every direction out from the city). There were a number of timeslots where you truly had FOMO for choosing one track over another, which is a design goal of a program committee – so, well done SD&D! There was some unfortunate setting in the AV equipment which interfered with shortcuts in Visual Studio in interesting ways, but surely that can be addressed somehow.

Kevlin Henney

The first law of developer conferences states Always Catch a Talk by Kevlin Henney if Available. It doesn’t teach you anything about a specific new thing, but it puts the entire universe into context, and always inspires you to go ahead and look up papers from the olden days that describe modern phenomena.

C# features

My biggest bafflement came not from the talks that showcased new C# features, such as the latest iteration of pattern matching and the like – as I usually get introduced to them when they show up as options in ReSharper – but by the old abomination that is default implementations on interfaces in C#8. This talk by Jeremy Clark was an eye opener. It is so jank you wonder how it could ever be released into production. My guess is that the compatibility argument from MAUI was the big reason, and it makes sense, but basically my instinct to stay away from it was right, but my guess is that you will have weird bugs because of it at some point in the future.

I also caught the C# Channels talk. I seem to recall the gestation of Channels, as if I remember correctly it was publicly brought into being through discussions on David Fowler’s twitter account (unless I misremember). Anyway, it is a highly civilised way of communicating between two async tasks with back pressure. Intuitive to use and safe. Like a concurrent queue but a lot nicer.

Micro services

Allen Holub had a number of talks on Microservices and if you can I’m sure you should see more of them, due to the abundance of other brilliant talks I only caught his test driven architecture talk which I will mention below. Other than him though there were talks by Juval Löwy and Neal Ford that covered architecture and micro services. I caught Software architecture foundations: identifying characteristics by Neal Ford and Sander Hoogendoorns’s talk on migrating to microservices in small steps, both worth watching.


There were a couple of security talks focussing on automating security as well as the updated OWASP top 10 chart of threats as well as a couple of talks by Scott Brady about – I am guessing – – Identity Server. The dizzying array of choices meant I didn’t go to the identity server talks, but they are definitely on my to watch-list if there is ever video from this.

The security automation ones though Continuous Security by Kim van Wilgen and Add Security into your Agile Process by Cecilia Wirén took you through what you need to really improve the security posture of your development process. Kim v Wilgen was more in-depth on tooling whilst Cecilia Wiren was more about the whole process and what to consider where. The only sustainable way forward is to automate things like dependency vetting/tracking and as much static code analyisis you can, to bring these concerns as far left as you can, menaing early in the process. Rewriting a function even before you commit it is easy. Having an automated fuzzing tool discover you have a buffer overrun vulnerability when you thought you were done is worse from a cost-of-remediation point of view, but of course letting a bad vulnerability out into the wild is an order of magnitude worse, so whilst catching them in the dev cycle is preferable, attempting to catch stuff late through more heavy handed automation that is too time consuming to run on every commit is still worth considering running periodically as it’s better than the alternative.

Tests drive everything

How to stop testing and break your codebase by Clare Sudbery was an amazing talk that really hit home. It was like an experiment of what if I just skip test-first for a bit and see what happens? brought out of time crunch, tiredness and a sense that it would be a safe trade-off because I know what I’m doing and – in her case – I have acceptance tests . Like I have noticed in various side projects, when you let go of the discipline the drawbacks come at you hard and fast – almost cartoonishly so. It was one of the most relatable talks I have ever attended.

Allen Holub’s DbC (Design by Coding):applying TDD principles to architecture was fascinating. It started out by being a bit “old man yells at clouds” about how real agile is index cards on a board, not Jira, and although yes, index cards or post-it’s on a physical board is preferable to an electronic board, the electronic board prevents me from having to commute four days out of the five, so – no. The points raised about authoring million detailed tickets ahead of time being a waste though, hard agree, and the rest of the diatribe against big design up-front I was all aboard with and probably to some extent already doing. The interesting bit was to come though.
He presented a hypothetical technical problem that needed architecting. Instead of drawing a diagram or writing specs, he whipped out an editor with his favourite version of junit and wrote some java code through TDD – all in one file – that implemented tests and classes that symbolised microservices and their endpoints, as well as the interactions between them. Light weight, easy to read for developers, pleasant tooling and at least as useful as a diagram. In both cases you start writing the code from scratch, but you have a design document that makes sense. I’m not 100% sold on the concept but it’s worth considering.

Various highlights

Tuesday morning keynote was about quantum computing, and reluctantly I must concede that it probably is the future, and the community seems to be looking for converts, but I just can’t go from quantum entanglement to taking data from a web page and shoving it into a database, so I guess I have to wait those three years before it hits the mainstream and it will become digestable for the likes of me. If you are into cryptography as in encryption, not the various ponzi schemes, you should probably get into it now.

I caught a Kate Gregory talk – on naming – after only being a fan off of her YouTube talks on C++ vs C, definitely worth seeing. She proposed the strategy of “just mash the keyboard if you can’t think of a name and go back to it later” was also brought forward elsewhere on the conference, the point being: don’t get stuck trying to come up with a name, start writing the code and as you start talking about what the thing you just wrote is and what it is responsible for, a great name will eventually become evident and then you use that. The effort of coming up with a good name is worth it, and with refactoring tools it’s worth just moving past the instant rather than making a bad decision. Once you have finished the feature and proceeded, the caveats and difference between the name and the actual implementation will fade into obscurity and when you come back to the same code in three weeks you will have forgotten all about it and can be misled by bad names as easily as if you hadn’t written the code yourself.


I really enjoyed this conference. Again, with a past in a program committee I really admired the work they put in to cause so much anxiety when picking talks. Obviously the QE2 conference centre in Westminster is newer so NDC London benefits from that, and if you want to see Troy Hunt and the core guys Fowler and Edwards you would be better off over to NDC, but SD&D had all the core things right and a wider array of breakout sessions, and infrastructure like the food was a lot less chaotic at SD&D than it usually is at NDC. Compared to BuildStuff and Øredev – those conferences I only attended as visitor to the city, so I didn’t have to commute, meaning of course that’s nice.

If you like the environment you’ll be pleased that there was no shilling or abundance of obscure t-shirts handed out that would have drained natural resources, but I suspect that SD&D would have enjoyed more sponsorships and an expo floor which allegedly they have had before . Since this conference was actually SD&D2020 postponed several times over the course of two years, it is possible that SD&D 2023 will have pre-pandemic levels of shilling. All I know is I enjoy free t-shirts to clothe the child. Regardless I strongly recommend attending this conference.

Life is friction

Life is just people and things working together to make things difficult for you. Like on a rainy windy day where you can just lean into the wall of oncoming air and water and just push through.

Most of these things you cannot really do anything about, and there is no point to complaining about it, but then there are small wins, like going around the corner of a big building and it taking a few seconds for the wind to change direction and blast you in the face again. Those few seconds are golden.

Anyway – one of those breaks in the rain is that I’ve switched off comments on my blog. There are two people on average that read a post, and rarely do they want anything from me. A handful of posts have over the decades accumulated hundreds of views. Among humans my writing has the attention it deserves.

The bots though are big, unrelenting fans and have an insatiable appetite for communicating all kinds of offers through commenting on my posts (that they can’t have read according to the page statistics).

I pay for a service that is supposed to deal with my popularly in the bot scene. An inbox zero-as-a-service, basically. Well those guys were annoyed that I sent too much traffic. Again two (2) readers per day generates enough spam bots that I either have to get an even more ludicrously expensive anti spam tier, buy a higher tier blog hosting to be allowed to add a captcha, or lastly self-host with expenses of both money and time.

I don’t want to do any of those as they cost money, and if you have seen the rest of the blog you’ll see why I’d rather not be spending any money on it. So I’m shutting the comments. I know this may lead to reduced “engagement” but the thing is, people that reach this page know how to reach me, so nothing is really lost, except friction.

I get that brief respite from the rain that you get at a large building site where the hoarding and scaffolding are overbuilt into a luxurious chip board arcade with strip lights and trip hazard warning tape everywhere. You get in out of the direct rain, but big drops from 70m up the scaffolding hit you directly on your skull through a gap in the chip board instead. It’s a win, but you’re never allowed to be too elated.

Anyway, if you need me, you know where to find me.


What are the genuinely difficult aspects of transforming your software function?

It seems everybody intuitively understands what brings speed and short time to market, and how that in turn automatically allows for better innovation. Also people seem to get that in the current stale market, with fast enough delivery you could even forego smarts and just brute force innovation launching new concepts and tweaks until profits go up and then declare a win as if you knew what you were doing that whole time. Secretly people also know that although you could rinse and repeat doing the naïve approach until retirement, optionally you could exert minimum effort and measure a bit better so that you know what you are doing so that you can focus your efforts.

So why aren’t everyone moving on this?

When you get a bunch of people in the same organisation you want to achieve some economies of scale and solve common problems once rather than once per team.

This means you delegate some functions into separate teams. Undoing this, or at least mitigating this, is difficult politically. Some people – with some cause – fear for their jobs when reorgs happen.

Sudden unexpected cost runaway is the biggest recurring nightmare of middle managers. Controls are therefore in place to prevent developer cloud spend to balloon.

Taken together however, this means teams are prevented from innovating independently as they cannot construct the virtual infrastructure as needed because of cost not being authorised, and they cannot play with new pieces of virtual infrastructure because they haven’t been approved by the central tech authority yet.

Happy New Year?

The current state of affairs

In 2020 I learned the meaning of the English expression Busman’s Holiday, and it generally applies to software developers that write code on their free time, but especially so during a pandemic with abundant remote working. Putting that aside, I will make some predictions of what will be happening over the coming year.


The Pestilence

Given how popular the Omicron strain has proven, my guess is that everybody will have had Covid, and the patience for government measures will have grown thin, especially given the attitudes with which they flout the rules within the government itself. If Labour takes power, of course this can all change and we can be heading for more lockdowns.

The Industry

Despite lockdowns and the inevitable destruction of the service industry (yes, for good reasons in managing the spread of the virus, but let us be honest with the consequences) the IT industry has fared reasonably well. As long as I have lived in this country there has been a general election every two-and-bit years, and we could be looking at one of those again, and in a run-up to that, Rishi Sunak will want to keep money pumped into the system, meaning IT people will most likely still do quite well for a bit longer.

The Great Resignation

From the discussions around recruitment before the above variant gained popularity, there seemed to be two main streams, people that want to work remote full time, and people who want to work in a hybrid capacity, where you do meetings and collaboration in the office, and focussed work remote – if not at home at least in a co-working space closer to your home. The crutch used by weak leaders to manage people – counting bums in seats – will probably need to be replaced by some kind of outcome-based measurement. Luckily that ought to align quite well with company targets. No company has a slide in an AGM saying “well revenue is down, profits are down but luckily we have 99.5% occupancy of our desks“, the goal is to make money, and with the right type of goals within an organisation you can have department and team goals that in some way works towards the overall business goals, but of course measuring the right thing is key, so – yes – it is harder than just counting empty desks.

My thinking is that if the pandemic calms down, we will se a subset of organisations that are unashamedly on-prem only, and those that look for work that is on-prem only will go there, but I suspect that it will be harder to hire for those positions.

The Continuous Delivery

People insist with this Agile malarkey, and even though “Scrum, but…” remains the dominant methodology, companies are starting to read Accelerate and realise that they need to move faster, so gradually obstacles are being dismantled. Management structures are tweaked, project management and budgeting is being replaced with product and portfolio management. Coordination exists in companies already. Organisations that are famously agile say they struggle to coordinate cross-cutting changes across an organisation, but in old enterprises, that coordination work is the thing they do well, because in their current day-to-day even the most trivial piece of work cuts across several teams and needs careful planning and second-guessing to be delivered safely. The big differentiator is to change the internal structure so that for 80% of changes, a single team can plan, test, construct and monitor features completely independently, while leaving some version of the existing structure to deal with the subset of changes where you still need to coordinate. If you achieve that, you are in a vastly better place than before.

The Hardware Shortage

Have you tried buying a graphics card? A car? Well, you may have noticed that there is a supply chain crisis in the world. US container ports are struggling now and what originally started with the double whammy of Chinese New Year and OG Covid shutting down electronics suppliers, got worse as there was a supply shock when the pessimistic demand prognoses turned out to have not accounted for stimulus checks inducing demand globally, and more recently there i are geopolitical issues when one of the main semiconductor suppliers globally, Taiwan Semiconductor Manufacturing Company (TSMC) is situated in region on the brink of war while at the same time Intel are struggling to produce any advanced processor nodes in their own fabs, even though they now are producing a competitive line of processors again.

My prediction is grim here, but let’s pretend like things will go well. I don’t think you should buy anytihng in 2022 if you can avoid it, which has been my advice from March 2020 onwards, that hasn’t changed.,

The Crypto Scams

Just like with drug trafficking and modern slavery, you can make a lot of money with cryptocurrencies and NFTs, and you can already see that the biggest profits are made when people are robbed of their coins.

As you dream up your practical use cases that will finally be the problem that crypto solves, just remember this: Like with all applications of cryptographic signing, the time it takes to encrypt or decrypt something is part of why it works, why it is secure. You will never have a world where these transactions are fast and secure. All exchanges for cryptocurrencies that trade fast circumvent a number of supposed features of a distributed ledger. There is no “it will be faster, eventually” unless you are prepared to sacrifice some of the key selling points.

Luckily China has decided that crypto currencies are inherently decadent and are clamping down on miners, and if western utilities start going after those that steal electricity with more zeal, we could start to see positive change.

Don’t forget that NFTs, Bitcoin and Eth singlehandedly is destroying the Paris Accord on climate change, You can heat a typical American home for six weeks on the energy required for one (1) bitcoin transaction. As computers become faster, this will gradually be worse as well.


As with any arbitrary point in time, the time immediately after will not be drastically different than the time immediately preceding it, so there will be much of the same next year, but I have still tried to make some statements that are specific enough that we can go back in a year to see what I got right and what I got wrong. Happy New Year!

Async Enumerable in C# / .NET 6


In recent times Microsoft have begun to performance test their web platforms. Whilst previous generations of their .NET framework and ASP.NET web platform had prioritised ease of development over performance quite dramatically, the latest generation ASP.NET Core performs quite well, on Linux no less.

After inventing the async/await model of abstracting away callback hell when writing asynchronous code, the New Microsoft, the Ones That Care About Performance realised that people will just allocate all the RAM in the universe if you let them, and that whilst engaging in the now very common practice of using ASP.NET Core to create web APIs that produce data as json payloads, users would mercilessly just serialise massive payloads of List<T> into one massive string that they would shove out onto the network, or have server endpoints that would accept arbitrarily large strings off of the Internet attempting to coerce into a List<T>, meaning ASP.NET Core services could be knocked offline by supplying a ludicrously large payload, and performance could be a bit erratic at times, depending in the size of data the user was requesting.

So what do they do? Well, a couple of things, but one of them is to introduce the concept of IAsyncEnumerable<T>, an asynchronous enumerable, that supports cancellation, clean exception handling and stable performance for handling variably sized payloads without suffering unpredictable performance impact.

The goal today is to successfully serve a payload in ASP.NET Core 6.0, and to deserialise it in a client application, also in .NET 6, serialising onto streams, deserialising off of streams, processing data without allocating massive payloads, also – beginning to receive data right away rather than to wait before the full payload has been buffered in its entirety in various services along the way before eventually reaching the end user.

Physics and leaky abstractions

Just to preface this – just like the async /await doesn’t fundamentally change physics, i e there is no getting away from the fact that you first kick off an operation and basically schedule code to be run when that operation has finished, leaving you to do other things. I.e. since your code will actually return to the caller directly after you’re scheduled the first async operation, the code has to return something in addition to the normal return value, it has to return a handle through which you can access the state of the function, and – once the operation has completed – the return value. This way the surrounding code has a chance to deal with the asynchrony but most of the time just pretend that the code is synchronous.

You see, if the human squishy brain cannot fathom mulithreading, don’t let me get started on asynchrony.

So with a normal asynchonous function that returns a scalar, the caller receives a System.Threading.Task that encalsulates the asynchonous state and eventually the return value. The async keyword lets you pretend it isn’t there and write synchronous code , as long as you put an await in before the asynchronous call is made.


You’ll notice though, like with monads, that when you’ve started wrapping your return values in Task<T>, it’ll go all the way across to the other side of the application, i e if your database code is asynchronous, the repository or other database access layer topology you have will be asynchronous too, and then you turn around and then you find that it has spread all the way to your ASP.NET controller. On the plus side, the ASP.NET controller automagically injects a CancellationToken that you can send all the way down to the database and get automagic cancellation support for long running queries if people refresh their page, but that’s an aside.

The point here is the contagion. You can attempt to force things to be different with GetAwaiter().GetResult() to block a thread while it’s evaluating, but that is very dangerous performance-wise, better to just let it spread, except for in places where Microsoft have been lazy, such as in Validation and Configuration, cause clearly when it would mean work for them it’s “not necessary” but when it’s eons of work for us they are fine with it. Our time is free for them.

Anyway, I mean it makes sense that the abstraction must leak in some cases, and IAsyncEnumerable is no different. Any one return value would fly in the face of the whole streaming thing. So awaiting a task doesn’t really make sense. Instead it’s iterators all the way down. Everywhere. Each level yield returns to the next, all the way down the chain.

Dapper allegedly comes with support for IAsyncEnumerable, but at the time of writing there is zero documentation supporting that allegation.

You can simulate that by writing this bit of code:

    public static async IAsyncEnumerable<T> QueryIncrementally<T>(this SqlConnection conn, CommandDefinition commandDefinition, CommandBehavior behaviour = CommandBehavior.CloseConnection)
        await using var reader = await conn.ExecuteReaderAsync(commandDefinition, behaviour);
        var rowParser = reader.GetRowParser<T>();

        while (await reader.ReadAsync())
            yield return rowParser(reader);

From that you can then pass the payload up iterator style, yield returning all the way up, until you get to the controller where you can declare the controller to return IAsyncEnumerable and the framework will handle it correctly.

Obviously as you cross the network boundary you have a choice in how to proceed, do you want to receive the data incrementally as well, or do you want to wait for all of it to arrive?

Since you made such a fuss in the first API, we will assume you want the consuming side to be as much work.

    private static async Task<Stream> GetStream(HttpClient client, string endpoint)
        var response = await client.GetAsync(endpoint, HttpCompletionOption.ResponseHeadersRead);
        var responseStream = await response.Content.ReadAsStreamAsync();
        return responseStream;

    public static async IAsyncEnumerable<T> HandleGetIncremental<T>(this HttpClient client, string endpoint)
        var stream = await GetStream(client, endpoint);
        var items = JsonSerializer.DeserializeAsyncEnumerable<T>(stream, CreateSerializerOptions());
        await foreach (var item in items)
            yield return item;

And then, of course, you yield return all the way up to the next network boundary.

Is this ready for prime time? Well, in the sense that Jay Leno was ready for prime time when he ceded the Tonight Show to Conan O’Brien, but everybody would probably like some more pace and less awkwardness.
Apparently letting lambdas yield return is on its way, and hopefully that can make it easier to pipe an IAsyncEnumerable through one API to the next, easily adding some filter or transformation mid flight rather than the incessant await foreaching that is now necessary.

Best is the enemy – stick with good

Working life, like any series of events, can be compared to other stories, such as those in cinema. Is your workday like Avengers Endgame when all your coworkers show up out of thin air and swarm to solve a difficult problem? Are you Malcolm Tucker of In the Thick of It helping your co-workers by providing astute observations and giving gentle constructive criticism? Or is it more like the middle of a 70s social realist movie when the alcoholic father / engineering manager promises you that although sure it’s bad now – mistakes have been made – but you know it’ll be great, we’ll stand up kubernetes and we’ll never deploy manually again?

Obviously – when they make a big budget movie out of the Phoenix Project, we can just look at that, but until then – what film are you living now? Which one would you like to be living?

You want to believe assurances of a bright future, but deep down, you know you’ve heard it before. Perhaps problems being indiscreetly alluded to in an early act comes back in the final act to cause a massive predictable calamity making you think your movie has a poorly crafted arc. Perhaps you give your social realism engineering manager the “you need to cut down, think of the kids” speech – but it’s met with denial. “Our network guys are diligent [to be fair -they probably are, regular John C Reillys the lot of them], it takes 2 minutes to make a configuration change – why would I take hours out of their day to write scripts to do things they complete in half an hour including the red tape we have imposed upon them? Do you realise how busy they are?”.

What if you want to switch franchises – so to speak? Get into a better movie? Let’s say your film is the social realism one, and after a few accidents in the workplace, the union is shutting the site, and the owners are threatening to move production overseas. Car factory, sounds Birmingham-based on the accents. Lovely soundtrack with early seventies Black Sabbath. Your character has to stop the mayhem on the factory floor so that the union will allow production to start before the owners scrap the factory for good, your budget is £0 but you happen to have massive rolls of black and yellow adhesive tape, some PPE and a loudhailer. Basically, you can turn your film around, you can do it – but you do have to literally start doing something.

I’m writing this to continue on a ball of yarn I’ve been unravelling in other posts. Basically I want to state that DevOps doesn’t need to mean shiny and new. Any type of automation that does the job is fine. You don’t have to change platforms , you can – and I personally mean should – start by automating the existing stuff and not by building a new feature complete platform. Take the first step! Stop dreaming about a service mesh and kubernetes. It won’t happen soon enough.

This next bit will be very marvel oriented, by the way, but feel free to translate this to your own cinematic universe. It’s like – you can manage to automate and ship software reliably, but you may not be ready to be Tony Stark. You are still be part of the MCU, but you won’t be an arms dealer billionaire or even an Australian Norse space God, or even a fighter pilot with accidental alien super powers and amnesia. The best you can hope for is to write PowerShell or bash. PowerShell and bash, perhaps. Cobble together some automation with whatever CLI you have laying around. Automate the simple things. Even if you are disrespected in the office like Agent Carter you can eventually save the day. The big first step is to figure out how all your hand crafted bespoke servers are really built and figure out how to build them from scratch with scripting. This is the painful, tedious first step that you have to take. How can I create my production environment using only scripting and free or affordable tools that my people already know how to use?

In too many companies the deployment automation is:

  1. Download packaged tested software from archive
  2. Disable monitoring to avoid scaring your on-call people
  3. Divert network traffic from node
  4. Decompress archive and copy files in place
  5. Restart services
  6. Re-enable traffic.
  7. Repeat 2 -6 for all other sides in the load balancer.
  8. Re-enable monitoring

This is not enough. There may be any number of unknown things that just live on your VMs without which things just wouldn’t work. Crucial OS settings that were made once that nobody remembers anymore. Such hidden things are the potentially big surprises that derail containerisation projects or cloud migrations. You need to Agent Carter the Whole Thing.

  1. Define networking. You have some leeway here – use a wild card cert, generate a new short-lived cert- create a load balancer or just a rule for a central load balancer. This depends on what you have in your infrastructure and what tools you know how to use, but basically – if the starting state is nothingness, after the automation is run, there should be a way for the outside world to find your service and know if it is healthy. If things already exist, your scripting should only make expected changes to it and be able to run multiple times without accidentally causing mayhem. Make sure any WAF rules or similar to enable access to dependent services are also set up here. If you can’t reach a necessary service at all, this should be immediately obvious from tooling without even digging into logs.
  2. Define virtual servers. If all you have is VMWare CLI, then create a VM based off of a suitable template. If you have some fancy cloud provider, use the highest abstraction level you can get away with. Azure Webapp, AWS ECS or Lambda. Stay away from raw VMs if you’re running in cloud, they are expensive.
  3. Install your servers to their desired infrastructure state and patch level. Ideally you use Ansible or even Powershell Desired State Configuration. There are so many non-trendy options that you already probably have a few installed. Chef or Puppet works too, if you have guys that know that stuff already. Find out what people already know and pick the simplest technology. The specific technology you choose isn’t key here, the big idea is learning how to take empty metal and get your stuff working there without having to do any manual intervention whatsoever. All of the infrastructure must be code.
  4. Now you’re at the point where the previous list is relevant. Of course depending on your choice of technology you may not need to repoint load balancers as some tools like chef and puppet support in-place upgrade. A central brain/source of truth will announce that new software exists, and you have to manage in place upgrades through ruby scripting if you’re unlucky, but it works . Either way, only here are we at what the previous CD solution thought was all of it.

You aren’t done until you can spawn a service as easily as your users shout “Another!”. You can get to this point with tools your guys already know. It may not as sexy is just flying straight through an enemy star destroyer using helm whilst your mechanical keyboard glows in addressable LED colours, but the point is your organisation most likely possesses the skill to do this already. You must take the first step.

Whichever cinematic universe your life’s film belongs to, should be proud at what you have achieved in the face of such adversity.

The Power of Sample Code

What is wrong with OOP?

In the culture wars between “Object Oriented Programming” and Functional Programming, you will find proponents of OOP that argue that we are doing fine – why should we change? and proponents of FP that lists a litany of inherent problems with what we are doing today and point to the ways FP solves them. After I once was at an Object Bootcamp with Fred George I believe the two main schools of thought are both wrong. All the problems listed by the FP peeps are correct, but they are not inherent in OOP, actually OOP addresses a few of them, but we are as an industry not doing OOP.

I may feel Fred George is the Messiah, but he is not alone in his views. Greg Young has similar concerns.

Inheritance is not the Big Deal

I am old enough to remember Borland C++ ads from the 90s. It focused a lot on inheritance, and reuse through inheritance became the USP for object oriented languages.

As soon as you have written some code though, you realise inheritance is the worst, as it creates undue coupling, making changes very hard to implement.

When Borland made those ads about how Porsche Turbo inherited the Carrera but implemented a big fat rear wing, they had begun their foray into C++ because it offered a way to handle the substantial boilerplate involved in writing a program in Windows. It was relatively straightforward to implement the basics and create a usable abstraction on top of the raw Windows API that made the developer experience much more pleasant.

As visual designers became a thing, they wanted a way to map properties with code, so that UI components (those things implemented as objects we mentioned above) could be manipulated by a developer in design mode. “Property” setters, basically syntactic sugar disguising normal functions, allowed the UI designers to read settings from the object, and replace them with what the developer types in. With this work, Borland and Microsoft were working to catch up with InterfaceBuilder from NeXT Computer (the same thing that lives on today in the Apple MacOS/iOS SDK) that had bolted a different type system on top of C and called it Objective C – but that had a world leading visual designer at the time. Anyway, I think they were in a hurry and didn’t think things through.

Approaches to deal with big programs

In a large codebase, the big problem is achieving low coupling but high cohesion. This means, you want all the code that belongs together to live together but you don’t want to have to make changes in seemingly unrelated code to modify a piece of functionality.

In large problems of old, you could call any subroutine from anywhere else, and many resources were shared, meaning between the time you set a value in a variable and you read from it, some piece of code in between could have modified the value, and you would not be automatically able to know where this access is made and how to prevent it.

In FP, we use modules for scoping, meaning you group functions into modules to aid readability, but the key concept, the Big Idea is immutability. After a value is created, it exists globally, but since they are read-only once created, the drawbacks of global state go away. There is no way to change something that somebody else relies on. You can transform it into a new thing that you need, but the original value hangs around until it’s no longer needed. It is harder to accidentally break other code with changes you are making

The Big Idea in Object oriented development is Encapsulation. You put the data with the code and manipulate abstractions. This means that if you get your abstractions right, you can change or replace these abstractions without needing to make sweeping changes in the codebase.

The original concept of object orientation relied on independent small sub programs that communicated by message passing, implicitly imagining like an “in tray” of messages that the object could process at its own pace and then send a response when the work was completed. However – objects were in C++, Java and C# was implemented as special dynamically allocated structs to which you made function calls, i e they became decidedly more synchronous than they were in Smalltalk or Simula. You would recognise Erlang Processes and Actors as looking more like OG objects. You also see that what made objects useful were that they shared properties we today associate with the term micro services, but on a smaller scale.

So what’s the problem, and what’s up with the title of this blog post?

Java, and C# arguably even more so, took the Big Idea and tossed it out the window. Property Get/Property Set to support novelties like graphical designers and visual components are a clear violation of encapsulation. Why are we letting objects access data that lives in other objects? The need to do that is a huge red flag that your model is incorrect. Both the bible, i.e. Refactoring, by Fowler and the actual Bible condemn this, this feature envy.

But why did these properties survive the nineties and live on into modern day? Why have they made things worse with auto properties?

Sample code

When you learn a new language, or to code in general, the main threshold is getting to the point where you write idiomatic code in that language. I e you use familiar phrases. You indent the code in a certain way, you name things according to a certain standard and you use familiar ways to do things like open a database connection, make a HTTP request et c, that a seasoned programmer would be familiar with. Unfortunately- in C# at least, these antipatterns are canon at this point, so to write properly encapsulated code would maybe cause a casual reviewer to ask WTF and be sceptical.

What is canon comes from the publicly available body of work that a beginner can reasonably access. Meaning, effectively Microsoft sets the bar when they announce features, document them and create samples.

There are some issues here. If you look at a large piece of sample code, you may notice how difficult it is to identify the key concept being demoed as the logging code or error handling bulk up the code in a way that is distracting, so brevity must be allowed to remain a priority, clearly.

At the edges where the code starts interacting with network and storage, this type of organisation isn’t inherently despicable either, so a blanket ban is perhaps not the way forward either.

How do we make it clear to new OO devs that when they fill that empty Models folder their project template creates for them with code they would be better off thinking OO proper?

By that I mean making classes that are extremely small, use value objects, prefer private fields, avoid properties et cetera. My suspicion is that any attempt at conveying this programming style through the medium of sample code in templates or documentation is doomed. The bulk of code necessary to not only prove the concept but to in fact make it part of the vernacular would require a large number of people making quite a lot of good code public do that new learners can assimilate the knowledge.

I think good OO code is scarce. Getting the abstractions right is just too hard, you will have compromises in various places, and all the tools tempt you with ways to stray from the narrow path of righteousness, but with modern refactoring tools you should be able to address some of the issues amd continually strive to make the code better.

Incidentally, with properly sized objects you can unit test without cheating (using internal helper methods, or by using mocks), so there is scope to brighten up the tests as well.

Automation and security

There is a recent spate of sophisticated attacks on software delivery mechanisms where cyber criminals have had massive success in breaching one organisation to get automatic access to hundreds of thousands of other organisations through the update mechanism the breaches organisation provides.

Must consider security at design time

I think it needs reiterating that security needs to be built in by default, from the beginning. I haven’t gone back to check properly, but I know I went back and deleted an old blog post because it had some dubious security practice in it. My new policy is, I would rather omit some part of a process than show a dodgy sample. There are so many blog posts you find if you search for “login form” that don’t even hash passwords. And rather than point beginners to the built-in password hashing algorithms that are available in .NET, and the two lines of code you have to write, they leave some beginners thinking it’s all right, just this once and breed this basic idea that security is optional. Something you test for afterwards if you are building something “important” and not something you think about all the time.

The thing is, we developers have tools that help us do complicated things – like break bits of code out from other bits of code automatically or rename specific constructs by a certain name, including surrounding text comments, without also incorrectly renaming unrelated constructs that share name.

It turns out cyber criminals too have plenty of automation that helps them spend very little effort breaking in to companies, and exploit this access in a number of different ways.

There is maybe no “why”

This has a couple of implications. First off, attackers are probably not looking for you per se. You may be a nobody, you will still be exposed to automated attacks that test your network for known vulnerabilities and apply automated suites of exploits to see what happens. This means that even if you don’t do anything that conceivably could have value to an attacker, you will still be probed.

The second thing is, to prevent data loss you need to make every step the attacker has to take a hardship. Don’t advertise what software versions your public facing servers are running, don’t let service accounts have access to things beyond what they need, do divide networks into segments so that – for example – one machine with ransomware cannot directly infect your entire network.

Defend in depth

Change any business processes that require people to open e-mail attachments as part of their job. Offer services that help people do their job in a more convenient way that is also more secure. You cannot berate people for attempting to do their job. I mean, you can but it is not helpful.

Move backups off site and offline of course, for many reasons. But, do remember that having to recover a massive storage system from a backup can still be an extinction level event for a business even if you do have a working reliable off site backup solution. If you lose a large SAN you may be offline for days, and people will not be able to work, you may need to bring sites offline while storage recovers. When you procure a sophisticated storage solution, do not forget to design a recovery strategy ahead of time for how to rebuild a massive spinning rust storage array from absolute zero while new data is continuously generated. It is a non-trivial design challenge that probably needs tailoring to how your business operates. The point is, avoiding the situation where you need to actually restore your entire storage from tapes is always best.

Next level

Despite the intro, I have so far only mentioned things that any company needs to think about. There are of course organisations that are actually targeted. Financial institutions, large e-retailers or software supply chain companies run a greater risk of being manually targeted by evildoers.


Designing a secure process for delivering software updates is not trivial, I am not in any position to give direct advice beyond suggesting that if you are intending to do that, to consider from the beginning how to track vulnerabilities but also how to effectively remove versions that have been flagged as actively harmful, and how to support your users if they have deployed something dodgy. If that day comes, you need to at least be able to help your users. It will still be awful, but if you treat your users right, you might still make it.


Your people will be exploited. Every company that has an army of customer service representatives will need to make a trade-off between customer convenience and security. Attacks on customer service reps are very common. If you have high-value clients, people will use you to get to your clients’ money. There is nothing to say here, other than obviously you will be working with relevant authorities and regulatory bodies, as well as fine tune your authentication process so that you ask for confirmation information that is not readily available to an attacker.


I don’t have any numbers on this, so I am unsure how big of a problem this is, but it is mentioned often in security. Basically, humans can be exploited in a different way. Employees can be coerced through intimidation, blackmail or bribery to act maliciously on behalf of an attacker. My suspicion is that this is less common than employers think, and that times when an employee was stressed or distracted and fell for a phishing e-mail, the employer would think “that is too obvious of a phish, this guy must have been in on it”.

It makes me think of that one time when a systemic failure on multiple levels meant that a cleaner accidentally started a commuter train that ran from the depot the length of the commuter railway Saltsjöbanan – at maximum speed – eventually crashing through the buffers and into a building at the terminus. In addition to her injuries, she suffered the headlines “train stolen and crashed” until the investigation revealed the shocking institutional failings that had made this accident possible. I can’t remember all of them but there were things from the practices in how cleaners accessed the trains, how safety controls were disabled as a matter of course, how trains were stabled, the fact that points were left set so that a runaway train would actually leave the depot. A shambles. Yet the first reaction from the employer was to blame the cleaner.

Anyway, to return to the matter at hand – yes, although I cannot speculate on the prevalence it is a risk. Presumably, if you hire right and look after your people you can get them to come to you if they have messed up and gotten themselves into a compromised situations where they are being blackmailed or if somebody is leaning on them. Breeding a strong culture of fear can be counterproductive here – i.e. let people think that you will help them rather than fire them and litigate as long as they voluntarily come forward. If you are working in a regulated industry, things are complicated further by law enforcement in various jurisdictions.