Code that was never executed in production

One of the greatest risk in software development is letting untested code slip in production. The general rule is: you should always execute your code and verify that it behaves as you expected before moving to production. Clearly we should prefer automated testing over manual testing, but at least we need to be sure that every part of the code was at least executed once before promote it to production.

A real example

Suppose we have this code that represents an Id based on a simple string.

public class StringId
{
    public String Value { get; set; }

    public static implicit operator String(StringId id)
    {
        return id.Value;
    }

    public override bool Equals(object obj)
    {
       //....
    }
}

And we have also a Customer class based on this type of Id

public class CustomerId : StringId
{
    public CustomerId(String rawValue)
    {
        this.Value = rawValue;
    }
}

public class Customer
{
    public CustomerId Id { get; set; }

    public String Name { get; set; }

    public String Surname { get; set; }

    public Int32 Age { get; set; }

    public Double TotalOrderAmount { get; set; }
}

Finally we have some services that handle accessing data in Sql Database with NHibernate and we have a function that return all customers. To simplify this discussion lets consider a service that keeps data in memory.

public class CustomerService
{

    public Dictionary<CustomerId, Customer> _inMemoryRepo = new Dictionary<CustomerId, Customer>();

    public void AddCustomer(Customer customer)
    {
        _inMemoryRepo[customer.Id] = customer;      
    }

    public IEnumerable<Customer> GetAllCustomers()
    {
        return _inMemoryRepo.Values
           .OrderBy(c => c.TotalOrderAmount)
           .ThenBy(c => c.Id);
    }
}

Trivial code isn’t it? Since it is super simple probably you think that there is no need for testing. If you believe that the above code is simple and correct, you missed a bug.

Let’s try to write a simple unit test that exercise the code.

[TestMethod]
public void verify_get_all_customers()
{
    CustomerService sut = new CustomerService();
    sut.AddCustomer(new Customer() { Id = new CustomerId("c1"), TotalOrderAmount = 10.0d });
    sut.AddCustomer(new Customer() { Id = new CustomerId("c2"), TotalOrderAmount = 5.0d });
    sut.AddCustomer(new Customer() { Id = new CustomerId("c3"), TotalOrderAmount = 16.0d });

    var result = sut.GetAllCustomers();
    result.Select(c => c.Id.Value)
        .Should()
        .Have.SameSequenceAs(new [] { "c2", "c1", "c3" });
}

This test is oversimplified, but it represent a similar test that you can write if the service access database trough repository interface.

This test is green, but you have a bug!

The real problem shows up only with certain test data. This new test can highlight the bug.

[TestMethod]
public void verify_get_all_customers_with_same_amount()
{
    CustomerService sut = new CustomerService();
    sut.AddCustomer(new Customer() { Id = new CustomerId("c1"), TotalOrderAmount = 16.0d });
    sut.AddCustomer(new Customer() { Id = new CustomerId("c2"), TotalOrderAmount = 10.0d });
    sut.AddCustomer(new Customer() { Id = new CustomerId("c3"), TotalOrderAmount = 16.0d });

    var result = sut.GetAllCustomers();
    result.Select(c => c.Id.Value)
        .Should()
        .Have.SameSequenceAs(new[] { "c2", "c1", "c3" });
}

Now examine the differencies: basically it is the same test as before, but now we have two customers with the same TotalOrderAmount, and the test fails with this message.

System.ArgumentException: At least one object must implement IComparable.

And this is caused by the .ThenBy LINQ instruction. This instruction tries to order objects based on Id property, but since it is a complex type, LINQ does not know how to order based on CustomerId class. The previous test never exercised the condition specified by the .ThenBy

The solution is really trivial, just implement the IComparable interface for the StringId base class and everything is green. The real problem happens when this error is discovered in production and you need to do some quick fix.

Lesson learned

This kind of problem is caused by letting slip in production code that was never executed, nor manually, nor with Unit Testing. This kind of code constitutes a time bomb in your system that can explode in every moment.

A possible solution is trying to cover all lines of code with Unit Test code coverage, but code coverage is no perfect. In the previous example if you run only the first unit test (the one that succeeds) you got 100% code coverage for CustomerService class. This happens because the code that was really not covered is inside the implementation of the ThenBy LINQ operator.

This can be a classic example on how difficult is writing Unit Tests that are able to discover every bug in your code.

