SOLID Principles: S is for Single Responsibility

Imagine you were writing the code modelling a car.  One you can drive, from the 1960s before they got too complex.  What does it look like?

class Car
{
    public void Accelerate();
    public void Brake();
}

Now, ignoring the fact that I should have started with an interface (and you can’t steer), there’s something very dangerous in this code.  It’s the assumption that a car is an object.  It’s not, it’s a phenomenally complex interlinking of components.  The driver may see it as one object, but you can be assured the manufacturer does not.

So what’s actually going on when you accelerate a car?  Well, for a start, you press down the accelerator pedal.  That’s the actual entry point to the system.  The Accelerate method is, at best, a simplification on top of that.  This opens a valve that lets petrol into the engine.  What happens then is extremely dependent upon the state of the engine.  For a start, if it’s not running, not very much is going to happen.  Indeed, your car will need some mechanism to prevent you from flooding the engine when it’s off.

We’re already creating an extremely complex object and we haven’t even started building code for the engine pistons yet.  It’s going to become a complete mess really quickly.  Unless, that is, we actually have objects that represent the physical components of the car.

The single responsibility principle is just a formalization of what we’re talking about here.  It says that a class should only do one thing and only that.  Valves should be represented by Valve objects, not by the Engine class or (shudder) implicit in the workings of the acceleration pedal.  Valve objects can then be reused for any similar valve anywhere in the car, or indeed in a power station model if it uses the same sort of valves.

Going back to how I learned to do object oriented programming, the Turbo Pascal User Guide had an example that featured a Line object.  It had properties for start point, end point and a method to draw it on the screen.

WHAT?

I can’t believe I didn’t notice how insane this was the first time I read it.  Let’s assume we’re using constructor injection.  So, to create a line object, I have to pass it a rendering context?  How about if I was trying to use it for visibility detection in a 2D maze?  I’m never going to draw the line, in fact the whole point would be that I’m not drawing the line.  And how about anti-aliasing?  Are you really going to put the logic for anti-aliasing into your line class?  It’s going to get pretty big if you do.

To put it more formally, rendering to the screen is a completely separate responsibility to that of dealing with the geometric properties.  This must have been a pretty common anti-pattern back in the day, because it’s the first thing Uncle Bob mentions in Chapter 9 of Agile Software Development.

Single Responsibilty:  It’s a Matter of Perspective

Let’s talk about the car example again.  Let’s say that we’re not trying to physically model the car this time.  Instead, we’re writing eBay Motors.  What do we care about then?  Well, mostly, model, age and colour.  Writing a car class with those properties makes complete sense this time.  There’s a well defined responsibility here: capture enough information to allow people to search for the sort of car they want.  It’s not a full model of the car, but it serves its purpose.

This is part of the point of SRP, but also its greatest problem: what exactly is a responsibility is a matter of perspective.  From the perspective of physical modelling, one approach is appropriate.  From the perspective of selling the heap of junk, quite another, simpler approach is appropriate.  Equally, a sale looks very different to different departments within a firm.  For sale people, it’s a source of commission.  For dispatch, it’s logistics.  For finance, it’s a series of payments.  These are different, linked, responsibilities and should be separated.

cookie-monster

You’ll recognize this as an interface segregation concern, but naively applying ISP will get you into even more trouble than it’ll get you out of.  A car is a different object and a different responsibility to the designer, manufacturer and salesman.  Trying to think in terms of unified models is right up there with sacrificing chickens to the cookie monster as unproductive techniques in software development go.  It gets even worse when you’ve got multiple people working on the same project who have different perspectives on the same responsibility.  In your car model, should you be modelling wear and tear?  Air flow?  Or, to get completely ridiculous, how about radioactive decay?  Do we need a Hadron class for our car model?

Actually, what it comes down to is that applying SRP is one of the two hard things in computer science: naming.  If you can describe what a class does, you’ve got a responsibility.  If you need to use the words “and” or “also”, you haven’t.  If the description is vague, you haven’t.   Even so, different people will name the same piece of code differently.  Equally, one man’s readable code is another man’s tangle of wires.

Uncle Bob will tell you to extract till you drop.  I think, ultimately, you have to find a point at which you yourself are comfortable and productive.  As you get used to the principles and start to know them in your bones, you’ll find yourself heading closer and closer to that point.  Just don’t start modelling the weak nuclear force.

SEO Snake Oil

I never really felt .NET “got” SEO and ScottGu’s latest post doesn’t really fill me with confidence.  Read this:

One simple recommendation to improve the search relevancy of pages is to make sure you always output relevant “keywords” and “description” <meta> tags within the <head> section of your HTML.

Oh yeah?  Tell that to Matt Cutts.  Meta keywords haven’t had weight in any respectable search engine this millennium.  As the article explains, meta description is next to useless as well. 

