Andy Crouch - Code, Technology & Obfuscation ...

Observations About If Statements

In this post, I want to highlight a couple of observations about the use of conditional if statements. All languages have a variety of the humble if statement. Programs would not be able to function without them and the logic they provide. Some might say they are the basis of very early AI but I digress.

The basic outline of an if statement is as follows:

if("a specific condition equates to true")
{
    DoSomething();
}
else
{
    DoSomethingElse();
}

This say’s that if the tested condition is true then execute the DoSomething() method. If not execute the DoSomethingElse() method. All pretty straightforward.

But, there are some obvious issues that we should look out for. We do not want to make our code unreadable or hard to understand.

The first observation relates to when many conditions are tested in one go which makes reading the if line a little harder. If reading the conditional test logic is hard then reversing it to understand how you get to the else is even harder.

if((person.Age > 18 && person.Age < 25) && 
   group.Name == "Test Group 1" || group.Name == "Test Group 5")
{
    DoSomething()
}
else
{ 
    DoSomethingElse(); 
}

Vs

var isPersonInTargetAgeRange = person.Age > 18 && person.Age < 25; 
var isATargetGroup = "Test Group 1" || group.Name == "Test Group 5";

if(isPersonInTargetAgeRange && isATargetGroup)
{
    DoSomething()
}
else
{ 
    DoSomethingElse(); 
}

Creating well-named variables and using them in the test condition makes it much easier to read. It is also easier to understand the reverse logic when determining how the else block is reached.

The next problem is the use of deep nested if statements. I have seen a lot of examples of this lately. Code such as:

public string Read()
{
    if(Path.DirectoryExists(_testDirectory))
    {
        if(Path.FileExists(_testFilePath))
        {
            if(!File.IsReadOnly(_testFilePath))
            {
                var file = File.Open(_testFilePath);
                if(file != null)
                {
                    file.Read();
                }
            }
        }
    }
}

The more conditions that are added add a further level of nesting. Code usually ends up like this due to extending requirements. Deep nesting makes it hard to understand the logic that leads to the actual execution of a piece of code. It becomes a lot harder when you have else clauses at multiple levels as well.

public string Read()
{
    if(!Path.DirectoryExists(_testDirectory))
        return;

    var testFileExists = Path.FileExists(_testFilePath);
    var testFileIsReadOnly = File.IsReadOnly(_testFilePath);

    if(!testFileExists || !testFileIsReadOnly)
	return;

    var file = File.Open(_testFilePath);

    if(file != null)
        file.Read();
}

The final issue I want to cover is the use of an if statement to wrap the body of a method. This is another approach which I have seen a lot lately. Something like:

public void AMethod(bool aCondition)
{
    if(aCondition != true)
    {
        LogCondition();
    }
    else
    {
        OpenConnection();
        RequestData();
        ProcessData();
        CloseConnection();
    }
}

Why is the else used? Why not just add a return in the if block and remove the else? The reverse of this is even more strange:

public void AMethod(bool aCondition)
{
    if(aCondition == true)
    {
        OpenConnection();
        RequestData();
        ProcessData();
        CloseConnection();
    }
    else
    {
        LogCondition();
    }
}

Why? Why would you write this? You should look to exit your functions and methods at the earliest opportunity. This is why approaches such as parameter checking are available in most languages. There are patterns that mean you can check and exit out if you get a null or unexpected value. Wrapping your method body like either of these examples is a clear signal you need to refactor your code.

public void AMethod(bool aCondition)
{
    if(aCondition != true)
        LogCondition();

    OpenConnection();
    RequestData();
    ProcessData();
    CloseConnection();
}

if statements are a core part of most programming languages but you need to ensure their use does not result hard to understand code. If you find yourself nesting if statements or if you find that your test conditions span multiple lines then you almost certainly need to refactor your code.

If you have any thoughts about this post then please contact me via twitter or email.

Improving SEO For Your Jekyll Site

Search Engine Optimisation (SEO) refers to how you increase the quality and quantity of organic traffic to your web site. There are many articles and tools available covering best practices. I would suggest this article to start with and then research the various points. Getting your sites SEO right is critical. It will increase your chances of people finding your content in search engines.

Working on a new site for Open Energy Market has made me investigate how well this blog is optimised. One of the first things I wanted to improve was its SEO score on web.dev. Before making the changes in this post the score started at 49.

