Sunday, 17 October 2021

Picking a Better Data Store


I like Entity Framework.  It's like arriving at Hogwarts and trying out your wand for the first time .  Sometimes you wave it, and it transforms your rat into a perfect water goblet.  Other times it just blows up in your face, and you have to spend the rest of your high school years trying to master the correct incantation.

The question is, "Why do you have to have magic to transform your code into SQL?"  I used to say for unit testing, but if I want to test my units (whatever a unit is), I could just run them against an in-memory database.  Why do we need to transform a rat into a water goblet, when we could just go out and buy a water goblet, and keep our pet rat?  A rat is not a water goblet, neither is my Linq code TSQL, nor is my aggregate a table.

I use Entity Framework for two reasons: because it's fun, and to show off.  You could say that it makes the code more interesting.  It reminds me of AutoMapper... a library that automatically copies data from one object to another, if the property names match.  If they don't... you can extend your mapping to cater for it.

This is boring:

A.X = B.X;
A.Y = B.Z;

This is cool:

AutoMapperCadabra(A, B);
// TADA!

However, one is easy to debug, and one is not.  That could be a bumper sticker, "Magic... it's not easy to debug!"

Anyway... what was the point of this blog again?  Ah yes... picking a better data store.  What if there was no need for magic?  What if you could just put your aggregate in a database?

And that's why we use document databases.  But there's more to it:

Document databases are typically designed to scale horizontally, splitting the data up in shards on separate nodes.  A relational database typically requires either vertical scaling, or to replicate the entire database to multiple read nodes.

In a document database your aggregate is read and written sequentially... everything for your aggregate is in the same place.  It's not necessary to find bits and pieces all over the hard drive and bundle them together.

But... relational databases have their place.  You can index almost any piece of data, find it, and discover everything it's related to.  Want to find out something complex, like all the brands of wands used to create water goblets where the rat tail was still protruding from the water goblet?  You can!  Not so quick with a document database, unless you read everything.

They also have a schema, meaning that the format of every row is consistent.  This could be important, knowing that whenever you load a record, it it will be in the expected structure.

So, it depends what you need.  You could always dump your changes into a couple of queues and have multiple consumers build up different kinds of data stores, if you really want to.

Tuesday, 27 July 2021

SOLID

Nerdy Monk with Kittens

SOLID
, YAGNI and DRY are acronyms commonly used to describe good programming practices.

DRY is not WET

DRY
is my favourite: Don't Repeat Yourself... instead of writing the same code twice, wrap it up in a function and put it somewhere where it can be easily found and re-used.  This also means if you have to fix a problem, or improve your code, you'll only have to make your change once.

I tend to take DRY to the extreme, by writing little tools, either in PowerShell, or Python, or a little desktop app that takes care of any monotonous task that I might have. The tasks are usually things to do with my dev environment, like automatically powering up useful AWS resources when I login to Windows, and adjusting settings in JetBrains' Rider, so that it only has to compile the bare minimum it needs in order for me to debug the code I'm working on. Other tools I've written include swapping in and out fake and real libraries that my code connects to, so that I can debug under a variety of conditions. These tools not only save time, but allow me to focus on what I enjoy, and what really matters.

DROP is WET

I'd love to invent my own acronym here, DROP: Don't Repeat Other People.

Whenever writing your own generic code, there should be a few things that come to mind... Why has no-one else written this before? Oh, maybe they have. Is there a NuGet package I can reuse? Because, really, if it's generic, and your code is better than any other open source library out there, perhaps you should be either creating, or contributing to open source.

YAGNI... unless it's a kitten!



YAGNI means You Ain't Gonna Need It.  The theory is that your code will be simpler if you delete (or don't write) code that you may need in the future.  It also means you don't have to test it.








SOLID is five principles:

Chaos from multiple responsibilities

1. Single Responsibility: 

A class should only have one responsibility.

Example:  A Person class should not contain code that ensures the email address is in a correct, standard email address format.  Email validation is generic and should go elsewhere.

2. Open / Closed Principle:

Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.