What does matter? 

  • The title tag.  It shows in the browser and so Google rates it as important information.  This is a welcome addition to ASP.NET 4.
  • Heading tags.  They’re typically in large print and summarize the article. 
  • Your URL matters, so you should try to make them readable.  URL routing has been missing from vanilla ASP.NET since day 1 and has been a pain to implement.
  • Links do, even if you mark them nofollow (although they don’t count as much).
  • The text of links matters as well.

So, all in all, there are some good features being covered here.  Still, it’s hard to know who this is aimed at.  If you’re writing a new solution for SEO, it’s unlikely you’d be choosing webforms anyway.  If you’ve got an existing solution, you’ve probably already solved these problems.  That probably only leaves existing solutions that are badly implemented and, frankly, these new features aren’t going to fix that.

York Notes for SEO

I don’t talk much about SEO, because it’s really hard to create posts as compelling as seomoz, but here’s pretty much everything you need to know:

  • You can do a lot worse than writing content people want to read and link to.
  • Observe web standards.
  • Google doesn’t use Javascript on pages much.  Javascript-only links are particularly stupid.
  • Age matters.  That’s why it’s better to do a permanent redirect rather than just move the page.
  • Don’t try to cheat.

Here’s some things that people do all the time that don’t work:

  • Writing “advertising copy” won’t help you on the web.  Google treats it as the spam that it is. 
  • Slapping everything into a DIV is silly.  Use markup like h1 and blockquote for the purpose for which it was intended.

Here’s some ways of cheating that don’t work:

  • White text on a white background will positively hurt.  Search engines will spot it, and will mark you down as a spammer.
  • Giving radically different content to the google bot from the user is called cloaking.  This can get you in the sin bin forever.
  • Link trading is basically spam.  Google will treat it as such.

Black Hatting (cheating google) is possible, but the guys who are good at it aren’t about to tell you how.

Technorati Tags: ,

Getting Out of the Configuration Game

I once took advantage of the published source code of the Microsoft Enterprise Library Data Access Block to make some firm-specific modifications.  One of those changes that only really makes sense in the target environment, nothing particularly general.  The Data Access Block, for those of you who aren’t familiar with it, is basically an improved version of the ADO.NET API, with some pretty useful support for stored procedures.  It’s not NHibernate, but it’s better than coding the API in the raw.

While I was there, I decided to rip out the stuff we didn’t use.  That turned out to be nearly all of it.  This was quite shocking to me, because I thought we used a fair chunk of the functionality.  I reckon that when it came down to it, two thirds of the library was non-functional.  The vast majority of the code, which I had no interest in, was there to support ObjectBuilder. 

For those of you who aren’t familiar with it, ObjectBuilder is Enterprise Library’s configuration system.  It was created to solve the some of the same sort of problems as IoC containers, but it also addresses some interesting concerns such as providing a UI for configuration.  Enterprise Library is also the original source of my ideas on environmental deltas.

So, how did I get rid of all of this code?  Well, I junked DatabaseFactory and used constructor injection again.  It took a bit of time, but I deleted two thirds of the code without an appreciable loss of functionality.

How Much is Too Much?

Before you think this is just an exercise in ragging the Pattern & Practices group, who are a pretty easy target, I want you to ask how much code your internal and open source libraries should be devoting to configuration.  Now, I doubt you’ll find many people arguing that two thirds is the right amount.  However, I bet you’re thinking that five percent is acceptable.  I’m going to argue the correct figure here is zero.

Let’s take a look at a successful open source library: log4net.  In some ways, log4net is even worse than the Data Access Block.  At least Enterprise Library didn’t require me to use ObjectBuilder.  The code was dead and irrelevant in our applications.  log4net, on the other hand, isn’t even usable without digging into its configuration system.  Because it’s so prescriptive on this point, it then proceeds to provide several alternative approaches to how to use its configuration system.

But I don’t want to use it at all.  I’ve got Castle Windsor already, why would I want two configuration systems?  If I develop a large application with a lot of libraries, I could end up with four of five configuration files.  And pretty much all of them aren’t exactly well thought out or powerful.  Want a variable to be consistent across the files?  You’d better get coding.

And this is where it gets really ugly.  APIs defining their own configuration system doesn’t save time, it makes work for the application developer.  Configuration is right on the outside of the Onion model and should be in one place, not dotted around your system.  The choice of how to configure the system should be up to the application developer.  Look at Retlang, it has no configuration at all.  Does it make it harder to get running?  Actually no, a small program can hard code everything in the Main method, a large program can use an IoC container.

The whole philosophy of constructor injection and IoC containers is that classes shouldn’t take on externalities they don’t need.  The same applies to libraries.  Be ruthless in applying the single responsibility principle and get configuration out of your code.