Categories
code development programming

Software Development as a Christmas Story

Gingerbread Christmas Tree
Oh Tanenbaum

We decorated the house for Christmas. A smaller project than most of the software I’ve worked on, but a useful reflection.

The Cost of context switching

Sometimes, in the middle of one task, you need to do another. Either because you were interrupted, or because you weren’t prepared. Consider the tree, a tall tree, one you need a ladder to decorate. But you left the šŸŒŸ in the attic.

You don’t just have the cost of picking up the star, you need to get down the ladder, fold it up, carry it upstairs, open the attic, unfold the ladder, climb to the attic, find the star, then pick it up and unwind all the other steps just to get back where you stated before you can continue the task of putting the Star on the tree.

It’s just a minute to get the star…

Yak shaving

Sometimes it’s more than just one thing. Sometimes to get to where you need to go, there’s a cascade of other tasks.

You want to put the tree up, but it’s the first time you’ve had a real tree, so you need a new base. It’s bigger than last year’s tree, so your lights don’t fit. So you need to go to the shops. But you need to fill up your car. And the tyre pressure warning light comes on so you need to top them up. And you need to check the tread depth whilst you’re there, and so on.

Programming in a nutshell

Performance at scale

Our tree stood up fine when it was delivered. But as it scaled out and the branches widened, it pushed against the wall, making it unstable in the condensed space. It fell over.

Luckily no lights or baubles were using it at the time, but it’s an interesting challenge holding up a heavy tree in one hand, trying to adjust it’s position with the other hand, as I avoided the puddles of water in the floor as my wife mopped them up. If you’ve ever worked support, this may sound familiar.

Turns out that it was harder to stabilise than I anticipated.

The branches were unevenly partitioned, providing more load on one side, so I had to stabilise it against the wall. And the tree was almost a foot taller than expected, which turned it out to be 2 foot taller than the base was rated for.

We upgraded the base to handle the load. It’s bigger than we need.

Technical debt

I have some old pre-LED tree lights and they slowly fail so each year I replace the unlit ones from the packet of spares but I haven’t been replacing the spares. Eventually, they will run out, and the spares will no longer be available. I’ll have to throw them all out and start again.

The new led ones don’t let me replace them individually. But they last longer and are cheaper to run.

Which debt is easier to live with?

With a big tree, those old lights aren’t long enough. So, do I buy another set for the rest of the tree that doesn’t match them, or throw out the existing ones and buy a longer set? The latter looks better, but throws out the sunk cost along with the lights.

You know computers, can you look at this for me?

No, I can’t fix your tree. I can navigate a garden centre. I know enough physics to keep a tree upright, eventually, and safely put the angel on, but I’ve no Idea how to grow one, or what that weird stand with 17 gears you bought does, or how to assemble your plastic one. And I’ve no idea what that bug in the tree is.

Merry Christmas. Catch you all in the New Year.

Categories
development programming security

You own your dependenciesĀ 

I mentioned as part of my Your API Sucks series that I don’t want your API to be the weak point in my application. But it runs deeper than that.

Every dependency you add to your project is a codebase whose maintenance schedule you need to know, whose security vulnerabilities you and your customers are exposed to, whose existence you depend on – whether it’s a long established company or a guy who wrote 12 lines of Javascript that everyone uses. Know how you’re going to keep using it when the existing support isn’t there.

Because it’s not just one dependency, it’s dependencies all the way down.

Of course, modern software can’t be built without collaboration, without using dependencies written by others, but where you have a choice, always choose the dependency that works closest to how you’d do it yourself, just in case you haveĀ to.

Categories
development leadership

Bootstrapping new developers

Dawn behind the trees
Start of a new day

When things are tough, do them often, to get more practice, as Sky Betting discuss in their recent blog post. It’s certainly something that I’ve noticed as we’ve moved to more regular releases, more regular planning and reducing feedback cycles.

One big thing I’m still learning how to do, where that doesn’t apply, is adding new developers to a team. I’ve been thinking about this after hearingĀ The Improv Effect talk about onboarding to a company on .Net Rocks 1253 : Onboarding is Culture with Jessie Shternshus

My usual approach doesn’t apply, because good teams are stable, so onboarding is rare, which makes it harder to know how to bring new people on to the team. I always try to write a short introduction, on a wiki, to introduce the project and list the useful urls, and the getting started steps, and I ask new developers to update it with any differences they find, to keep it up to date.

Most of the team knowledge doesn’t come from there. It comes from the rest of the team. So the team needs to be built so that the onboardee collaborates with other members of the team from day one. Getting involved in code reviews, asking questions. I’m sometimes tempted to give as little information as possible to encourage asking questions, but that’s not how psychology works, and I’ve had more than a few gotcha moments where someone who’s been on the team for a while says “I didn’t know that was there” or “oh, soĀ that’s why we do it that way”, and I have to revisit the onboarding story again, and wait for the next chance to validate it.