Gian Maria.

What is

Programmers should speak the language of domain experts to avoid miscommunication, delays, and errors. To avoid mental translation between domain language and code, design your software to use the language of the domain. Reflect in code how users of the software think and speak about their work. One powerful approach is to create a domain model.

The ubiquitous language is a living language. Domain experts influence design and code and the issues discovered while coding influence domain experts. When you discover discrepancies, it's an opportunity for conversation and joint discovery. Then update your design to reflect the results.

The Art of Agile Development

Is it all about terms?

Some time ago I had the pleasure to meet with some friends for a GUISA meeting.

Andrea Saltarello gave the “Ubiquitous Language Smackdown” talk in which he shared his experience. We made a very similar experience ourselves (same terms, same communication issues with our customer), but I was firmly convinced that this approach could be used only on projects and was not suitable for products where domain experts are our clients (we craft business software for SME and Public Sector).

Based on our experience every client speaks it’s own language; it can depends on the market, the geographical location (even within the same country) and company size.

Among our products there’s a Manufacturing execution system; if we talk to a mechanical parts manufacturer we can refer to “Bill of Materials”, but if we talk to a fashion manufacturer and we say “Bill of Materials” the games are over: “your product is not for us, we don’t deal with BOM”. Their bill of materials (IT: “distinta base”) is “Scheda tecnica”; I don’t know how to correctly translate it with the correct meaning in english, maybe there’s not this distinction. If we talk with a PCB assembly company, “Scheda tecnica” means “Product Sheet”.

With all these terms referring to the same piece of functionality how can we design and code our model in an Ubiquitous way?

We gave up on UL until…

No, it’s all about Meaning…

One year later I was asked to do a three days class on CQRS+ES, usually I drop these kind of requests because it’s not our business, our goal is to delivery (working) software to our customers; teaching others to do the same is community stuff.

This time I made an exception, and something happened: “Semantic… semantic… semantic…” I found myself talking all the time about domain semantics and how domain semantics can help us to shape our models.

Probably that GUISA talk was the inception, unconsciously we started to use and profit UL in a new way (thanks again Andrea).

The whole thing emerged clearly with Evenstorming.

There's a sign on the wall but she wants to be sure
Cause you know sometimes words have two meanings

Stairway to Heaven - Led Zeppelin

We can’t use Ubiquitous Language with different customers and in our code base but we can use it on a smaller scope: a single organization.
Within a single organization Ubiquitous Language is an invaluable discovery tool; Ubiquitous Language exploration has become the cornerstone of our Evenstorming process (..more on slideshare).

…and Behaviour.

As expected, when we found that the same term is used by the people in the organization with different meanings we have probably saved many hours of work; I ask the users to write down on a wide blank post-it the meaning of every single term as soon as it materialize in any command / event / readmodel post-it.

The discussion starts and leads us very quickly to domain discovery down at the rainbow’s end!

Yes, that’s the fastest way to get to the “Pot of Gold”: term => meaning => use cases => behavior.

Stay tuned for the next post, I’ll tell you how Ubiquitous Language helped us to discover behaviour and model the “Document” aggregate in our DMS.

(spoiler: it’s not a single Aggregate root)

Why configurations are important

When you start working with .NET technologies it seems natural to place application settings inside app.config/web.config files, but this approach usually fails to be useful in long term for various reasons:

  • When a software is composed by multiple services it is good to have a single configuration point
  • Config file mixes application specific settings with .NET settings (es. assembly redirect and connection string)
  • Xml is not the best human readable format
  • Frictions for automatic deploy (web.config transform, SlowCheetah, etc)

Resist the urge for complexity

As a good rule of thumb, architectures capable of launching rocket into space should be avoided, unless launching a rocket is the real need. If you only need a better configuration manager for a set of services, simplicity should be the key.

Simplicity is the ultimate sophistication. Leonardo da Vinci

Keep It Simple, Stupid. Wikipedia

Since I love designing software architectures the risk is producing unnecessary complexity, and I’m trying to change this attitude. The goal should be designing the simplest thing that could possibly work:

Solving simple problem with complex solution, #FAIL.

Solving simple problem with simple solution, #GOOD.

Solving complex problem with complex solution, #GOOD.

Solving complex problem with simple solution, #GENIUS.

