Welcome to

Magenic Technologies Community Blog

Sign in | Join | Help

Aaron's Technology Musings

Who let this guy on the podium?

Single Responsibility Principle can be Taken Too Far

In the .net framework, every single class you ever write will violate Single Responsibility Principle (SRP).

Why?

Every object in .net has a method called GetHashCode.  And... horrors of horrors, every object has a method called ToString.  You can, and often, need to override one or both of them.  They provide certain functionality to everything, up to, and including, drumroll.... allowing objects to generate hash codes and allowing them to be converted to strings.

I guess it is time to quit coding in .net and simply adopt Ruby.  Oh, wpps, the object class in Ruby has methods too.  In fact, it would not surprise me that you could override them in a consumer class that, say, inherits from object (evil grin...) My bad.  Next idea?

The question, I suppose, is this - how much do we want to allow our primitive objects to do?  From time to time, I hear people state that CSLA and TDD are not compatible - and one big reason is that CSLA allegedly breaks SRP, because neither are all it super class methods public, and you have a lot of things you get with CSLA that don't relate purely to what the object is supposed to do in it's 'pure' state.

I have even heard arguments that inheritance is broken, and should never be used.  Every is-a is a has-a just waiting to grow up.  Every set of private methods is a new class waiting to be discovered.  And so on and so forth.

Hmm... seems like we are going a little far there.  Lets go back to why encapsulation is a good thing.  You see, the fewer external points of input something has, the less we have to test.  Opening up everything simply adds to the test load.  I suppose if you are full on test-driven, that might be ok.  But doesn't that beg the question... why are we orienting our entire design around whether a unit test can be written for it?  I mean, unit testing is important, but isn't this a little far?