To quote Robert C. Martin (Uncle Bob): 

When a single change to a program results in a cascade of changes to dependent modules, that program exhibits the undesirable attributes that we have come to associate with “bad” design. The program becomes fragile, rigid, unpredictable and unreusable. The open-closed principle attacks this in a very straightforward way. It says that you should design modules that never change. When requirements change, you extend the behavior of such modules by adding new code, not by changing old code that already works.[1]

This means, if you have created a class that is being used, don't make changes unless you're fixing bugs.  Inherit from it instead, and make the changes there. Of course all the cool kids are preferring composition over inheritance these days, so adding a property that's an object is fine, but work with abstractions. When I do this, I might use an interface like IContainX, and then implement a new interface IContainY. That way, your object can be extended with any existing code being referred to (X) remaining unchanged.

If you used TDD properly to build the class, and you're not actually changing the behaviour... You can make performance improvements as long as your original tests pass.

3.  Liskov Substitution Principle:

Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.

So, if the Tesla class inherits from the Car class, you might not want to have a method Car.FillUpWithPetrol(), or you should simply not create a Tesla class inheriting from the Car class.

4.  Interface Segregation Principle:

Many client-specific interfaces are better than one general-purpose interface.

The reasons:
  • Because any implementation should ideally implement every member.  When testing, and creating fakes, mocks or stubs, we don't want to have to care about whether or not a member is implemented if it's not related to the test.
  • Unnecessary complexity (See my blog post on reducing complexity).  Not everyone who flies in a plane wants to see all the controls in the cockpit of a Boeing 747.  All they may need is a button to call the flight attendant.

5.  Dependency inversion principle:

Depend upon abstractions, rather than concretions.

This is often done using dependency injection. It's a way of loosely coupling objects. You don't solder wires from a lamp into a wall socket... you create interfaces, which both the lamp and source of electricity can use.

The way SOLID's used is a bit funny.  I say it's funny, because when I interview someone they usually remember SINGLE RESPONSIBILITY and waffle through the rest. Yup, we're only human. I've heard the word SOLID used a few times, when the speaker's intention was to refer to single responsibility. I don't think it really helps to ask about it at interviews, directly. It's possible that a good answer just shows that the person's attended many interviews. Perhaps a better test would be to offer some code, and ask what the interviewee would change about it. Although, when I've done that in the past, I tend to get a lot of silence... so who knows?

References:

Saturday, 23 March 2019

Microservices in a nutshell

 (or how to build a high performance distributed application / website that is easy to maintain)

Microservices at a high level is about splitting code horizontally based on context specific data models.  A single application could therefore consist of many services, each with its own business logic, data model and database.

There are drawbacks to creating Microservices.  The problem with popular patterns, is it's easy to consider them to be the right way to do things, but often the best approach is determined through experience, and considering what is really important for the specific context.  In many scenarios you will achieve better performance running code on a single computer, and you'll be able to develop it faster.  Nevertheless, for when it is a good approach, here are some advantages of splitting code into Microservices:

  • All words in a model have a single meaning.  This avoids confusion and complexity which could come about from a large model.
  • Less chance of code conflict: Development teams can focus on single services, without writing code that conflicts with teams working on other services.
  • Services fail independently, rather than the entire system going down.
  • Services can be written in different languages.
  • A single service can be updated without affecting anything else.
  • Enables continous delivery: services can be released independently when a feature is done, without waiting for a feature in another service.
  • Easy to understand, as a small piece of functionality.  New developers do not need to understand the entire application.
  • Scalability - easy to scale and integrate with 3rd parties.  Components can be spread across multiple servers.
Microservices can use event sourcing and CQRS to have optimized databases, so that any views which require extremely fast queries can have denormalized copies of the data, formatted specifically for their associated queries.

Event sourcing is a design pattern where changes to an application's state are stored as a sequence of immutable events, rather than directly modifying the current state. These events represent each action taken, allowing the system to recreate the current state by replaying the event log. This approach provides a complete audit trail and enables easy reconstruction or rollback of past states. It is commonly used in scenarios that require high levels of traceability and consistency.  A well known example of event sourcing is most source control software, which record the changes, rather than the state.