Jarvis need “now”, is moving settings away from multiple config files and having a single “configuration manager”; a json file with all the configuration is good enough to start. There are also some little pain for configuration, leading to a simple Configuration Manager class to encapsulate access to json configuration file with some facilities.

Keep in mind DevOps

Releasing sofware must be an easy and well documented procedure and Operational people should be facilitated in troubleshooting wrong configruations.

One of the pain point to address with the new configuration manager is getting rid of this code.

var sysUrl = new MongoUrl(ConfigurationManager.ConnectionStrings["system"].ConnectionString);
var sysdb = new MongoClient(sysUrl).GetServer().GetDatabase(sysUrl.DatabaseName);

This code can bite during deployment. Suppose a connection string is missing; when the service starts it chrashes without any useful log or clue of what is wrong. Logging raw exception can be good for developers, but fails to be useful for operational people. If you got a MongoException or a NullReferenceException with a stack trace you have absolutely no clue of what is wrong and where you can fix the error. One of the goal of good configuration manager is creating good logs full of useful information to troubleshoot wrong settings.

Thanks to a new configuration manager, I can simply substitute standard ConfigurationManager with the new implementation, leading to code version 2.

var sysUrl = new MongoUrl(CqrsConfigurationManager.Instance.GetSetting("connectionStrings.system"));
var sysdb = new MongoClient(sysUrl).GetServer().GetDatabase(sysUrl.DatabaseName);

The only difference is in the new CqrsConfigurationManager class; if the setting is missing I got a meaningful log: Required setting ‘connectionStrings.system’ not found in configuration: http://localhost/Jarvis/Debug/config.json. This log gives two important information: What is missing and where I should add the configuration.

Fail as first as possible (and with good log)

The situation is still not optimal because it address only missing configuration but not bad ones. What happens if the configuration is present but is wrong (es. wrong mongo connection string)? The answer is: it depends.

Usually the code will throw some exception somewhere and only when the configuration is really used. The when problem is one of the worst. If your software needs the address of a special mongo instance where it should save commands that raised exception during execution and that settings is wrong, the service starts without any error log, giving you false confidence that everything is good.

It is only when the code uses that connection string that you start having error logs, probably containing: MongoDbException: Unable to connect to server fingolfin:27017: No such host is known and absolutely no clue on how to fix it.

The rule is: I want my software to detect as soon as possible wrong configuration settings, and log every information needed to do the fix!. This lead to code version 3.

MongoDatabase sysdb = null;
CqrsConfigurationManager.Instance.WithSetting("connectionStrings.system", setting =>
{
    var sysUrl = new MongoUrl(setting);
    sysdb = new MongoClient(sysUrl).GetServer().GetDatabase(sysUrl.DatabaseName);
    sysdb.GetStats();
});

The semantic is simple; WithSetting accepts an optional lambda that should consume and/or validate the setting in a single step. If no exception is thrown or lambda returns empty string, configuration is considered to be good. If the connection string is wrong I immediately got an exception: Error during usage of configuration ‘connectionStrings.system’ - Config location: http://localhost/Jarvis/Debug/config.json - error: Unable to connect to server fingolfin:27017: No such host is known.. This log contains enough details to understand what configuration is wrong and where it should be fixed.

This is especially good if the setting is complex, ex: a comma separated list of integers.

List<Int32> parsedConfig = new List<int>();
CqrsConfigurationManager.Instance.WithSetting("coefficientList", setting =>
{
    var splitted = setting.Split(',');
    Int32 tmp;
    foreach (var number in splitted)
    {
        if (!Int32.TryParse(number, out tmp))
        {
            return "The value " + number +
                    " is not a number. I'm expecting a list of integer number comma separated.";
        }
        parsedConfig.Add(tmp);
    }
    return "";
});

If a wrong string 13,24,3O9 is found in configuration file (there is an O letter instead of zero in last number), the system will log this message: Error during usage of configuration ‘coefficientList’ - Config location: http://localhost/Jarvis/Debug/config.json - error: The value 3O9 is not a number. I’m expecting a comma separated list of integer.. Whenever a setting is consumed by the application, it is useful to consider a little variant of the famous rule found in Code for the maintainer

Always code as if the person who ends up installing your software is a violent psychopath who knows where you live!

Next post will deal on: Where do you specify location of json config file used by CqrsConfigurationManager?