Code Reviews: An Accurate Window into a Team's Health

Pull requests and code reviews are one of the most powerful software quality tools we have available in our tool-belt.

Even when flying (han) solo on a project, I tend to create feature branches and PRs and review my own code after a short break; I usually find a few things I can improve when doing that, with the added benefit of being able to switch easily to other work if needed.

In teams, the benefits are many and more significant: extra pair of eyes are always better in spotting improvement opportunities and catching mistakes, they consistently raise the quality of the project in all areas to the best of the team’s knowledge rather than individuals, they reduce the project risk by sharing knowledge and breaking down information silos while upskilling everyone. To a much much lesser degree of importance, they are about guarding the project against YOLO pushes of crap code – that’s more relevant for public, open-source projects; if that’s your main reason for using pull requests and code reviews, that’s a sign of bigger root problems in the team.

However, this post isn’t about those more commonly known benefits; it’s about how code reviews are one of the best places to observe and gauge a team’s health. I recently thought about this as I was reading the excellent book called “The Five Dysfunctions of a Team”, recommended to me by my dear colleague Mehdi Khalili.

In the book, Patrick Lencioni talks about the following five core team dysfunctions which build on top of each other. I’ll go through them and note how they can be observed in PRs and code reviews… Read more

Integration Testing in Azure Functions with Dependency Injection

I’m a big proponent of integration and functional tests (or “subcutaneous tests” if there’s a UI). Done efficiently and sparingly, they give you the biggest bang for your buck when it comes to confidence in the overall well-being of the majority of your system.

Dependency injection is ubiquitous these days, and ASP.NET Core MVC’s seamless support for integration testing via the Microsoft.AspNetCore.Mvc.Testing NuGet package has made this kind of testing simple when using dependency injection. However, I found that when dealing with Azure Function Apps, a similar setup is not as effortless as installing a package and using a WebApplicationFactory, especially since Azure Function projects aren’t set up for dependency injection out of the box. Fortunately, after a bit of digging under the hood of Microsoft.AspNetCore.Mvc.Testing and Microsoft.AspNetCore.TestHost, I’ve been able to create a similar testing experience which I’ll go through below… Read more

How to Version Your .NET NuGet Packages, Libraries and Assemblies + Azure YAML Pipelines Example using .NET Core CLI

I often see arbitrary patterns used for versioning packages and assemblies, especially for internal projects, with the only common goal being that the versions are increased with each release. There is rarely a distinction between NuGet package Version, AssemblyVersion, FileVersion and InformationalVersion and they’re commonly all set to the same value, if set at all. That’s not to blame anyone, having all these different ways to set a version is darn confusing.

However, if you plan to release a public NuGet package, or an internal package that could be heavily used, you’ll be making your life, and your users’ lives a lot easier, and avoid creating a “dependency hell”, if you distinguish between the above versions and follow a meaningful versioning strategy like Semantic Versioning.

If you haven’t heard about Semantic Versioning, here’s the TL;DR… Read more

Common C# async and await misconceptions

.NET Programmers have traditionally shied away from writing asynchronous code, and mostly for good reason. Writing asynchronous code used to be arduous work and the result was difficult to reason about, debug and maintain. That became exacerbated when you threw concurrency into the mix – parallel or asynchronous – as that’s harder to consciously follow for our brains which are optimised/trained for non-concurrent and sequential logic.

The compiler magic of async/await since C# 5.0 and the Task-based Asynchronous Pattern has immensely improved that experience, mainly by abstracting asynchronous code to read like synchronous code. In fact it’s been such a big hit that it’s spread and been adopted by many other popular languages such as JavaScript, Dart, Python, Scala and C++.

This has resulted in a trend of more and more asynchronous code popping up in our code-bases. That’s mostly a good thing, because leveraging asynchrony in the right place can lead to significant performance and scalability improvements. However, with all great magic, comes great misconception. I’ll go over some of the most common ones below which I encounter often… Read more

Good Practices for Enterprise Integrations over the Azure Service Bus

Integrating systems over a good messaging infrastructure has many benefits if done right. Some of these are system/network decoupling and platform agnosticism, independent scalability, high reliability, spike protection, a central place to keep an eye on your integrations and more depending on your situation.

Many of these benefits are vast topics on their own. But the point of this article is to go over some of the pitfalls when implementing large-scale integrations over a messaging infrastructure and guidelines for avoiding them.

These are based on my learning from a recent project which involved improving a client’s existing integration between 5+ large systems. While the messaging infrastructure in use was the Azure Service Bus, I believe most of these points apply to all other message-based integrations and service buses… Read more

The Dangerous EF Core Feature: Automatic Client Evaluation

Update: starting from EF Core 3.0-preview 4, this damaging default behavior has been greatly limited, although not completely turned off.

Recently when going through our shiny new ASP.NET Core application’s logs, I spotted a few entries like this:

The LINQ expression ‘foo’ could not be translated and will be evaluated locally.

Odd.

I dug around in the code and found the responsible queries. Some of them were quite complex with many joins and groupings, while some of the other ones were quite simple… Read more

Create Your Own Visual Studio Code Snippets

Visual Studio Code Snippets are awesome productivity enhancers; I can only imagine how many millions of keystrokes I’ve saved over the years by making a habit out of using them.

Although a lot of common code you use daily might not be available out of the box, adding them yourself is very simple… Read more

Allowing Only One Instance of a C# Application to Run

Making a singleton application, i.e., preventing users from opening multiple instances of your app, can be easily implemented using a Mutex.

A Mutex is similar to a C# lock, except it can work across multiple processes, i.e. it is a computer-wide lock. Its name comes from the fact that it is useful in coordinating mutually exclusive access to a shared resource… Read more

Modeling PowerToys for Visual Studio 2013

I rarely use tools that generate code, however, one that has become a fixed asset of my programming toolbox is Visual Studio’s class designer. It’s a great productivity tool that helps you quickly visualize and understand the class structure of projects, classes and class members. It’s also great for presentation of code-base that does not come with a UI, e.g. a Class Library… Read more

Git: Commit with a UTC Timestamp and Ignore Local Timezone

When you git commit, Git automatically uses your system’s local timezone by default, so for example if you’re collaborating on a project from Brisbane (UTC +10) and do a commit, your commit will look like this:

commit c00c61e48a5s69db5ee4976h825b521ha5bx9f5d
Author: Your Name <your@email.com>
Date:   Sun Sep 28 11:00:00 2014 +1000 # <-- your local time and timezone offset

Commit message here

If you find it rather unnecessary to include your local timezone in your commits, and would like to commit in UTC time for example, you have two options… Read more