Ho hum, settling into a stride here, starting to feel like I’m making headway. Must shake off the habit of writing these things stream of consciousness; I think I need a cigarette. Last time I talked about substitutability, and the Liskov Substitution Principle, mentioning Wall-E and his amazing hot-swappable eyes. This time I want to talk about a related concept; another heuristic for flexibility:

Code Composability

Code Composability is on my mind a lot at the moment. The goal of composability is to write a system in terms of smaller parts that can be wired together to produce a smoothly running whole. I’m starting to think that composability might be the key heuristic for OO design: the sine qua non of design patterns, and the pot of gold at the end of Liskov’s rainbow.

Waaaaaay back in September when I was writing about QA and testability, I introduced an example of a non-testable system, and a more testable alternative. I reproduce a chunk of that article here:

Unit tests FORCE you to design composable units of functionality.

Okay, an even bigger secret… this one is going to make me really unpopular.

Most programmers SUCK at object-oriented programming. I know this, because I sucked at OO programming, and I didn’t even realise it. I was awful. This is because OO design is fundamentally hard and human beings don’t think in terms of objects, they think in terms of procedures.

Quick: off the top of your head: write a function for making tea.

Here’s my attempt.

function Make_A_Cup_Of_Tea(bool milk, int numSugars) { kettle = new Kettle(); kettle.Fill(TheTap); kettle.Boil(); cup = new Cup(CupColour.Blue, CupSize.Large); cup.Add( new TeaBag() ); kettle.Pour(cup); if(milk) cup.Add( TheFridge.GetMilk() ); if(numSugars > 0) { sugarsAdded = 0; while(sugarsAdded <= numSugars) cup.Add( new Sugar() ); } return cup; }

That’s object oriented, right? It uses objects and everything. New, freshly constructed objects, too, – not second hand ones.

Nope, this isn’t an OO solution to making tea, and it’s completely impossible to unit test. A testable solution might look something more like this:

function HotDrinkProcess(drinkPreferences, waterProvider, cupboard, pantry) { var cup = cupboard.Fetch(drinkPreferences); var ingredients = pantry.Resolve(drinkPreferences); ingredients.ForEach(item | cup.Add(item)); waterProvider.Fill(cup); this.Result = cup; } var drink = new HotDrinkProcess( new TeaPreference{milk:true, numSugars:2}, serviceProvider.Fetch(typeof(AbstractKettle)), serviceProvider.Fetch(typeof(AbstractCupboard)), serviceProvider.Fetch(typeof(AbstractPantry))) .Result;

No sane person would offer that as the first thing that comes to mind when asked to write a Make_Cup_Of_Tea function. It’s just plain unnatural, but in the next couple of articles, I want to show why this crazy tangle of service providers and small objects is a better solution. Back to the here and now

I never got around to writing those “next couple of articles”, mostly because I’d picked a stupid example, and it turned out to be really hard to write about TDD using making tea as an analogy, but also because my writing style was even more insufferably arrogant then than it is now, and it fills me with RAGE to look at the damned thing. I think I have a better example now, and I’ll be uploading it to Google code at some point so that you can all have a look at it and mock me.

Before we get to that, let’s talk about Wall-E’s eyes some more. Wall-E can swap one pair of eyes for another, because they act just like the old pair – they are substitutable. The ability to build up a complete working system from smaller, swappable parts is composability, and there are some important guidelines to follow if you’re going to achieve it. Number one is: Don’t build lenses inside eyes

This is covered really well at the Google Testing Blog by some sober guy. He’s awesome, you should read his entire blog.

Let’s take another contrived example.

public class RoboticEye { private Lens _Lens; private SensorArray _Sensors; public RoboticEye() { _Lens = new Lens(); _SensorArray = new SensorArray(); _Lens.DirectLightTo(_SensorArray); _SensorArray.DataHandler = SendMessageToRoboticBrain; } private void SendMessageToRoboticBrain(SensorData data){} }

