Category Archives: Unit Testing

Yet another practical pocket guide on writing clean code

Being a big proponent on crafting beautiful, robust and maintainable code, I have read several books and articles on the subject.  One of my favorite resources is a book titled “Clean Code” by Robert C. Martin.

I would propose that such a resource be readily available in the company library and would even go as far as advocating for every software engineer joining the company to either have read this book or is required to read this book as part of the on-boarding process.

In summary what is clean code:  Code which mostly abides by the SOLID principles of software design.  In my own words.

Methods should have a single responsibility.  It is better to have a class with many small methods that have a class with a small number of large methods.

Methods should not be overly long. A well known and acceptable measure is that a method should not span the entire code editor space in Visual Studio, when viewed over a 15″ laptop monitor.  For example, this is a long method:

On the otherhand, this is a nice, short and terse method:

Methods should return early if possible.  This avoid too many nested iffs.  For example, consider the following method which takes in input object of some sort

   private void InitializeActionMethods()
        {
            if (_configurationManager.Configuration == null)
            {
                Logger.Warn("Some configuration is not defined.");
                return;
            }

We fail fast and early.  In contrast, we could written the code like this:

   private void InitializeActionMethods()
        {
            if (_configurationManager.Configuration =! null)
            {
                // continue
            }

This creates a code base with too many nested-iffs which is hard to read and maintain.

Method names and variables should clearly indicate purpose.  I often say code is a story.  Write code as if you are writing a story.  Books with shorter paragraphs are more engaging than books with longer paragraphs.  I often see developers naming variables using acronyms instead of taking the time to craft out descriptive variable names. Again, if code is a story, we need to clearly identify the characters.

Entities themselves should have single responsibility.  This one is also easy to violate.  I have seem some very large and weird looking classes over the years.  I have also seen classes that are almost impossible to refactor and unit test as it is composed of a collection of large, deeply nested methods with a large number of inter-dependencies.  Keep classes small.  I have told my devs that is is better to have a code base with thousands of small entities that one with a small number of large entities.  The former system, if well organized, is easily to reason with, maintain, modular and robust.

Entities should have dependencies passed to them.  The term coined for this is dependency injection or inversion of control.  I always get confused here but the idea is for a factory to construct a car, it needs to have all of its dependent bits, such as assembly line, etc.  These must be explicit and defined up front.

Unit test, unit tests and more unit tests. I cannot emphasize this enough but any component in the system should have an associated unit test which is concise.  There are well documented strategies for crafting awesome unit test but they should abide by the AAA principle of Arrange, Act and Assert.  Google this. Also, make these test very easy to follow.  All dependencies should be arranged or created up front.  if you are resolving entities from some container somewhere, which includes configuring some sort of logger, which requires some additional piece of configuration somewhere, you probably need to step back and rethink your tests and class design.

Code should be closed for modification and open for extension, as stated in the Open/Closed Principle, code should be easy to extend but closed for modification.  This is a tough one but think if it this way.  If you start creating code with long switches, then it is time to sit back and think of some patterns to use.

Code should be robust against anomalies but at the same time need not be overly micro-optimized.  Beautiful code means that it is easy on the eye, easy on the mind, free flowing, yet robust against extremities.  This includes excellent exception handling and logging.

Happy Coding.

Advertisements

Some defensive coding practices against environmetal uncertainties – part 1

1. Always consider Environment.CurrentDirectory as opposed to Assembly.GetExecutingAssembly().Location, when getting current working directory.

This innocent looking line of code causes grief.

var pathToSqliteDatabase = Path.Combine(Assembly.GetExecutingAssembly().Location, "SqliteDb.db3");

Why?

Let’s just first ignore the fact that a test harness should be going directly to a database since this is part of the problem. But if you are running a test harness that has to resolve a location to an SQLite database instance you will get interesting results.

If using MSTest, the above line of code resolves to the current test project’s working folder. So if your test project was in c:\dev\SQliteAdventures, pathToSqliteDatabase to be

c:\dev\SQliteAdventures\bin\Debug

However, if you decided to change to NUnit and have ReShaper installed, the same above line of code now resolves to some random location:

In my case, it looked like this:

C:\Users\knji\AppData\Local\Temp\jahvgmug.pjb\s5hvswgs.kil\SQliteAdventures\assembly\dl3\086a6c5d\1860476f_4375d001\

Changing the above line of code to

var pathToSqliteDatabase = Path.Combine(Environment.CurrentDirectory, "SqliteDb.db3");

will return the current result regardless of the operating environment. So this is preferable here.

2. Carefully consider using x86 vs x64 versions of 3rd party dependencies.

The System.Data.SQLite.dll .NET connector for SQLite, for example comes, with an x86 and x64 version. When executing tests using MSTest, x86 version of the is required since the MStest runner executes within the 32 bit Visual Studio process. However, if you are running NUnit via ReSharper, which executes within its own 64 bit process called JetBrains.ReSharper.TaskRunner.CLR45.x64.exe, you need the x64 bit version of this dll otherwise you get image loading exception. Besides testing against abstractions or fakes, I do not yet know to automate this. Ideas always welcomed.

To be continued…..