Chefs and Cooks

I’m pretty good at cooking, if I do say so myself. That may be because I only cook a handful of dishes, or that may be because I’m extra attentive to the ingredients, the taste, and am obsessive about the details.

But, and this is an important distinction: I’m not a chef. I cannot make those beautiful and delicious meals chefs can, nor would I be able to if someone asked.

In the same vein, I can write tests, and I write lots of tests through TDD; but I’m not QA. My tests are documentation, bounds exploring, code that reflects decisions made, and an early warning system for potential problems in the architecture, but, my tests are not the tests a QA person would produce, and confusing the two would have the same effect as confusing my cooking abilities for a chef’s.

In case I haven’t hit the point hard enough home, let me say it outright:

QA has a very important job, a job that keeps most software afloat without the business even knowing it. All the TDD in the world can’t supplant the ability of QA to head off danger, and just saying “Developers can write tests too” doesn’t make Developers QA.

This is a very important lesson that some companies forget, and the markets remind them.

This post comes from my daily email list. If this sort of content appeals to you, you can sign up for the daily email below.

How many decisions do you make?

It’s amazing how many decisions we make in the course of developing a feature:
– How should this work?
– what does a developer need to call this method?
– What other parameters should we add?
– What should logging look like?
– How do we add new capabilities to this feature?
– Where should we store settings for this feature?

and on, and on, and on.

The cognitive load itself can be a bit heavy, and then there’s what can happen when you mix the features together. It starts to look like spaghetti if you aren’t careful.

One of the wonderful things about TDD is that it can help you make those decisions and it can show you the impact of those decisions far faster than implementing logging or setting storage or how parameters get added if you hadn’t had tests in place.

Without TDD, you have to implement a feature in at least two out of three layers of your application: either UI and Code, or Code and Database. With TDD, you take that time and you cut it down to just code.

That’s pretty remarkable, and can help you make decisions faster.

I’m covering this (and more) at the free webinar on March 5th, titled “Intro to TDD For .NET”. We’re not going to spend much time on the mechanics of TDD, rather we’re going to spend the time showing how TDD can actually help you. If that’s interesting to you, sign up here.

Meet your team where they are

There’s a lot of cool stuff out there that I’ve never had a chance to work with, and having just finished watching all of the .NET Conf 2020 videos(!), I’m excited to see what’s on the horizon and what’s available now. So I should probably just start suggesting this stuff when I’m working on a team, right?

Wrong. Dead wrong. As wrong as a person can be.

The team, any team has a culture, and that culture, the business context, the political context, the financial context, and the social context dictate how much a team can take on and whether the team is willing to learn something new. One of the many mistakes I’ve made is to try to show I can help out by suggesting new things to try; and that’s never worked well for me in situations where all those contexts weren’t lined up in my favor.

Sometimes people say no not because something can’t be done, but because something can’t be done given the current culture, political, business, or social context on the team. Recognizing the difference will go a long way to helping your team grow and thrive.


P.S., if the team is pushing back with ‘no’ a lot (an unenthusiastic ‘yes’ is also a no), it’s worth examining those contexts; what’s going on? What’s keeping the team from being engaged? The answers may surprise you.

Some things aren’t built to be tested

Reactive forms are fun in angular, and fun here means “not fun”.

They’re ‘fun’ because they’re meant to be testable; and easier to reason about, and they are… so long as you don’t do anything advanced, like form controls interacting with each other; or FormArrays, or anything like that.

Or, if you aren’t into Angular; have you ever tried to test an ASP.NET MVC (not .NET Core) controller?

There’s about 12 lines of mocking you have to do to unit test it; and it is a nightmare.

There are those that try to force testing into those situations; as if it’s a good idea to poke yourself in the eye.

Software is built by humans; and sometimes those humans didn’t try a ‘test first’ approach to their code. Trying to isolate and test in these situations means taking on a lot of brittleness by using Mocks and Stubs; and is that really the best use of our time?

There are times that if it hurts you should ‘do it until it doesn’t hurt’, but this isn’t one of those times. If you don’t have control over a library or framework and you find yourself encountering lots of pain trying to write tests for something that interacts with that library, maybe the best answer is… don’t.

Don’t write unit tests for their own sake

One problem I often hear about is that TDD is hard; and so teams come away with the idea that if they ignore TDD, and just write Unit Tests, they’ll get the value of TDD without the hard parts.

Let’s put aside for a moment that the tests are not the valuable part of TDD, and just go with the sentiment.

The desire to write unit tests lasts about as long as the team’s willpower to deal with the onslaught of issues they come across, but generally not longer than that.

At which point team members stop writing unit tests; or if they do, it’s because someone forces it as a part of check-in. That in itself speaks volumes.

Somewhere along the line our industry caught the belief that unit tests are valuable; and that they’re what teams should strive for. We’re all paying the price for that, though most of all the people that have to write tests because their definition of done says to.

