by neokya on 9/15/16, 10:25 AM with 158 comments
by ewjordan on 9/15/16, 12:46 PM
All the horrid Java libraries that we hated working with 10 years ago were created because of slavish devotion to the single responsibility principle, short methods, DRY, and testability. The absolute worst codebases I've ever seen sprung from an overaggressive concern for extensibility.
I do agree with the guiding principle, that when you're writing code, it should be written for other people to read and work with. But sometimes that actually does mean that a class should represent an object that does more than one thing, and you shouldn't fight it. Sometimes a gritty algorithm really does make the most sense if it's laid out as a 40 line function in one place rather than spread across 5 different classes so each part is independently swappable and testable. Sometimes you really don't need extensibility, you know that up-front, and building it in just pisses off everyone that ever has to touch your code because now they have to go through five or six "Find implementing classes" dances to find the actual code that runs when your interface methods (of which, of course, there's only a single implementation) are called. Don't even get me started on abuses of dependency injection when it's not necessary...
Part of me is glad that these concepts are so commonly discussed, because they really are good things to consider, and can make code much tidier and easier to work with in the best case. But it takes a lot of experience to know when and where you should and shouldn't follow these "rules", and it tends to be much easier to unwind a novice's spaghetti code and tidy it up than it is to pick apart a poorly conceived tangle of abstraction and put it back together in a way that makes sense.
by gravypod on 9/15/16, 1:13 PM
I've had one discussion that stood out. We were talking about functional programming and I said that the idea of functional programming was the segregate state to the smallest unit of computation that must operate on it. I was met with my "friend" just blindly telling me to "stop saying that". I asked for a counter argument to that statement but they just said that I should stop saying that.
We as a community are horrible at speaking about code quality , evaluating each others work, and even just sifting out opinions from facts. It's crazy and it's something that needs to change if we want to take our field to a future where we can all be happy with the code we are writing.
I've got some suggestions I'm happy to talk to others about. My email is in my about page on this website. Please comment here or email me and I'd like to talk about this!
by taneq on 9/15/16, 1:13 PM
The single responsibility principle should really be "exactly one" rather than "not more than one". If a function is responsible for less than a whole thing, it shouldn't be a function on its own.
by keithb- on 9/15/16, 1:59 PM
This is a tenet that will lead inexperienced developers astray. This "rule" is just too ambiguous. Extensibility is a fascination for object-oriented programmers but in my experience doesn't have a lot of successful examples. Typically I have seen this manifest itself in either a Command+Composite style where every meaningful class is a composite of other SRP classes, or in a proliferation of interfaces that seldom have method definitions and are instead used to enforce coding standards or dependencies.
KISS is incompatible with this rule and you should kill this rule with fire because simple is not extensible. Perhaps when the goal is extensibility then should you consider other developers, but if you are developing a "beige" application then you should not consider extensibility. Instead, just assume that release management will handle changes, i.e. another developer will update rather than extend your class and that will be released in version 1.1.
Of course, to do this also means admitting that version 1.0 of your class was pretty much garbage and that it needed to be "extended". Tough pill to swallow for some.
by mosselman on 9/15/16, 1:01 PM
Maybe there should be a 'click-bait' button on HN with which we can report things as such, along with posts such as 'Why I won't be using popular-technology-x ever again' and '10 things I hate about SQL'
by pyrale on 9/15/16, 12:59 PM
Not sure I agree with this one. While abstractions are a great way to reduce the length of code, sometimes they break readability. When you read code, sometimes, you feel like you don't read a solution to your problem, but a way to solve your problem masked behind abstractions far removed from the domain concepts.
That's why, sometimes, redundancy is better than the wrong abstraction.
by z5h on 9/15/16, 3:22 PM
Consider a biography: you could simply collect facts about a person and write them in an arbitrary order and call it a biography. It could be a complete and accurate account, and still be impossible to read or follow.
Well written code is not only complete, but it also guides the reader through the logic.
Consider the difference between:
statuses = []
reporter = Reporter.new
jobs.each do |job|
statuses << job.complete && !job.error
end
and job_statuses = jobs.map do |job|
job.complete && !job.error
end
job_status_reporter = Reporter.new
In the first case, we see statuses declared. Statuses of what? Not yet clear. And the code that updates it is separated by unrelated code. Also, what will reporter be reporting?
In the second case, map and better naming are used making it clear that we are getting a status for every job. Aha! I don't even need to look at the implementation of the do block to understand what's happening.by k2xl on 9/15/16, 12:53 PM
I remember when looking into neural nets, the basic python code to get one running was super easy for me to understand. However, I also realize that the optimal, most efficient methods of neural network libraries are way more complicated (and for good reason).
by baron816 on 9/15/16, 12:59 PM
by kasey_junk on 9/15/16, 2:16 PM
In a SaaS environment the code needn't be extensible as there is only 1 copy of it. It is much more important for the code to be changeable, rather than extensible and in many cases the things you do to make code extensible make it harder to alter fundamentally.
Its important to understand that how you deliver your software is one of the biggest guiding factors in how you design your software and take that into account.
by pif on 9/15/16, 12:28 PM
by swalsh on 9/15/16, 2:46 PM
Good code, you can search it... even if the majority of it is unfamiliar. Find a piece, and say "oh this is probably the spot" with out ever executing it.
by pif on 9/15/16, 2:13 PM
An excerpt: We are practically the only industry where completion and success are synonymous. If the foundation of a one-year-old home is crumbling and its roof is plagued with leaks, would anybody actually call that a success? Despite being filmed and produced on budget, is there anyone who would not be ashamed to have Gigli on their filmography? Of course not! So why are the products we create – complex information systems that should last at least fifteen years – be held to a different standard?
Now think back those projects of yours. How many would you say are maintainable by someone with less business knowledge and a weaker grasp of the system’s design? How many will not snowball into an unmaintainable mess? How many do you truly believe could last fifteen years? I’ll bet that number is quite a bit lower than all of them.
by erlich on 9/15/16, 2:43 PM
I write code that I come back to and don't understand, and realise its terribly complex because I understood everything at the time, but could not imagine what it would be like coming back after a month to make a change, or for someone new to try to understand it.
Code is for people to understand.
Some people think its for being able to write good tests, eliminating all side-effects and shared state, for the computer to be able to run quickly and optimise, to be easy to read.
But its really just about being able to be understood. Most time will be spent in maintenance.
When you modify and debug, you are diving into the middle. You are not walking through the code base from the beginning and reading all the comments.
It needs to be understandable from all locations.
I'm a strong believer in micro-modules. Left pad et. al. I try to create small modules which do one thing well that I can trust and not have to think about.
by drakonka on 9/15/16, 2:23 PM
by abhas9 on 9/15/16, 4:54 PM
This quote always sticks in my mind :)
by antoaravinth on 9/16/16, 5:52 AM
I can remember a instance, when I started my carrier. I was a JS developer. I wrote a module with Functors, Compose, Partial etc.
In code review my team told they didn't understand anything and reading such a code is not pleasant for them. I was upset, I was thinking why my team is not happy with it.
Today I can make lot of sense; stick to the pattern/design of your team. If your team follows / loves functional programming in your project, stick to it. If not try to advice them why functional programming would be better than normal approach.
End of the day, all it matters is writing simple, elegant code which others can understand.
by textmode on 9/15/16, 3:23 PM
The easier it is to remove code from someone else's program, the "cleaner" the code.
That's my definition of "clean code".
For example, I just had to edit the code for a text-only browser to remove a few "features". For example, the author recently decided it would be a good idea to non-interactively access no-content refs in a page such as "prefetch" and other garbage.
by k__ on 9/15/16, 5:23 PM
Yes, most things in the article are nice to have, but you can't teach everything in a month and people need to be prodcutive to be worth their money.
by partycoder on 9/15/16, 4:52 PM
When this rule is not respected:
1) You end up with lot of coupling
2) Unit tests end up with a lot of overhead
by caub on 9/15/16, 1:30 PM
by JustSomeNobody on 9/15/16, 12:15 PM
I'm passing on this article.