Some benefits of event sourcing are:

  • It provides a 100% reliable audit log of the changes made to a business entity.
  • One can get the state of an entity at any point in time by replaying events.
  • Communication between services without too much concern about a service being unavailable.
CQRS stands for Command Query Responsibility Segregation.  CQRS means that instead of CRUD, where the same entity is updated via the same interface, the command to update the entity can be applied to a different model to the query to retrieve the information.

Some benefits of CQRS include:
  • One can create a view database (readonly) combining everything for a particular UI view.
  • Supports multiple denormalized views that are scalable and performant.
Microservices can be deployed in containers.

Some benefits of containers:
  • Platform independence: Build once, run anywhere.
  • Much smaller than VMs.
  • Effective isolation and resource sharing.
  • Speed: Start, create, replicate or destroy containers in seconds.
  • Smart scaling: where you only run the containers needed in real time.
  • Simpler to update OS for all containers than multiple VMs.
  • Free from issues associated to environmental inconsistencies.
  • Roll-out & roll-back with zero downtime.

Thursday, 14 March 2019

High Precision Timing in SQL Server

Here's a simple snippet I wrote for high precision timing in SQL:

DECLARE @startTime datetime2;
DECLARE @endTime datetime2;

DECLARE @counter int = 0;
DECLARE @iterations int = 1000;

SET @startTime = SYSDATETIME();

WHILE @counter < @iterations
BEGIN
-- code to time here

SET @counter = @counter + 1;
END;

SET @endTime = SYSDATETIME();
SELECT DATEDIFF(MICROSECOND,@startTime,@endTime) / @iterations

Friday, 12 August 2016

Well Organized Unit Tests

Some people write unit tests by copying all of the arrange code to every unit test, so they will end up with code like this:

[TestMethod]
public void MyFunction_with_some_condition_does_something()
{
    // Arrange
    // 20 lines of setup code
    ...

    // Act
    ...

    // Assert
    ...
}

[TestMethod]
public void MyFunction_with_some_other_condition_does_something_else()
{
    // Arrange
    // The same 20 lines of setup code as above with one minor modification
    ...

    // Act
    ...

    // Assert
    ...
}

Of course the problem with this is that if you change one thing in your method's implementation, you may need to change every unit test, and it can get messy.  This makes people lazy, and they will neither want to make changes, nor fix their unit tests.  I'm not sure why people forget about good programming principles like DRY when it comes to unit tests.  So you could do something like this, and keep your unit tests small (3 or 4 lines each), easy to read and change:

private MyFunctionRequest myFunctionRequest;

private void Arrange_MyFunction(bool condition1 = false, bool condition2 = false)
{
    myFunctionRequest = new MyFunctionRequest
    {
      ...
    };
    if(condition1)
    {
      ...
    }
}

[Test]
void MyFunction_with_some_condition_does_something_else()
{
    // Arrange
    Arrange_MyFunction(condition2:true);

    // Act
    target.MyFunction(myFunctionRequest)

    // Assert
    ...
}

This looks okay, until you start to work with multiple methods in a class and find that you have to split your test class into regions and you have member variables that only pertain to a specific region.  Using regions is often an indication that your class is doing more than it should.  A better way to organise your tests is to have one class for each method being tested, like this:

[TestClass]
public class MyServiceTests
{
    protected MyService target;

    [TestInitialize]
    public void Init()
    {
        target = new MyService();
    }

    [TestClass]

    public class MyFunction_Method: MyServiceTests
    {


        private MyFunctionRequest request;



        private void Arrange(bool condition1 = false, bool condition2 = false)
        {
            request = new MyFunctionRequest
            {
                //...
            };
            if (condition1)
            {
                //...
            }
        }

        [TestMethod]

        public void With_some_condition_does_something()
        {
            // Arrange
            Arrange(condition1:true);

            // Act
            var actual = target.MyFunction(...);

            // Assert
            ...
        }