Unit tests are a brittle, implementation (and thus point in time) specific method of determining the correctness of a particular approach to solving the problem:

They say nothing about whether the problem was actually solved, however.

Integration tests, for all their problems, at least can say with certainty that the problem you set out to solve was solved, whereas unit tests carry no such guarantee; yet with many of the same costs of an integration test.

We should push back harder against the idea of unit tests. It forces tests to follow code; and given production code that obstensibly works, no one is going to invest the time to change it to make it easier to test after the fact.

The missing ingredient to unit tests is that they don’t force you to change how you build software, because, let’s be honest, changing how you build software to make it testable is neither simple nor easy.

Building the political capital needed to bet the future of your company or your reputation on TDD is definitely not simple or easy.

Those are the roadblocks for any team that wants to build sustainable software: Learn; build political capital; change our style.

With those road blocks, why would you want to make it harder on yourself by writing unit tests because “that’s what you’re supposed to do”?

The answer is, You wouldn’t.

If code that’s easy to change and easy to check for correctness are things you want, then TDD can help you get there; but if you think you need to write tests because someone told you you should write tests without changing how you write code to be more testable; then take this as permission from me to not write tests. You’ll be happier, your team will be happier, and you’ll save yourself a lot of trouble.

First comes the slop, then the good stuff

Do you ever struggle with your code? Like, you know the answer is there somewhere, but whatever is popping out onto the IDE from the keyboard is definitely not it?

After a few times of this, you finally have the mental model that aligns perfectly with the problem and the solution just flows out.

It feels good, right?


Do you ever try to get to that magical feeling without producing, for lack of a better term, the slop first? Whether it’s code, a blog post, an email, or just a systems architecture diagram?

It doesn’t work, does it. You end up spinning your wheels and producing the slop anyway.

Turns out, this is normal and expected and we should embrace the slop:

Here’s to bad code?

This post originally appeared in my daily email newsletter. If this post interested you, sign up below to get more like it, daily*.

*ish.

Quick Fixes

How many times — when you’ve encountered a metaphorical system on fire– decided you’d implement a temporary ‘quick fix’ that you’ll come back to later?

How many times have you come back to it?

Quick fixes should really be called: “Stuff we’ll never come back to and we’ll grimace whenever we talk about”.

There are two ways to not have quick fixes:

– Perfect foreknowledge of the system you’re trying to build and how it will be used

OR

– Incremental and flexible design that you’re confident you can change

Guess which one is attainable?

On March 5th, 2021, I’m hosting a webinar titled “Introduction to Test Driven Development for .NET” which I probably should have titled How can TDD help my team build better systems? Naming is hard. Be that as it may, this webinar goes into the strategic benefits of TDD, and when it is (and isn’t) useful to adopt, all with real world examples from .NET.

Sign up here, and I look forward to seeing you on March 5th, 2021!

Does your code reward the right behavior?

We have rooms in our house; bedroom for sleeping, kitchen for cooking, dining room for dining, and my office is meant for work but in practice doesn’t reward work. There aren’t big distractions; but with the size of my keyboard, the (lack) of depth to my desk, and the fact that I have a curved monitor that *doesn’t* support a Vesa mount, I end up spending as much time fighting with the things on my desk as I do working, or at least it feels that way.

The solution, of course, is to buy furniture / set up all the things I need so that I don’t need to move anything around to work and to put the effort into ensuring that the entire focus of my office is work.

It sounds easy, right?

So why don’t we do that in our code bases?

A codebase should reward certain actions and discourage others. For instance, if you write Microservices, and you want to be sure you can’t reuse code, then setting up micro-repositories (one repository per service) might be an approach to solving that. You could also solve it through manual human intervention or “style guides”, but if we’re being honest we know they’re either ignored or used as a cudgel against those we don’t like. A mechanical guard against actions we don’t want developers to take in the codebase is the best way to go — it’s enforced by the unfeeling machine, and we don’t have to worry about hurting human relationships over the problem. Micro-repositories do this for Microservices (the fact that they both have ‘micro’ in front of them is coincidental, one does not imply the other).

We say this in our code, but not enough in our infrastructure or in our team setup: The right thing should be easy, the wrong thing should be impossible.

One step towards operating proficiently as a software team is to ensure that your team’s procedures, setup, guidelines, and rules that you want enforced are enforced at a mechanical level — a level that results in very neat paths for people to follow without devoting brain power to it.

Programming is hard enough without devoting brainpower to rules that should be enforced mechanically.

A lament about code reviews

When you start out working on a new feature or system; it’s easy to get caught up in the micro:


How should this method work? What should the consumer see? Where do I put this? What do I name it?

And all of those are good questions to ask; but even though they feel like giant obstacles before you start, they become pebbles once they’re done.