So, assuming your company has a good story for onboarding employees, how to you take a fresh start, or a start from another project, and build them into your team?

Categories
quickfix

Paperless and warning free

there's a dog driving that car?
Do you have a licence

As a quick follow up to my post on the new process for endorsements following the demise of the paper counterpart driving licence.

First, a clarification, the change in the DVLA is for the paper counterpart to the photo id licence, not the paper licence that existed before the photo id licences. Many people will have been switched to photo id by moving house though, so it’s only the hardcore who won’t be included.

I got confirmation from the car hire firm 24 hours in advance that I needed to print out my endorsements sheet, by which point I no longer had access to a working printer, so I was glad I’d tried it beforehand. The guy at the desk noted that it was a new scheme, and also mentioned that if I hadn’t printed it out, they would need to call a DVLA verification phone number which is very busy when it’s not shut. So still a number of teething problems to sort out.

Do if you are hiring a car, get yourself over to dvla in advance (any time within 21 days) and get your endorsement sheet printed. It might just save you from long queues and grumpy car hire staff.

Categories
code development

Cognitive load : fluent interfaces and friendly apis

a friendly robot, sitting down
Is your interface friendly?

To continue my mini series on cognitive load, following my previous post on static vs extension methods, a couple more examples to consider. Extension methods are often used as an entry point into a fluent interface, allowing a style which can be easier to read and eliminate the need for confusing, overly long parameter lists, multiple overloads or parameter objects.

They can also be used to humanize the interface, based on the understanding that the user experience of an API should be as important as the user experience of a website or application.

In the first example, I put together a quick concept for date comparison, to see if a fluent style is more readable than arithmetic operations on dates. Decide for yourself if that’s true. I discovered that making fluent operators is often harder than usual naming considerations, especially when the same word can be used to mean subtly different things.

In the second example, which I found fascinating, chaining is used to turn a conventional c# method into something more akin to a functional language with the intent of making the operations clearer and refocusing unnecessary interim storage steps. I’m not sure this is always the best approach, but I’ll definitely be adding these helper methods to my toolkit.

Categories
code development

Cognitive load : static vs extension methods

Cheese board sitting on cans of tomatoes
Extending tools beyond their original purpose

A c# specific example to follow up my blog post on cognitive load, since it coincidentally came up at work.

What are extension methods?

The example concerns c# extension methods. For those of you who aren’t C# developers, they allow you to create a static method that can be called as if it was a class method, without needing to modify the original class. They’re mainly useful for extending classes or basic types with new functionality, such as business-specific rules. For example, the LINQ library extends IEnumerable types with a number of functions, including Where() which provides the filter functionality found in functional programming, allowing users to write code like:

int[] array = {2, 3, 4, 5, 1};
return array.Where(x => x % 2 == 0); 
// returns {2, 4}

The x => x % 2 == 0 in the above snippet is a lambda expression that takes an input x (for the Where method, each member of the array) and returns the result of the expression on the right of the arrow.

LINQ example

The discussion centred around whether extension methods like the above were preferable to code using static methods such as :

int[] array = {2, 3, 4, 5, 1};
return Where(array, x => x % 2 == 0);
// returns {2, 4}

As you can see, here array is passed as the first argument (which is what extension methods do behind the scenes).

The example I raised looked like the following, where a number of these methods are chained together. Note that all the methods return a new result, as they are built to allow immutable collections, such as input buffers.

Static methods

filteredthing = Linq.Where(thing, x => x.Deleted == false);
orderedthing = Linq.OrderBy(filteredthing, x => x.CreatedDate);
result = Linq.Select(orderedthing, x => new y(x.Name, x.Id)); 

Chained extension methods

thing.Where(x => x.Deleted == false)
    .OrderBy(x => x.CreatedDate)
    .Select(x => new y(x.Name, x.Id)); 

I argued that the former requires more thought, and therefore a higher cognitive load to understand which variable to use, and the density of code requires makes it less readable and therefore makes the next developer’s job harder.

String example

The most interesting example however, was the one that started the discussion. Which of the following forms do you prefer, and why?

mystring.IsNullOrEmpty()

or

String.IsNullOrEmpty(mystring)

In particular, note that we don’t have the variable or code proliferation as in the LINQ example, and the return value is an explicitly different type.

The most persuasive argument I heard against the extension method version is that it explicitly works when mystring is null, which leads to a counterintuitive situation where, as developers, we are trained to spot potential NullReferenceException problems, and will immediately view the first form with suspicion, until we realise it is an extension method.

