TIL: Dictionary keys are converted to lowercase too on serialization

Today, I needed to pass a dictionary between two ASP.NET Core 6.0 API sites. To my surprise, on the receiving side, I got the dictionary with all its keys converted to lowercase instead of PascalCase. I couldn’t find any element on the dictionary, even though the keys had the same names on each API site. This is what I learned about serializing dictionary keys.

Serialization with Newtonsoft.Json

It turns out that the two API sites were using Newtonsoft.Json for serialization. Both of them used the CamelCasePropertyNamesContractResolver when adding Newtonsoft.Json.

Something like this,

using Newtonsoft.Json.Serialization;
using Newtonsoft.Json;

var builder = WebApplication.CreateBuilder(args);
builder.Services
    .AddControllers()
    .AddNewtonsoftJson(options =>
    // ^^^^^
    {
        options.SerializerSettings.NullValueHandling
            = NullValueHandling.Ignore;

        options.SerializerSettings.ContractResolver
            = new CamelCasePropertyNamesContractResolver();
            //    ^^^^^
            // This is what I mean
    });

var app = builder.Build();
app.MapControllers();
app.Run();

With CamelCasePropertyNamesContractResolver, Newtonsoft.Json writes property names in camelCase. But, Newtonsoft.Json treats dictionary keys like properties too.

That was the reason why I got my dictionary keys in lowercase. I used one-word names and Newtonsoft.Json made them camelCase.

To prove this, let’s create a simple controller that read and writes a dictionary. Let’s do this,

using Microsoft.AspNetCore.Mvc;

namespace LowerCaseDictionaryKeys.Controllers;

[ApiController]
[Route("[controller]")]
public class DictionaryController : ControllerBase
{
    [HttpPost]
    public MyViewModel Post(MyViewModel input)
    {
        return input;
        //     ^^^^^
        // Just return the same input
    }
}

public class MyViewModel
{
    public IDictionary<string, string> Dict { get; set; }
}

Now, let’s notice in the output from Postman how the request and the response differ. The keys have a different case. Arggg!

Postman request and response bodies
Postman request and response bodies

1. Configure Newtonsoft.Json naming strategy

To preserve the case of dictionary keys with Newtonsoft.Json, configure the ContractResolver setting with CamelCaseNamingStrategy class and set its ProcessDictionaryKeys property to false.

When registering Newtonsoft.Json, in the SerializerSettings option, let’s do:

using Newtonsoft.Json.Serialization;
using Newtonsoft.Json;

var builder = WebApplication.CreateBuilder(args);
builder.Services
    .AddControllers()
    .AddNewtonsoftJson(options =>
    // ^^^^^
    {
        options.SerializerSettings.NullValueHandling
            = NullValueHandling.Ignore;

        options.SerializerSettings.ContractResolver
            = new CamelCasePropertyNamesContractResolver
            {
                NamingStrategy = new CamelCaseNamingStrategy
                {
                    ProcessDictionaryKeys = false
                    // ^^^^^
                    // Do not change dictionary keys casing
                }
            };
    });

var app = builder.Build();
app.MapControllers();
app.Run();

For more details, see Newtonsoft.Json docs to Configure NamingStrategy dictionary serialization.

After changing the naming strategy, let’s see the response of our sample controller. That’s what I wanted!

Postman request and response after changing NamingStrategy
Postman request and response bodies

What about System.Text.Json?

To maintain case of dictionary keys with System.Text.Json, let’s set the DictionaryKeyPolicy property inside the JsonSerializerOptions to JsonNamingPolicy.CamelCase.

In our Program.cs class, let’s write,

using System.Text.Json;

var builder = WebApplication.CreateBuilder(args);
builder.Services
    .AddControllers()
    .AddJsonOptions(options =>
    // ^^^^^
    {
        options.JsonSerializerOptions
            .DictionaryKeyPolicy = JsonNamingPolicy.CamelCase;
            // ^^^^^
    });

var app = builder.Build();
app.MapControllers();
app.Run();

For more naming policies, see Microsft docs to customize property names and values with System.Text.Json.

2. Use a comparer with dictionaries

Another alternative is to use a dictionary with a comparer that ignores case of keys.

On the receiving API site, let’s add an empty constructor on the request view model to initialize the dictionary with a comparer to ignore cases.

