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


2/25/2009
Level: Intermediate
Tags: SOLID Principle
Comments: (14)
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) (11:42) (1440x900)
Download (12.77) (11:42) (960x600)

Links/Resources:


Comments: (14)

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

prettyreplica said....

Replica Watches Collection

Bvlgari Watches Replica, Swiss Rolex Watch Collection, Best Fake Watch ,Cartier Watches ,Discount Watches , Fashion Watches , Wristwatch, Fake Watch, Wholesale Watches, Jewelry Watches, Replica Jewelry Watches. How to choose Sales Replica Watches the perfect Rolex Watch IWC Fake Watch for you. Buying a Rolex Jewelery Watches watch is certainly a large Jacob & Co. Watch Replica investment, as Rolex Replica Watches watches certainly cost Emporio Armani Replica Watches more than the average wristwatch. Most Rolex watches such as the Rolex yacht master, cost Replica Watch thousands of dollars. Chopard Watch Replica However, Replica Breguet Watches be aware Fake Franck Muller that you will be buying a watch of TAG Heuer Watches that will not Replica Watches ,Jaeger LeCoultre Replica Watches only Ebel Watches Replica work your whole lifetime, it will also look pretty Replica Watch good doing it. However, a Zenith Replica new Replica Mont Blanc Watches Rolex watch may simply be too much money for some people. Wholesale Replica Watches If that is Replica Bvlgari the Replica Handbag case, Jacob & Co. Watch Replica consider buying a Ebel Wristwatch pre-owned Rolex watch Luxury Vacheron Constantin instead. Whether you buy a new or used Rolex watch, you will definitely enjoy the Rado Replica Watches use of Patek Philippe Mens Watches a finely made watch made by the Fake Chopard Watches finest watch company in the last one hundred Replica Watch years. A Gucci Replica Watch Rolex, watch, Replica Patek Philippe Watches omega or cartier wristwatch Luxury Audemars Piguet are all good investments,Ulysse Nardin Watches but the Swiss Luxury Watches Rolex is simply the best Special Watches .

watches brand | Luxury watches | replica hangbag | Luxury watches | replica watch | Very Nice Bag | Real Replica Watches

A Lange&Sohne Watches     Aigner Watches     Alain Silberstein Watches     Audemars Piguet Watches     Bell&Ross Watches     Breguet Watches     Breitling Watches     Bvlgari Watches Replica     Cartier Watches     Chanel Watches Replica     Chopard Watches Replica     Concord Watches     Corum Watches     D&G Watches     Dior Watches Replica     Ebel Replica Watches     Emporio Armani Watches     Ferrari Watches     Franck Muller Watches     Glashutte Watches     Gucci Watches     Hermes Watches     Hublot Watches     IWC Watches     Jacob&Co Watches     Jaeger LeCoultre watches     Longines Watches     Louis Vuitton Watches     Michele Watches     Montblanc Watches     Movado Watches     Omega Watches     Oris Watches     Panerai Watches Replica     Patek Philippe Watches     Philip Stein Watches     Piaget Watches     Porsche Design Watches     Rado Replica Watches     Raymond Weil Watches     Richard Mille Watches     Roger Dubuis Watches     Rolex Japan Watches     Rolex Swiss Watches     Sarcar Watches     Swiss Watch International     TAG Heuer Watches     Tissot Watches     Tudor Watches     Ulysse Nardin Watches     Vacheron Constantin Watches     Versace Replica Watches     Victorinox Swiss Watches     Zenith Watches  

Balenciaga ;   Bally     Burberry     Chanel     Chloe     Christian Dior     Coach     D&G     Fendi     Gucci Handbags     Hermes     Jimmy Choo Handbags     Loewe Handbags     Louis Vuitton Bags     Marc Jacobs Handbags     Miu Miu Handbags     Mulberry Handbags     Prada     Thomas Wylde Handbags     Versace Handbags     YSL Handbag  

A Lange&Sohne Watches     Aigner Watches     Alain Silberstein Watches     Audemars Piguet Watches     Bell&Ross Watches     Breguet Watches     Breitling Watches     Bvlgari Watches     Cartier Watches     Chanel Watches     Chopard Watches     Concord Watches     Corum Watches     Dior Watches     Dolce&Gabbana Watches     Ebel Watches     Emporio Armani Watches     Ferrari Watches     Franck Muller Watches     Glashutte Watches     Gucci Watches     Hermes Watches     Hublot Watches     IWC Watches     Jacob&Co Watches     Jaeger LeCoultre watches     Longines Watches     Louis Vuitton Watches     Michele Watches     Mont Blanc Watches     Movado Watches     Omega Watches     Oris Watches     Panerai Watches     Patek Philippe Watches     Philip Stein Watches     Piaget Watches     Porsche Design Watches     Rado Watches     Raymond Weil Watches     Richard Mille Watches     Roger Dubuis Watches     Rolex Japan Watches     Rolex Swiss Watches     Sarcar Watches     Swiss Watch International     TAG Heuer Watches     Tissot Watches     Tudor Watches     Ulysse Nardin Watches     Vacheron Constantin Watches     Versace Watches     Victorinox Swiss Watches     Zenith Watches  


2/1/2010 8:08:07 PM


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



So, you Human...?



Submit this story to DotNetKicks
Shout it