Would Your Objects Praise You?

In the book of Psalms, we can read a passage where King David thanks and praises the Lord for making the human body and soul a wonderful creation:

Oh yes, you shaped me first inside, then out;
you formed me in my mother’s womb.
I thank you, High God – you’re breathtaking!
Body and soul, I am marvelously made!
I worship in adoration – what a creation!

You know me inside and out,
you know every bone in my body;
You know exactly how I was made, bit by bit,
how I was sculpted from nothing into something.
Like an open book, you watched me grow from conception to birth
;
all the stages of my life were spread out before you,
The days of my life all prepared
before I’d even lived one day.

Psalm 139:13-16 (The Message)

Though I am not perfect, I am perfectly made.  I did not ask for either a working set of eyes or a complex and functional brain.  Never did it occur to me that my heart would be responsible for pumping my blood or that my lungs would filter the oxygen from the air that I breathe.  I am not a creator of life, but I do create a virtual kind of life, where instead of blood and oxygen there is a complex symbiosis of binary mathematics and electrical pulses.  As a software developer, I do bring life to objects that are responsible for the inner workings of my system.  I sometimes wonder whether the objects and components that we build for our software would thank and praise us in the same degree that King David praised his Creator.

Lately, there has been a popular trend going on in blogs and podcasts around object-oriented programming, notably with the SOLID principles, a composite of acronyms about key design principles introduced by Robert C. Martin.  One of the principles that I adhere stronger than the others is the Single Responsibility Principle (SRP).  According to Wikipedia’s definition,

The single responsibility principle states that every object should have a single responsibility, and that all its services should be narrowly aligned with that responsibility.  [Wikipedia].

In the words of Uncle Bob, aside from a type having a well defined responsibility, it should have one, and only one, reason to change.  Going to back to the human body, we can clearly see that our inner components are highly cohesive and loosely coupled.  For example, when I pick up a broken piece of glass from my kitchen’s floor and suddenly I cut myself on the finger of my right hand, I shouldn’t expect my right eye to go blind.  Nor do I expect the other fingers to stop working!  Of course not!  That’s because I am wonderfully made!  And so are you!  When I cut myself, my body knows how to heal itself and within days I have no scar.  Leaving the “cutting” aside, we can clearly see how the eyes, the nose, the tongue, the teeth, the nails, the hair, the skin, etc., all have a single and specific responsibility, and if one member should stop working, it can be replaced by another compatible member.  For example, we can do heart transplants, lungs transplants, etc.  Given that the human body is so much more complex than any software ever created, how come that when my printer driver stops working, the whole operating system goes down with it?  How come when a component in an application stops working, it affects other components as well?  Take, for example, a tree: it looks very simple on the outside, but inside of it, God has clearly encapsulated the inner workings of the tree.  A tree that’s been around for decades can still grow and participate in photosynthesis.  It’s incredible.  Software systems tend to be replaced every year or two.  Anyhow, I want to keep writing on the topic of single responsibility for an object.

Suppose you have the following simple Car class:

Now, what do you think about the methods (or responsibilities) of this class?  Does it violate the SRP principle?  Here’s a simple test you can do to answer these questions (if you answer ‘NO’ to any of these questions, then you know that your class doesn’t adhere to the SRP principle.  Even better: if the question doesn’t seem to make any sense to you, then it’s a ‘NO’ by default):

  • Can a car change gears by itself?
  • Can a car change a radio station by itself?
  • Can a car drive itself?
  • Can a car idle by itself?
  • Can a car park itself?
  • Can a car start itself?

