Thursday, April 21, 2011

Design Patterns - The WHY

Over time I have had the pleasure and indeed on rare occasions the misfortune to interview many software engineers.

One thing that you learn in interviews is how poorly some basic ideas are understood....

Factories
A very common misconception is the humble Factory Class.

A lot of people seem to miss the point. It's often been described as a place to collect together constructors, as if bunching them together in a single file was a goal in itself.

It's the WHY question that matters. Why on earth would you use a factory class?

The answer is quite simple. It's all about reducing dependencies.

It's all about dependencies
If I have a class ShapeManager that understands and cares about shapes, but has no particular need to know about or care about the particular type of a shape, then I want to preserve that separation. I am prepared to go to quite some lengths to prevent that class ever knowing about a Square, Circle or Triangle. As soon as it does know about individual shapes all is lost.

For example, if I suddenly see the error of my ways and change all the Simple Regular Polygons to a single class, my ShapeManager should ideally remain unchanged. I should not have to go into ShapeManger and look for all places where I have a particular instance of Square, Triangle, Pentagon, etc. and change them. That way lies madness.

Loading Shapes
Somewhere it the ShapeManger, I may care to load in Shape from a file. I could code it directly, but then my ShapeManager needs to start knowing about the types of Shape in the file. Madness I tell you.

What if I pass in an IShapeFactory, in this case an instance of ShapesFromAFileFactory()?

Now my ShapeManager sees an Interface which has a Function GetNextShape(), which unsurprisingly returns a Shape.

Now when I add a Simple Regular Polygon, or change the way shapes are stored, or even move the storage of the Shapes to the database, ShapeManager remains unchanged.

And I can also pass in an ShapesForTestingFactory() in my unit tests and run the tests without any external dependence on databases or Files.

The ShapeManager code is now more testable, it's less fragile, and please don't underestimate this part, it's more understandable to people who know about standard design patterns.
That bit matters a lot in a large software team. Depending on schedules, any of a half a dozen engineers with a passing knowledge of an area may be working on a change or a fix. If they see a Factory and know from roughly what is going on, then there's less "figuring out" to do before they can get started.

Monday, April 11, 2011

The State of things

The humble state machine has been implemented many many times, but enums are no longer the way to do it.

At the heart of things, you have some information about our current condition or state, and you have things that can happen, ie Events.

Some Events are valid for our current state, some are not.

If we use an object to record our state, then the object can have member functions to deal with events.

So, if we start with an AbstractState which cares about Enable, Disable, Pause, and Continue events. We give it virtual functions for each of these and in each case, we throw an "Invalid Event For State" exception, detailing the Name of the Current State and the Event.

Our Enabled State, derives from this, and implements Disable, and Pause.

IState Disable() {
  return DisabledState; // this is just a static instance.
}

IState Pause() {
  return PausedState; // this is just a static instance.
}

If you try to "Continue" an Enabled State, then you get an exception

For each state, you override the functions to deal with the possible events.

To process an Enable event, your code then calls

currentState = currentState.Enable();

And so on.

Do exercise care in deciding that you cannot go from state A to state B. Someone may take a personal dislike to you and all your children based on some artificial restriction that you enforce.

Friday, April 1, 2011

Names ending in 2

It's almost always a wrong thing to have a variable, class or function whose name ends in 2.

class SensorReadingTransform sensorReadingTransform;
class SensorReadingTransform2 sensorReadingTransform2;

Anyone care to make a guess as to the difference between the 2 classes above.

Does this code "speak to you"

Are you going to have to go look in the class to have any idea what the difference is?

If I'd renamed the first one, and created the second one as follows

class SensorReadingLinearTransform sensorReadingLinearTransform;
class SensorReadingNonLinearTransform sensorReadingNonLinearTransform;

Now you have at least a starting point. Yes, that's what I need, look further, or no, that's ok, I need to look somewhere else.

And truly, if the best name you can come up with is "Foo2" then that says a lot about the need for some rethinking.