In my case, I was passing a metadata dictionary between the two sites. I could use a StringComparer.OrdinalIgnoreCase to create a dictionary ignoring the case of keys.

This way, no matter the case of keys, I could find them when using the TryGetValue() method.

public class MyViewModel
{
    public MyViewModel()
    {
        Dict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
        //                                    ^^^^^
    }

    public Dictionary<string, string> Dict { get; set; }
}

Voilà! That’s how we can configure the case of dictionary keys when serializing requests and how to read dictionaries with keys no matter the case of its keys.

If you want to read about ASP.NET Core, check how to add a caching layer and how to read your appsettings.json configuration file. To avoid KeyNotFoundException and other exceptions when working with dictionaries, check my idioms on dictionaries.

Happy C# time

Don't duplicate logic in Asserts: The most common mistake on unit testing

We have covered some common mistakes when writing unit tests. Some of them may seem obvious. But, we all have made this mistake when we started to write unit tests. This is the most common mistake when writing unit tests and how to fix it.

Don’t repeat the logic under test when verifying the expected result of tests. Instead, use known, hard-coded, pre-calculated values.

Let’s write some tests for Stringie, a (fictional) library to manipulate strings with a fluent interface. Stringie has a Remove() method to remove substrings from the end of a string.

We can use Stringie Remove() method like this,

var hello = "Hello, world!";

string removed = hello.Remove("world!").From(The.End);
// "Hello,"

Don’t Copy and Paste the tested logic

When writing unit tests, don’t copy the tested logic and paste it into private methods to use them inside assertions.

If we bring the tested logic to private methods in our tests, we will have code and bugs in two places. Duplication is the root of all evil. Even, inside our tests.

Please, don’t write assertions like the one in this test.

[TestMethod]
public void Remove_ASubstring_RemovesThatSubstringFromTheEnd()
{
    string str = "Hello, world!";

    string transformed = str.Remove("world!").From(The.End);

    Assert.AreEqual(RemoveFromEnd(str, "world!"), transformed);
    //              ^^^^^
    // We duplicate the Remove logic in another method
}

private string RemoveFromEnd(string str, string substring)
{
    var index = str.IndexOf(substring);
    return index >= 0 ? str.Remove(index, substring.Length) : str;
}
building of apartments
That's a lot of duplication. Photo by Joshua Chai on Unsplash

Don’t make internals public

Also, by mistake, we expose the internals of the tested logic to use them in assertions. We make private methods public and static. Even to test those private methods directly.

From our Unit Testing 101, we learned to write unit tests through public methods. We should test the observable behavior of our tested code. A returned value, a thrown exception, or an external invocation.

Again, don’t write assertions like the one in this test.

[TestMethod]
public void Remove_ASubstring_RemovesThatSubstringFromTheEnd()
{
    string str = "Hello, world!";

    string transformed = str.Remove("world!").From(The.End);

    Assert.AreEqual(Stringie.PrivateMethodMadePublicAndStatic(str), transformed);
    //              ^^^^^
    // An "internal" method exposed to our tests 
}

Use known values to Assert

Instead of duplicating the tested logic, by exposing internals or copy-pasting code into assertions, use a known expected value.

For our sample test, let’s simply use the expected substring "Hello,". Like this,

[TestMethod]
public void Remove_ASubstring_RemovesThatSubstringFromTheEnd()
{
    string str = "Hello, world!";

    string transformed = str.Remove("world!").From(The.End);

    Assert.AreEqual("Hello,", transformed);
    //              ^^^^^^^^
    // Let's use a known value in our assertions
}

If we end up using the same expected values, we can create constants for them. Like,

const string Hello = "Hello";
// or
const string HelloAndComma = "Hello,";

Voilà! That’s the most common mistake when writing unit tests. It seems silly! But often, we duplicate Math operations and string concatenations and it passes unnoticed. Remember, don’t put too much logic in your tests. Tests should be only assignments and method calls.

If you’re new to unit testing, read my post on how to write your first unit tests in C# with MSTest and check the 4 common mistakes when writing your first tests. Also, don’t miss my Unit Testing 101 series where I cover more subjects like the ones from this post.

Ready to upgrade your unit testing skills? Write readable and maintainable unit test with my course Mastering C# Unit Testing with Real-world Examples on Udemy. Learn unit testing best practices while refactoring real unit tests from my past projects. No tests for a Calculator class.