I have written before about how I build this site with Jekyll. After a little Jekyll SEO optimisation research, I discovered the Jekyll SEO Tag gem. The gem automatically generates recommended SEO meta tags for each page and post in your site. The following are some of the tags created as part of the configuration and content of the site:

  • Page title. This will be generated with the site title and/or description appended.
  • Page description. If you use a description tag in your forward matter this will be generated otherwise it will be skipped.
  • Canonical URL. The fully qualified URL to your post or page.
  • Next and previous URLs on paginated pages. When generated on a paginated page, the gem will include the URLs for the next and previous pages.
  • JSON-LD Site and post metadata for richer indexing. This article covers the use of this tag,

See here for a full list of tags that can be configured and generated.

To install jekyll-seo-tag you need to add the following to your Gemfile:

gem 'jekyll-seo-tag'

Next, you need to add the plugin in your sites _config.yml:

plugins:
  - jekyll-seo-tag

And finally you need to add the following on the line before your </head> tag:

{ % seo % }

(Without the spaces between the brackets and the % character. Shown as such here to prevent Jekyll from compilling the command)

Once these settings are added you can run:

gem install jekyll-seo-tag

That will install the plugin. Once you start your site back up and view the page source you will see the tags and the content generated by the plugin. On re-running web.dev my SEO score had increased to 92. This is without adding specific keywords or any other changes.

I will write up in a future post other optimisations for SEO as I decide on the ones to implement. For now, the little work it took to add this useful plugin is well worth it.

If you have any suggestions or questions about this post then please contact me via twitter or email.

Typing For Developers

There are a lot of articles about the skills that developers need to build a great career. One thing that always seems to be missing is the importance of typing. Every so often an article will appear but it is never promoted with the same importance as other core skills.

It seems to be one of those things that are assumed for a developer. You spend all day in front of a computer and so you can type, right? Wrong. I have seen even very experienced developers who two finger type or type looking at the keyboard. What is the impact of not having good typing skills and what can you do about it?

The answer to both of those questions is “a lot”.

The impact is on productivity. Not so much how much you deliver but more about your hands keeping up with your brain. When you are in “the zone” and the solution is flowing the last thing you want is for you not to be able to transfer it from the brain to file. If you look at the keyboard to type then you can not possibly know where on the screen you are typing. This can become even more of a problem if you pair program regularly. “Typing Performance Anxiety” is a real thing. We have all been there in front of someone else when our existing typing capability seems to halve.

Being able to type fast is one part of typing well. The other part is using the keyboard to prevent the break of flow in typing. When you take your hand off the keyboard to use the mouse to perform a task you lose track of your thinking. This doesn’t mean you have to switch to Vim (or Emacs) to become a fluent typist. It does mean that you need to learn the keyboard shortcuts for your application. Most applications even allow you to change the shortcuts. This means you can align them between applications and only have to know a limited set. You will gain considerable time and prevent considerable pain by only using the keyboard.

The final area to be impacted is accuracy. If you can type well then you are able to type accurately. This can save considerable time in correcting your output.

So, how can you improve your typing? In an age where everybody wants to self improve there is a range of sites that can help. keybr seems to be a simple tool that can help as does typing.io and Speedcoder.net. The last of these is actually geared to writing code as well. I personally have found that it doesn’t matter which tool you use. It is more about the discipline of practice. In fact, when I made a concerted effort to improve my typing years ago I would just copy text from a document in a side by side set up. I did it for 15 minutes a day for a month solid and I noticed a great improvement. After that first month, I would still practice a couple of times a week.

The final thing I have to say about typing is to find a keyboard that works for you. The keyboards that come as standard these days vary in quality. Different people prefer different travel and layouts. You may benefit from trying a mechanical keyboard. Or you might find that the shallow travel of laptop keyboards works better for you. Do not be afraid to experiment.

If you have any opinions, suggestions or questions about my views here then please contact me via twitter or email.

Readable Code Part 5 - Wrapping Up Code Readability

After a short interlude for an Easter holiday, I wanted to bring to an end my series on readability. This post will look at a few peripheral things to keep in mind when developing readable code.

First up is formatting. Formatting covers a few areas. Line width, Tabs vs Spaces and syntax flow all fall under this.

