Saturday 19 December 2015

On side projects...again

Recently I stumbled across an interesting Stack Overflow question:

I don’t program in my spare time. Does that make me a bad developer?

The answer with the most up votes was from a user called red-dirt who makes a number of excellent points. One interesting point in particular is that a professional musician will practice a maximum of six hours day, so spending eight hours a day developing software should be plenty. This point makes sense to me. If you spend a long time doing something you should get better at it, right? By my calculations if you spend five to six years developing software you will hit the theoretical 10,000 hour mark required to become expert at something. But here’s my problem, most software developers with five to six years experience aren’t experts. I have more years experience that this and I don’t consider myself anywhere near an expert. The point I am trying to make is, while I absolutely do not think it makes you a bad software developer if you don’t program in your spare time, in my experience the best software developers I’ve worked with are the ones who have programmed in their spare time. Ultimately, I still think side projects are important.

Why aren’t all software developers experts?

So why aren’t all software developers experts? I have a few theories.

I suspect a big problem is attitude. Some developers don’t love their jobs and simply aren’t interested in learning. They are happy to repeat a single year of experience over and over.

Sometimes the work an employer gives you isn’t very interesting or challenging. Of course with a good attitude you can still learn, or failing that find a new job. But what if that aren’t many great jobs around? I live in the north east of England and while there are a lot of software development jobs, you could hardly compare it to major technology centres like London or San Francisco. There simply aren’t that many great companies to work for near where I live. Or maybe I just haven’t found them.

Perhaps your job is interesting and challenging, but is it interesting and challenging all the time? In my experience this isn’t the case. A significant percentage of work is quite mundane and doesn’t increase your skills. Again, you could argue that a new job would solve this problem, for a period of time at least.

Another problem could be training, on the job and formal. After finishing school I did a computing degree and got a software development job. University was mostly a waste of time and my first job didn’t provide me with a particularly strong set of skills. Don’t get me wrong, I enjoyed my first job and I learnt a lot, but neither the job or my degree made me a good software developer. In hindsight I feel like I stumbled around in the dark for the first four years of my career. Some might say I’m still doing that.

There are several factors that exacerbate the training problem. There is a huge amount to learn, a lot of misinformation and no clear path to becoming a good software developer. It’s not even clear what makes a good software developer! With all these problems I’m not surprised it’s difficult to become an expert in software development.

Conclusion

In conclusion, what I’m saying is that to be a really good software developer I think you need to either:

  1. Be very clever
  2. Land the perfect job with great mentors that consistently challenges you
  3. Supplement your knowledge by putting in hours out of your job

From my experience one and two are in short supply which means the majority of people are left with category three.

Tuesday 6 October 2015

Using the TestCaseSource attribute in NUnit

I’ve used NUnit for the last few years but I only recently discovered the TestCaseSource attribute which is very useful in certain circumstances.

The scenario

Imagine you have a DeviceInformation class. It’s job is to take a user agent, parse it and provide information about the device. The class could look something like this:
public class DeviceInformation
{
    public bool IsDesktop { get; private set; }
    public bool IsMobile { get; private set; }
    public bool IsTablet { get; private set; }
    public string Manufacturer { get; private set; }

    public DeviceInformation(string userAgent)
    {
        // Some code here which sets the class properties
    }
}
One way to attack this is to create a bunch of user agents and use the TestCase attribute to confirm that multiple user agents return the same result.
private const string USER_AGENT_IPHONE_4 = "...";
private const string USER_AGENT_GALAXY_S5 = "...";
private const string USER_AGENT_LG_G4 = "...";
private const string USER_AGENT_GALAXY_TAB = "...";

[TestCase(USER_AGENT_IPHONE_4)]
[TestCase(USER_AGENT_GALAXY_S5)]
[TestCase(USER_AGENT_LG_G4)]
public void IsMobileDevice_UserAgentIsMobile_ReturnsTrue(string userAgent)
{
    Assert.IsTrue(new DeviceInformation(userAgent).IsMobile);
}

[TestCase(USER_AGENT_GALAXY_TAB)]
[TestCase(USER_AGENT_GALAXY_S5)]
[TestCase(USER_AGENT_LG_G4)]
public void IsAndroidDevice_UserAgentIsAndroid_ReturnsAndroid(string userAgent)
 {
     Assert.That(new DeviceInformation(userAgent).Manufacturer, Is.EqualTo("Android"));
 }

