9 ms·
Solid Relevance
- ajuc 6y agoThere's 2 approaches to programming: - make it easy to extend (lets's call it SOLID in this context) - make it easy to rewrite (let's call it KISS) OO developers think that the first approach is The Only Way but both can be right, especially with high-level declarative languages and with tasks small enough (relative to the language expressive power). SOLID makes it easier to modify programs (in predetermined directions) without understanding the whole. KISS makes it easier to understand the whole program. SOLID accumulates inefficiencies over time because people program with tunnel vision. KISS takes longer to modify as it grows and eventually exceeds the capacity of human brain. SOLID is mostly OO, KISS is mostly declarative. If you want to feel safe changing code unit tests are nice, best practices and design patterns are nice too, good architecture is appreciated. But the best is just to understand everything that happens. Only then truly fearless programming is possible. Once you go big enough you have to use SOLID but before that it's a cost.
- BossingAround 6y ago> SOLID makes it easier to modify programs (in predetermined directions) without understanding the whole. In my experience, in predetermined directions is almost never the direction the piece of code needs to evolve. Maybe I'm bad at reasoning about the future changes, but I'd guess that most people are utterly bad about this. This makes OCP more like an ideal to be aspired to, and beaten with when one inevitably fails.
- nendroid 6y agoIf you look at it objectively. There's a very clear reason why OOP inevitably fails. Maybe a better way to put it is that SOLID is an ideal that OOP aspires to be but fails. Either way SOLID is a bad set of axiomatic design principles. It's sort of an arbitrary group of rule of thumb principles picked to spell out SOLID.
- deleted 6y ago[deleted]
- discreteevent 6y ago> But the best is just to understand everything that happens. Agreed, but unless you have written all the code yourself then this is hard to do. We have to be able to black-box things in order to manage complexity and make progress quickly. For this SOLID helps but if it is applied a too fine a granularity then it can make things worse (and I think micro testing things with mocks etc can cause this) "There is no theoretical reason that anything is hard to change about software. If you pick any one aspect of software then you can make it easy to change, but we don’t know how to make everything easy to change. Making something easy to change makes the overall system a little more complex, and making everything easy to change makes the entire system very complex. Complexity is what makes software hard to change. That, and duplication." https://martinfowler.com/ieeeSoftware/whoNeedsArchitect.pdf https://martinfowler.com/ieeeSoftware/whoNeedsArchitect.pdf
- nendroid 6y agoI disagree with Martin very much. Programs can be made easy to change without introducing complex OOP abstractions. There is a simple rule that Martin fails to ever mention. Use combinators as much as possible and segregate as much logic as possible from IO. That's it.
- deleted 6y ago[deleted]
- eyelidlessness 6y agoI can see how SOLID and OOP seem to be related, but the principals of SOLID can (and IMO should) be applied to FP as well. In fact one of the clarifications in Uncle Bob’s letter hints at this, by expressing that substitution is about subtypes, not inheritance. This is of course common in statically typed FP languages like Haskell (or FP approaches in statically types imperative languages like TypeScript, Swift, so on). But even in dynamic languages like Clojure, substitution of subtypes of a given interface is pervasive; I would even say it’s foundational to the language’s core concepts. I’d even go further to say that FP languages and approaches are much more likely to guide developers toward SOLID naturally than imperative languages and approaches.
- nendroid 6y agoI feel that SOLID doesn't even work well with OOP. Overall it's just saying "be more modular" in a programming paradigm that's one of the least modular styles ever created.
- eyelidlessness 6y agoAgreed, though I also feel that even OOP doesn’t work well in OOP.
- zaphar 6y agoI look at it with the rubrik: KISS is for coding. SOLID is for system design. There is overlap obviously but SOLID becomes even more important when you have N+2 systems that interoperate. KISS is one way to help ensure you have a SOLIDly designed system when you are coding it. But it helps to understand the principles in SOLID when you are designing a monolith or a set of microservices.
- drewcoo 6y ago> There's 2 approaches to programming Written like a programmer! And therein lies the bug. Unless SOLID is the negation of KISS, the world tends to have more than two options. How about DRY, for instance? Off by at least one.
- Silhouette 6y agoSoftware is still if statements, while loops, and assignment statements — Sequence, Selection, and Iteration. That seems an extremely narrow view of modern programming. But then isn't this the same man who made the claim about there not being any new programming languages left to find?
- he0001 6y agoCurious, what new has been found?
- nendroid 6y agoThere's a style of programming with no concept of loops or jumps. It's called functional programming. There's other styles that are drastically different as well. Most of these styles aren't new though.
- commandlinefan 6y agoWell, at the risk of being pedantic, I think you're being pedantic: at the machine-code level, all those function calls resolve to jumps and their recursive base-cases are terminating cases of loops. Functional programming is a great way of organizing loops and jumps, but they're still loops and jumps.
- ajuc 6y agoAt the machine code level there's no Iteration just GOTO :)
- commandlinefan 6y agoWell, there's unconditional goto (jmp) and conditional "goto" (branch).
- lerptime 6y agoHe's not talking about machine level code. He's talking about while loops in regular programming. I don't think the person was aware that there are paradigms that avoid looping. To be more pedantic and get even lower level than machine code, at the theoretical level the basis of computation can be either procedural or functional. See lambda calculus and Turing machine for more info.
- nendroid 6y agoSOLID is just a random arbitrary acronym about some principles that are somewhat obvious. However most people don't fully understand these principles deeply. What happens is if you are using OOP you are not using SOLID to its full extent. Ironic that SOLID comes from OOP. Either way SOLID are arbitrary rules of thumb. Grouped together arbitrarily to spell out SOLID and kind of maybe sort of right depending on your opinion. 1. SRP. Gather together the things that change for the same reasons. Separate things that change for different reasons. I disagree. Unless this thing is talking about namespacing which is more of an aesthetic/psychological thing... You should not organize your program this way where logic of one thing is tied with the logic of another thing. All things should be ungrouped as much as possible. You should also separate all things that "change" and all things that don't "change" and try to keep the things that "change" as small as possible. All logical modules in your program should be separated as much as possible at the lowest layer, nothing should be grouped... and higher layers should be compositions of lower layers. But the basis of your program at the lowest layer: everything should be separated and nothing should be grouped. In other words use combinators as MUCH as possible. OOP's promotion of methods that operate on shared mutable external scope actually prevent you from doing this. 2. A Module should be open for extension but closed for modification. Agreed. The problem is if your program is OOP your modules are objects which group methods together through shared mutable state. It means that you cannot extend one method without modifying the entire object. So basically OOP practitioners can never modify an addOne method into addTwo. They can't even add an addTwo method into the object as that constitutes modification. What they can do is inject that entire object into another object. Either do this or use inheritance which OOP says is just bad. Instead. Use combinators. You have an addOne combinator? Create an addTwo combinator. Recompose your combinators to form the higher level logic you wanted. 3. A program that uses an interface must not be confused by an implementation of that interface. Yeah I mean sure. Don't have your flatten Function be able to operate on an integer. 4. Keep interfaces small so that users don’t end up depending on things they don’t need. Agreed the problem is, the definition of an object in OOP usually ties muteable state and logic together. Your average object has a getter and setter which are tied together by external scope, so by definition OOP ties together things that shouldn't belong together. You are not keeping your interfaces small.... by definition it is already too big. If you defined the logic as I said above separating state changes away from combinators you'd have even smaller interfaces. One for changing state. And the other logic is stateless. 5. Dependency inversion principle. I mean yeah. Write your logic in layers. The problem is OOP people only use this principle at the module level. The better way to program is to have all your methods follow the dependency inversion principle. You can't do this if methods are modifying external scope shared by another method. Use combinators and by definition every sector of your program is following this principle not just "modules"
- feoren 6y agoUncle Bob sounds like someone trying to tutor a young golfer by talking about how his shoulders are aligned, how wide apart his feet are, how he's gripping the handle, etc. Dan North sounds like he's objecting to that style and prefers just yelling "JUST HIT THE BALL FAR" at his students over and over.
- jeremyjh 6y agoI'll be honest I almost never find myself agreeing with what I understand Bob Martin is advocating but this whole post makes sense to me. I may have to re-read some of his other stuff. I don't do much OOP but all of these principals make sense in a FP context as well and I think he does a good job of untangling accidental associations with specific OOP features/patterns in this article.
- ch_123 6y ago> His points were that the Open-Closed principle isn’t very important anymore because most of the code we write isn’t contained in large monoliths and making changes to small microservices is safe and easy. IMHO, Open-Closed applies just as well to entire microservice architectures as it does to individual classes. For example, I've seen services for general-purpose tasks such as job scheduling or generating PDF reports which required devs to change the code to add a new job type or report type. These services were replaced by services where the new application-specific types could be defined through an API, which meant that those services were "done" and reduced the amount of work required to use them.