        [TestMethod]

        public void With_some_other_condition_does_something_else()
        {
            // Arrange
            Arrange(condition2:true);

            // Act
            var actual = target.MyFunction(...);

            // Assert
            ...
        }
    }
}

If your method being tested is particularly complicated, you could break it down even further, like this:

[TestClass]
public class MyServiceTests
{
    protected MyService target;

    [TestInitialize]
    public void Init()
    {
        target = new MyService();
    }

    [TestClass]

    public class MyFunction_Method: MyServiceTests
    {
        private MyFunctionRequest request;

        [TestInitialize]
        public void Init_MyFunction_Method()
        {
            request = new MyFunctionRequest();
        }

        [TestClass]
        public class With_some_condition: MyFunction_Method
        {
            [TestMethod]
            public void Does_something()
            {
            }
        }
    }
}

In Visual Studio, your solution explorer will look like this:


Friday, 24 June 2016

C# In Memory Search Performance Comparison

Just in case one ever wants to do really fast in memory searches, it's useful to know which classes are the fastest, so I did some tests.  Here are the results from searching for a million integers in an array of a million integers.

Warming up...

Single threaded search...

Testing HashSet...
Create (and sort) took 209ms
Search took 208ms
Total time 417ms

Testing Dictionary...
Create (and sort) took 375ms
Search took 117ms
Total time 492ms

Testing BinarySearch...
Create (and sort) took 187ms
Search took 554ms
Total time 741ms

Testing SortedList...
Create (and sort) took 419ms
Search took 543ms
Total time 962ms

Testing HashTable...
Create (and sort) took 1180ms
Search took 530ms
Total time 1710ms

Multithreaded search...

Testing HashSet...
Create (and sort) took 114ms
Search took 65ms
Total time 179ms

Testing Dictionary...
Create (and sort) took 218ms
Search took 55ms
Total time 273ms

Testing BinarySearch...
Create (and sort) took 186ms
Search took 168ms
Total time 354ms

Testing SortedList...
Create (and sort) took 431ms
Search took 171ms
Total time 602ms

Testing HashTable...
Create (and sort) took 972ms
Search took 343ms
Total time 1315ms


And here's the source code I used to get these stats:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Collections;

namespace PerformanceTesting
{
    class Program
    {
        static void Main(string[] args)
        {
            Random rnd = new Random();
            var warmUp = Enumerable.Range(0, 1000000)
                .Select(i => rnd.Next())
                .Distinct()
                .Take(100000)
                .ToArray();
            var randomIntegersToStore = Enumerable
                .Range(0, 10000000)
                .Select(i => rnd.Next())
                .Distinct()
                .Take(1000000)
                .ToArray();
            if (randomIntegersToStore.Count() != 1000000)
                throw new NotSupportedException("Incorrect number of integers");
            var randomIntegersToSearchFor = Enumerable.Range(0, 1000000)
                .Select(i => rnd.Next())
                .ToArray();
            var tests = new List<ITest>
            {
                new HashSetTest(),
                new DictionaryTest(),
                new BinarySearchTest(),
                new SortedListTest(),
                new HashTableTest()
            };
            Console.WriteLine("Warming up...");
            Console.WriteLine();
            foreach(var test in tests)
            {
                test.Initialize(warmUp);
                test.Search(warmUp, false);
            }
            Console.WriteLine("Single threaded search...");
            Console.WriteLine();
            RunTests(tests, warmUp, randomIntegersToStore, randomIntegersToSearchFor, false);
            Console.WriteLine("Multithreaded search...");
            Console.WriteLine();
            RunTests(tests, warmUp, randomIntegersToStore, randomIntegersToSearchFor, true); Console.ReadLine();
        }