Question

Which form do you prefer, and would either one stop you in your tracks as you were scanning code and break your train of thought.

Categories
code data development programming quickfix

The Getting Better Moment

image
At the stroke of midnight, your code will turn into a pumpkin.

Inspired by The Getting Better Moment – You’ve Been Haacked , this is my story of my first job and a getting better moment.

During my summer break in university, back in 1999, my local council, who part funded my university education, back in the days before student loans, found me a placement at a local charity to develop a CPD database to track the exams their members took every year.

It was an Access database, installed on one machine on the network. With manual backups. It stored the pass/fail data in a set of bit fields in the database, requiring some complex sql to answer the common “who hasn’t done this course yet” mail merge query, it used VBA to parse those SQL queries into a screen full of check boxes to allow users to search.

None of that was my getting better moment though. I went from being a very shy geek at the start of the placement to a slightly less shy geek with a lot of confidence in my code. It was the first thing I’d written that was out in the real world and I was proud of it.

Until the first work day of 2000, when it stopped working. Despite the initial suspicions of the customer, it wasn’t a y2k bug. There was a bug in the end of year routine. What it was meant to do was create an empty exam results table for the new year, then rewrite the rest of the system to point to that table do that all the queries, screens and reports were up to date. It failed because it wasn’t properly tested. And I spent a whole day in their office, feeling sheepish, rebuilding the queries, screens and reports by hand to fix the mess.

But that wasn’t my big learning moment. That came exactly a year later, with another call, and another broken database. A lot of pressure now, trying to remember a fix from 12 months before on 18 month old code. It took longer than the first time, but I spent some time afterwards documenting the fix, testing the end of year rollover, and simplifying the code so I was capable of debugging it.

Luckily the customer was reasonably happy, as they didn’t run many exams in the first week of the year, and they understood you don’t get perfect solutions when you pay student placement wages, but I have tried hard since then to keep the customer happy and keep bugs that are fixed, fixed. All software has bugs in it, it’s how you deal with them, and the customer, that separates a professional from a beginner. The experience set me on the path towards TDD, open and honest communication, and not wanting to pick up support calls out of hours, which is a great motivator of quality. If you can lie on a beach, knowing you won’t get called because your code just broke, you’re doing it right.

What’s your getting better story?

Categories
code development programming test Uncategorized

Apprentice programmer

unlit olympic flame

Let’s talk about plumbing, and customer service, and an experience I had recently with a company I won’t name. Overall the experience was good, but I don’t want anyone to get into trouble because they’ve misinterpreted what I have said here. (and if you’re wondering about the picture : the Olympic flame isn’t lit either).

A couple of months ago, our gas combination boiler failed. It refused to start and complained that the flue was blocked. I sighed because we’d had the bearings on the fan replaced last year. So I called the service company to get it fixed.

A couple of days later, I was working from home to let the service technician in. He was fairly young but identified a problem. Unfortunately, a new part was required, so he had to come back the next day. He came back, replaced the part, fired up the boiler and all looked good. The next morning, no hot water and a flue warning šŸ˜¦ it was the weekend by this point so we got a senior employee, who identified an error in the replacement part (fitted the wrong way) and identified the original problem as a blocked inlet. 5 minutes to identify, 1 hour to dismantle the boiler to get to the blockage and put it back together.

He finished, switched the boiler off, and then made sure it fired when put back together. Problem solved.

So, what did I learn, and why am I posting this on a programming blog?

Firstly, a monthly fee means that I didn’t have to worry about callout or parts, which was great, and left me less annoyed than I might have been.

Secondly, your first fix might not be the right fix. It looked right and it passed the first test, but caused problems later on (at the next restart). Ever written the wrong test and thought the problem was solved? Threading has caught me out in that way before.

Thirdly, just because it passes the test, doesn’t mean the problem is fixed. The boiler fired easily when the case was open and there was more airflow, but didn’t fire when the case was closed. Ever had a bug that only appeared in production or in a system test?

Fourthly, experts will find problems quicker than rookies, but rookies still need to learn.

Fifth, sometimes the only way to fix a problem, even a small one, is to tear everything apart, blow on it, and put it back together again.

The second guy also said something that struck a chord, as I’ve been trying to do it myself : he was disappointed that the company didn’t send the junior out with him so he could pass on his experience so that he’d learn for next time. Apparently, the fault itself is rare, so it’s a good learning opportunity. For developers : fix your own bugs, as there are a lot of things apprentice developers will see in the first few years after they graduate that are rare enough not to come up in university but common enough to be real problems in the real world. For example,
trusting user input (and the related buffer overrun bugs).

So, what have you learned from other professionals?