Happy testing!

Two C# idioms: On defaults and switch

This post is part of the series "C# idioms"

  1. Two C# idioms
  2. Another two C# idioms
  3. Two C# idioms: On Dictionaries
  4. Two C# idioms: On defaults and switch This post

In this part of the C# idioms series, we have one idiom to write more intention-revealing defaults and another idiom to convert mapping code using a switch to a more compact alternative using a dictionary.

Use intention-revealing defaults

When initializing variables to default values, use intention-revealing alternatives.

Are you initializing a string variable to later assign it? Use "". Do you want to return an empty string from a method? Use string.Empty.

The same is true for collections. If you’re initializing a collection to later add some elements, use the normal constructors like new string[length]; or new List<string>();.

But, if you want to return an empty collection. Use Array.Empty<string>() or Enumerable.Empty<string>().

Replace switch with a dictionary

Replace switch mapping two types with a dictionary.

Turn every value in the case statements into a key in the dictionary. And, turn the returned value in every case into the value of the matching key in the dictionary.

To replace the default case, take advantage of the TryGetValue() or GetValueOrDefault() methods.

Before, to map from a credit card brand name in strings to a CardType enum, we did this,

public static CardType MapToCardType(string cardBrand)
{
    CardType cardType;

    switch (cardBrand)
    {
        case "Visa":
            cardType = CardType.Visa;
            break;

        case "Mastercard":
            cardType = CardType.MasterCard;
            break;

        case "American Express":
            cardType = CardType.AmericanExpress;
            break;

        default:
            cardType = CardType.Unknown;
            break;
    }
    return cardType;
}

After, replacing the switch with a Dictionary,

public static CardType MapToCardType(string cardBrand)
{
    var cardTypeMappings = new Dictionary<string, CardType>
    {
        { "Visa", CardType.Visa },
        { "Mastercard", CardType.Mastercard },
        { "American Express", CardType.AmericanExpress }
    };
    return cardTypeMappings.TryGetValue(cardBrand, out var cardType)
                ? cardType
                : CardType.Unknown;
}

C# 8.0 and Dictionaries

Also, we can use the newer switch syntaxt from C# version 8.0 to write more compact switch.

Starting from C# version 8.0, switch are expressions. It means we can assign switch to variables and use switch as returned values.

Notice how we use a discard _ in the default case to throw an exception.

public static CardType MapToCardType(string cardBrand)
{
    return cardBrand switch
    {
      "Visa" => CardType.Visa,
      "MasterCard" => CardType.MasterCard,
      "American Express" => CardType.AmericanExpress,
      _ => CardType.Unknown
    };
}

Voilà! These are the C# idioms for today. Remember to use intention-revealing defaults and take advantage of the new C# features for switch.

If you want to check more C# recent features, check my Top 16 newest C# features. To get rid of exceptions when working with dictionaries, check Idioms on Dictionaries.

And, don’t miss the other C# Idioms.

Happy coding!

My Top 16 newest C# features by version

C# is a language in constant evolution. It has changed a lot since its initial versions in the early 2000’s. Every version brings new features to write more concise and readable code. These are some C# features I like the most and use often. Hope you find them useful too.

Let’s start with the best C# features by version, starting from version 6.

C# 6.0

String interpolation: $”Hello, {name}”

Before with string.Format(), we could miss a parameter or add them in the wrong order. If we forgot a parameter, we will get a FormatException.

With string interpolation, we can inline variables directly in the string we want to build. To use string interpolation, before the opening quote of your string, let’s add $ and wrap our variables around {}.

Before with string.Format(),

string.Format("Hello, {0} {1}", title, name);

But, if we forgot to add one parameter,

string.Format("Hello, {0} {1}", title/*, I forgot to add the name parameter*/);
// ^^^^^
// System.FormatException:
//    Index (zero based) must be greater than or equal to zero and less than the size of the argument list.

After with string interpolation,

$"Hello, {title} {name}";

Now, it’s clearer if we’re missing a parameter or if we have them in the wrong order.

Null-conditional (?.) and null-coalescing operators (??)

Starting from C# 6.0, we have two new operators: null-conditional ?. and null-coalescing ?? operators. These two new operators helps us to get rid of null values and NullReferenceException.

With the null-conditional ?. operator, we access a member’s object if the object isn’t null. Otherwise, it returns null.