        private static void RunTests(IEnumerable<ITest> tests,
            int[] warmUp, int[] randomIntegersToStore, int[] randomIntegersToSearchFor,
            bool multithreadedSearch)
        {
            foreach (var test in tests)
            {
                test.Initialize(warmUp);
                Console.WriteLine("Testing " + test.GetType().Name.Replace("Test", "") + "...");
                var stopwatch = Stopwatch.StartNew();
                test.Initialize(randomIntegersToStore);
                stopwatch.Stop();
                var createTime = stopwatch.ElapsedMilliseconds;
                Console.WriteLine("Create (and sort) took " + createTime + "ms");
                test.Search(warmUp, multithreadedSearch);
                stopwatch.Restart();
                test.Search(randomIntegersToSearchFor, multithreadedSearch);
                stopwatch.Stop();
                var searchTime = stopwatch.ElapsedMilliseconds;
                Console.WriteLine("Search took " + searchTime + "ms");
                Console.WriteLine("Total time " + (createTime + searchTime).ToString() + "ms");
                Console.WriteLine();
            }
        }

        interface ITest
        {
            void Initialize(int[] randomIntegers);
            void Search(int[] randomIntegers, bool multiThreaded);
        }

        class HashSetTest : ITest
        {
            private HashSet<int> hashSet;
            public void Initialize(int[] randomIntegers)
            {
                hashSet = new HashSet<int>(randomIntegers);
            }

            public void Search(int[] randomIntegers, bool multiThreaded)
            {
                if (multiThreaded)
                    Parallel.ForEach(randomIntegers, i => hashSet.Contains(i));
                else
                    foreach (var i in randomIntegers)
                    {
                        hashSet.Contains(i);
                    }
            }
        }

        class BinarySearchTest : ITest
        {
            private List<int> list;
            public void Initialize(int[] randomIntegers)
            {
                list = new List<int>(randomIntegers);
                list.Sort();
            }

            public void Search(int[] randomIntegers, bool multiThreaded)
            {
                if (multiThreaded)
                    Parallel.ForEach(randomIntegers, i => list.BinarySearch(i));
                else
                    foreach (var i in randomIntegers)
                    {
                        list.BinarySearch(i);
                    }
            }
        }

        class SortedListTest : ITest
        {
            private SortedList<int, int> list;
            public void Initialize(int[] randomIntegers)
            {
                list = new SortedList<int, int>(randomIntegers.ToDictionary(i => i));
            }

            public void Search(int[] randomIntegers, bool multiThreaded)
            {
                if (multiThreaded)
                    Parallel.ForEach(randomIntegers, i => list.ContainsKey(i));
                else
                    foreach (var i in randomIntegers)
                    {
                        list.ContainsKey(i);
                    }
            }
        }

        class DictionaryTest : ITest
        {
            private Dictionary<int, int> dictionary;
            public void Initialize(int[] randomIntegers)
            {
                dictionary = randomIntegers.ToDictionary(i => i);
            }

            public void Search(int[] randomIntegers, bool multiThreaded)
            {
                if (multiThreaded)
                    Parallel.ForEach(randomIntegers, i => dictionary.ContainsKey(i));
                else
                    foreach (var i in randomIntegers)
                    {
                        dictionary.ContainsKey(i);
                    }
            }
        }

        class HashTableTest : ITest
        {
            private Hashtable hashTable;
            public void Initialize(int[] randomIntegers)
            {
                hashTable = new Hashtable(randomIntegers.ToDictionary(i => i));
            }

            public void Search(int[] randomIntegers, bool multiThreaded)
            {
                if (multiThreaded)
                    Parallel.ForEach(randomIntegers, i => hashTable.ContainsKey(i));
                else
                    foreach (var i in randomIntegers)
                    {
                        hashTable.ContainsKey(i);
                    }
            }
        }
    }
}

Wednesday, 14 January 2015

Resharper settings for C#

There used to be some useful Resharper settings at http://daniellang.net/5-resharper-settings-for-c4-coding/, but Daniel Lang, the guy who wrote them has since lost that page.  So, as I figure out my Resharper settings again, I'll post them here.

The idea is that if you don’t like this formatting:













...and prefer this:



















...In Code EditingOther, at Align Multiline Constructs make sure that Array, object and collection initializer is unchecked.