image Unless you’re the lucky owner of the Knight Rider, you probably answered ‘NO’ to a few of these questions.  For every question or observation you have answered ‘NO’, you should more than likely refactor the class and move some of its responsibilities elsewhere.  But where exactly can you move these responsibilities?  Well, before we dive to some of these answers, let’s see if we can directly some of the original questions pertaining to our Car class:

  • Can a car change gears by itself? ANSWER: Sure, if it has an automatic transmission.  Otherwise, only the driver can shift gears.
  • Can a car change a radio station by itself?  ANSWER: Nope, only the driver (or the passenger) can change the radio station.
  • Can a car drive itself? ANSWER: Not unless it’s KITT!  Only a driver can drive a car.
  • Can a car idle by itself? ANSWER: Sure it can.
  • Can a car park itself? ANSWER: Nope! Only a driver can know how to park a car.
  • Can a car start itself? ANSWER: Uh, no.  Once again, only the driver can start the car.

Do you see how by answering such questions or observations you can better get through a cleaner design?  The pattern is pretty simple too: Can a [type] [action in the infinitive] itself? Though I picked a very trivial example, you could do the same test for any of your classes, e.g., an Order class, an Employee class, an Account class, a Repository<T> class, even interfaces!  Continuing with our beloved Car class, we see that it has a couple of responsibilities it cannot fulfill by itself, because either it doesn’t make sense that it should, or plainly that it isn’t logical for the class to offer those services in the first place.  From our answers, we can also see that we need another class to make all well orchestrated: a Driver class.  The driver should know how to fulfill some of these responsibilities.  How would you associate the Driver to a Car?  You can go with the Dependency Injection pattern on this one if you like, or pick another strategy.

image

So we talked about a few things here: the Bible, Knight Rider and Uncle Bob.  But more importantly in this post, we talked about some easy and simple techniques we can use to determine whether methods or properties (responsibilities) actually belong in the right type.  Unfortunately, following this technique isn’t a silver bullet for every situation!  You must still rely on your experience and wisdom to better answer that question.  If you are part of a team, that’s even better because it is those deep and insightful conversations that actually bring about a much suitable solution.  For example, what if our Car needs some reparations?  Should we create a Repair() method in the Car class or the Driver class?  Well, you can first of all use our little technique to answer this question:

  • Should a car be able to repair itself? ANSWER: Not in this world, that’s for sure!
  • Should a driver be able to repair a car? ANSWER: Well, it depends!  Maybe the driver can repair the car, and if not, maybe we should introduce a Mechanic class that knows how to repair the car.  This is when we should discuss it in front of a whiteboard.

I hope this little tip will help you to better evaluate your design.  And don’t stress too much about it if your design doesn’t follow the SRP or any of the SOLID principles.  Just be thankful that you’re wonderfully made and that you have Google at your disposal.

This post has been viewed: 1875 times. kick it on DotNetKicks.com

 

Similar posts you might be interested in reading:

4 Comments

  1. Would Your Objects Praise You? | No Brainer Profits:

    [...] See original here: Would Your Objects Praise You? [...]

  2. Corey Furman:

    Nice analogy, Brian. I would add that it depends upon what level of abstraction that you are currently working on. Take for instance an employee’s time for a given day. The principle to which you are speaking applies to a particular activity, such as “cleaning” between 8 and 9am. In my world, this low level object has no methods. Those activities are aggregated into a collection, which is a property of the employee on that day. This is the first level of abstraction that has methods. Next, employees are collected into a property of a department object.

    My point is that as you go up the chain of parent objects, you loose SRP, unless your design calls for *many* objects.

  3. Brian Di Croce:

    @Corey: Absolutely! The same is true for either entities or value objects having only properties (state) and no methods (behavior). Not every object should have only properties, only methods, or a mix of both. It all depends. For instance, in .NET, there are a couple of interfaces that are empty (no methods defined), which act as a marker interface. That’s their responsibility, even though they’re empty.

    Sometimes, just naming an object appropriately can make a big difference in helping us to know whether its class violates the SRP. I had many cases that just by naming a class differently drove me to actually transform it to an abstract class, an interface, or even split the class in two classes.

  4. Kotaro:

    Thanks for the great article, Brian!

Leave a comment

Powered by WP Hashcash