The null-coalescing ?? operator evaluates an alternative expression if the first one is null.

Before,

string name = ReadNameFromSomewhere();
if (name == null)
{
    name = "none";
}
else
{
    name.Trim();
}

After,

string name = ReadNameFromSomewhere();
name?.Trim() ?? "none";

It executes Trim() only if name isn’t null. Otherwise, name?.Trim() returns null. But, with the ?? operator, the whole expression returns “none”.

Expression body definition (=>)

Now, one-line functions are truly one liners. We can use => to declare the body of methods and properties in a single line of code.

Before,

public int MeaningOfLife()
{
    return 42;
}

After,

public int MeaningOfLife()
    => 42;

nameof expression

As its name implies, the nameof operator returns the name of a variable, type or member as a string. It makes renaming things easier.

Before without nameof,

public void SomeMethod(string param1)
{
    if (string.IsNullOrEmpty(param1))
        throw new ArgumentNullException("param1");
}

After with nameof,

public void SomeMethod(string param1)
{
    if (string.IsNullOrEmpty(param1))
        throw new ArgumentNullException(nameof(param1));
        //                              ^^^^^
}

C# 7.X

Throw expressions

Now, throws are expressions. It means we can use them inside conditionals and null coalescing expressions.

We can combine the ??, throw and nameof operators to check required parameters inside constructors. For example,

public class Movie
{
    private readonly string _title;
    private readonly Director _director;

    public Movie(string title, Director director)
    {
        _title = title;
        _director = director ?? throw new ArgumentNullException(nameof(director));
        //                      ^^^^^
    }
}

Notice, how the ?? operator evaluates the expression on the right, which is a throw.

new Movie("Titanic", null);
//  ^^^^^
// System.ArgumentNullException: Value cannot be null.
// Parameter name: director

out variables

We can inline the variable declaration next to the out keyword using the var keyword.

Before, we had to declare a variable in a separate statement,

int count = 0;
int.TryParse(readFromKey, out count);

After, inlining the variable declaration,

int.TryParse(readFromKey, out var count);
//                            ^^^ 

Instead of declaring a variable, we can use discards _ to ignore the output value. For example,

int.TryParse(readFromKey, out _);

I’m not a big fan of methods with out references. But, with this feature I like them a bit more. I prefer tuples.

Tuples

Speaking of tuples…Now we can access tuple members by name. We don’t need to use Item1 or Item2 anymore.

We can declare tuples wrapping its members inside parenthesis. For example, to declare a pair of coordinates, it would be (int X, int Y) origin = (0, 0).

We can use named members when declaring methods and deconstructing returned values.

Before,

Tuple<string, string> Greet()
{
    return Tuple.Create("Hello", "world");
}

var greeting = Greet();
var name = greeting.Item1;

After,

(string Salutation, string Name) Greet()
{
    return ("Hello", "world");
}

var greeting = Greet();
var name = greeting.Name;

Even better,

(string Salutation, string Name) Greet()
{
    return ("Hello", "world");
}

var (Salutation, Name) = Greet();

Do you remember discards? We can use them with tuples too.

(_, string name) = Greet();

Asynchronous Main methods

Now, async Main methods are available in Console applications.

Before,

public static int Main(string[] args)
{
    return DoSomethingAsync().GetAwaiter().GetResult();
}

After,

public static async Task<int> Main(string[] args)
{
    await DoSomethingAsync();
}

Pattern matching

With pattern matching, we have more flexibility in control flow structures like switch and if. Let’s see a couple of examples.

On one hand, we can avoid casting types inside if statements.

Before without pattern matching, we needed to cast types,

var employee = CreateEmployee();
if (employee is SalaryEmployee)
{
    var salaryEmployee = (SalaryEmployee)employee;
    DoSomething(salaryEmployee);
}

After, with pattern matching, we can declare a variable in the condition,

if (employee is SalaryEmployee salaryEmployee)
//                             ^^^^^
{
    DoSomething(salaryEmployee);
}

On another hand, we can use a when clause inside switch.

Before, we had to rely on if statements inside the same case, like this

var employee = CreateEmployee();
switch (employee)
{
    case SalaryEmployee salaryEmployee:
        if (salaryEmployee.Salary > 1000)
        {
            DoSomething(salaryEmployee);
        }
        else
        {
            DoSomethingElse(salaryEmployee);
        }
        break;

    // other cases...        
}