var user = UnitOfWork.GetRepository<User>().GetAll().Where(u => u.Name.ToLower() == lockedUser.Name.ToLower()).SingleOrDefault();

Vs

var user 
    = UnitOfWork
        .GetRepository<User>()
        .GetAll()
        .Where(u => u.Name.ToLower() == lockedUser.Name.ToLower())
        .SingleOrDefault();

And

public static bool IsFalse(this bool b)
{
    return b == false;
}

Vs

public static bool IsFalse(this bool b)
{
  return b == false;
}

Tabs vs Spaces has been discussed to death and I have never understood the problem. Pick one as a team and stick to it. Splitting your code vertically or horizontally makes no difference to the compiler. But, it can make it easier to read when structured vertically by statement. This is especially helpful with more fluent API’s as shown above. As I have covered in previous posts, the key is consistency. This consistency should be applied across projects and be enforced company-wide. This will help in onboarding developers, code reviews and team productivity. When interviewing you should make a point of asking to see their style guide. If they don’t have one then suggest you would like to lead the development of one if successful. If you don’t agree with some small points in an existing guide then adapt or decide that the use of spaces is just too unreasonable.

Consistent formatting choices lead to agreeing on a code line length. In years gone by a lot of organisations would work to 80 characters per line. This stems from hardware limitations. Today most people have at least Full HD screen resolutions, if not 4k. I would still argue that a shorter line length makes for easier code to read. It also means that you can reduce context switching by having multiple files open in an editor side by side. A lot of editors try and automatically wrap long code lines across multiple lines. This makes code inconsistent and hard to read. I tend to set my max character count per line to 100.

Next I want to cover deep nesting. Deep nesting makes code very hard to read and is normally a code smell. By deep nesting, I mean code such as:

public void foo(object[] args)
{
    if (args != null)
    {
        foreach(var arg in args)
        {
            if (arg != null)
            {
                if(typeof(arg) == String)
                {
                    foreach (char c in arg)
                    {
                        Console.WriteLine(c);
                    }
                }
                else
                {
                    Console.WriteLine(arg);
                }
            }
        }
    }
}

In most cases there is a better way to structure the code. Just breaking the nests down into methods improves the readability.

public void foo(object[] arguments)
{
    if (arguments != null)
        return;

    foreach(var argument in arguments)
    {
        if (argument != null)
            continue;
    
        if(typeof(arg) == String)
            OutputByCharacter(argument);
        else
            Output(argument);
    }
}

private void OutputByCharacter(string argument)
{
    foreach (char character in argument)
    {
        Console.WriteLine(character);
    }
}

private void Output(object argument)
{
    Console.WriteLine(argument);
}

This leads on nicely to Code Grouping. Grouping and ordering of methods and functions by the use of white space should be done in the same manner you would group your paragraphs in prose. Again agree on how you will do this and enforce it. There are different grouping approaches I have seen such as:

  • Grouping by access modifier. This results in all public methods being together and then all protected methods and then all private methods.

  • Grouping by use. This means that public methods are generally defined first along with protected methods. Private methods are generally defined under the first public or protected method that uses it.

I like the second of these approaches. It means that you do not have to scan to the bottom of a source code file to find a private method. It is usually within a few lines of the code that calls it. This means it aids reading and reduces (but does not prevent) context switching. There doesn’t seem to be a best practice around grouping.

Finally, I want to cover source code file organisation. This can sometimes be governed by the framework you use. If it is not then you need to organise files in logical groupings and namespaces to make finding files simple. There are different ways to do this and even approaches such as Clear Architecture. If you have to create your own structure then group related items. One project I have worked on has a Services directory. Within that directory is over 300 business logic and domain related service classes. It is hard to navigate and to find code. Don’t do that.

So that’s, mostly, what I have to say about improving code readability. It comes down to two main things:

  • Write code that is clean, logical and easy to digest. Code is written in a language. Language is a method of communication. Either you or someone else will read your code many times over its lifetime. You do not want to confuse or hide the meaning of the code. Think about Unix and how some systems developed in the 1970s are still in use. That code will have been read thousands of times. Are you happy that your code could survive like that?

  • Any supporting readability guides, formatting or project structures should instil consistency. Work with your team to agree on what you feel is a good level of readability and stick to it. Build checks into your code reviews. Encourage your team if they commit code in a way that is not in line with the guide. Think of your code as words on pages which are your files in the book that is your project.

