# 88 - Creating SOLID Code: Single Responsibility Principle (SRP)


2/25/2009
Level: Intermediate
Tags: SOLID Principle
Comments: (13)
Author:
Stephen Bohlen
 
Presented By:
Codebetter.com


This is the first in a 5 part series where we will explore the tenets of the S.O.L.I.D principles.

In this first episode we will take a look at the S (Single Responsibility Principle) and see how following this principle can help us to create cleaner, more manageable code

S - Single Responsibility Principle
O - Open/Closed Principle
L - Liskov Substitution Principle
I - Interface Segregation Principle
D - Dependency Inversion Principle
Click here to Watch this Episode

Download (17.28 MB) (11:42) (1440x900)
Download (12.77 MB) (11:42) (960x600)

Links/Resources:


Comments: (13)

Aleh Matus said....

Strictly speaking, each class in this example still has more than one responsibility in the end. For example, Report Printer has one do-responsibility. It is responsible for the print workflow: getting the data for the report, formatting the data, and sending it to the output stream. Report Printer also has three know-responsibilities. It is responsible for knowing where to get the data, knowing who to ask to format the data, and knowing that the output stream is the console. One way to achieve single responsibiliy (SRP) for the Report Printer class is to remove all its know-responsibilities by appling dependency injection (DIP).


2/26/2009 9:02:44 PM

Steve Bohlen said....

@Aleh:

Patience, my friend, this is part 1 of a 5-part series and if you look carefully at the SOLID acronym you will see that DIP isn't until the 5th installment :)

If I were to perfectly redesign the classes all in the first episode, what would be left for the subsequent installments when I *do* need to focus on DIP?

Trust me, DIP (and for that matter OCP, LSP, and ISP) are coming and by the end we should (hopefully!) see a better overall design leveraging all of the SOLID principles.

Thanks for the comment though because it zeros us in on the very important fact that most of these principles are actually most valuable when all taken together as a self-reinforcing group) rather than in isolation as is being presented here.

With luck, by the end of all 5 of the installements this will be more apparent once all of the other principles are brought into play.  In a sense this is the downside of releasing these in separate 10-minute units rather than all at once in a single hour-long screencast but as creators we all have to live within the confines of our medium of choice :)


2/27/2009 12:49:43 PM

flipdoubt said....

I was going to make a similar comment about where the different responsibilities are being instantiated and working together, but I will be patient. One thing I am (patiently) waiting to see is how the output from one responsibility will be passed to the next. The data access and report formatter responsibilities can't return void in a production app. I understand why you want them separate, but how you keep them separate but pass the work product from one to another seems to load up my code with a bunch of assumptions. Still, eagerly waiting to see what happens.


3/2/2009 5:45:27 AM

Steve Bohlen said....

@flipdoubt:

That's a great point, but you're not going to see the passing back of data out of the operations in this series as its moving too far away from the core of the intent (to show refactoring by applying SOLID principles).

You do bring up a very important point however but its soluble by defining the operations of the components (e.g., the DataAccess class) in terms of returned interfaces as well (e.g., IReportData or similar) so that this too is a coupling in terms of abstractions rather than implementations.

Nice catch that the sample fails to address this aspect of the SRP (and other loose-coupling) but that's how I usually recommend addressing it.


3/2/2009 2:45:37 PM

flipdoubt said....

Thanks for the prompt reply, Steve. Can you recommend any tutorial's that go all the way with a concrete example that shows the separated responsibilities passing work products around?

The IReportData you suggest is where I get in trouble. If it has methods that read a byte[], then the data consumer has to make assumptions. If it is more like a list of entities or a more memory friendly IEnumerable of entities, is that too specific of an implementation? What would Uncle Bob do?


3/3/2009 5:18:22 AM

Steve Bohlen said....

@flipdoubt:

Yeah, I think I 'spoke' too quickly there with IReportData; in my real world, it would in fact probably by IEnmerable<ReportElement> returned from DataAccess.GetData() and that's about the best level of abstraction I can hope for in such a case.

This goes to a point (I agree with) that I read someone on a blog make one day (and I paraphrase): "there is no such thing as tight or loose coupling -- there is only coupled or non-coupled code.  The trick is to always couple to abstractions rather than implmentations."

And I love the "What would Uncle Bob do?" question -- its a great way to consider arriving at the proper solution :)


3/3/2009 7:05:35 AM

Wayne Godfrey said....

First - I love what you're doing here and really appreciate the length of the videos (kinda SRPish).

My first reaction when watching this video was similar to Aleh's in that it seemed you still ending up with one of your classes having multiple responsibilities. ReportPrinter was still "responsible" for getting the data and formatting the report - it just handed the work to another class. It just had that "smell" to it as I've heard many say.

I'll try to stay patient and see if DIP will remove the "code smell".

Thanks again!


3/5/2009 9:03:41 AM

Derek said....

@flipdoubt:

"What would Uncle Bob do?" - that's brilliant! :)

@Steve:

Once again nice series of screen casts; I've read the book but the film was better.


3/7/2009 9:22:10 AM

nightshade427 said....

I'm not sure I understand the way the responsibilities were broken out. Why does the printer class know where to get data? Isn’t that knowledge for a report to have not a printer? Doesn't a report need to know where to gets its data and not the printer? Doesn’t a printer just print data given to it? Would it be better to have the Report class depend on ReportData and ReportPrinter and have ReportPrinter depend on ReportFormater . Then in print method of the Report have the Report get the data it needs from ReportData and pass that to ReportPrinter, which then the ReportPrinter hands off to ReportFormater. Leaving the other principles out of the picture I was thinking something like this, it is a slightly different breakdown of responsibilities, what are your thoughts?

public class Report{

  public void Print(){
    var data = new ReportData();
    var printer = new ReportPrinter();
    printer.print(data.GetData());
  }

}

public class ReportData{

  public string GetData(){
    Console.WriteLine("Getting Data...");
    return "test data";
  }

}

public class ReportPrinter{

  public void Print(string dataToPrint){
    var formater = new ReportFormater();
    string formated data = formater.Format(dataToPrint);
    Console.WriteLine("Printing Report...");
  }

}

public class ReportFormater{

  public string Format(string dataToFormat){
    Console.WriteLine("Formating Report...");
    return "formated data";
  }

}


3/8/2009 2:43:22 PM

Ryan said....

How were you transforming:

new ReportPrinter()

into:

ReportPrinter reportPrinter = new ReportPrinter();

This seems like a really handy shortcut and I just spent way too much time trying to figure out how to do it!

Thank You


3/23/2009 2:24:38 PM

Claudio Lassala said....

Great series of webcasts on SOLID, guys.

Quick CodeRush tip: if you want to create a class without the default constructor, use the "c," template. That way you don't have to remove the ctor every time.  ;)


3/28/2009 11:22:27 AM

Bog Saggett said....

Great screencast. Just one suggestion. Could you speak a little slower please? Some parts were a little hard to comprehend because of the speed of talking, particularly as to me you have an accent :)


4/12/2009 3:41:41 AM

Darren said....

What Visual Studio Add-In are you using? Looks sweet!


5/1/2009 9:35:03 PM


Name: *
Email (not displayed): *
Url:
Comments: *



So, you Human...?