Now, with pattern matching, we can have separate cases,

var employee = CreateEmployee();
switch (employee)
{
    case SalaryEmployee salaryEmployee
            when salaryEmployee.Salary > 1000:
    //      ^^^^
        DoSomething(salaryEmployee);
        break;

    case SalaryEmployee salaryEmployee:
        DoSomethingElse(salaryEmployee);
        break;

    // other cases...
}

I found it more readable this way. Let’s keep the conditional case before the one without conditions.

Tools on a workbench
Photo by Oxa Roxa on Unsplash

C# 8.0

switch expressions

Speaking of switch statements, starting from C# 8.0 switch are expressions. It means we can assign a switch to a variable or return a switch from a method.

Before a switch looked like this one,

CardType cardType;

switch (cardBrand)
{
    case "Visa":
        cardType = CardType.Visa;
        break;

    case "MasterCard":
        cardType = CardType.MasterCard;
        break;
        
    case "American Express":
        cardType = CardType.AmericanExpress;
        break;
        
    default:
        throw new ArgumentException(cardBrand);
}

After with switch as expressions,

CardType cardType = cardBrand switch
{
    "Visa" => CardType.Visa,
    "MasterCard" => CardType.MasterCard,
    "American Express" => CardType.AmericanExpress,
    _ => throw new ArgumentException(cardBrand)
};

Switch expressions are more compact, right? Did you notice we assigned the result of the switch to the cardType variable? Cool!

Indices and ranges

If you have used negative indices in Python, you would find this feature familiar. In Python, we use negative indices to reference elements from the end of lists.

We have a similar feature in C#, not with negative indices, but with the index from end operator, ^.

With the index from end operator, the last element of an array would be array[^1].

Before, we had to substract from the length of the array to access an element from the end. The last element of an array was array[array.Length - 1].

var helloWorld = new string[] { "Hello", ", ", "world!" };
helloWorld[helloWorld.Length - 1]; // "world!"

After, with the index from end operator,

var helloWorld = new string[] { "Hello", ", ", "world!" };
helloWorld[^1]; // "world!"

In the same spirit, we have ranges. An array without its last element would be array[0..^1]

var helloWorld = new string[] { "Hello", ", ", "world!" };
string.Join("", helloWorld[0..^1]); // Hello,

Null-coalescing assignment (??=)

Do you remember the ?. and ?? operators? Now, there is another operator to work with null. The null-coalescing assignment operator, ??=. It only assigns a variable if its value isn’t null.

Before,

int? magicNumber = ReadMagicNumberFromSomewhere();

if (magicNumber == null)
    magicNumber = 7;

After,

int? magicNumber = ReadMagicNumberFromSomewhere();

magicNumber ??= 7;

Using declarations

A variable preceded by using is disposed at the end of the scope. We can get rid of the parethensis around using statements and the brackets wrapping its body.

Before,

using (var reader = new StreamReader(fileName))
{
    string line; 
    while ((line = reader.ReadLine()) != null)  
    {  
        // Do something  
    }  
}

After,

using var reader = new StreamReader(fileName);
string line; 
while ((line = reader.ReadLine()) != null)  
{  
    // Do something  
}

Nullable reference types

With C# 8.0, all reference variables are non-nullable by default. Any attempt to dereference a nullable reference gets a warning from the compiler. Goodbye, NullReferenceException!

To declare a variable that can be null, we need to add to its type declaration an ?. The same way we have always declared nullable value types like int?. For example, a nullable string would be string? canBeNull;

This is a breaking change. We need to turn on this feature at the project level. To do so, let’s add <Nullable>enable</Nullable> inside the PropertyGroup in our csproj files.

For a console application, the csproj file with this feature turned on look like this:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <Nullable>enable</Nullable>
    <!--      ^^^^^^    -->
  </PropertyGroup>

</Project>

Before, if we access a member of a null reference, we get a NullReferenceException.

string name = null;
SayHi(name); // <- System.NullReferenceException
// ^^^
// System.NullReferenceException: 'Object reference not set to an instance of an object.'
// name was null.

void SayHi(string name)
  => Console.WriteLine(name.Trim());

But now, we get a compiler warning,

string name = null;
// ^^^^^
// warning CS8600: Converting null literal or possible null value to non-nullable type.