If you have enjoyed this series or have any opinions around the idea’s I have outlined in these posts please contact me via twitter or email. I would certainly like to discuss them in more depth.

Readable Code Part 4 - Extending Languages For Readability

In this next post in the code readability series, I want to cover the use of language extensions. This is a powerful feature of a lot of modern languages. From C based languages through to dynamic languages such as Python. But, it is almost never mentioned in relation to code readability. Usually, we use extension methods to wrap Type utility methods or create project specific functionality. Here I want to look at taking it a bit further to improve readability at a solution level.

Modern languages use a limited set of operators and keywords like their forerunners. A number of current languages all have between 30 and 40 reserved keywords. Given the amount of research undertaken in language design, it amazes me that as a profession we use such limited and unfriendly syntax to develop code. I might argue that we have actually made it harder than it once was.

Take for instance:

IF ((A.GT.B).AND.(B.LT.C)) THEN

END IF
     
IF ((C.GT.D).OR.(B.EQ.C)) THEN

END IF

That is FORTRAN syntax. A language that was first released in 1957. Compare this to:

if((a > b) && (b < c))
{

}

if((c > d) || (b == c))
{

}

The above could have been taken from any C language tree derived language from the last 40 years. FORTRAN’s design goal was “to create the first ‘user-centered’ programming language.” It focused on “the reduction of mechanistic instructions into simple English commands with algebraic formulas. Its language focused more on the problem the person using the computer wanted to solve than on the machine’s operations.” How often do you feel that the language you use has similar goals? Given that we are pushing more people to the role of a programmer the question must be why are we repeating the obfuscation in each language in each new variant?

Back to readability. How much easier is the FORTRAN code above than the C derived language code? Considerable I would argue. While if statements are easy to read and generally make sense, no one would argue the same for the C language && or || operators. && is the most confusing as in most English based languages, & is shorthand for ‘and’. But, in C derived languages & is an operator to obtain the address in memory of a variable. I assume that this operator was defined before the operator for ‘and’. For most people && does not relate to shorthand for ‘and’ and neither does || for ‘or’. I suspect most people would find reading the FORTRAN versions easier.

So how could we use extensions to improve the readability? Using C# and its Extension methods we could end up with the following:

if(a.IsGreaterThan(b).And(b.IsLessThan(c)))
{

}
	   
if(c.IsGreaterThan(d).Or(b.Equals(c)))
{

}

We can achieve this prose like readability by using the following, simple extensions.

public static class BooleanExtensions
{
     public static bool And(this bool firstCondition, bool secondCondition)
     {
         return firstCondition && secondCondition;
     }
     
     public static bool Or(this bool firstCondition, bool secondCondition)
     {
         return firstCondition || secondCondition;
     }
}

public static class IntegerExtensions
{
    public static bool Equals(this int number, int comparisonValue)
    {
        return number == comparisonValue;
    }
    
    public static bool DoesNotEqual(this int number, int comparisonValue)
    {
        return number != comparisonValue;
    }
    
    public static bool IsGreaterThan(this int leftValue, int rightValue)
    {
        return leftValue > rightValue;
    }
    
    public static bool IsLessThan(this int leftValue, int rightValue)
    {
        return leftValue < rightValue;
    }
} 

This is an improvement over && and || and simplifies the reading of > and <. Most developers will say that this is a minor improvement. That it adds little benefit to code readability. But what if you apply the same logic as you build your project to solution and domain logic and entities? What you would end up with is a solution specific Domain Specific Language (DSL). This should make the code simple to read and more importantly understand. You can essentially change your chosen language to be simpler to read and work as you need. You are no longer constrained by the limited operators and keywords it has decided to implement. This enforces consistency throughout your code base. There is far reduced developer centric variations. It also means it is easier to automate your style guide. A secondary benefit unrelated to readability is that we can apply tests. We can write simple code once and move on to composing logic and objects.

If you implement the idea’s here then you should follow the same rules that I outlined in the previous post. Your extension method/function names should follow a consistent theme. If you create a IsNullOrEmpty string extension then an extension that checks for Null or Empty List’s should be named likewise. You should also consider how you structure your extensions. They should exist at the lowest level possible. If your language supports generics then use that to handle common extensions across types.

If you have any opinions around the idea’s I have outlined in this post or would like to discuss them in more depth then please contact me via twitter or email.