// More tests to cover the IsDesktop, IsTablet and Manufacturer properties here
This is a trivial example and there are already quite a few user agents. You can see that if I were to thoroughly unit test DeviceInformation I would need a lot more user agents and a lot more tests. As the number of users agents increased the number of attributes on each test would increase and the tests would become more difficult to maintain. Each time a user agent was added I’d need to scan every single test and make sure new attributes were added where appropriate.

Using the TestCaseSource attribute

From the NUnit documentation:
TestCaseSourceAttribute is used on a parameterized test method to identify the property, method or field that will provide the required arguments.
This means you can use a property, method or field to hold all of the user agent strings for a particular test rather than specify each one in it’s own attribute. Here I’ve used arrays to organise user agents into groups:
readonly string[] mobileUserAgents =
{
    USER_AGENT_IPHONE_4,
    USER_AGENT_GALAXY_S5,
    USER_AGENT_LG_G4
};

readonly string[] androidUserAgents =
{
    USER_AGENT_GALAXY_TAB,
    USER_AGENT_GALAXY_S5,
    USER_AGENT_LG_G4
};

[Test, TestCaseSource("mobileUserAgents")]
public void IsMobileDevice_UserAgentIsMobile_ReturnsTrue(string userAgent)
{
    Assert.IsTrue(new DeviceInformation(userAgent).IsMobile);
}

[Test, TestCaseSource("androidUserAgents")]
public void IsAndroidDevice_UserAgentIsAndroid_ReturnsAndroid(string userAgent)
{
    Assert.That(new DeviceInformation(userAgent).Manufacturer, Is.EqualTo("Android"));
}
Now each test only has one attribute, much better. Also, to keep the snippet short I’ve only added two groups of user agents, but for a thorough test I’d add a lot more. For example appleUserAgents, tabletUserAgents, desktopUserAgents, backBerryUserAgents, windowsPhoneUserAgents etc. Now when you want to test a new user agent you simply create a new user agent variable and add it to the appropriate arrays. The is no need to change individual tests. Easy.

Sunday 4 October 2015

What is Command Query Separation?

What is Command Query Separation (CQS)? It’s a principle created by Bertrand Meyer which states that any operation in code should be one of two types; a query or a command, but not both.
  • Query. This isn’t a database term, it simply means that the operation should return some data and not have any side effects. Repeated calls to a query should return exactly the same result
  • Command. This is an operation that takes some action, it has side effects, it can change your programme state
For example:
public ShoppingCart GetShoppingCart();

public void AddItemToShoppingCart(Item item);
GetShoppingCart() is a query, because the signature shows it returns data. AddItemToShoppingCart() is a command because it returns void.

Is CQS the same as CQRS?

No. They share some terminology but CQS is a programming principle that applies to the methods on an object. Command Query Responsibility Segregation on the other hand is pattern that splits queries and commands into separate models.

Why is CQS useful?

I had a lightbulb moment when I read a chapter of Code Complete 2 entitled “Conquer Complexity”. It lists numerous good practices programmers use including writing short methods, writing small classes, using meaningful variable and class names, avoiding deep inheritance hierarchies and breaking up larger systems into smaller sub-systems. The author, Steve McConnell, finishes the chapter with the following:
“A primary goal of software design and construction is conquering complexity. The motivation behind many programming practices is to reduce a program’s complexity”
In hindsight I feel a bit stupid. I hadn’t realised that all the these familiar principles served the same purpose, to reduce complexity.
CQS wasn’t listed in that chapter, but it’s no different, it helps reduce complexity. If a code base strictly follows CQS then you can trust an interface without digging into the implementation. If a method returns a value, it’s a query and can be called safe in the knowledge it won’t change anything, no matter how often it’s called. If a method returns void, it’s a command and more care is required.

Sunday 20 September 2015

Book review - Clean Code

