Tuesday 4 February 2014

A most Practical lesson in Clean Code

Our wireless thermostat recently shuffled off its digital coil and I can only assume is on its descent to robot hell.  The maldesign on the device is subtle that you can imagine even a half-competent engineer signing off the specifications without noticing the error.

Just to be clear - this isn’t a metaphor or some contrived example to prove a point - although I’m hoping one day it will be. Our thermostat is broken, its the middle of winter and we are very cold.

The thermostats wireless receiver is a mains powered device that sits in an operations chain in series with the timer control unit. Every few minutes the thermostat receiver polls the wireless thermostat and the input line from the timer. If both are true, it flipflops its output to TRUE - and the heating comes on.

As an additional feature the unit also has a manual override button - so if you want to ignore the thermostat and timer input you can force your heating on. I won’t go all UML on this right now, but you can imagine a reasonably simple diagram that explains this all.

But what I’m facing with a faulty thermostat and its faulty “Manual Override” button. I’ve seen the wiring diagram - an override switch that bypassed the circuitry isn’t very difficult to add. It’d literally be a switch that shorts two physical wires. I don’t want a “manual override” button that relies on the same faulty circuitry that I’m trying to override - I want an external independent mechanism.

The override should adhere to the same interface declaration as the normal thermostat, have the same dependencies at a factory level, but its operation entirely driven by a public method. That way, it could be injected into a test with an instantiated timer or used if thermostasis isn’t a customer requirement for this sprint.

And then BAM! My thermostat was just a metaphor* for The Substitution Principle all along!  Its not always enough just to assume that because you declared an interface and implemented it that you have covered all the bases. Zero-To-One is a great step, but Zero-To-One-To-Many is the path you are trying to lay down to make maintenance easier.

And that’s the take-home lesson for today, in a very practical sense. Clean-Code programming lessons in applied engineering:
  • The Thermostat, the Override and the Timer should all fill the signal control interface. (Substitution Principle)
  • The signal control interface should just be concerned with being a programmable gate. Two input wires, One output wire. (Interface Segregation)
  • Each component should do what is says on the tin (Ronseals Law)
  • The factory should be responsible for constructing and wiring them together (Factory Construction)
  • Each object should pass its signal on to the next (Dependency Injection)
  • The override responsibility and the thermostat responsibility should not live in the same object (Single Responsibility Principle)
Until next time: Enjoy your warm house, keep coding, and remember to think inside the box!

 * = Actually not a metaphor, our house really is brass monkeys right now.

Monday 3 February 2014

Programming with the Man Flu (Comfort Zone Programming)


To cut the explanation short, Last week I was taken out of action for four or five days with Man Flu. And like all sofa-bound individuals reached for the trusty laptop and immediately opened my IDE to get some uninterrupted* programming time in with the determination that this wasn't going to be a total waste of time.

* = Programming time was frequently interrupted by naptime.

Attempts at developing software under these conditions were met with varying degrees of success - some tasks were quite possible while others not so much.Your brain uses some 20% of your energy, and in my energy-restricted flu-coma my immune system had clearly decided to shut down those pesky thought processes that were hogging system resources.

The end result was a pared-back subset of programming and refactoring skills and I was focused on just doing the things I knew how to do - the core actions that I could perform on autopilot. Coding in my Comfort Zone.

Comfort Zone programming is a reflection on your skillset, and in your confidence in those skills. I naturally tended toward the things I found easiest and away from 'difficult' tasks - when you have no brainwidth, go with what you know.

Over this time I performed several pre-emptive refactors of non-critical systems. Clearly I could spot problems, demeter violations, better injection patterns - but lacked the judgement to ignore problems off the critical path.  I was also quite happy spending a few hours writing some packet processors for data bytestreams, which I attribute to a lot of the image processing and network code I've written in the past rising to the surface.

While dying from Man Flu isn't a great way to identify your comfort zone - and not an experience I'd recommend for anybody - The process of identifying what you are good at provides value not only because you can Keep Doing It, but also because you can stretch further, learn something and better yourself.

Comfort Zone programming has helped me learn which skills I default to when times are hard - what my reflex actions are - who my autopilot is.

Learning what to learn is one of the hardest skills to develop, and in this instance I've got a list of the "difficult" tasks my fever brain avoided, and my programming autopilot wasn't able to handle.  Over the coming weeks I'll be able to reflect upon that list and get practice at my weaker refactoring and programming skills, to drill them into my brain until even my autopilot can manage them.

The take home lesson here - and your challenge, should you decide to accept it, is to get out of your comfort zone. And a great way to do that might just be to get in to your comfort zone and see what it looks like. Identify the skills that you don't use enough, follow the advice you frequently ignore.