18 ms·
CUPID – the back story
- j_san 6y agoUncle Bob has actually written a blog post about Dan's presentation: http://blog.cleancoder.com/uncle-bob/2020/10/18/Solid-Relevance.html http://blog.cleancoder.com/uncle-bob/2020/10/18/Solid-Releva...
- jdlshore 6y agoThe article mentions the Bob’s post, and criticizes him for reacting to the slides out of context—that is, without seeing the pub talk that the slides were from, or contacting Dan to understand what the slides were about.
- smusamashah 6y agoLink to slides https://speakerdeck.com/tastapod/why-every-element-of-solid-is-wrong https://speakerdeck.com/tastapod/why-every-element-of-solid-...
- jacques_chester 6y ago> Code is not an “asset” to be carefully shrink-wrapped and preserved, but a cost, a debt. All code is cost. The analogy to accounting is still useful and I believe correct. Assets depreciate (lose their value) and have carrying costs (storage, insurance, interest etc) that are booked as expenses. Put another way, a phrase like "all existing code incurs costs" is an accurate analogy. So too is "all code is an asset", because it implies the former.
- sorokod 6y agoSure, but replacing code with new (cheaper?) code has cost in itself. All the author has to offer here is a recommendation to "Write simple code", presumably one that follows his "fits in my head principle".
- jacques_chester 6y ago> Sure, but replacing code with new (cheaper?) code has cost in itself. Of course. That's true of many assets, usually this is called the "replacement value" of the asset. You use replacement value and depreciation to calculate whether replacement is the best option, or whether to extend the life of the asset you already have. Tockey's Return on Software is a fairly readable guide to some of these topics: https://www.amazon.com/Return-Software-Maximizing-Your-Investment/dp/032156149X https://www.amazon.com/Return-Software-Maximizing-Your-Inves...
- js4ever 6y agoLoved it! I agree with most of it as well, I'm so fed up with preparing with abastractions to things that will probably never occur (changing the underlying DB for eg) I changed my coding style a decade ago to focus on producing code that is as simple as possible to read/maintain with as few abastractions layers as possible.
- edoceo 6y agoYea, 20+ years on PostgreSQL. Why would I change my DB away from the perfect one?
- TimTheTinker 6y agoOne never knows what the future may bring. Long-lived OSS software is a relatively stable bet, but the point still stands.
- rootsofallevil 6y ago>One never knows what the future may bring. Exactly, so make the changes when you need them, otherwise you are relying on hitting the abstraction lottery
- jacques_chester 6y agoMaintaining database abstraction layers and the like is a real option used to hedge the risk of the holdup problem. But like any real option, it has a carrying cost. That means it's an economic question, there is no purely technical rule that can give you a robust answer to whether or not to abstract something away. I feel the industry has a long hangover from the 80s and 90s in terms of the holdup problem. Oracle, basically, created a massive externality of anxiety about vendor lockin that continues to impose drag to this day.
- TimTheTinker 6y agoAgreed. “Our software currently runs on Oracle but can be switched to MS SQL Server or DB2 with about a day’s work” used to be an admirable and economically valuable statement. In the majority of cases, I think a simple “runs on Postgres” is even more valuable today (unless your product is a database abstraction layer).
- krona 6y agoThe author presents a series of strawman arguments to debunk SOLID, and then suggests that instead we should make software as complex as possible but no more complex than the coders own comprehension. In my experience this commonly how incomprehensible codebases evolve; the code is comprehensible right up to the point that it isn't, and by that point it's too late to change anything.
- rootsofallevil 6y agothat's an interesting take, what would you consider strawman arguments in the article?
- sorokod 6y agoNot the person you asked but, I would say that the expectation that SOLID provides or should provide, unambiguous guidance
- refactor_master 6y agoFor example, the open-close principle. The author blames this advice on tooling of the 90s and proposes instead “Change the code to make it do something else”. This has nothing to do with tooling, but the fact that pulling the rug under an established code base could have very unintended effects, compared to simply adding and extending functionality without touching what is already there. By doing as the author suggests you’ll end up with either 500 broken tests or 5000 compiler errors in the best case, or in the worst case an effectively instantly legacied code base where you can’t trust anything to do what it says. I once had to change an entire codebase’s usage of ints to uuids, which took roughly 2 whole days of fixing types and tests, even though logically it was almost equivalent. Imagine changing anything and everything to “make it do something else”.
- garethrowlands 6y agoIt has a fair bit to do with tooling. For example, C++ suffers from the fragile base class problem and some changes can cause long compile times. Nowadays, we have tests and deployment pipelines that are explicitly designed to let us make and deploy changes safely. Honestly, if you cannot change your code, you have a problem.
- bwilliams 6y agoI read the article and didn't really feel that they disagreed with, or debunked any of the principles. It reads like they formed their own understanding of each principle and maybe disagreed with how they were taught, or how the principles are sometimes presented. This change in outlook of existing thoughts/ideas is how many crafts grow, such as martial arts, painting, philosophy, etc (instead of stagnating). Sometimes we need to frame things in a more modern manner, and sometimes we need to discard them completely. In this case, I think re-framing the concepts is helpful, and I found it to be an interesting point of view. I agreed with a good amount of it, but I don't think we need to discard SOLID principles just yet.
- pydry 6y agoThis alludes to one of my main beefs with SOLID - the lack of a clear definition. What counts as a "responsibility", for instance. Where I see one responsibility some people see two and vice versa.
- barbazoo 6y agoI agree. In a way that's one of the strengths of SOLID in my opinion. All places I've worked at had slightly different versions of what e.g. SRP meant. And that's ok. It's a way to make sure your team writes code in a way their teammates would expect. Whether that's objectively good code or not doesn't matter as much to me.
- SideburnsOfDoom 6y ago> What counts as a "responsibility", for instance. Where I see one responsibility some people see two and vice versa. The Single Responsibility Principle is not a rigorously defined Scientific law, where the "responsibility count" can be exactly measured and minimised. It is a subjective design guideline, with elements of experience, of context and of "I know it when I see it". This does _not_ make it useless. It is still very useful indeed. But you do have to understand that disagreements over it are not always about "who is objectively right" but "which style makes the most sense in context".
- agnosias 6y agoHonest question: if you don't do dependency inversion, or if you don't depend on interfaces/abstractions that can't be mocked - how do you unit test your code? Unit testing is the only reason pretty much all of my code depends on interfaces. Some people seem to consider this a bad thing/over-engineering, but it's how I've seen it done in every place I've worked at. How do you do it?
- Xunjin 6y agoI wish to know this as well. And what about functional programming languages?!
- garethrowlands 6y ago> Honest question: if you don't do dependency inversion, or if you don't depend on interfaces/abstractions that can't be mocked - how do you unit test your code? The author isn't actually demanding you change your tests (unless they are unnecessarily complicated). > Unit testing is the only reason pretty much all of my code depends on interfaces. Some people seem to consider this a bad thing/over-engineering, but it's how I've seen it done in every place I've worked at. Unit tests require 'seams' to divide the tested code into units but those seams don't have to be interfaces. Some languages don't have interfaces at all - Ruby, say - and they unit test just fine. The pattern of every Foo having a corresponding IFoo is a bad thing - you should replace IFoo with smaller role interfaces. Having an IFoo if it isn't necessary to test Foo and there's only one implementation is indeed over engineering. > I wish to know this as well. And what about functional programming languages?! Unit testing's much the same in functional languages, though it tends to be easier because pure functions are easier to test. But how code gets its dependencies tends to differ a bit. It may help to think of dependency injection as parameterisation. Or, perhaps, parameterisation where you don't use the parameter immediately. Suppose I want to test a function foo that depends on another function bar: fun foo() { return bar()+1 } Well with objects and interfaces, I can do this: interface IBar { bar() } class Bar(): IBar { fun bar() { return 2 } } class Foo(val bar: IBar) { fun foo() { return bar()+1 } } And then I can make a test double for Bar in my test, and when I invoke foo, then it will call the bar of my test double. Now, of course, in this example, I could test with the real Bar and I don't need a test double. That's partly because the example is simple but also because foo and bar are pure functions. But let's ignore that and see how we can do the same in a functional language. fun foo(n: Int) { return bar()+n } The question is, how can we control the value of bar in our tests? The simplest answer is that, since bar is varying (between test and prod), then bar is a parameter: fun foo(bar: ()->Int, n: Int) { return bar()+n } Now the reason we don't do this in OOP languages is that we won't have bar at the call site. That is the production code calls foo like this: foo(n) and not like this: foo(myTestBar, n) That's why our test code looks like this: val myFoo = Foo(myTestBar) assert(myFoo.foo(3)).isEqualTo(something) though, if foo takes its dependency as a parameter, the test could just look like this: assert(foo(myTestBar, 3)).isEqualTo(something) But the prod code won't look like that, it only passes n. So we need to pass bar before that. That's why we pass bar to the constructor in the OOP version. OOP languages generally expect you to pass all the parameters to a function when you call it but some functional languages don't require this. That is, you can pass bar on its own - a mechanism known as 'partial application'. You'd use it like this: // Do this when 'wiring up' the application val myFoo = foo(myTestBar) // now I only need to pass n myFoo(n) If your language doesn't provide partial application, then you can do the same with a function that captures the dependency: // Do this when 'wiring up' the application val myFoo = {n-> foo(myTestBar, n)} // now I only need to pass n myFoo(n) Now, notice that, since bar is just a function (of type ()->Int), I didn't need to create a separate interface IBar. For this purpose, functions "just work". They are equivalent to interfaces containing a single function (Java's SAM recognises this, if that's familiar to you). Notice also that an interface of a single function is as small as it can be. Often, we'll see a class Bar with, say, ten methods, and a corresponding IBar also with ten methods. SOLID's Interface Segregation Principle says to prefer small 'role' interfaces over obese interfaces such as the ten-methods IBar. And, of course, if you're using functions, that happens naturally. Hope this helps.
- pfraze 6y agoFYI this is not referring to TBL’s SOLID project
- shock 6y agoSome of the points the author makes are good, but some are severely misguided. An example: > The Single Responsibility Principle says that code should only do one thing. Another framing is that it should have “one reason to change”. I called this the “Pointlessly Vague Principle”. What is one thing anyway? [...] If a change request comes in to change the format of the logs to include milliseconds and you're running a search and replace over the code base, you've broken the SRP. We can argue that is a good thing or a bad thing, but that's what it means. I think it's a bit of both, a trade-off, like most things.
- balfirevic 6y agoI believe that would be violating DRY, not SRP.
- sorokod 6y agoThe author rejects "Single Responsibility Principle" as “Pointlessly Vague" and offers instead the “Fits In My Head” principle. That is apparently better due to some hand wavy discussion which leaves no room to explain why same hand wavy justification would not apply to original. stopped reading after that.
- jonnypotty 6y agoI think it's saying simple, dogmatic rules aren't a good idea and don't reduce complexity. Trusting a dev to not write functions that are unreasonably complex IS a good rule if you spend the time to check and review code. Fitting your code around a load of "best practices" will basically always increase complexity because you've expanded the list of requirements the code has to conform to.
- sorokod 6y agoI don't think these principles are dogmatic, they rather give you a direction. Can you see that the rule "your code should have single responsibility" is more specific then "write simple code" ?
- herval 6y agoHow is “fits in my head” not dogmatic, though? And how does fitting around practices necessarily increase complexity? If you’re a jr engineer used to write a mess of code to solve a problem, and have to decompose it following a set of principles, you may end up with something SIMPLER very easily. The whole point about principles is they lead to better outcomes. Problems arise when you confuse them with “rules that can’t be broken” or (as in this post’s case) just refuse to understand them and come up with your own half-assed heuristics - either to justify your code, for lack of experience, or just... to talk at a conference :-)
- garethrowlands 6y ago"This article isn’t about those principles, that will be my next post." The article does not present an alternative to SOLID, that's the next article.
- hyko 6y ago“The Single Responsibility Principle says that code should only do one thing” Except it doesn’t really say that. Without understanding the S, the OLID is bound to seem like mindless pedantry.
- refactor_master 6y agoTo me this blog doesn’t really formally/finally refute anything, but is simply saying “don’t over-engineer your solution”. > “dependency inversion has single-handedly caused billions of dollars in irretrievable sunk cost and waste over the last couple of decades” Oh please. Is there anything in programming that hasn’t had the “Irreparable harm to humanity” sticker attached to it by now?
- gfody 6y agoI like to imagine a final analysis of all code ever written by humans, after some ai hypermind from the future has digested it, turning out to be 99.999% dependency injection boilerplate
- jonnypotty 6y agoSo becuase our industry is so unprofessional that you can literally point to loads of it and say "that has cost humanity billions", this entire argument is stupid and actually there is no problem at all? Not sure that's the right attitude.
- refactor_master 6y agoSo what would you have done to end up in the alternate universe where it hadn’t cost humanity billions? Rational agents and perfect knowledge does not exist outside of economic theories.
- DanielBMarkham 6y ago1. Watching the tech community over a really long time, please guys, don't swing violently from "A is all good!" to "A is all bad!" It was good for something, else so many people wouldn't have successfully used it for so long. Work more on discrimination functions and less on hyperbole please. Future generations will thank you for it. 2. "...coupled with the way most developers conflate subtypes with subclasses..." Speaking as somebody who both likes SOLID and could write this essay/present the deck, I think there's a lot of confusion to go around. There are a lot of guys coding classes using rules better suited for types. There are a lot of guys applying OO paradigms to functional code and vice-versa. In general, whenever we swing from one side to the other on topics, it's a matter of definitions. There is no such thing as "code". There's "thinking/reasoning about code" and there's coding. You can't take the human element out and reason abstractly about the end product. Whatever the end product is, it's a result of one/many humans pounding away on keyboards to get there. 3. My opinion, for what it's worth: as OO took off, we had to come up with heuristics as to how to think about grouping code into classes, and do it in such a way that others might reasonably get to the same place ... or at least be able to look at your code and reason about how or why you did it. That's SOLID and the rest of it. Now we're seeing the revenge of the FP guys, and stuff like SOLID looks completely whack to them, as it should. It's a different way of thinking about and solving problems. ADD: Trying to figure out who's right and who's wrong is a (philosophical) nonsense question. It's like asking "which smell is plaid?" Whatever answer you get is neither going to provide you with any information or help you do anything useful in the future. (Shameless plug: Just submitted an essay I wrote last week that directly addresses reasoning about types in a large app)
- cghendrix 6y ago+1 on the hyperboles. You see so many articles with titles like “Never use a singleton unless you want to lose your marriage like me”
- deleted 6y ago[deleted]
- elric 6y ago> don't swing violently from "A is all good!" to "A is all bad!" Indeed. This clickbaity style of laying out arguments is not terribly constructive. Software is not black/white. It's entirely grey. And there's a lot of room for contextual nuance everywhere. Principles like SOLID (and DRY, and YAGNI, etc) are principles. They are not laws. Principles are guidelines which can help you make solid (heh heh) decisions. They are subject to context and judgement. If good software design were as easy as memorizing a couple of acronyms, we'd all be out of a job. But it's not. It takes practice and experience. Writers and academics can make things easier by presenting accumulated experience in principles and guidelines, but there are no silver bullets. It's unfair and pointless to expect SOLID (or anything else) to apply in any and all cases.
- recursivedoubts 6y agoThe Single Responsibility Principle (and the related Separation of Concerns Principle) have been particularly damaging in the context of UI development. They are reasonable principles and often do apply, but there are times when the concept of Locality of Behaviour is better for overall system simplicity and stability: https://htmx.org/essays/locality-of-behaviour/ https://htmx.org/essays/locality-of-behaviour/
- lifeisstillgood 6y agoMany years ago I read an article about Boeing's chief engineer - he apparently had the "whole aircraft in his head" - it as a schematic but as a series of deeply understood components the fitted together (from Bernoulli's principle to hydraulic pressure equations and the weight of fuel distribution as tanks empty. The whole enchilada). There is nothing particularly magical - one assumes that the top 10% of any MIT graduating class could be taught to do the same over a decade or less. But I am guessing that it needed a organisational effort to ensure the bits added never got beyond one person, and that he was comfortable saying "stop". Every railway and new or refurbished bridge needs to be signed off by a railway engineer - who can and should refuse if it is sub-standard. Keeping our software under the same degree of control will need similar levels of handing the keys of the kingdom over to a small number of devleads. And ensuring they do not encounter unmanageable conflicts of interest.
- skohan 6y agoI always took SOLID with a grain of salt, because they clearly started with the acronym and worked backwards to the constituent parts. Is Liskov's substitution principal really one of the 5 most important pillars of software design, or is it just the best one that starts with an L?
- jdlshore 6y agoOne of Bob’s anecdotes is that it took him several years after he started teaching the SOLID principles to realize that they could be rearranged to form the word “solid.” So, no, I don’t think he started with the acronym.
- Transfinity 6y agoThe author mentions in the post, and I think I agree, that Liskov substitution is the most "principle-like" of the principles in that it's pretty much always applicable. If the child object can't be substituted for he parent object, then you haven't really extended it, you've just made another unrelated class that happens to share some code. Inheritance is probably the wrong pattern here, and if you call what you've done inheritance you're going to confuse the person who next touches this code.
- skohan 6y agoI'm not arguing that it's not a real thing, but how often does the LSP come up in your day to day life as a programmer? I have not thought about this once, and I do not think there is a problem this has solved for me in 10 years.
- mypalmike 6y agoIt's not always easy to discover interface commonality. But when you do and it's a good abstraction, there are definitely benefits over scattering ifs and switches throughout your code.
- he0001 6y agoSOLID isn’t very good, but most of the alternatives are worse. I mean if the author thinks the SOLID principles are vague, but then go on saying “it should fit in my head” seems not like a good replacement. That is also very vague and arbitrary. Perhaps the author should combine them and it gets somewhat less vague.
- hertzrat 6y agoHe says the principles are wrong and says instead to just write simple code, but doesn’t offer suggestions for how to keep it simple. As if simple code is easy to write. There’s nothing more simple than a giant list of global variables. SOLID is an attempt to keep the code as simple as possible as it grows in size and complexity. It’s not perfect but anything is lousy if you misuse or overdo it
- Sammi 6y agoHe writes at the end that there's a follow up post coming with exactly what you ask for.
- einpoklum 6y ago"single responsibility" is not reducible/replaceable with "code that 'Fits In My Head'". Our head may very well fit two pieces of code which are disparate and which would be use to separate into distinct functions. ---- "Open-Closed Principle... was sage advice in an age where ... we hadn’t figured out refactoring yet ..." Well, as far as I'm concerned, we haven't "figured out refactoring" yet. I'm currently working with a group of people 75% of whose' work is just gradually and slowly refactoring an existing codebase. "Nowadays, the equivalent advice if you need code to do something else is: Change the code to make it do something else! It sounds trite, but we think of code as malleable now like clay" That may be true when you're writing code for your own use, or the use of a very small group of people (the large "user base" doesn't work with the code, they interact with what the code does). When you're writing a library, or code with which near-strangers need to work, you can't just willy-nilly change things. Moreover, you must strive to make your code good enough so that it doesn't need to be changed all the time; an ever-changing codebase is difficult to rely on (unless somebody takes a snapshot, and is back in the case of never-changing code). --- ... but I do appreciate some of the points made. Defining what "one thing" means is definitely not trivial and obvious, for example.
- burade 6y ago>When you're writing a library 99% of developers are working in boring business software with 2-3 other developers. 99% of codebases will be touched by maybe a dozen developers in its entire lifetime.
- The_rationalist 6y agoDid you make up those numbers out of your head? When you don't refer to a specific (Meta)analysis you can still make up numbers from guessing but if you do you should give intervals e.g replace 99% by most
- geofft 6y agoThe thing that strikes me the most about SOLID and the associated suite of practices and doctrines ("clean code," "craftsmanship," etc.) is the complete lack of evidence. What you have is a series of anecdotes from people pushing particular strategies saying that they think the thing they're saying is a good idea and other things are a bad idea. That doesn't tell you very much about whether the code worked in context, especially on teams of large numbers of developers. It doesn't tell you very much about whether the sample code on a blog that is (allegedly) more readable or understandable is actually more readable or understandable to others. And many of the folks pushing strategies, giving talks, etc., seem to be better known for being consultants about how to program than for programming per se. I have, I think, access to more empirical evidence about good and bad programming practice than any blog or talk that a SOLID advocate has given - but it's all internal to my employer's source control repo and you can't see it. If I could, I could easily point to code that has tried to follow "proper" design and has turned into Enterprise FizzBuzz and I could also point to short, readable code that doesn't follow any of the SOLID principles but it doesn't matter because you can read the entire thing in 10 minutes. Now I admit that I'm not offering evidence either, and as much as I agree with this article, it's also a first-principles argument. It says, for instance, that in our modern era recompiling a system from scratch is cheap and you don't need the open-closed principle, which I strongly agree with, but I can't immediately point at an example of a system that followed the open-closed principle and accreted into cruft, nor at a system that intentionally keeps its internals easy to edit and has worked well. I think we ought to do something about it as an industry. I don't have great ideas about how. I suppose we could look at open-source code (does Git follow SOLID? Chrome? TensorFlow? OpenStack? what about systems that do the same thing but with very different architectures, like GCC vs. LLVM?). But open-source code is generally subject to different development pressures and expectations than internal code, and the question many of us are trying to answer is, how do we write code at our day jobs that works well? All that said, I will say this article matches my (anecdotal) experience - and I would go further and agree with the comments that you want to test your system in its entirety, including running the actual database in tests instead of swapping it out. Just like it's much easier to recompile something now than it was in the '90s, it's much easier to spin up a database in a cloud VM/container/etc. than it was in the '90s. Dependency inversion and injection is a workaround for environments where unit tests are easy but integration tests are hard, and making integration tests easy both solves this and has a range of other benefits for software quality (and development velocity) too. (And actually there's a potential piece of empirical evidence here: software that doesn't have per-unit licensing costs, either open-source software with no costs or cloud SaaS with continuous billing based on usage, has been beating traditional enterprise licensing. I think you could argue that a big reason for that is that you can spin up that software in a CI environment or on a developer's machine. I can run a local MySQL much more easily than I can run a local Oracle DB, so I'm much more likely to do it, and we're much more likely to go to prod with MySQL, in turn.)
- pbw 6y agoUsing the word “wrong” here feels click-baitey when he admits many of the principles are right in certain cases or certain ways. The opposite of every great truth is a great truth. If a principle were true across all space and time with zero exceptions or nuance then software development would be easy. I very much like the “fits in your head metric” though and I wrote about it at length here: https://tobeva.com/articles/brain-oriented-programming/ https://tobeva.com/articles/brain-oriented-programming/
- nightowl_games 6y agoI spent some time in Web Apps between video game jobs. I got into some tense conversations where I, as manager, recommended against the abstraction layers the Senior Developer was trying to explain to the team on a whiteboard. He said something like "Why do all the game developers write code like that?". He handed me Uncle Bob's Clean Architecture. Uncle Bob is something of a meme to me. I read the book and couldn't figure out how to explain how I thought this style was inferior to what I had done in games before. Ive been thinking about that ever since it happened. How could I explain to this guy my programming philosophy? Last night, back in games, after refactoring the same piece of layout code for several hours, I finally arrived at the irreducible, simple, clean result that I wanted. I slotted it into our code base, and mentally noted how I would onboard the team to it on Monday, and how they would instantly understand because the resultant code is so simple. Then it came to me: "Unit Tests are like pouring concrete on your code base." Same goes for using "the wrong abstraction". Sometimes you want concrete to encase your precious technology. The problem is when people are writing sub par code, then they pour all this concrete on it via Unit Tests, Inheritance and Abstraction Patterns. It can become harder to improve the core logic of the system if it's distributed across many files, and enshrined in Unit Tests. I've dedicated over 10 years to coding, and only now do I think I can write clean code that is worth encasing in concrete. I think there might be a general flaw in the idea that everyone should be writing tests. I'm not certain about this, it's just my general intuition based on my experience. They are pros and cons to every design decision. I acknowledge that they are many pros to these kinds of designs, I'm just enumerating some cons that have arisen from my experience.
- villasv 6y ago> "Unit Tests are like pouring concrete on your code base." My experience is the exact opposite. Tests make me feel safe to perform code changes a bit more aggressively than simple refactors. If behavior coverage is slow, I spend more time double checking I'm not breaking stuff along the way. Sometimes changing implementation will mean changing tests too which might seem to be defeating the point, but this is because the test isn't good yet so it's an opportunity to improve the test and stop leaking implementation details. To me, it pays off handsomely in the long run.
- gtsop 6y agoThe author inverted the way we rationaly understand reality. Instead of observing and concluding, he concluded and then retro-fitted observations - he actually admited this by stating his motivation was to make an anti-solid presentation for the sake of it, I'm not making this up. Thus it is unfair for us to try and contradict his arguments, it's like talking to a conspiracy theorist, they will glue random facts trying to support a pre-decided conclusion. Having said that, this post is very shallow. Even if there is merit to criticising the SOLID principles (and I would be very interested in such a criticism), you can't just do it an a couple of sentences.
- andybak 6y agoYour reply makes it sound like you missed the tone and context of the post. Light-hearted and intended to poke a few sacred cows... But also you seem to be denying two important possibilities: 1. Something can be both flippant and insightful. 2. A "couple of sentences" is sometimes all that is needed to trigger a light-bulb moment in someone else's head. We're not writing legal treatices here. We're trying to transfer insight from one conscious brain to another using an imperfect medium.
- gtsop 6y ago> Your reply makes it sound like you missed the tone and context of the post. Light-hearted and intended to poke a few sacred cows... If that is the context and tone, then I must admit I missed it. > But also you seem to be denying two important possibilities I don't disagree this can happen. Let's see what the future will bring. Still I feel the writer could have done a better job going into more detail.
- burnished 6y agoWhat? The post isn't a scientific article, its a persuasive piece. The hypothesis -> testing -> results model of understanding is great for problems it can be easily applied to. Design doesn't seem to be one of those.
- FpUser 6y agoI do not waste my time trying to prove / figure out what is the "proper" way of doing things. I use whatever approach I feel suits better for particular case and do not give a flying hoot about what's the latest fashion.
- vsareto 6y agoSRP is vague because it really depends on how your team prefers to draw boundaries around the responsibilities. Some places choose to have meatier responsibilities (an entire ETL pipeline as one class), or prefer smaller responsibilities (same ETL pipeline, but each stage of it is a separate class). Both of these could use roughly the same amount of code, whether it's implemented in 1 class or across 3 classes. Some of this is driven by how user stories and work is organized. SRP never really recommended how large those responsibilities should be, but that's almost impossible to do given how widely programming is applied (especially for a quick acronym parroted in interviews). Had it tried to specify this size, we would likely be dealing with "OLID" instead of "SOLID", since it would be much easier to criticize. It comes down to how many tabs you want opened in your IDE and how good you are at moving between them and keeping the object relationships in your head. If I have a god object to handle one responsibility, I only have to look at one file, but it might be thousands of lines long. Or I can reduce that down to tens of files open with hundreds of lines each. Or it could be hundreds of files with only around ten lines each. The god object allows me to mostly forget about any object relationships or abstractions. But I pay some price by having to learn the entire god object before being able to sensibly work on it. If I have some object inheritance like: IPipeline -> AbstractPipeline -> SqlPipeline -> PostgresPipeline, SQLServerPipeline, MySqlPipeline IPipeline -> AbstractPipeline -> NoSqlPipeline -> MongoPipeline, CosmosDBPipeline (every architect dreams of this) It's easier to change things per database without affecting the others. Since each of these products change independently of one another (Mongo doesn't consult Microsoft about SQL Server), it makes more sense to do it this way as opposed to having a god object when you know you must support these other databases. On the other hand, if you know you will only ever use Postgres, IPipeline, AbstractPipeline, SqlPipeline/NoSqlPipeline become mostly useless abstractions. This also varies greatly whether you're trying to build building blocks for other developers or just trying to ship a product. Principles aren't always going to apply to both of those, and SRP might be one of them. It wouldn't hurt to add "depending on how your team defines responsibilities" at the end of SRP.
- sorokod 6y agoI think that the problem with SOLID principles was the use all capital letters and the word principles instead of guidance. Now that that original sin has been committed, it is super easy to take shots at it.
- zoomablemind 6y agoAs the author described it in the preface, the topic was rather meant to be engaging and entertaining for the occasion. So let's not confuse this with a true debate over SOLID. > "... So what would I do instead? I thought there might be a one-to-one correspondence for each of the SOLID principles and patterns, since there is nothing inherently bad or wrong with any of them, but as the saying goes, “If I were going to Dublin, I wouldn’t start from here.” " As anything, SOLID is a guideline, not a dogma. The purpose is to encourage developers to approach the design of their code mindfully. Personally, in my memory the advent of SOLID principles coincided with widespread promotion of better approaches to testing. These principles indeed helped design for better testing. And better testing provided more freedom for changes going forward. If another set of priciples help one's projects better attain the set goals, well, sure, embrace these by any means.
- sbussard 6y agoThe argument against the Liskov Substitution principle was the most interesting to me. It uncovers the principle that makes the world go round: composition. While it’s easy to decompose code into components of single responsibility, I think the rules of composition are not clearly understood. Category Theory has already told us that composition depends on context (what the thing is used for). Yet some problems are intrinsically coupled, having relationships across layers of abstraction. In those cases the developer should broaden the definition of what “one thing” is. A process emerges for writing such code: gather deep understanding of the domain > develop an accurate mental model for what is to be accomplished > make wise choices on how define categories of code. Overall not wrong, just insufficient.
- mdoms 6y agoThere's a big push across all of Dev Twitter right now to do away with SOLID. To say I think it's misguided is an understatement. There's a similar push underway to do away with unit tests. The direction of our industry right now is very concerning to me. And honestly, this may be an unpopular opinion, but I think a lot of it is driven by people who disagree so vehemently with Bob Martin's politics that they overcorrect and start throwing out his good work too.
- callmeal 6y ago>There's a similar push underway to do away with unit tests. I agree with that push, as long as there's some other way of validating requirements. In my team, that's done with integration tests and our core principle is: code that is integration tested does not require unit testing. That principle surprisingly covers a good 70-75% of the codebase, leaving us with a few core unit tests for the secret sauce of our product.
- resonantjacket5 6y agoI think the push against SOLID is fine. I've never really seen the 'single-responsibility' part ever really followed or used in a way that made sense. I haven't really seen a strong push against unit tests?
- drooby 6y agoYou’ve never seen SRP in practice? This is honestly concerning. You’ve never seen like a User class that only encapsulates fields and methods relating to a User abstraction?
- resonantjacket5 6y agoI meant more as for non-trivial classes when people are deciding when to break up a class the "single responsibility" part is too loosely defined to the point where I've never seen people actually use it as a metric. I agree classes can grow too large the hard part is what rubric actually used for delineating it and just saying "single responsibility" really hasn't by itself been useful.
- king_magic 6y agoYawn. Exceedingly tired of these “X is bad” kind of posts. People can critique things all day - it’s hell of a lot harder to create something new, and those are the kinds of pieces I’m interested in.
- lamontcg 6y agoThis is a ranty and poor article, and I will continue to use SOLID. As with everything, just mindlessly applying the principles without consider if the resulting code is simpler/better or more complicated/worse is the wrong way to do it.
- EasyTiger_ 6y agoMy god what awful clickbait
- andy_ppp 6y agoThe tech community constantly give their opinions as truth (the article is an example of this). I wonder if YC could be a position to do some quantitative research about what works, especially as companies evolve their codebase and if that even matters as much as we software engineers feel it should.
- nautilus12 6y agoWhy everything you know about software engineering is WRONG, and this one WEIRD trick you can do to get ahead of the pack.
- njharman 6y agoI was hopeful, because I tend to think most "universal" principals are 80% working around problems/limitations/design choices of, at the time, mainstream programming languages (C, C++, Java). Which don't apply to (some) other languages (which have different limitations of their own). But, I don't think this author gets it (what the SOLID elements actually are, nor how they are moot when using languages that solve the same issues they are solving).
- Syzygies 6y agoSOLID acronym: https://en.wikipedia.org/wiki/SOLID https://en.wikipedia.org/wiki/SOLID As a pure mathematician, whenever I find myself reading an acronym-heavy paper I know I'm in the wrong part of town.
- sholladay 6y agoAt first, I thought this was going to be about the Solid Project (which is sometimes stylized as SOLID) by Tim Berners-Lee. It's not. That would have been fun. Regarding SOLID principles being outdated, I disagree. The high level concepts of SOLID are good and just as relevant as ever. While the author proposes that code is now less risky to change, I would argue that the asynchronous, distributed systems that we often work with today are significantly more complex and error prone. The world also got hooked on dynamic languages for the past couple of decades, although it feels like that shift is slowly reversing. Software bugs have become a routine part of daily life, partly because there's more software but also because we build that software more haphazardly to achieve deadlines for ever expanding sets of features. Today, a large number of developers lack proper education or training and have relatively little experience. We work in teams where there's a lot going on besides writing code and there's more distraction around us than ever before. To me, there's no shortage of reasons to worry about changing a line of code. I spend a lot of my time trying to understand and reduce that risk so that I and everyone around me can be more productive in the long run. The SOLID principles are a useful guide in that effort. That said, you may want to update your interpretation of SOLID within the context of your latest coding practices. For me, that meant applying SOLID to functional programming. At first this seems odd, since much of the language around SOLID implies the use of classes and object-oriented programming. But it turns out there is a lot of overlap between the philosophies of SOLID and functional programming. [1] 1: https://dev.to/patferraggi/do-the-solid-principles-apply-to-functional-programming-56lm https://dev.to/patferraggi/do-the-solid-principles-apply-to-...
- surfsvammel 6y agoTo me Single Responsibility means that the code should do one thing and one thing only, on the abstraction level which it exists. The example given by OP is about ETL. Is that one thing or more than one thing? It depends on the abstraction level. If you are talking about a data access object, sure let it do all those things because when considered on that abstraction layer it does one thing, access data. But if you are looking at individual functions or methods, that is one abstraction layer further down, then S in SOLID says you should not mix extraction and transformation, for example. It all depends on context and SOLID are principles not law.
- majkinetor 6y agoTo me, there is one fundamental principle: Better code is the one that takes lowest time in total to get from point 1 to point N by mediocre developer and in the same time result in lowest amount of help desk tickets Its the essence of MIT vs New Jersey design style (i.e. worse is better) The problem is, its impossible to measure that (unless we tap in parallels universes) which is why design is a form of art in real world.
- jesseryoung 6y agoAs nearly every poster in this thread mentioned, this headline is click-bait. I don't blame the author actually, this is very targeted click-bait (OO programmers) and I took the bait and actually enjoyed the read. The criticism of SRP hits home for me - I try and write SOLID code when I can and SRP is challenging to follow. I struggle jumping between "Does this really fit SRP?" and "I can probably justify SRP here." I usually settle on the author's "Fits my head" and justify that when doing code reviews with my co-workers. The author's comments on OCP don't accurately reflect my experience with the field of modern software development. I've worked on many projects (even green-field projects in the last 3 years) that have been very expensive and risky to change, where work absolutely needed to be additive because you couldn't trust refactoring tools to handle everything that needed to be changed.
- ssijak 6y agoLet me guess, they were Python or Ruby projects?
- pron 6y agoThere's much here I agree with -- and especially with the general lesson of "don't get too hung up on principles," but at one point the article speaks of "1980s entity modelling," in a denigrating way, as if methods of formalisation age. It's like saying that doing logic-style type-level programming or SQL is "1970s logic modelling", and using high-order functions combinators is "1950s functional modelling." Many of the interesting ideas in programming languages from the 1980s haven't yet come of age, let alone grown outdated. Also, it is true that there's much we learn over the years, but also much we forget and reinvent.
- Pxtl 6y agoTL:dr; SOLID is basically a set of principles saying "keep things small and modular and encapsulated so you can keep them in your head at each layer", and so the specifics of SOLID are silly but the overarching goal is sound.
- tcgv 6y agoThe issue with SOLID is not that it's wrong or outdated, it's that some people think it's something you learn in five minutes by reading its Wikipedia page, which it isn't. It takes a lot of effort to develop skills to adopt SOLID effectively. > When I look at SOLID, I see a mix of things that were once good advice, patterns that apply in a context, and advice that is easy to misapply. I wouldn’t offer any of it as context-free advice to new programmers. Off course! I wouldn't offer any OOP architectural/programming principle as context-free advice to new programmers. It's easy to misinterpret it if you don't contextualize it, show how it's used in real projects, discuss advantages and disadvantages, and so forth. > The Single Responsibility Principle says that code should only do one thing. Another framing is that it should have “one reason to change”. I called this the “Pointlessly Vague Principle”. What is one thing anyway? This gives me the impression that the author indeed misinterpreted this principle, just to name one, oversimplifying it. If you like the author have trouble understanding the Single Responsibility principle, take a look at "On the Criteria To Be Used in Decomposing Systems into Modules" by David Parnas [1]. It seems to me that the author also oversimplified the other principles as well, maybe on purpose, for using controversy to attract attention to his post. [1] https://www.win.tue.nl/~wstomv/edu/2ip30/references/criteria_for_modularization.pdf https://www.win.tue.nl/~wstomv/edu/2ip30/references/criteria...
- fuzzy2 6y agoThe only way someone could arrive at the conclusion that “write simple code” is superior to any clean code principles is when they have already “absorbed” and perhaps transcended these principles. What does this tell us? It takes a mature developer. You cannot tell a junior developer to just “write simple code” and then expect any kind of sensible result. But then, you also cannot tell them to write SOLID code. Indeed, you need to teach the basics first: How to understand the requirements. How to write any code that fulfills them. How to write legible code that fulfills them. How to write good code that fulfills them. If you dump these principles onto developers that have not yet learned the proper developer mindset, the outcome will most likely be disaster. It is very hard to repair the damage. Only after a developer can actually write good code can you teach them how to take it to the next level. How some libraries are just so awesome to use without having to check the docs. How to conceive code you’ll look at in 6 month and think “damn, that’s some shit”. Why every single clean code principle is a recipe for disaster – if told to juniors.
- mekoka 6y agoThe problem with SOLID is not SOLID, it's the fetishism that sometimes surrounds it. I get it, rules are attractive as they make everything easier. You put on blinders and follow the track. But the fact that there's so much disagreement about how to best build software, with valid arguments in all sides of the multiple spectra, should hint at its truer nature as a craft (some would say a philosophy, but I haven't yet reached that level of enlightenment) rather than an exact discipline. Isn't it time to perhaps get comfortable with the idea that there are no perfect solutions, only trade-offs and that the right answer is most likely "it depends"? I understand that some people feel protective of their investment at internalizing the various "principles", but learning them doesn't give anyone a license not to think and to mindlessly apply them. And yes, SOLID is mostly useful in its essence, but over time parts of it have caused confusion and have not always aged well (https://codeblog.jonskeet.uk/2013/03/15/the-open-closed-principle-in-review/ https://codeblog.jonskeet.uk/2013/03/15/the-open-closed-prin...). At a more personal level, the DIP section of this article hit close for me, as I've (again) lived the described scenarios a mere week ago. Sometimes `main()` is all you need and all you'll ever need. The extra tooling is also debt. If you choose to incur it, it must palliate to an actual problem that you actually have, else YAGNI.
- hankchinaski 6y agoto me the whole saga of “clean code” and “solid” it’s just pseudo-science predicated by people who have made a fortune selling books and consulting on the subject. unfortunately software engineering it’s not an exact science and that’s for that specific reason that I rather consume these concepts with a pinch of salt and not take them as axioms
- makach 6y agoThe SOLID principles are associated with model driven development, and that paradigm. These principles have helped me in many ways improving code, and explaining why it needs to be that way. It makes it easy for me to bring consistency to the code base and bring new people into the project. There is definitively room for new models and new paradigms when writing code, and I welcome that. The click-bait article is just that... click-bait. It silly and reminds me of the "climb that tree" quote. Consistency has always been a big deal for me. Different code-bases needs different principles, standards and models. If you are consistently wrong you can consistently fix your issues. My experience is that if you are inconsistent, you usually will end up with the dreadful spaghetti of things.
- dralley 6y agoThis post is a better summary IMO https://www.reddit.com/r/programming/comments/hhlvqq/its_probably_time_to_stop_recommending_clean_code/fwb6hxf/ https://www.reddit.com/r/programming/comments/hhlvqq/its_pro...
- ChicagoDave 6y agoI love this, especially the comment on DIP. We went way overboard with dependency injection implementations.
- c3534l 6y agoI'm not a huge fan of SOLID, but when writing OOP in a conventional style, I have found that it works pretty well. All the principles play nicely with each other. You don't have to write SOLID, but you probably shouldn't write Java code like you're a Haskell developer because that's not a natural or common way to write Java. Writing simple code is great. For when you can write simple code. For everything else, people invented things like SOLID. We need and want to do complicated things and maintain complicated codebases. If you want to do simple things simply, I'm not even sure OOP is a great model, let alone SOLID, which is an attempt at simplifying people's OO constructions. For all intents and purposes, SOLID is how, in fact, you write simple code in complicated projects. "Single responsibility" is a much better heuristic than "fits in my head" because code expands and gets bigger. It fits in your head now, but no decently sized, actively developed project stays simple. When do you break it up? When it starts taking on multiple responsibilities. Yes, that isn't objective. But the alternative proposed is even less objective. Additionally, "fits in your head" is inferior because it assumes you already understand the codebase. If you are new to the code base, trying to weave through the functions and objects called to figure out what it does, looking at code that does multiple things is confusing and hard to synthesize without first understanding the whole. And you can't understand the whole until you understand the pieces. Single responsibility is much more specific and identifiable than the author's alternative. The author mis-attributes the Open-Closed principle to a performance optimization. The open-closed principle allows me to make assumptions about what a class is doing and how it behaves. This is because I know it hasn't been modified. Wikipedia notes that the original formulation of the term, a closed class or module "has been given a well-defined, stable description." The point here is that if you don't let something be fundamentally changed during runtime, then you can reason about it. It is definitely not a performance hack. The author states that the Liskov Substitution Principle is the principle of least surprise, which is surprising as you cannot substitute one principle for the other. This suggests to me that the author does not actually understand the meaning of this principle, especially as he fails to give a substantive critique and unhelpfully declares that you should write simple code. The Liskov Substitution principle is, again, how we reduce the apparent complexity of code so it allows us to reason about it more effectively. This next one is baffling. The author of this article recounts the anecdote showing an instance where the interface segregation principle would have been helpful in designing the code. However, the author appears to be unable to gleam from that anecdote the underlying principle being advocated and is fixated on the fact that in the story the code was refactored. Since the anecdote describes an implementation, the author is unable to see it as anything other than a design pattern. The author claims this principle has cost billions of dollars in damage. He does not feel the need to explain this or provide a citation. Just, you know, billions of dollars in damage. Like we just all know that this powerful decoupling principle just set a large fortune on fire and this is plainly obvious to everyone. Next he says "the real principle here is option inversion." No, it isn't. I don't know where the author got this from. But I suspect given what he's said previously that it just sort of made sense to him and then decided that must be what this principle is about without any further discussion. But the author is none the less actually correct that you can over-use this principle to over-complicate code before it really needs to be that complicated. These are, of course, ultimately rules of thumb that work well together. Common sense and experience are still required. Robert C. Martin has an unusual habit of giving advice that sounds kind of stupid at first glance, until you actually try it out for yourself. His "rules" often have hidden reasons behind them that only become clear when you write code with them. I suspect that the author did not give SOLID a serious shake as his criticisms all sound strongly like someone who read about SOLID, failed to internalize their meaning or give the technique a try, and is now attacking a strawman with advice that, quite unlike Robert C. Martin's style, sounds okay at first glance, but you quickly realize does not translate into actionable advice when you're coding. I've heard "fits in your head" before. It sounds like what you want, but it does not allow you to identify problems early and predict what sorts of changes you might need to make to the code to prevent those problems. Especially if you're a beginner, try writing according to SOLID principles. See if it helps. After you understand why those are the principles and why they all go together by seeing what sorts of decisions it causes you to make in your own code, you're free to ignore it having at least learned what the advice actually is.
- wasnthere 6y agoThe article, imho, reads like the main goal of the author is to prove he has a bigger dick than Uncle Bob’s... sadly, he fails miserably at it.
- nottrobin 6y agoI think a couple of the criticisms are valid - mostly the criticism of dependency inversion. But overall I think the article (if we were to take it seriously) basically represents a nihilistic point of view that says "there's no point trying to have principles - code is either subjectively good or it isn't". I'm as sympathetic to heterodox criticism as anyone, but this desire to throw away any received wisdom at all definitely seems misguided to me. (For what it's worth, I think the single responsibility principle and the open closed principle are particularly valuable. I'm open to persuasion on the others)
- coldtea 6y agoSOLID is folk wisdom to begin with. Most of developing (as opposed to computer science) is unresearched old-wives-tales and cargo cult. Is SOLID any good? Who knows? Who proved it? Heck, who even did tests?
- HALtheWise 6y agoOne of the most useful pieces of programming advice I have been given is to make an abstraction on the third time you solve a given problem. It encourages making abstractions for common tasks, but also acknowledges that in a large codebase the wrong abstraction is an order of magnitude more expensive than not having an abstraction at all, and it's unlikely that you have enough information to make the right abstraction the very first time you are looking at a problem. As with all things, there is a cost (slightly more code duplication for rarely-solved problems) but also huge benefits in having really solid abstractions built from lots of experience.
- resonantjacket5 6y agoThe main problem I see is that the overall SOLID principles while still correct, the original definitions used are too outdated and heavily imply inheritance everywhere. Single Responsibility, honestly I like 'separation of concerns' much more. People tend to think single responsibility means use tiny classes and single line functions. Open closed principle stating "should be open for extension, but closed for modification" infers to many it's about inheritance only. Open for customizability would be much better. Liskov Substitutions seems like its talking about inheritance when it really also applies to interface usage in general. Dependency Inversion principle is interpreted by many to be use dependency injection everywhere etc... I wish someone would go and update these definitions for the modern world.
- sbmthakur 6y agoOn this note, can anyone recommend a good tutorial that introduces SOLD with Typescript?
- jmgimeno 6y agoSOLID (or any set of design principles) are important in the sense that you should think twice when you don't obey them. So it is not necessary that they are strictly well defined: they are stopping points for thinking not for marking on a YES/NO list.
- sterlinm 6y agoHmm, I came here for a discussion of the history of the security identifier... https://en.wikipedia.org/wiki/CUSIP https://en.wikipedia.org/wiki/CUSIP
- tpoacher 6y agoIn other words, "I present here a particular interpretation of SOLID, and then demonstrate that this interpretation is problematic". "Join us next week when I will introduce a new acronym, whose interpretation will be superior to this interpretation of SOLID".