Scott Hanselman

Hanselminutes Podcast 145 - SOLID Principles with Uncle Bob - Robert C. Martin

January 8, '09 Comments [8] Posted in Learning .NET | Podcast | Programming
Sponsored By

photo_martin_r My one-hundred-and-forty-fifth podcast is up. Scott sits down with Robert C. Martin as Uncle Bob (@unclebobmartin) helps Scott understand the SOLID Principles of Object Oriented Design.

Subscribe: Subscribe to Hanselminutes Subscribe to my Podcast in iTunes

Do also remember the complete archives are always up and they have PDF Transcripts, a little known feature that show up a few weeks after each show.

Telerik is our sponsor for this show!

Building quality software is never easy. It requires skills and imagination. We cannot promise to improve your skills, but when it comes to User Interface, we can provide the building blocks to take your application a step closer to your imagination. Explore the leading UI suites for ASP.NET and Windows Forms. Enjoy the versatility of our new-generation Reporting Tool. Dive into our online community. Visit www.telerik.com.

As I've said before this show comes to you with the audio expertise and stewardship of Carl Franklin. The name comes from Travis Illig, but the goal of the show is simple. Avoid wasting the listener's time. (and make the commute less boring)

Enjoy. Who knows what'll happen in the next show?

Technorati Tags: ,,,,

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web
Thursday, January 08, 2009 10:59:55 PM UTC
Really nice podcast, Scott and Bob. You guys really managed to make the SOLID principles clear.

Today I saw a post at CodeThinked blog, about a potential security risk in ASP.NET MVC's automatic model binding, and in the comments Simone showed how Interface Segregation can be used not only to make the API cleaner but also more secure.
Wookie
Friday, January 09, 2009 1:57:43 AM UTC
Hey Scott;

This was a great podcast.

For listeners still learning about Test-Driven Development (TDD), I got this feeling that SOLID principles really make the most sense when you first live in a TDD world. If I showed these SOLID principles to my non-TDD co-workers, they would likely argue that this mostly seems like tedium and wasted code. And in a non-TDD world, they may be right.

