Live data from Hacker News

I don't love the single responsibility principle

sklivvz.com

61–70 of 125 posts

Re: I don't love the single responsibility principle

#61
post #12

So Uncle Bob talks about SOLID. There is one S there and then we have O, L, I and D. Applying SOLID is a balance of all of these things. We are craftsmen applying knowledge and skill to code. Trying to figure out SRP in isolation is not practical. When you attempt to apply SRP in balance with the other principles, you get more of the give and take that matches reality. There are trade offs and deciding what those tra…

I'd love to see a pragmatic take on the open/closed principle. I've seen a colleague extend a class, override the method in question by copying in the code from the super-class, then modifying it in the sub-class. Afterward he then replaces all instantiations of the old class with the new class. 'Open for extension / closed for modification' seems like it would lead to a nightmare in a few years.

So that is a really dogmatic approach to open/closed that is from the original formulation like 25 years ago. I've never encountered someone who would follow that practice when every instance needed to be changed (I assume Meyer would have construed that as a bug and allowed modification in that case). Even the less dogmatic Meyer definition of open/closed most people have left behind as it relies on implementation inheritance which is decidedly out of favor (and I believe rightly so).

In the more modern reading of the open/closed principle if you have multiple different variants on the behavior of a thing, you compose those variants in via an abstract interface. Then as you need to add even more variants you needn't change the original code any more only introduce more concrete implementations of the abstract interface that you compose at instantiation time as necessary. This approach is especially useful as your variant behavior grows. That is, a single boolean switch is probably easier to reason about than 2 implementations on an arbitrary interface. But once you get to 3 it becomes less obvious which is better. Any more than that and I usually reach for an interface without too much thinking about it.

Re: I don't love the single responsibility principle

#62
post #56

Earlier quoted context omitted.

Unfortunately here, Rails encourages putting each class into a separate file, so you have 10 classes spread over 10 files, which does increase complexity. I dislike having a class/module per file.

This can be solved with standard IDEs. Putting two modules or classes into a single file pretty much guarantees a level of coupling. This does not reduce complexity.

By that definition, I could just as easily argue that requiring different files for every class reduces cohesion. The idea that class definitions and file definitions are in any way related is a leaky abstraction.

Re: I don't love the single responsibility principle

#63
post #13
post #8

>> The future is pretty irrelevant, so asking to design based on future requirements is uncanny. The future is irrelevant? That's exactly what design is for -- to protect you from the future. If you didn't care about the future there would be no need to design at all. A good way to evaluate various candidate designs is to imagine future use cases and ask which design holds up better. A good design will respond really…

I think that putting cohesion and coupling on a 1 dimensional axis is kind of disingenuous. There are an infinite number of design changes that could be made and some of them increase coupling, some of them increase cohesion and all number of variations between the two variables. The best designs will find cohesion and coupling at local maximums.

I'm not saying you are wrong, but most of the literature indicates that high cohesion is correlated with loose coupling. The entire industry treats them as an axis so I don't think it is disingenuous for the author to do so.

Re: I don't love the single responsibility principle

#64

Earlier quoted context omitted.

"As an example, creating a function and calling it twice from two similar classes is much easier to read than inventing an intermediate class that is an ancestor of the two (something I see very often from the hardcore OO folks)." You really see this a lot? As far as I can remember using inheritance over composition for de-duplicating code has been considered bad practice in OO circles for at least 15 years.

I definitely still see it, "best practices" once enshrined, change slowly.

Wow, that's terrible, but I'd prefer if you referred to those people as "out of date OO people" as opposed to "hardcore OO people". Even though I don't consider myself a "hardcore OO" person now, when I did this would bother me.

Re: I don't love the single responsibility principle

#65
post #24

I like many of the author's points. Pragmatism, thinking instead of blindly following principles, pushing back against size as a metric for measuring responsibility. I think Robert Martin's work absolutely deserves examination and critique. However, I don't share the author's definitions of simple and complex. Stating that "binding business rules to persistence is asking for trouble" is flatly wrong. Au contraire, It…

Unfortunately here, Rails encourages putting each class into a separate file, so you have 10 classes spread over 10 files, which does increase complexity. I dislike having a class/module per file.

That is standard practice in many languages.

Re: I don't love the single responsibility principle

#66
post #58
post #51

Earlier quoted context omitted.

Often, though, a series of complicated if statements is hinting at a type system for your objects that hasn't yet materialized in your code. I find it's a good idea to always look at cascading if statements and switch statements and ask, "Would this be cleaner if I reified these concepts as types?" http://en.wikipedia.org/wiki/Reification_(computer_science)

This is the single most important trick for factoring out shitty code. I cannot believe how many times reification collapsed complexity in our code base, or how not using it was the source of bugs. If you have cascading ifs, there is a good chance there is a huge set of ifs for every place this type system is missing. Meaning, if you wanted to add another "case" to a feature, you are modifying cascading ifs in 5-10 p…

So to reify a type involves making an abstraction, which is odd because reify seems the inverse of making an abstraction...

Re: I don't love the single responsibility principle

#67
post #23

I rarely ever use classes anymore. My life is complicated enough, I like my code to be simpler. I used to be proud of my complex classes hierarchy and clever designs.. now simple objects and mostly functions. I don't and won't argue with anyone who prefer to use class hierarchies, but it really annoys me when I need to spend 5mins wrapping my mind around all those class relationships where a simple imperative (or fun…

Couldn't have said it better. Classes are useful, but only occasionally so. About the only time I find myself using classes is when there's several functions that have a very strong relationship to a particular portion of state (like when using an ORM). The rest of the time it's referentially transparent functions.

Re: I don't love the single responsibility principle

#68

I generally go by file size now, after 200 lines, we need to find an OOP excuse to split (interestingly, I almost never merge, but there might some thermodynamic reason for that).

I do it this way simply because I don't like having to scroll too much.

Re: I don't love the single responsibility principle

#69
Size is, and has always been, at least in my opinion, a symptom of failing the single responsibility principle. Its not the cause. Its only useful as an indicator, you still have to look at the case, figure out if the function / class is doing more than one thing. And even then, a function / class can do more than one thing, to increase cohesion, and limit bloat / complexity.

General rule I use: does this block / section of code increase complexity of the overall purpose of the function or class. If it does, it should probably move, likewise if it isn't relevant to the overall functionality / behaviour it should also probably be moved.

Everything is a trade off in the tech world. You can't argue you are right or they are wrong, only that you are right in this instance or that.

Re: I don't love the single responsibility principle

#70
post #56

Earlier quoted context omitted.

This can be solved with standard IDEs. Putting two modules or classes into a single file pretty much guarantees a level of coupling. This does not reduce complexity.

By that definition, I could just as easily argue that requiring different files for every class reduces cohesion. The idea that class definitions and file definitions are in any way related is a leaky abstraction.

I've never been a fan of the class-file coupling. It pulls me out of the mental model I'm trying to build in my head and forces me to think about file organization which is almost always inconsistent with the language semantics I'm dealing with.

I've used IDE's that make this more or less painful, but none that actually solved it. If anyone has any suggestions on one that does, I'd be interested to try it out. I don't really care what language. I can pick up enough to see what it feels like.

I also want to say that rich hickey talked about a file as a unit of code not being very good, but I don't recall where, or if he really said it. I want to say it was in a Datomic podcast right around when details about it were coming out.

Post reply on HN