And, according to Igal on Stack Overflow, the following should also be set, however they appear to be set by default:

  1. In Braces Layout, set Array and object initializer to At Next line (BSD Style).
  2. In Other, make sure that Continuous line indent multiplier is set to 1.

Saturday, 5 January 2013

How to Write Super Fast Code

The great thing about programming is that the proof is in the pudding.  If you've done a good job, your program works, meets the requirements and doesn't throw exceptions at the user.  The same goes for performance.

Writing uber fast code is a fun challenge that can be very rewarding.

Consider a conversation like this:

Code reviewer:  If you create a new variable and typecast it, and then check it for null, it will be faster than if you just use "is."

Developer:  Why do you say that?

Code reviewer:  Check out www.programming-guru.com/whatisayistruth.  In his article, Sir Jon Skeet MD PHP MCSD, says so.

Developer:  Here's some code which tests the performance of both versions.  My version is 0.00001 milliseconds faster.

The conversation is over, and there's no need for a pointless debate.

Performance is something that a programmer should keep in the back of his mind at all times, however in most cases the readability of code is the most important.  One only needs to ensure that something performs quickly if there's a chance that it will be noticeably slow.

Many years ago, when I was still in school, I wrote a program that needed to be amazingly fast.  I wanted to squeeze as many calculations per clock cycle that I possibly could.  Because of my need for speed, I chose to write it in assembler.  And so, it looked something like thousands of lines of this:

MOV AX, 42
JMP CX
DOG BRK
FOX 1
R2  D2
SUB MRN, DX
C3  PO
RAB BIT
etc., etc....

Okay, I've forgotten a lot of assembler, so the example may be inaccurate, but at least it worked.  Well, not exactly... because from time to time it would access invalid memory addresses and I'd have absolutely no idea why, and my computer would just freeze, or restart, or whatever computers used to do back in the DOS days.

So, how does one write super fast, stable, readable code?

Here are the steps:
  1. Find the problem areas.  There's no need to make any changes in code that is not slow.
  2. Measure the time taken.
  3. Write functionality tests.  If you're using a test driven approach, you should already have tests to ensure that any changes will not change the functionality.  If you don't, then write them.  
  4. Additionally, you could also write performance tests, like unit tests, which indicate a problem if an area of code is changed to be slower than it should be.
  5. Make your changes.
  6. Measure the performance.
1.  Finding the problem areas.

Areas that have the potentially to cause trouble are calls to slow hardware, like network calls and loading large files, calls to slow third party methods, and loops within loops.

If you've already written the code and you want to find out where the bottlenecks are, you can use a profiler.    I like ANTS Performance Profiler for .NET.  Start by fixing the biggest bottlenecks.

If you're writing the code and just want to make sure that it's efficient, then look out for the three potential problem areas that I mentioned earlier, calls to slow hardware, calls to slow third party methods and loops within loops.

On the subject of loops within loops, I want to make a quick comment about LINQ, .NET's slick way of working with lists.  The important thing to understand about LINQ is when it runs the code;  It only runs the code when you actually ask for the values:

For example, if you have something like this:

public IEnumerable Dogs
{
    get
    {
        return Animals.OfType();
    }
}

It would be very efficient to do something like this...

var dogs = Dogs;

...because the variable dogs will know how to return a list of dogs, but won't actually loop through the list of Animals until it's used.

However, this would be very inefficient...

for(int i = 0; i < Dogs; i++)
{
    Dogs.ElementAt(i).Bark(); // It will loop through the Animals list here
}

...because it will loop through the entire Animal list every time you call Dogs.ElementAt().

This is far better:

foreach(Dog dog in Dogs)
{
    dog.Bark();
}

The following, although not ideal, but useful if you want to work with i, will be almost as fast as the above code:

var dogs = Dogs.ToList(); // It will only loop through the Animals list here
for(int i = 0; i < dogs.Count; i++)
{
    dogs[i].Bark();
}

2.  Measure the time taken

You can time a specific piece of code in C# like this:

var watch = new Stopwatch();
 