For example, Single Responsibility code is not immediately "easier to read". You have to dig through lots of functions (because they're all small) and you can get lost in the call stack. At 4-7 lines / function, a 12 step algorithm can be divided into 2 functions, one of which then divides into 4 functions of which one divides again... etc. In that context, it can seem easier and cleaner to just write one 36-line function instead of 9 functions at 4 lines each. I mean 36 lines isn't really that tough to understand, right?

However, when it comes to testing those functions and providing code coverage, it becomes evident why smaller parts are better. If the function method has a single purpose and a single reason to change, then it's very easy to test that function. Sure you have to dig 4 levels into the call stack to see the actual code, but when the method is wrapped in tests, it turns out that seeing the actual code is far less important.

And take a look at Dependency Inversion.

Without a TDD environment, this DI thinking actually results in adding instability. "Depending only on abstractions" means that I have more connection points and (seemingly) more places where things can "go wrong". I'm suddenly now responsible for ensuring that I can handle anyIRectangle rather than just my own Rectangles. I have actually introduced a new point of failure b/c other people's IRectangles may not behave according to my undocumented assumptions. (like the Square Height example in the podcast)

It's very similar with interface segregation. When I break the monolithic object into 10 different pieces, I now have 10 new classes to maintain. And I'm subject to misinterpretations of how these objects differ (especially because they likely share some common piece).

Of course, add tests and you flip this around.

In a test-driven world, you are documenting your assumptions via these tests. So now instead of just tedium and more points of failure, I'm actually getting more stable points of communication and thus less failure.

Personally I think the SOLID principles are excellent, but they have to placed in the right context. If I started applying these practices to the code I wrote at work tomorrow, I would wreck a lot of things :(
Friday, January 09, 2009 8:39:28 AM UTC
Good points Gates VP.

I guess that, like most things in life, the secret is on finding the balance. I work on a huge, 10+ years old system, with lots and lots of big classes like "UserManager" and "ReportManager", and if I ever dared breaking this down in 30 or 40 small classes I would be received with death threats at the next day, not to mention that I would have to spend at least a couple of months just to be sure that I didn't destroy something (as one would expect from such a system, our code coverage is very small, even though we try to do it for new code).

So while writing new stuff I try to use the SOLID principles to at least not let me go the other way around, i.e. add even more responsibility and even more dependencies on an already overloaded classes. And then here and there when I find a good candidate I do a little bit of SOLID refactoring in a way that I can test and that the rest of the team don't have to learn a whole new API all at once.
SomeRandomGuy
Monday, January 12, 2009 6:08:03 PM UTC
Great podcast, really enjoyed it.
Tuesday, January 13, 2009 9:16:18 AM UTC
The Liskov substitution principles is one of my pet peeves. The name is horrible, but the principle is easy to grasp: make sure your subtypes can be used whereever your supertype can. A simple measure can be taken to avoid LSP problems: never override a concrete method implementation! In fact, make every method implementation final!

Yeah, I'm a zealot. Can you see the scary gleam in my eyes?

Also, I know uncle Bob said that the square/rectangle issue has been debated to death, but I still can't stop my fingers from typing. Arguably, the technical problem in this particular case is mutability: you cannot implement setters correctly. But setters are evilish by nature, because they violate encapsulation. When you remove the setters, you can let square subclass rectangle without any technical problems. (Philosophically speaking, it is still weirdish to speak of the width of a square of course. And there are other problems: what if you create a rectangle instance with width == height?)
Thursday, January 15, 2009 4:28:56 AM UTC
@einar

I like the points you make. With Uncle Bob's own advice, it makes some sense to separate the Rectangle and Square interfaces into their mutable and immutable components. In various places in your code base, you might need to read an object's width and height. Why shouldn't you be able to use a square for this? In other places, you may want to set an object's "side". Why wouldn't a rectangle be sufficient here? (You can imagine that setting a rectangle's side is the same as setting both width and height.) You can SOMETIMES treat a square as a rectangle, and can SOMETIMES treat a rectangle as a square. It's a chicken-and-egg problem to figure out which one is more basic than the other. However, if we figure out what combination of behavior each of these possesses, we might arrive at something like this:

interface ReportsSide
public int GetSide

interface SetsSide
public void SetSide(int side)

interface ReportsWidthAndHeight
public int GetWidth
public int GetHeight

interface SetsWidthAndHeight
public void SetWidth(int width)
public void SetHeight(int height)

class Square : ReportsSide, ReportsWidthAndHeight, SetsSide
public int GetSide
public int GetWidth
public int GetHeight
public void SetSide(int side)

class Rectangle : ReportsWidthAndHeight, SetsSide, SetsWidthAndHeight
public int GetWidth
public int GetHeight
public void SetSide(int side)
public void SetWidth(int width)
public void SetHeight(int height)


Something neat in Cocoa is that collections are split into their mutable and immutable forms. NSMutableArray inherits from NSArray. While this is implemented in Cocoa as inheritance from a concrete base class, one could imagine that these are just interfaces. This allows you to avoid strange things like how Java's immutable collection wrappers throw NotImplementedExceptions whenever you try to modify them, which seems like a violation of the Liskov substitution principle.

Java's type system is good but not great. I've heard very good things about Haskell's type system. It seems like Haskell allows you to add interfaces to any type, even one that you didn't write. This might sound scary, but (as I understand it) it still respects encapsulation. Haskell embraces that there is a difference between what an item IS and how an object can be USED, and it also wisely realizes that this information might not all exist in one place. This is the Liskov substitution principle freed from the shackles of classical OO languages. Java and C# are holding developers back. Ruby represents one alternative. Scala, F#, and Haskell represent another.
Thursday, January 15, 2009 9:36:30 AM UTC
@Daniel

Indeed. I sometimes think that the type systems in Java and C# are the wrong mix of things, and hence they tend to get in the way as much as they help. Perhaps developers would be better off with either "more typing" (a richer, statically typed system with type inference, as in Haskell, Scala or F#), or "less typing" (a more flexible, meta-programmable, dynamically typed system, as in Ruby or Python). In particular, the need for explicit typing all over the place seems like needless noise to me. I know there are things happening in C# to include more implicit typing, but in Java it is just awful. In general, we need to avoid that the semantics of the code is drowned in syntax. If we can get help from the compiler and still have a light-weight, clean syntax, then that's fine. If not, then I'd go for slim syntax over compiler help any day. Unit tests will cover most parts of my behind in that scenario anyhow.
einarwh
Friday, January 23, 2009 12:46:57 AM UTC
Scott,

I was wondering if you'd heard what Joel Spolsky had to say about SOLID on the latest Stackoverflow Podcast, based on listening to this Hanselminutes podcast.
Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.