Once a system is built and shipped; the focus then turns to the system, and keeping the system running and reacting to the world around it.

What’s funny is that you end up asking the same exact questions, just on a larger scale:

How should this module work? What should the customer see? Where does this fit [in our system]? What do we call it?

The point is, even though those micro questions are important; they have far less impact on the outcome than the larger questions of how the system works together.

Or, to put the observation another way:

We spend far more time in code reviews on the micro questions; and less on the macro questions, even though 9 times out of 10 it’s those macro questions that will cause a problem later on.

Last Week in .NET #25 – I am (g)root

In what I can only describe as a “lead magnet”, here’s a copy of my weekly .NET newsletter, creatively titled “Last Week in .NET”. If this sort of thing interests you sign up for the newsletter or subscribe to the podcast. ♥

This is Last Week in .NET for the week that ended… well.. last week (January 16th, 2020). It was a rocky week last week; and more of the same expected this week for the Washington DC area, and with an inauguration and Martin Luther King day as our backdrop, let’s dive into what happened last week in the world of .NET.

Releases 📢

📢 .NET 5.0.2 has been released. This release fixes CVE-2021-1723 | ASP.NET Core Denial of Service Vulnerability attack. If you run .NET Core on Kestrel, you’re vulnerable to this attack, so update immediately. There are several bug fixes for ASP.NET Core, the .NET runtime, and Entity Framework Core 5 included as well.

📢 In the same vein, .NET Core 3.1.11 has been released with the same CVE 2021-1723 fix, as well as some backported fixes from .NET 5.0.2 and other fixes specific to .NET Core 3.1.

📢 Not to be left out, .NET Core 2.1.24 has also been released and at this point you can probably guess what I’m going to say: They fixed the aforementioned CVE vulnerability, as well as several backported bug fixes and bug fixes specific to .NET Core 2.1.

Speaking of .NET Core 2.1: Its End of Life is August 21, 2021 As stated in the blog post,

After that time, .NET Core 2.1 patch updates will no longer be provided. We recommend that you move any .NET Core 2.1 applications and environments to .NET Core 3.1 in first half of 2021. It’ll be an easy upgrade in most cases.

Parenthetically, of course, I hope your upgrades go better than mine usually do. I seem to hit every upgrade problem that could exist.

📢 Windows 10 version 20H2 Build 19042.746 has been released to the beta channels and these are chock full of security fixes that probably don’t matter to you and I, but matter greatly to enterprises.

📢 IdentityServer 5 has been released This is the first major release under the new company’s banner, and here’s to many more.

🍾 You can now write C# for embedded systems using NanoFramework THIS IS INCREDIBLE. I used C when writing the firmware for Jewelbots (Because let’s be honest there were no alternatives), and I’m excited to see that .NET is now a viable option. Part of me wants to take a few weeks and rewrite the firmware in Nanoframework, just to see if it’s possible, but the other part of me knows it’ll have to take a backseat to my TDD courses and classes. I will add it to the list, however.

Other .NET News

🎂Nuget celebrates its 10th birthday Just three more years until it becomes a bratty teenager.

🎥The EF Core team releases a video discussing what’s coming in EF Core 6 They used the survey to help guide their thoughts for EF Core 6; and while I have a personal disdain for survey-driven-development, I understand why they’d want to do it. There’s also a github issue related to EF Core 6 in case watching videos to get information is not your jam.

There’s a cheatsheet showing how to use C# 9 features from the team at Okta. Real world use cases for these features is a nice thing to show off, and I’m here for it. Special thanks to Heather Downing ([https://twitter.com/quorralyne](@quorralyne on Twitter) for the link.