string? canBeNullName = null;
SayHi(name);
// ^^^^^
// warning CS8604: Possible null reference argument for parameter 'name'

To get rid of the compiler warning, we have to check for null values first.

string? canBeNullName = null;
if (canBeNullName != null)
{
    SayHi(name);
}

C# 9.0

Records

A record is an immutable reference type with built-in equality methods. When we create a record, the compiler creates ToString(), GetHashCode(), value-based equality methods, a copy constructor and a deconstructor.

Records are helpful to replace value-objects in our code.

public record Movie(string Title, int ReleaseYear);

Top-level statements

All the boilerplate code is now gone from Main methods. It gets closer to scripting languages like Python and Ruby.

Before, to write the “Hello, world!” program in C#, we needed to bring namespaces, classes, methods and arrays only to print a message out to the console.

using System;

namespace HelloWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

After, it boils down to only two lines.

using System;

Console.WriteLine("Hello World!");

C# 10.0

File-scoped namespace declaration

With C# 10.0, we can simplify namespace declaration inside our classes.

Before,

namespace Movies
{
    public class Movie
    {
        // ...
    }
}

After, we can reduce the level of indentations by using a semicolon on the namespace declaration,

namespace Movies;

public class Movie
{
    // ...
}

ThrowIfNull

ArgumentNullException has a helper ThrowIfNull() to help us check for required parameters in our methods.

Before,

public void SomeMethod(string param1)
{
    if (string.IsNullOrEmpty(param1))
        throw new ArgumentNullException(nameof(param1));
        //                              ^^^^^
}

After,

public void SomeMethod(string param1)
{
    ArgumentNullException.ThrowIfNull(param1);
    //                    ^^^^^
}

Global using statements

C# 10.0 reduces the boilerplate from our classes even further by hiding common using declarations.

Before, a “Hello, world” program looked like this,

using System;

namespace HelloWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

Now, with Top-level statements and global using statements, it’s a single line of code,

Console.WriteLine("Hello World!");

This is a feature is enabled by default, but we can turn it off in our csproj files. For example, this is the csproj file of a Console app with global using statements and nullable references.

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <!--            ^^^^^^    -->
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

Voilà! These are the C# features I like the most. Which ones didn’t you know about? Which ones you use most often? What features would you like to see in future versions?

Do you want to learn more about the C# language? Check my C# Definitive Guide. It contains the subjects I believe all intermediate C# developers should know. Are you new to LINQ? Check my quick guide to LINQ with examples. And, don’t miss my C# idioms series.

Happy coding!

Monday Links: Farmers, Incidents & Holmes

Today I want to start a new series: Monday Links. I want to share interesting and worth-sharing blog posts, articles or anything I read online in the last month or two. You may find them interesting and instructive too.

Farmers always Worked From Home

We’re in the work-from-home era. But, farmers have always worked from home. This article states we all got the work-life balance wrong. Speaking about a farmer neighbor…“He does what he needs to, and rests in between”. Read full article

An Old Hacker’s Tips On Staying Employed

An ode to personal brand. Build a reputation that will take of you on rough times. The “Two and Done” principle was my favorite. When making a decision, present your case only twice. After that, say that you have outlined your options and you want to move on taking somebody else’s idea. Read full article

MOCR 2 during the Apollo 13 crisis
Houston, we have a problem! Photo by NASA, Public Domain

Secrets of great incident management

Incident commander, driver, communicator, recorder, researcher…It reminds me one of those movies about space missions. “Houston, we have a problem!” Outages are stressful situations for sure. People running, pointing fingers, making phone calls…the worst thing is when only you figure out you have an outage when you get a phone call from one of your clients. Arrggg! Read full article

Patterns in confusing explanations

It explains how not to explain things. I felt guilty of doing some of these anti-patterns. The ones about analogies, ignoring the whys…One piece of advise I liked was to write for one person in mind. Imagine a friend or coworker and explain the subject to her. Read full article

What Programmers Can Learn From Sherlock Holmes

What Sherlock Home stories and programming have in common. Not all facts are obvious to everyone. We all have one Lestrade in our programmer’s life. I liked those two things. Read full article

Voilà! These were my most favorites reads from the last couple of months. See you in a month or two in the next Monday Links! In the mean time, stay tune to my Unit Testing 101 series to learn from how to write your first unit tests with MSTest to how to write custom assertions.

Happy reading!