Okay, here we have a RoboticEye class. When we create a new RoboticEye, it creates a Lens, and a SensorArray. It sets the Lens to direct light onto the SensorArray, and it registers itself to handle the data from the SensorArray. This is logical – it doesn’t make sense to create an eye without a lens or without sensors, but allowing the eye to construct its own dependencies makes it impossible to test certain scenarios. Here’s one such scenario

// If the lens is broken, it should throw a BrokenLensException public void Test_That_Broken_Lens_Throws_BrokenLensException() { // O NOES! How do I create a RoboticEye with a broken lens? }

In order to test what happens when you use an eye with a broken lens, we need to be able to provide a broken lens to the eye in the first place. One way to do that is to expose the lens on the _public interface _ of the eye, like this:

public class RoboticEye { public Lens{ get; set;} public RoboticEye() { … } }

Now I can have direct access to the Lens, but not the SensorArray. In order to write my test, I’ll have to expose that, too.

public class RoboticEye { public Lens{ get; set;} public SensorArray{ get; set;} public RoboticEye() { … } } // YA! Now I can haz test! // If the lens is broken, it should throw a BrokenLensException public void Test_That_Broken_Lens_Throws_BrokenLensException() { var eye = new RoboticEye(); eye.Lens = GetBrokenLens(); eye.Lens.DirectLightTo(eye.SensorArray); Assert.ThisThrows(eye.LookAtSomething); }

Ewwww… now we have multiple calls to objects inside the eye so that we can do the set up that should happen inside the constructor. This is a clear violation of encapsulation. We’re reaching into the object and telling it what to do. Our object is no longer a responsible agent. We have to micro-manage it every step of the way.

Instead we can construct the object like this:

// If the lens is broken, it should throw a BrokenLensException public void Test_That_Broken_Lens_Throws_BrokenLensException() { var eye = new RoboticEye(BrokenLens, WorkingSensorArray, SensorDataHandler); Assert.ThisThrows(eye.LookAtSomething); }

Providing all the services that an Eye uses in the constructor means that our Eye keeps control of all its own wiring. We can compose the object from multiple parts, and use broken or fake parts in testing, but still keep all the wiring private. This is called Dependency Injection for the obvious reason that an Eye depends on a Lens and a SensorArray, and we are injecting them instead of letting it create them by itself.

Now we can test all kinds of interesting scenarios:

public void Test_That_Robot_Checks_For_Missing_Sensor_Array() { var eye = new RoboticEye(WorkingLens, null, SensorDataHandler); Assert.ThisThrows(eye.LookAtSomething); }

or provide useful replacements for individual parts

public class SensorDataHandler_WithLogging : ISensorDataHandler { public LoggingSensorDataHandler(IOutput output, IBrain brain) {…} public void SendMessageToBrain(SensorData data) { Output.Write(data.ToString()); Brain.Process(data); } } // with our logging sensor handler, we can write sensor data to the console and never pass it // to a RoboBrain – we can test the sensor from inside an eye without needing to reach inside that eye. // Yay substitutability and composability. public void Dump_Sensor_Data_To_Console() { var output = new ConsoleOutput(); var fakeBrain = new FakeBrain(); var eye = new RoboticEye(WorkingLens, WorkingSensorArray, new LoggingSensorDataHandler(consoleOutput, fakeBrain)); eye.LookAtSomething(); }

So injecting dependencies via the constructor means that we can test all kinds of interesting scenarios. It also means that you can swap out an implementation at run time, and that makes your code flexible and flexibility is always good when the boss asks you to make a “quick change”. Let’s do the question of the week:

So… the fourth question I ask of a potential hire is “Can you name a design pattern, and an implementation of it in the .Net framework”?

If you immediately say “Singleton pattern”, then you lose – I’ll come back to why you lose next time (or the time after, when I get around to it). My favourite design pattern, and the one that’s easiest to talk about in the .Net class library is almost certainly:

The Strategy Pattern

The strategy pattern is a solution to this requirement:

public interface ISolutionToProblem{ void SolveTheProblem(Problem p); } public class CleverSolution{ public void SolveTheProblem(Problem p) { …} } public class DumbSolution{ public void SolveTheProblem(Problem p) { … } } public class NonSolution{ public void SolveTheProblem(Problem p){ … } }

We have an algorithm called SolveTheProblem, and there are many ways to execute it. The Strategy pattern says “create a new class per solution to the problem”, and allows you to swap them out at run time.

Here’s an example of its usage in the .Net framework:

private List myListOfNumbers = new {6, 34, 65, 7, 23, 1, 3, 6, 8,4 ,3,2, 249387}; public void Can_Sort_Numbers_Ascending() { var mySorter = new AscendingOrderNumberSorter(); var mySortedList = myList.Sort( mySorter ); var lowest = mySortedList.First(); // for each number, make sure it’s greater than or equal to the previous number mySortedList.ForEach(n => { Assert.That(n >= lowest); lowest = n}); } public void Can_Sort_Numbers_Descending() { var mySorter = new DescendingOrderNumberSorter(); var mySortedList = myList.Sort( mySorter ); var highest = mySortedList.First(); // for each number, make sure it’s lowererererer than or equal to the previous number mySortedList.ForEach(n => { Assert.That(n <= highest); highest = n}); }

The List class has a method Sort(IComparer T);

If you want to sort a list of RobotEyes according to Eye.Lens.SerialNumber then you can create a new implementation of IComparer that knows how to do that for you. The List.Sort method uses different strategies to sort its members, and you can extend its behaviour by providing a different implementation of the IComparer strategy. Each strategy is a responsible agent that knows how to do one thing, and one thing only.

If you’re scrolling through at high-speed, this bit is important

Okay, I promised our mullet-sporting ex-intern that I’d try and keep these articles shorter, so I want to quit now before I sober up. You might be wondering, “Injecting dependencies via the constructor looks like WIN for composability, and composability is WIN in its own right, but isn’t it a total pain in the ass to write code that looks like this”:

public Robot ConstructRobot() { // first build the left eye // which needs a brain var brainConfig = ConfigurationManager.GetConfig(“brain”); var roboBrain = new RoboticBrain(brainConfig); // and a sensor data handler var logFileLogger = new LogFileLogger(“eyeLog.txt”); var sensorDataHandler = new LoggingSensorDataHandler( logFileLogger, roboBrain); // plus a lens, and a sensor array var lens = new Lens(); var sensorArray = new SensorArray(roboBrain); var leftEye = new RobotEye(lens, sensorArray, sensorArray); // phew… now the right eye … // now the head // &amp;c. ad nauseum var Robot = new Robot(leftEye, rightEye, head, body, legs, wtf, lol, this, is , ridiculous, dude); }

And the answer is “Yes, that would be a total pain – except that we don’t do that”. Instead, what we do is this:

var MagicThingy = new BuilderOfThings(config); var myRobot = MagicThingy.BuildMeA();

Next time I want to return to exactly how MagicThingy does its magic, and touch more on composability with a slant toward Design By Contract, which is, liek, teh best rule evar!!!! for teh oo programing, d00d. srs. Also, I’d like to be able to talk about composability in a real-world application, and drop the silly examples with robots and fairies because – frankly – they’re insulting to my SUPERIOR INTELLECT.

PS. We’re moving all this stuff to a new blog! That means we’ll get code formatting and so forth,. I’m kinda peeved because I’ve only just worked __out __ .bc how all the formatting options

no

work in textile

Related Articles: Object oriented programming: a bluffer’s guide – read more about object oriented programming interview questions

Bob Gregory


Request a Demo

© 2006 - 2019. All Rights Reserved.