💸Mobilize.NET can convert your VB and VB.NET Apps to.NET Core This seems like a neat little utility, and while there’s a company behind it, if you have a VB or VB.NET application, this may be your ticket to making the migration to .NET Core (and .NET 5). Check it out and let me know how it performs for you. (special thanks to Dee Dee Walsh (@ddskier on twitter) for the link.

📝Mana Pichova shares networking improvements made in .NET 5 this is a great read but is definitely on the heavier side. If networking is your jam, give this post a read.

📝Jimmy Bogard talks about ActivitySource and Listener in .NET 5. These classes are replacements for DiagnosticSource and Listener, so if you use either of those, give this post a read.

🌟ZeroSharp – a way to compile C# to native code, has hit 1000 stars on Github this is a wonderful milestone, and while github stars don’t pay the bills, it’s nice to see a .NET library hit wide usage.

😲The analysis of the Solarwinds Hack digs deeper, this time into replacing MSBuild. SUNSPOT was another malware vector in the Solarwinds hack, and this article goes deep into how it was used to replace MSBuild. This thing gets scarier and scarier.

😲Speaking of scarier and scarier, nuget packages can run arbitrary code on your system, and now I’m going to lie in my bathtub and rock gently, and that fantasy of buying a mountain cabin and living off the grid grows a step closer to reality.

🤼Jetbrains is hosting an AMA on January 21st, 2021 on Reddit and you’ll now have the opportunity to ask them how it feels to have Microsoft nipping at their heels for 21 years straight.

📝Khalid Abuhakmeh writes about what he’s learned in his time in .NET and there are some good lessons in there. Give it a read.

💰There’s a job opening for a REST API software engineer at Microsoft The only downside is it appears to be only for Redmond, Washington. In other words, not pandemic friendly.

💰There’s another job opening for Microsoft in the Atlanta area, and this one appears to allow remote This is for the OXO team, which is not, to my chagrin, is not pronounced ‘the hug and kiss and hug’ team.

🎥Headspring is hosting a webinar on January 21st detailing how they migrated an application to .NET core, this will dive deep into the strategy and tactics behind the migration, and should be a good event to attend if you’re thinking of doing the same.

📈The Azure team details its performance improvements from migrating from .NET Framework to .NET Core 3.1 It’s always great to see these sorts of in-depth analyses, and this one is no different.

📝Are you thinking of moving to Microservices, or event driven Architectures? IF so then you’ll want to read about Durable queues from Stephen Cleary. These primitives are necessary for an event-driven architecture, and it’s always great to read Stephen’s work.

Other News and Sundries

📝Microsoft is close to running all its own services on Azure. Not running your own services on your own cloud is generally a bad signal to send to the world when you want them to trust your cloud, and kudos to Microsoft to fixing this glaring issue.

🚂Bethesda, recently purchased by Microsoft, is making an Indiana Jones game YAAAAS. Sign me up.

😲The Parler ‘hack’ is a masterclass in bad ideas having bad outcomes If you haven’t kept up: Parler relied on several external services for security; but when those services were yanked away (due to Parler hosting neo-nazi and insurrectionist content), their code took the absence of such services as a reason to approve whatever action the user was trying to take. It’s the equivalent of your house security system letting everyone in if the phone-line goes down. There’s so much more to the Parler hack, from the lack of rate-limiting to the ability for people to pull down 60-70TBs of information from Parler’s AWS hosted storage, which — to add insult to injury, results in a massive egress bill from AWS to Parler, on top of AWS no longer hosting Parler.

🤗In the Things to make you feel good department](https://khalidabuhakmeh.com/six-famous-artists-quotes-that-apply-to-programming) Khalid Abuhakmeh shares six quotes from artists that apply to programming. We could all use some good news right now.

🎙Scott Hanselman interviews Amanda Silver about an entire division going remote during the pandemic When we said “The future of work is remote”, I’m not sure we were counting on a pandemic being the catalyst.

🤦‍♂️Github fired and then re-hired the person who made an internal team chat that said “Nazis are about” in the Capitol Insurrection This disgusted me when it happened: A Jewish github employee was fired for warning the company about literal nazis. The head of HR later fell on their sword for this egregious failure of leadership by the company, and it reinforces my question: Where the hell is the adult leadership at Github? Between the ICE contract and this, I’m not sure they realize what political sphere their company inhabits.

👨‍👩‍👧‍👦Techbash 2021 is going to tentatively be in person in the Pennsylvania Poconos. Is it just me or is this a little too soon? I mean, we’re recording the highest number of deaths ever from COVID and our vaccination plans are woefully under implemented at best. There is a virtual option, at least, so that’s good.

🐦Microsoft’s twitter game is getting better with a gif to show you show to de-clutter your screen. Where has this knowledge been all my life?

🎣There’s a phishing attempt at githubverification.com and it looks rather impressive. Be careful out there, folks. Special thanks to Tess Rinearson for the catch.


I’m hosting a webinar titled “Intro to TDD for .NET”), and if you’ve been wondering what TDD is, or at this point why you should care about it, this webinar is for you.

And that’s it for what happened last week in .NET. I’m George Stocker, and I help teams double their productivity through Test Driven Development. As always you’re a wonderful audience, and I will see you next week. Thanks.

Upcoming Events


FREE Intro to TDD for .NET live training – this 1 hour online webinar dives into what TDD is, why it’s useful, and how to get started with it in .NET.


Other services you may be interested in: (New Year, new prices!)

Private TDD Immersion Training for .NET teams – this 8-hour class provides your .NET team with the foundation and essentials needed to bring TDD to your production code-base. If your team wants to pursue TDD but is stymied by how to make it work in the real-world, this class is for you.

TDD Coaching Retainer – Mastered the basics but still aren’t able to bring TDD to your production code-base without a lot of mocks and stubs (and let’s face it: general pain)? With TDD coaching, I’m on-call to pair with your team whenever you need help. It’s a cost effective way to help your team get unstuck and deliver sustainable value, faster.