watch.Start();
for (int i = 0; i < 1000000; i++) { }   // Execute the task to be timed
watch.Stop();

To cater for caching and JIT compilers, it's usually good to run your code once just before timing it.

3.  Write functionality tests

4.  Write performance tests

Just in case you want to ensure that neither yourself, nor anyone else changes anything to drastically increase the time taken then you could write a performance test.

In C#, the easiest way to test is probably using TimeoutAttribute, eg.

[Timeout(200)]

...but using a timer, like the Stopwatch class, will allow you to be more specific about exactly what you're testing and why you need it to be fast.  In fact, the Timeout attribute can be extremely unreliable, especially if the test runs before any of the other tests, so it's better to use a timer.

The acceptable time in this test should be a lot more than what it actually takes, because the speed of a test can change according to the computer it runs on and the other processes that are running simultaneously.

A more accurate way to do this would be to copy an exact duplicate of your high performance code into the test, and test that it isn't much slower.  It's not ideal, but I don't think there's a perfect way to do this.

For example:

public void MyTest()
{
    const int iterations = 10;
    const long buffer = 200 * iterations;
    var originalCodeTimer = new Stopwatch();
    var currentCodeTimer = new Stopwatch();
    for(var i = 0; i < iterations; i++)
    {
        originalCodeTimer.Start();
        MyOriginalCode();
        originalCodeTimer.Stop();

        currentCodeTimer.Start();
        target.Foo();
        currentCodeTimer.Stop();
    }
    if (currentCodeTimer.ElapsedMilliseconds > 
        originalCodeTimer.ElapsedMilliseconds + buffer)
    {
        Assert.Inconclusive();
    }
}

private void MyOriginalCode()
{
    // A complete copy of the code or a call to a copy of the code
    // that I originally wrote and timed
    // ...
}

In order to get more accurate timings it's usually best to run the method being tested a few times and get an average time.

Of course, since this isn't an exact measurement it should probably be treated differently to normal tests.  You may want to consider keeping these tests separate from others, so they are not run every time your unit tests and integration tests run.  Another way to do this might be to use Assert.Inconclusive() if you're using MSTest.  Instead of showing a red X or a green tick, this shows a yellow exclamation mark, and places the test result under Skipped Tests.  That's not exactly what it would mean, but it will attract attention and people can see quite easily why it was skipped if you make it clear in your test.

You could do something like this:

if(timeTaken > expectedDuration * 2) 
{
    if(timeTaken < expectedDuration * 4)
        Assert.Inconclusive("Took two to four times expected duration.");
    else
        Assert.Fail("Took four times expected duration.");
}

5.  Make your changes.

In most cases, what you'll be looking to do is this:

    Any slow code that can be called less often should be called less often.

You may be tempted to use multi-threading in an attempt to increase speed.  Multi-threading increases the complexity of your application and doesn't always make it faster.  Measure the performance and decide if the increased complexity is worth the performance gain.  If you decide to go with multi-threading, check that you've considered other alternatives, the target environment, and thread safety.

6.  Measure the performance.

And only keep your changes if your measurements confirm that it's faster and it passes your testing.


Images:

1. Courtesy of Jon Whiles at FreeDigitalPhotos.net

Wednesday, 2 January 2013

The Characteristics of a Master of Programming

Today I was thinking about the characteristics that a master of programming has.  From experience I have found that some personality traits can be learned.

This is the list of characteristics that I came up with:

  • He loves programming.
  • He enjoys being creative.
  • He is organized.
  • He is calm.
  • He has lots of knowledge and experience.
  • He enjoys learning.
  • He is open minded, so he likes asking questions and getting his work peer reviewed, and does the best he can with the information he receives.
  • He loves challenges and is confident in his ability to solve any problem.
  • He is 100% focused on creating perfect software.  Nothing else matters.
  • He is always looking for the most effective way to write a piece of code or solve a problem.
What do you think?

How to reduce complexity and know enough.

Quality We have a great QA. His code is like a Rolex. You look at his gherkin, and smile.  It says what it's testing, in plain English, ...