After a few years of putting it off I’ve finally got round to reading Clean Code by Uncle Bob. I’m glad I did. It’s one of a handful of books that regularly appears on lists of must read programming books.
Why do I like this book?
  • The main reason is that it’s fundamentally about how to write simple code that humans can understand. The importance of this cannot be overstated. It’s not enough that code compiles and meets all the requirements, code must be easy for other developers to understand.
  • It’s about details, and I like details. Many of the code smells and heuristics covered in Clean Code are small details. For example, unnecessary comments, vertical distance between variable declaration and usage, code formatting, method size. They may be small but when you add them all up, they make a significant difference to your code
  • Each chapter is short, easy to read and to the point. While the book as a whole isn’t short, about three hundred pages excluding appendices, you can sit down for half and hour, take in a chapter and learn something from it.
  • There are plenty of examples. Each chapter contains plenty of small examples and the last two chapters rework larger pieces of code using some of the principles covered earlier in the book.

Thursday 30 April 2015

Book review - Peopleware

I’ve been meaning to read Peopleware ever since I heard read about it on Joel Spolsky’s blog a few years ago. It was written by two software development project managers who came to the realisation that “the social complexities on most of the projects we’d known simply dwarfed any real technological challenges that the projects had to deal with.” The book is comprised of many short examples of the types of social problems they faced and suggestions on how to deal with them. One of the key words in the last sentence was short. I imagine many other books on management are dry and long winded. Peopleware on the other hand is an easy, enjoyable read that crams a huge amount of content into each short chapter. Much like rework you can pick it up for fifteen minutes and get something out of it.

Why read Peopleware?

I’m not a manager and I have no intension of becoming a manager any time soon, so why read this book? Firstly, it’s incredibly interesting. Secondly, it’s relevant to all software developers, not just managers. For example there is advice on overtime, office environment, innovation, hiring staff, meetings, leadership, making change possible and email. And this is just scratching the surface.

What did I learn?

There’s a huge amount to learn by reading this book but a few parts stood out to me.
  • The flight from excellence. The authors talk about the friction between the client’s desire for quality and the builder’s desire for quality. The client often isn’t concerned about code quality, they just want a finished product for their consumers. Builders (developers) on the other hand get a deep sense of pride from achieving high quality code. We’ve all been there
  • Making change possible. The insight in this chapter about why people resist change really hits the nail on the head. It’s argued that the resistance comes from emotion, not logic and I can’t help but agree. There’s also some good suggestions on how to make change easier
  • Productivity. This is a theme covered by a number of chapters. Flow is highlighted as being essential for productivity, as is quiet and the avoidance of distractions like email, telephone and multi-tasking

Some quotes

I know quotes like this don’t really mean much out of context, but I still like them, so here’s are some of my favourites.
“The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted”
“The fundamental response to change is not logical, but emotional”
“Change won’t even get started if people feel safe”
“The managers function is not to make people work, but to make it possible for people to work”
“People under time pressure don’t work better, they just work faster”
“Innovation is all about leadership, and leadership is all about innovation”

Monday 16 March 2015

What makes a good software developer?

What makes a good software developer? I've been thinking about this question quite a lot in the past few years, even more so recently since I've been involved in interviewing candidates. 

Many people with much larger brains than myself have written about this, but here's my take. Knowledge and experience are very important. I could make a list of technical skills I think are essential for a job on the team I am currently part of. If someone else were to write a similar list I've no doubt it would be different. This is why I think knowledge and experience definitely play a big part in what makes a good developer but it's a good attitude that is key. 

What constitutes a good attitude? Here are a few things that I believe are important:

  • Enjoyment - You must enjoy creating software. This is absolutely fundamental. It's impossible to be good at something you don't enjoy 
  • Learning/self improvement - I'm not saying you need to spend hours reading books or creating software in your own time, although that will get you far, I mean at the very least take time to improve at work. Identify weak skills, learn from more experienced colleagues, read blogs when you have ten minutes spare
  • Caring - Please give a crap! Care about writing good code, care about coming up with the best solution possible, don’t settle for the first idea that pops into your head. Care about your team, care about your culture, care about everything!
  • Be open to new ideas - Don't reject something simply because it's new, you don't know much about it or it's not the way you’ve always done things
  • Take responsibility - Don't just complain about problems or leave them for others to fix, take action 
  • Simply doing what you've been asked to do is not enough - Typically companies want developers to build features and fix bugs as fast as possible. Unfortunately a codebase is like a car, it needs servicing, regularly, otherwise small problems become big problems. A good developer will identify and fix these problems