The fact is - if you are using .net, you do not have 100% test coverage.  The .net framework has a method on string called Split.  I use it a great deal when parsing.  I am pretty sure nobody, except perhaps, somebody at Microsoft, maybe, has ever written a unit test for it.  Did you write a test for it?  No?  Then technically, you don't have 100% test coverage.  You took it as a leap of faith that someone at Microsoft tested that.  Unless your tool that reports test coverage includes framework bits in it's coverage calculation... which probably none of them do (I haven't checked... do I need to?).

In other words, you take it on faith that the 'evil empire' has tested the .net framework... and therefore, you don't.

Now, lets say you use CSLA - a framework used by 100s of companies on several continents.  Maybe I am going out on a limb here, but if you use CSLA, doesn't BusinessBase, with all it's inherent functionality, replace what object would be of you were doing straight POCOs?  My open question for the commenters is this (a call for papers, if you like) - where is the border drawn between code we have to test, and code we take on faith that works?  Clearly, testing 'object' is too far, since most test programs don't consider it in coverage calculations.  Clearly, testing your own class you just wrote is not too far, since it is, well, untested.  There is a middle-ground in-between those two extremes.  I want to know where people think the line of demarcation is...

Published Tuesday, October 16, 2007 6:49 PM by aarone

Filed under: , ,

Comments

# re: Single Responsibility Principle can be Taken Too Far @ Wednesday, October 17, 2007 5:05 PM

I think you want 100% test coverage for sure (if you can actually do it then good for you!) and should strive for it but should be satisfied with something like 90% amidst deadlines. However, saying something like everything should be public and inheritance is broken is ridiculous. Sure in a test driven environment you might not need encapsulation but, frankly, encapsulation isn't intended to provide value for the developer of the class it's for the consumer of the class. If I'm to use some 3rd party framework the last thing I really want is to see a gigantic nasty class system with no encapuslation or aparant methodology. It would be impossible to understand! They have access to those tests so the purposes seem obvious but I would not. I would like to know that the underlying code is 100% test covered but when it comes to using a 3rd party framework a clean, encapsulated class library with clear points of inheritance used to implement my custom behavior is incredibly important.

Test driven development is AWESOME for an 'application'. But for a framework or even the framework portions of an application inheritance and encapsulation are crucial.

JustinC

# re: Single Responsibility Principle can be Taken Too Far @ Friday, October 19, 2007 8:57 AM

"lets say you use CSLA - a framework used by 100s of companies on several continents"

The above is justification used by people without legitimate arguments for use of a product.

"lets say you use DDT - a pesticide used by 100s of countries on several continents"

C'mon

# re: Single Responsibility Principle can be Taken Too Far @ Friday, October 19, 2007 9:06 AM

Not to go off topic, but DDT is very effective against malaria - there is a case that many prominent people have made - including the World Health Organization: link here: http://www.nytimes.com/2006/09/16/world/africa/16malaria.html?n=Top%2FReference%2FTimes%20Topics%2FPeople%2FC%2FCoburn%2C%20Tom). The point of talking about usage here is that, you can say what you want about CSLA, but saying that it is unproven or untested isn't one of them, given there are 100s of companies that, in fact, use it in production, and have for several years. Inheriting from framework code used by lots of people in production environments and inheriting from your own classes you just got done writing are clearly different things. My fear is that people are going to start throwing the baby out with the bathwater in the rush to go pure POCO with everything. Just like the rush to ban DDT in every situation, going down that road with good intentions, has actually done a great deal of harm (see above NYT article) - so would banning inheritance in the name of pure POCO Everywhere All The Time.

aarone

# re: Single Responsibility Principle can be Taken Too Far @ Friday, October 19, 2007 2:55 PM

I really enjoy building applications.  Over the span of one's career working for consulting firm X or company Y, in this or that industry, be it a small or large customer, perhaps building shrinkwrapped software or perhaps building apps for internal consumption, there are so many variables, it is difficult to speak in absolutes.  Every combination results in a unique context where a different solution may be more or less appropriate.

I don't think CSLA is in any sort of jeopardy.  I do think that TDD has been perculating on the collective minds of many great developers/engineers, and it is important to understand the "best practices" that are really only now emerging for common consumption in the world of MSFT .NET.  Java has been around about 6-7 years longer than .NET, and we are getting tons of tools and techniques as the cross-pollination of developers occurs.  So this is all necessary and healthy conversation for folks like me (a VB/ASP Mort from way back).

With all that stage-setting... if you are in a context where TDD is applicable... I guess I have come to view TDD as more than a testing philosophy.  It is a design and development philosophy, driven by the discipline of asserting against a phantom API in rapid succession, and supported by a healthy amount of refactoring to remove "code smells" that result in the quest for green.  I cannot overstate how fundamentally different (wrong) this feels for a veteran of more traditional Architecture Driven Development.

So I know where you are coming from, but the result of TDD style development is going to be very different.  The classes that are produced tend to become pretty granular by comparison.  More public members perhaps, dependency injection or "IoC" are the norm, mocks actually become central, interfaces are prolific... you get the idea.  

What this ramble is trying to express in essence is that it is probably a mistake to view POCOs/SRP/etc from the perspective of Architecture Driven Design.  They seem like over-engineering (or over-something).  For me, I try to view all of this as part of the TDD style of development, which is a solution and not always THE solution.

Kirk

# re: Single Responsibility Principle can be Taken Too Far @ Friday, October 19, 2007 3:13 PM

I think I understand what you are saying Kirk.

However, I suppose my concern would be that we have to look at the aggregate of moving parts.  More moving parts can, if they are written correctly, be fine.

I went to a talk on DDD the other day, which I understand has had a big influence on the TDD community (BTW, I have purchased Evans' book and am reading it this weekend - so I could very well be wrong about things).  I heard, in the talk, that part of DDD is seperating state from behavior and putting them into different classes.  When I heard that, I had a couple of reactions - namely - wow... we have come a long way since Holub, when we were going to have big smart encapsulated objects that you could fly to the moon if you needed to.

At one point in your career - if you did not grok encapsulation, you were unemployable.  Now, suddenly, we have domain objects (largely data), and things like repositories and such that act on them (largely methods without state).  How is that different than, say, having data and function libraries?  Are we back to Nick Worth and Algorithms + Data = Programs?

Whether CSLA is compatible with this isn't my biggest concern... but repeating the mistakes of our collective past as an industry, kinda, is.  I am gonna laugh my ass off in 5 years when we re-discover encapsulation again :)

aarone

# re: Single Responsibility Principle can be Taken Too Far @ Friday, October 19, 2007 9:53 PM

1) Are you trying to say that Domain models that use POCO don't use encapsulation?

2) Re: DDT - probably very effective against most mosquito varieties. Let's simply ignore its property of accumulating in the fatty tissues of the animals that eat mosquitos as it travels up the food chain until it starts being the cause of death of people because it's good at solving our immediate mosqito problem. (sarcasm intended)

Real point: If a framework decreases testability because it doesn't follow SRP it might be time to refactor the bath water while keeping the baby.

Confused

# re: Single Responsibility Principle can be Taken Too Far @ Saturday, October 20, 2007 9:36 AM

I am going to say something that might take you by surprise on your first point.

I don't know for sure.

I thought I heard, at a talk, that Domain classes separate behavior and state into separate classes.  To me, that would infer that you don't have much encapsulation, since it is unclear to me how you would modify internal state - in a manner other than through public property settors - if your objects lack methods.  If true, to me, that would mean that your objects lack much encapsulation, since the state of them is pretty much open to the world.

Now, I will admit that I have skimmed, but not read thoroughly, Evans DDD book, as well as a few blog posts on the issue, and have gone to the aforementioned talk.  What I need to do is actually buy the book and read it.  When I talk to people about DDD and TDD, I get a lot of, what seems to me, conflicting ideas about what the best practices are - which tells me I need to go to the source material and form some better conclusions, rather than getting it all second hand.

If after reading that, I come to a different conclusion, I will do something that may surprise you - I will correct myself and put up a new blog post.  I am not afraid to change my mind about something when presented with good evidence.  Fair enough?

aarone

New Comments to this post are disabled
Powered by Community Server, by Telligent Systems