Solid Programming - No Thanks

  Рет қаралды 210,285

ThePrimeTime

ThePrimeTime

27 күн бұрын

Recorded live on twitch, GET IN
Article
www.freecodecamp.org/news/sol...
By: Yiğit Kemal Erinç | x.com/erinccodes
My Stream
/ theprimeagen
Best Way To Support Me
Become a backend engineer. Its my favorite site
boot.dev/?promo=PRIMEYT
This is also the best way to support me is to support yourself becoming a better backend engineer.
MY MAIN YT CHANNEL: Has well edited engineering videos
/ theprimeagen
Discord
/ discord
Have something for me to read or react to?: / theprimeagenreact
Kinesis Advantage 360: bit.ly/Prime-Kinesis
Hey I am sponsored by Turso, an edge database. I think they are pretty neet. Give them a try for free and if you want you can get a decent amount off (the free tier is the best (better than planetscale or any other))
turso.tech/deeznuts

Пікірлер: 798
@JayHiza
@JayHiza 25 күн бұрын
"Program until you NEED abstraction" is on point. I was having this debate at work yesterday, and I said something very similar. Unless you're a savant, who can architect a program entirely in your mind, the most logical thing to do is to write code until you realize that abstraction would be beneficial, implement it, and continue writing code. To do otherwise is just wasting time in my opinion.
@zeez7777
@zeez7777 25 күн бұрын
Yes, but the important part here is to actually be aware of that and introduce the abstraction and refactor. But you're right.
@somniad
@somniad 25 күн бұрын
Big important problem with this statement: the savant also can't architect it in their mind. Nobody is that good. It's not a little bit out of normal reach to the point where you could get it if you had experience and thought reaaaaally hard about it. Requirements change.
@AndrewBrownK
@AndrewBrownK 25 күн бұрын
spoiler: nobody is that savant
@defeqel6537
@defeqel6537 25 күн бұрын
This is a good starting point, another is to abstract platform specifics. Abstraction can just be a C/C++ declaration too though.
@Linkario86
@Linkario86 25 күн бұрын
​​@@zeez7777this is where it starts to crumble. It's tricky though. If you abstract everything beforehand, there is a big tendency to over engineering. If you don't do it there is suddenly no time and money for refactoring, and "it works" so why bother? But it works bad, slow, hard to read and maintain and it's crumbling.
@angelcaru
@angelcaru 26 күн бұрын
liquid programming
@hextech687
@hextech687 25 күн бұрын
Ahhh yes the Bruce Lee paradigm
@sebastienpautot
@sebastienpautot 25 күн бұрын
Programming with inferior genes
@grexpex1807
@grexpex1807 25 күн бұрын
naked programming
@iMagUdspEllr
@iMagUdspEllr 25 күн бұрын
Solidus programming
@jimgorlett4269
@jimgorlett4269 25 күн бұрын
venom programming
@PaulPhilp-pe5oe
@PaulPhilp-pe5oe 26 күн бұрын
This topic always reminds me of the famous Miles Davis quote: "Learn the score, then throw it away" is a quote often attributed to jazz musician Miles Davis. The quote emphasizes the importance of mastering the fundamentals and techniques of one's craft, but then being able to move beyond them and improvise freely.
@jeffreyjdesir
@jeffreyjdesir 26 күн бұрын
😮 Great knowledge from my legend that I didn't even know. Thank you! Competent practitioners of most advanced skills tend to realize this one way or another.
@banatibor83
@banatibor83 25 күн бұрын
True! But there are much more software developers out there who are not on this level.
@filipg4
@filipg4 25 күн бұрын
My brother in Christ, SOLID is not fundamentals, it's literally the highest level possible trash knowledge that is as far from fundamentals as possible.
@PaulPhilp-pe5oe
@PaulPhilp-pe5oe 25 күн бұрын
@@banatibor83 True. Nothing I've ever written is the 'Sketches of Spain' of software, so I keep learning, mastering and owning what I can.
@LusidDreaming
@LusidDreaming 25 күн бұрын
It should be noted that there are also just flat out bad scores that no creative freedom can fix (without entirely replacing the original)
@rampantporcupineandfriends3793
@rampantporcupineandfriends3793 25 күн бұрын
This reminds me of the book A Philosophy of Software Design. It states that you should only create an abstraction if it reduces the complexity of the system. It calls abstractions that are a net drain on the simplicity of the system "shallow" and ones that are a net gain as "deep". The book also acknowledges that this means that one piece of code may have to do multiple types of tasks.
@Dogo.R
@Dogo.R 25 күн бұрын
Define "complexity".
@rampantporcupineandfriends3793
@rampantporcupineandfriends3793 25 күн бұрын
@@Dogo.R The books definition of complexity is this. "Complexity is anything related to the structure of a software system that makes it hard to understand and modify the system. Complexity can take many forms. For example, it might be hard to understand how a piece of code works; it might take a lot of effort to implement a small improvement, or it might not be clear which parts of the system must be modified to make the improvement; it might be difficult to fix one bug without introducing another. If a software system is hard to understand and modify, then it is complicated; if it is easy to understand and modify, then it is simple." -John Ousterhout The book starts by introducing this definition and then goes on to describe how to recognize this complexity and how to mitigate it. I've been using its principles in my current project, and I've been really enjoying it. :) I feel like it helps make up for my lack of intuition as a relatively new programmer. I shared the book here because I feel like a lot of what Prime says lines up with the book pretty well. If you like Primes software design philosophy maybe check it out for a more detailed and structured take on things. This is a talk where he introduces his book kzbin.info/www/bejne/mJ62coyiqpWBmbs
@monad_tcp
@monad_tcp 25 күн бұрын
Essential complexity versus accidental complexity.
@rampantporcupineandfriends3793
@rampantporcupineandfriends3793 25 күн бұрын
@@monad_tcp Yes, at the end of the day every system you create will have complexity. But you should aim to keep that complexity close to the minimum needed to get the job done. When looking at Primes design principles through this lens you can interpret his idea that you should start with the "concrete" of a solution and discover the abstraction later as an attempt to limit complexity. Similar ideas are explored in the book which spends a lot of time talking about how to spot bad abstractions and how to find good ones. However, there are some significant differences between the books philosophy and what I understand of Primes philosophy. For instance, the book is not as opposed to starting your design process by coming up with an abstraction.
@swapode
@swapode 25 күн бұрын
​@@rampantporcupineandfriends3793 You start your design process with something you know, which is something Prime seems to be struggling with in general, as seen by his arguments against TDD (assuming that you need to know pretty much the entire project before you can write meaningful tests, which is just an absurd understanding). Sometimes you obviously know that certain abstractions are central to your project.
@AndrewBrownK
@AndrewBrownK 25 күн бұрын
A lot of these seem to convey an emotion of "if you ever have to refactor this, then you made a mistake. You should predict and/or accommodate the future perfectly" I'd much rather see principles around the idea that "you cannot avoid refactoring, the only question is how to make it as painless (or dare I say easy) as possible" and a lot of that difference is diametrically opposed when it comes to the guidance on inheritance
@deloftie3619
@deloftie3619 25 күн бұрын
All of the SOLID principles are to facilitate easy and painless refactoring. Most modern devs don't care that much about maintenance and refactoring though (they just made a pile of mud and then move project and/or job and start again) which is why you get videos like this that are saying don't bother with SOLID principles.
@Chisegh
@Chisegh 25 күн бұрын
@@deloftie3619 In my experience solid principles make refactoring harder because more often than not you build the wrong abstraction, resulting in first having to undo the abstraction and then building the right one. In a perfect world where we can perfectly predict the future solid makes sense. Reality is very different though.
@deloftie3619
@deloftie3619 25 күн бұрын
@@Chisegh I don't follow what you mean by "undo" the abstraction. If you follow SOLID principles you never need to change your existing code as your product changes or matures. You are only ever adding new code It is the exact opposite of having to predict the future, which is what you have to do with procedural code because you have to either know that function X does everything it will ever do or you have to add new functionality to the existing function X as you develop. This is because functions are tightly bound (it is difficult to say to your exist code "Stop using this function, use this one instead") so existing functions are constantly changing and growing, which massively increase the complexity of the functions and the risk that bugs will be introduced. I've worked on so many software products where after a few years every function is a collection of if statements for all the new functionality that has been piled upon the function over the years
@AndrewBrownK
@AndrewBrownK 25 күн бұрын
@@deloftie3619 to put it simply, I disagree. "it is difficult to say to your code, stop using this function, use this one instead" I only find that to be difficult when the functions entail large amounts of state, which is you guessed it, from OOP The worst nightmare refactors I've ever seen have all involved unnecessary class hierarchies and the inability to fix problems without causing problems in new places, or ripping everything inside out to procedural again. When procedural code just does what it says right in front of you, instead of reaching through so many abstractions, it is easy to refactor by comparison. Especially with a dash of functional programming to minimize use of state overall.
@deloftie3619
@deloftie3619 25 күн бұрын
@@AndrewBrownK "I only find that to be difficult when the functions entail large amounts of state, which is you guessed it, from OOP" Well its not state I'm worried about in this situation, its binding. If you have a function that is called in a 100 places in your code and then you need to alter how some of those places behave you have a tough time about it. I've seen so many large functions with multiple paths that have been added over the years to account for new functionality that has had to be brute forced into the existing function. And don't get me started about having to slowly increase the parameter size of a function as the function becomes responsible for more and more. "involved unnecessary class hierarchies" Well sure, the "I" in SOLID is essentially don't have class hierarchies that can break your code. "When procedural code just does what it says right in front of you" It does, and it is perfectly fine for small projects that won't change much. I've nothing against procedural code, I write C and procedural Python all the time. But it is a nightmare to have to maintain procedural code in any large system (again binding) that grows and matures as the business requirements evolve. Which is exactly what OOP was invented for.
@roberthoople
@roberthoople 26 күн бұрын
The whole OOP vs Functional thing just didn't make any sense to me when I first fell down the rabbit hole, but after hearing enough of it I've come to realize it's a false equivalency. Basically it's just click bait to get views on articles and videos. I just write and organize my code for the best balance between readability and optimization, which turns out to just basically be Functional OOP. Although, I do get people's beef with inheritance, and when I first learned OOP I way overused it. Since then, I only use inheritance when it's the best way to solve a problem, which is very rare, but very powerful in those rare situations. Yet it's another thing people want to fight about and claim a position of being anti or pro on... So it's no wonder all the software on my PC and phone are getting worse and worse with every new release.
@samgraham182
@samgraham182 26 күн бұрын
Thank you! I had to maintain an overused inheritance project in Ruby once, it was horrible. Everything was hidden. I had to read code for hours and hours just to grok anything. Then I got reassigned to another issue that was higher priority in another project. RIP whatever issue that was, it's been a decade and I still remember the frustration.
@cloudboogie
@cloudboogie 25 күн бұрын
@@samgraham182 Oh man, that's classic ruby. I don't miss working with it: bloated rails, annoying metaprogramming in the least expected places, "rockstar developer with god complex" coleagues, cultish "the rails way", hours long discussions about code style, etc.To hell with it
@hextech687
@hextech687 25 күн бұрын
I dont really study programming too much (Im more of a make things work kinda guy, trying to change this). Im very much a vibes based programmer. The realizations you have come to are very close to what I have been leaning towards when building things. Locality of behavior is really important for me. The only reasons I break it is if the same logic is needed elsewhere and should be aligned. When I have to read 4 different files to figure out what one functions does I get very angry and want throw laptop.
@blarghblargh
@blarghblargh 25 күн бұрын
when people do the "functional vs oop" thing, they are raising the problems with oop, then trying to come up with something to contrast it with. but structured programming wasn't en vogue anymore when these comparisons first cropped up, and functional programming seemed like the new hotness (despite being invented some time in the 50s through 70s). so fp got saddled with oop's baggage, being nominated as the next big island of thought to jump to. turns out neither is a good dogma, and they're just different ways to add abstraction to a program. abstraction can be valuable, but it comes with a set of ongoing costs. it should be deployed in hesitation, when it produces significant value in return, when you have a provable, reasonably sizable, and current burden that it resolves.
@Asto508
@Asto508 25 күн бұрын
I honestly don't believe that you only use inheritance very rarely. Every time you use an interface/abstract class, you are using inheritance. The Strategy pattern is one of the most useful applications of inheritance and it's rarely not useful at all. It enables you to swap out implementations in parts of your code that don't ripple through other areas and that alone makes it such a wonderful tool for long term maintenance.
@DarylMetzler
@DarylMetzler 25 күн бұрын
I think a big ding against SOLID is that theyre called "principles". Theres only one principle, and it is "manage complexity". Maybe these should be called "perspectives" (the name Lens or Optic already got stolen by the FP folks) And the perspectives are best understood by the outcome of violating them: - SRP: no god classes - O/C: avoid fragile base classes - Liskov: dont have your subtype do something completely different - ISP: no thousand method interfaces - DI: dont couple to dependencies. Ive seen time and again that avoiding this (decent, vague) advice, the worse and more convoluted the code gets.
@mgoonga
@mgoonga 19 күн бұрын
I work in a game engine project which was initially designed with SOLID in mind. At the beginning a lot of those abstractions just seemed unnecessary. However, as the project grows and becomes really big it starts to pay off! It is just a pleasure to work with such a project. For example the basic windowing system was changed two times already from QT to SDL and than to GLFW. Nobody new this would be so at the start. However, as the windowing code is abstracted in a separate static library and communicates with core through small interfaces like IInputObserver which calls abstract functions like OnKeyDown/Up etc. changing the whole windowing system takes a few hours and produces no bugs AT ALL! This is just a simple example. The whole project is like that. A big project created with SOLID in mind is a pure gem!
@SKULDROPR
@SKULDROPR 25 күн бұрын
Prime is so correct at the end there. (Almost) Always write out concrete versions of your classes, then go back and abstract them. It took me 10 years to learn this (I am a slow learner). This way you know what parts are repeated a lot, you can then tease them out and abstract them as needed. Your overall structure will make more sense from the first abstraction attempt, instead of doing it as you go along, where you can't predict your ass from your elbow.
@sasieightynine
@sasieightynine 9 күн бұрын
Could you please explaining this in more detail or refer an article that does?
@SKULDROPR
@SKULDROPR 9 күн бұрын
@@sasieightynine I didn't read it anywhere unfortunately. It is just a pattern that I learned to recognize after making the same mistakes over many years. I suppose an easy way of putting it is something like this: Start by writing your program in the dumbest, most straight-forward way possible. Iterate upon this and try to tease out any repeated parts and abstract them, but only abstract them if you NEED to. Don't just abstract things for 'the future', it doesn't exist. You are in for a world of pain if you go down this path. Instead, focus on the problem at hand, and possibly the most predictable outcomes if you have the resources to spare.
@optimisticenigma283
@optimisticenigma283 26 күн бұрын
Jesus these bots be saying anything, gosh
@FRAMEDSKATEKREW69
@FRAMEDSKATEKREW69 26 күн бұрын
Googles priorities are in the wrong area 😔 they can shadow ban us for saying cursed words but can’t do that with bots 😂
@_BonsaiBen
@_BonsaiBen 26 күн бұрын
Thumbnails ok tho 🤣😎
@electrolyteorb
@electrolyteorb 26 күн бұрын
i am a BSD enthusiast
@penewoldahh
@penewoldahh 26 күн бұрын
Jesus these bots be saying anything, gosh
@nikolaygruychev2504
@nikolaygruychev2504 25 күн бұрын
Jesus these bots be saying anything, gosh
@ReneHartmann
@ReneHartmann 26 күн бұрын
The problem with SOLID is that one needs a lot of experience to understand and interpet it in a way that's actually useful, but if you have this experience you don't really need SOLID.
@damdoumibou3ajaja338
@damdoumibou3ajaja338 25 күн бұрын
This is not a problem. This is true everywhere in software. Experience is key to everything. Principles written in books are worthless without it. That's why in his Book "Clean code". Robert C. Martin goes into extreme lengths to explain that we need to think hard about and experiment long with the SOLID principles he is proposing. Nowadays, they are just catchphrases used in interviews or in Pull Requests to make an argument...
@Dom-zy1qy
@Dom-zy1qy 25 күн бұрын
I kind of agree to a certain degree. Single responsibility and dependency inversion are pretty easy to understand and don't require much experience to benefit from.
@evancombs5159
@evancombs5159 25 күн бұрын
​@@Dom-zy1qy of single responsibility is so simple why do so many people, including the article in this video get it wrong?
@Justin73791
@Justin73791 25 күн бұрын
@@damdoumibou3ajaja338 Robert C. Martin recommends principles that can not be implemented well regardless how much experience you have. 12 lines per function is just the wrong foundation no matter how you apply it.
@owenreynolds8718
@owenreynolds8718 25 күн бұрын
I think of it as "SOLID adds no marginal value over what you already should learn". For example, that part where the article says "logic and a database in the same class violates SRP". Well, basic OOP already says to de-couple by slapping an abstract interface over the DB (if the project is large, mostly in the final state, and expects to swap out different databases). Thinking of that as fixing an SRP violation adds nothing useful. Likewise, learning about public-interface/private-implementation is worse if it starts with "here's SRP, now we're going a learn a technique to avoid it".
@grandeau3802
@grandeau3802 25 күн бұрын
There are basically three main (or meta) principles above all: KISS, DRY and No-Principle-is-Sacred.
@lifelover69
@lifelover69 24 күн бұрын
I generally agree, but I have worked on codebases that were a nightmare due to taking DRY literally :)
@georgehelyar
@georgehelyar 24 күн бұрын
DRY has its own problems and can lead to tight coupling so there's a balance to find there as well.
@Nightwulf1269
@Nightwulf1269 23 күн бұрын
Fully agree to KISS. For me YAGNI is important too. But DRY is a difficult one. I generally won't repeat myself implementing the same logic in different places for the same types. But e.g. having the same string at different places doesn't bother me.
@cod3r1337
@cod3r1337 23 күн бұрын
I'd say YAGNI is way more important than DRY
@Nightwulf1269
@Nightwulf1269 23 күн бұрын
@@cod3r1337 for sure! I try to concentrate on KISS and YAGNI for my projects as well in my day job and private projects. And, what I in addition to that absolutely hate is when people are writing code in different languages in exactly the same way. E.g. writing a microservice in Go with hundrets of dependencies as they would in Node or Java. Go is all about KISS and that is absolutely ridiculous!
@DeathSugar
@DeathSugar 25 күн бұрын
Generally Liskov principle states "dont let the tail wag the dog", so hierarchy of classes should be in sane composition with each other. Rust traits are the good example of following the principle
@almicc
@almicc 25 күн бұрын
I find it so annoying to have the question "hm, database isn't saving correctly, let me see what happened" and then I need to open PersistenceManager, DatabasePersistence, InvoicePersistence, and Invoice before I can start debugging. Thanks SOLID, very understandable! Worst part is you'll go right to Invoice and wonder where the database saving is, and so you need to search for Invoice and then you find InvoicePersistence and then you realize that there's no logic, it's an interface. Now you need to search for InvoicePersistence to find where it's implemented, then you find DatabasePersistence. And then turns out the bug isn't there, it's actually in some random file that calls invoicePersistence.save() and it turns out someone passed a FilePersistence to the wrong method somewhere else and so DatabasePersistence.save() was never actually getting called in the first place.
@jeffreybritton3338
@jeffreybritton3338 25 күн бұрын
Brilliant comment
@deloftie3619
@deloftie3619 25 күн бұрын
Yeah but you need to first ask yourself why are you doing any of that. It isn't anything to do with SOLID. You have separated your code base into small easy to test units and then didn't test any of them. If you have to instantiate the entire system to figure out where a bug is occurring then something has gone seriously wrong earlier in development.
@MaddieM4
@MaddieM4 24 күн бұрын
​@@deloftie3619 You say that like `saveInvoice(invoice, database)` would be difficult to test. OOP tends to be hostile to tests in my experience, because intractably bundling data and functions makes it very difficult to validate that the right side effects happened to the right objects at the right time. That's not me arguing for FP, but a strict separation of data and logic is literally always healthy. I also, and I say this as a huge fan of testing, warn that your test suite will entrench any structural status quo that you test. This means that structural methodologies that cause large sprawling implementations (like OOP) will become calcified by your test suite. If you do try to refactor those abstractions later to be less cumbersome, you'll be glad the tests are keeping you safe, but they'll also double the effort of the project, and that's the trade-off.
@volvo340variomatic9
@volvo340variomatic9 24 күн бұрын
@@deloftie3619 In my experience, the nasty bugs are between layers (of abstraction). Unit tests are fine, but automated integration tests that cover multiple layers (e.g. from UI to database and back) can be gold.
@deloftie3619
@deloftie3619 24 күн бұрын
@@MaddieM4 "That's not me arguing for FP, but a strict separation of data and logic is literally always healthy. " The problem with that is that in large systems the code becomes tightly coupled data pipelines that are very hard to change. Imagine it like stringing together a whole load of Linux commands with pipes and then deciding a few years into production that actually the data format between two of the pipes needs to change. In OOP you are trying to, as much as possible, get rid of "data" as a separate concept to "behaviour". This obviously can be hard to achieve, particularly if engineers are used to thinking of systems as data pipelines with procedural functions manipulating a piece of data and then passing it on. But if you can crack it you find you can open up your system to be much easier to change and evolve. And all the SOLID principles are doing are showing how that can be achieved.
@andrewshirley9240
@andrewshirley9240 25 күн бұрын
OOP is pretty bad when you build something under the philosophy of "I want this behavior to be standard everywhere" but then it turns out that behavior varies slightly and need independent implementations that you're trying to wildly tie together in dumb, complex ways. Procedural is bad when you say "I'm just going to build what needs to be done" and then you end up with a system where changing one flag means you need to track down 30 different places in code to add the same if statement in every independent implementation and everything burns down if you miss one. As prime says, it's all intuition, you're going to need to be able to make reasonable assumptions about how a particular problem is likely to evolve as it grows, and use the correct approach accordingly.
@Asto508
@Asto508 25 күн бұрын
Your first sentence is literally what OOP is not about. One thing that OOP tries to solve in an elegant way is the need for polymorphism, so exactly that you need partial different behavior within an otherwise same-behaving object. It's exactly one of the strengths of inheritance to allow specializations that stray away from the generic inherited parts. It's the whole point to allow easy modification for "non-standard behavior" instead of creating a whole replica that only differs on a miniscule level to its parent.
@techsuvara
@techsuvara 25 күн бұрын
Being too stubborn with the "this should be standard everywhere" will absolutely be a terrible idea. You need to be flexible.
@defeqel6537
@defeqel6537 25 күн бұрын
Sounds like your understanding of OOP is missing an understanding of the Single Responsibility Principle and Open/Close Principle
@AloisMahdal
@AloisMahdal 20 күн бұрын
"track down 30 different places in code" -- lol, and you wish it's just in code, and not in DB schemas, logs, maintenance scripts running on some forgotten raspberry shoved in between drywalls, frontend (JS *and* CSS). say, adding a message severity level seems trivial but it can become a *real big adventure*[tm] real fast. or worse -- slow, with bonus side quests such as angry customers or dozens of people standing around awkwardly in warehouses being paid for doing nothing because what? you did *not* know that `danger` is a valid severity? you were naiive to think that it looks like enum, quacks like enum, but no oh boy this string is free like the bird and yes the whole frontend went down because, and only because you did not fall back on unknown string when f**ing switching style=`color: ...` in Vue? (i know, weirdly specific -- it did not happen in production to me but it drives me up the wall how easy it is to make exactly that mistake, when working on "hey do not over-engineer me" kind of codebase)
@AloisMahdal
@AloisMahdal 20 күн бұрын
@@Asto508 aside, but I recommend Christopher Okhravi's last video on this topic, "Only Use Inheritance If You Want Both of These". i love his channel, especially the last "wave" -- he came back after a long hiatus and now he's just killing it with much smaller and focused videos
@splitpierre
@splitpierre 25 күн бұрын
Now THAT was SOLID video. Thanks Primeagen, I've been coding for about 10 years now, have read about SOLID before, but I've never fully agreed to all principles, I like going with the flow, just like you, start with concrete and hands dirty right on, then I take a sense on what actually needs to be abstracted and move on, thing is I thought I was a poorer programmer cause I don't fully agree with SOLID, this video gave me a lot more confidence as I honestly agree with practically all the arguments you brought. Being a good programmer is finding a balance in between strong principles and compromises, for the overall benefit around the application being built, our mental health, our future-self, project turn-over, quality, maintainability... a balance in speed and quality.
@muslim8622
@muslim8622 25 күн бұрын
Hi Prime, generally I like your take on programming, but on this one, I kind of disagree with some of your points. The Single Responsibility Principle might seem like overkill for a small project and I agree with your stance, but as the project grows and its components become critical and sensitive, separating concerns becomes more valuable. This helps to prevent one part from crashing the entire system. For example, if the rendering layer crashes because of issues with the cache, it doesn't make any sense. The Liskov Substitution Principle isn't about advocating for inheritance per se, but rather highlighting some of its challenges. Classes should be inherited based on their behavior rather than just their properties. If class A inherits from class B, we should be able to use B wherever A is used. In this regard, using composition instead of inheritance makes sense. Using an interface or trait enables us to define a contract for class behaviors, so if A and B used interface/trait, they can be exchange As for the Open-Closed Principle, I don’t think there can be a valid argument against it. As you are saying everyone uses the strategy pattern, everyone uses the Open-Closed Principle. "Closed" refers to consuming an API, while "open" pertains to building this API. When we say "closed," we imply that the main logic of our application must be “stable” and our main free from considering implementation details. For example, when I use a library, an API or even a (high-level) language, I focus on the algorithm; I write it, my logic is correct, so my code is completed. If there's a bug or a need to optimize the tool, change the database, or tweak something under the hood, it's not my concern-it's implementation details. And if there’s a new feature landing on the API, it’s good. But the main logic of my application shouldn't change because of such changes. My general stance in programming is just don't over-abstract, don't jump the shark. There're good patterns and good practice but not always necessary.
@LyleChristine
@LyleChristine 12 күн бұрын
Very well articulated and I agree on your critique.
@UNgineering
@UNgineering 25 күн бұрын
"single responsibility principle" doesn't mean the class should only do one thing (although uncle Bob argues for that too), it means it should only be beholden to a single stakeholder, i.e. it should only have a single reason to change. but you're right in that this isn't the law, if it makes a small app way more complicated for the sake of adherence to SOLID, then it becomes counterproductive. Liskov is for Barbara Liskov :)
@Arcwise
@Arcwise 25 күн бұрын
Finally someone who gets it. The biggest problem with SOLID is that it is being misunderstood at the most fundamental level.
@Sc0nes
@Sc0nes 25 күн бұрын
Gather together the things that change for the same reasons. Separate those things that change for different reasons.
@halim7725
@halim7725 25 күн бұрын
Exactly. The architecture of your software should mirror the business units of your enterprise depending on it, or the diversity of your stakeholders in general.
@chickenmonkey88
@chickenmonkey88 23 күн бұрын
"beholden to a single stakeholder". Have you thought about what that means critically?
@shawnington
@shawnington 5 күн бұрын
@@chickenmonkey88 your mom
@TECHN01200
@TECHN01200 26 күн бұрын
My gut feeling is have a tendency to under abstract because abstracting from a concrete state is easier than to make concrete from an abstracted state. It almost always is a one way road.
@steamer2k319
@steamer2k319 25 күн бұрын
Regarding pre-emptive abstraction: You Ain't Gonna Need It ...until you do... But most people only get ~5% of such predictions right--which leaves ~95% useless, brittle, noisy wasted-effort if allowed into the codebase. As Prime said, by the time you have proof that the abstraction is needed, it's easy to extract out exactly what's needed from your initial concrete implementation.
@Asto508
@Asto508 25 күн бұрын
I think those numbers are not really reflecting reality. Or maybe they do and I'm just biased. Depending on the domain and personal experience level, you can more or less safely predict future requirement changes and plan where abstractions might be needed and where not; and if you needed them in hindsight, you are glad that you prepared for it when there was plenty of time.
@steamer2k319
@steamer2k319 25 күн бұрын
@@Asto508 The percentage definitely goes up with experience but it's also definitely low for juniors. One of the most significant ways seniors increase their odds is by simply making a lot fewer baseless assumptions/predictions. Software engineering is fairly easy to change on short notice, especially if you're familiar with e.g., JetBrains' refactoring tools and also if the code sticks to what's actually needed / in-use. What's hard to change on short notice is architecture/infrastructure so it is good to get that as right as you can up front. Still technology is complex enough that the first #83 features of a platform will align really closely with your requirements and then six weeks in you try feature #84 and find you got bit in the @$$ by it's marketing. Then you transition onto platform plan B because the large gap it has on feature #6 is actually easier to close even after re-implementing 🙄.
@defeqel6537
@defeqel6537 25 күн бұрын
@@Asto508 it also heavily depends on whether the code is contained or spread through the code base like cancer, and on the flip side (somewhat) if there is some "god class" thing going on
@Asto508
@Asto508 25 күн бұрын
@@defeqel6537 If the code has a high coupling, then that's just an example of doing it wrong and doesn't have much to do with pre-mature abstraction
@defeqel6537
@defeqel6537 25 күн бұрын
@@Asto508 I agree, but your abstraction may be the interface of the concrete implementation too. As long as there is a single piece of code handling the functionality, it is simple enough to extract a polymorphic abstraction later on.
@zbyniew
@zbyniew 25 күн бұрын
Your enthusiasm is infectious. Love the content, man
@ThundersLeague
@ThundersLeague 24 күн бұрын
I really love those SOLID arguments of "Well if I add a Printer interface now, _when_ I will need to add a Database Printer, it will be just implementing this interface". And then: - 99% of the time this reality never comes because business priorities change, or your project gets cancelled because you spent way too much time trying to come up with the proper abstraction instead of implementing business value - 0.9% of the time it does come but you still need to refactor it anyway because printing to a log file vs printing to a database is different enough that you couldn't anticipate everything - 0.1% of the time you actually created the right abstraction, but even then you spent 2+2 hours upfront on the Printer interface + FilePrinter, and another 1 hour later on the DatabasePrinter, vs 2 hours upfront on only the FilePrinter, and 2+1 hour later on the Printer Interface + DatabasePrinter.
@ProfMonkeys
@ProfMonkeys 25 күн бұрын
The comment about knowing when to abstract and when not to abstract really resonated with me. My sense is that the SOLID principles become more valuable as your app gets larger and more complex. When you are first writing a small app, many of the principles cause more problems than they solve. When it is easy to execute on them, great, do it. When it is awkward or difficult to do it, wait until you actually have a need to actually do them. Many times, the best choice is to just be mindful about how you can avoid closing doors on your design unintentionally.
@markemerson98
@markemerson98 25 күн бұрын
locality of behaviour is a thing - if you have to reach outside to a wider radius from where your working then your cognitive load shoots out the park - so to speak - which seems counter intuitive of the principle that we want our code to be easier to read and understand
@deloftie3619
@deloftie3619 25 күн бұрын
This is the problem that we are stuck in this cycle of someone writes poor code and then someone else has to debug that code and find out why it isn't working. So everyone is constantly trying to understand what the hell the other person wrote. At this level having a procedural style "everything is happening in this one function" approach makes this easy. The problem with that is that you end up with a God awful mess at any abstraction higher than the specific bug or issue the programmer is trying to fix. These apps become balls of mud, where fixing specific problems is trivial but any larger change becomes almost impossible. So the cycle becomes an app that it is easy to fix what your buddy wrote a day ago but you have to throught he whole app out every few years and start again. Developers are so used to this cycle now that they see anything else as an impossible utopia
@raccoons_stole_my_account
@raccoons_stole_my_account 23 күн бұрын
It's almost like people who created SOLID are in the business of consultancy aka never actually solving any problems because they need a next paycheck. Imperative programming is very easy and straightforward, once you know your problem and your program, you map one on the another. OOP is a cult where to solve a problem you need to travel to a shrine, pay a high priest a bribe, burn incence to the gods, hope for ten years and then interpret random events like proof it did actually work. Guess which one corporate parasites prefer.
@ionuttiplea4666
@ionuttiplea4666 24 күн бұрын
After watching your videos for a while, on topics like this and more, now I can have arguments with my Senior Colleagues about stuff related to this, and man that is a lot of fun. Related to this video's topic, I actually happened to stumble into a bad abstraction, and because of your videos I was able to identify that it was bad Keep up the good work @ThePrimeTime
@pseudocoder78
@pseudocoder78 25 күн бұрын
I think ThePrimagen should push his new paradigm: SOLIDR, single responsibility, etc, etc, etc and then R for "If all else fails just RAW DAWG IT IN THERE WHEREVER YOU WANT"
@XKCDism
@XKCDism 25 күн бұрын
In my experience there are VERY few hard rules or principles one should follow, but a lot more guidelines. When I first started programing my OOP inheritance tree would make the Habsburgs blush. And then during the functional renaissance I tried to use it everywhere and it didn't work out. because a functional approach didn't fit the problems. Remember paradigms serve us to solve problems we don't serve paradigms, use the right tool for right problem and don't be dogmatic. Some problems are easily solved by inheritance, or composition/interfaces, or a functional approach. And experience and your personal discretion will help you make that right choice.
@jakubrogacz6829
@jakubrogacz6829 24 күн бұрын
Because all of them are solutions but also constraints on otherwise possibleto calculate code. Same as languages, ideal one would allow me to do anything, best up to declaring new keywords andsemantics if I need to while preventing me from usinng that on accident.
@n8ged8
@n8ged8 16 күн бұрын
Totally agree to all the statements in this video! Before you start programming you have to think about what you want to deliver. Do you want to build code that is very flexible and general because it will be part of a project that changes the next 10 years or do you want to deliver specific code for a specific problem that will not change. I almost always choose the last solution which means less code, less (abstract) thinking and less effort regarding time spent which means being very efficient and very cost effective. And this year my new friend ChatGPT solved some annoying or complex coding problems for me (but you have to know how to use this tool) so this makes it even more efficient.
@jjurksztowicz
@jjurksztowicz 25 күн бұрын
Inheritance is just one way to implement polymorphism. If you need polymorphism, then the complexity will accrue somewhere, in the class hierarchy, a switch statement, or elsewhere, you can't really avoid it.
@defeqel6537
@defeqel6537 25 күн бұрын
Clean Code actually has a decent section on this: "Data/Object Anti-symmetry"
@canepaper967
@canepaper967 20 күн бұрын
For every rule in programming there are exceptions. I prefer to look at writing code as just a selection of rules of thumb, where there are preferred ways to do it and non-preferred ways that are ranked in order of most to least appropriate. But sometimes you have to select the thing at the bottom of the list because that's the only way you can reasonably implement it. Sometimes a function HAS to do more than 1 thing for efficiency reasons because otherwise you'd be looping through the same data multiple times. Sometimes a function HAS to return more than 1 value for that same reason. As long as you understand the code this is perfectly valid.
@flannn6
@flannn6 25 күн бұрын
It is really cool how you understand the ideas behind each language. As a go developer i feel well represented by you =)
@ssamani24
@ssamani24 25 күн бұрын
2:06 This is the main point. Using SOLID principles is great and all but if you’re implementing abstraction after abstraction where the readability, testability, and maintainability suffers, it means you need to scale back and refactor. But more often then not SOLID principles can help you achieve those goals but like many other aspects, developers can take things too far. It’s the old adage “if all you have is a hammer, everything looks like a nail” (and that’s how I feel about functional programming also)
@Dan_Diaconescu
@Dan_Diaconescu 26 күн бұрын
your voice is smoother since quitting Netflix, faang bad for health confirmed
@sournois90
@sournois90 26 күн бұрын
oh i didn't know he quit
@mamneo2
@mamneo2 25 күн бұрын
Incroyable.
@TheArrowedKnee
@TheArrowedKnee 25 күн бұрын
He quit?
@abelnagy9877
@abelnagy9877 25 күн бұрын
@@TheArrowedKnee yup
@rupertsmith6097
@rupertsmith6097 25 күн бұрын
You can do SOLID in functional programming too. Interface = higher order function.
@jaymaj21
@jaymaj21 22 күн бұрын
I feel that the real problem is the appropriation of existing connotation-laden english words like clean, or agile, or solid. If he called it Robertist Code instead of Clean Code, or Martinist Manifesto instead of Agile Manifesto, or UncleBobist Principle for solid principle, I would have nothing against it. Just imagine how creepy it would be if religions were named using existing everyday words - say if we had to use the word "genuine" for "Christian" or "honest" for Hindu and so on.
@CaptainWumbo
@CaptainWumbo 24 күн бұрын
I think the sad thing is a lot of the time that "amateur" 300 line function we wrote when we started is where we come back to when we realise having 1000 lego blocks all over the floor is not nicer than having one lego millenium falcon. Your lego blocks are the primatives of the programming language itself, the for loops and the structs and whatever. You don't need to make your own weird duplo blocks.
@kashperanto
@kashperanto 24 күн бұрын
It's funny, because the original meaning of "single responsibility" was that the code is responsible to/focused on the needs of one person/stakeholder/user, and has *nothing* to do with how the code is literally structured. From Wikipedia (but I heard this elsewhere, too): "The single-responsibility principle (SRP) is a computer programming principle that states that "A module should be responsible to one, and only one, actor." The term actor refers to a group (consisting of one or more stakeholders or users) that requires a change in the module."
@isodoubIet
@isodoubIet 23 күн бұрын
That's a remarkably useless principle.
@ITPMMentor
@ITPMMentor 26 күн бұрын
Appreciate the solid reflections on this topic. Hard to get inputs from practitioners sharing examples of how to effectively apply these principles in the real world
@james.lambert
@james.lambert 25 күн бұрын
My first rule of programming is write reusable code. Reusable code makes it easy to not repeat yourself, it is easy to "reuse" in tests to verify it, it is easy to reuse existing code when refactoring into new abstractions. After finishing a function or class if you have a hard time imagining that thing being used outside of the specific use case it was written for then you should rethink the design.
@scoutchorton
@scoutchorton 21 күн бұрын
17:17 “you abstract when you realize the abstraction” Love this principle. I’m building some Rust code to translate data between two programs, including a common format I made to make processing easier. During that process and discovery of how the two applications have their data formatted, I’ve discovered ways I can abstract and make common functionality between the two. I didn’t start with that, but discovered it as I realized two things worked similarly. Also the abstractions under Single Responsibility are totally not needed and the exact reason why I hate Java. I shouldn’t need 5 classes to read a text file
@saheemsiddiqi3220
@saheemsiddiqi3220 25 күн бұрын
I feel SOLID applies well at the overall class design level, but it starts to become a problem if you need to defer to these principals, line by line or property by property of a class. Take OCP. The first thing you need a clear understanding of is if, by design, you want the class to be extensible. If the answer is no, then relax the need for abstractions. SOLID needs to be applied in the context of an architecture, where you really want to focus on these principals where "parts" of your architecture interconnect, but within...you can afford to be a bit fast and furious with how you code things. And if you're wrong, then refactor.
@wtfusernamecrap
@wtfusernamecrap 3 күн бұрын
Thanks, fully agree. It's pretty wild to advocate for abstractions in a world where many coders can't even name a function properly, let alone prevent the name from being a straight lie after the third implementation change. Write a straight forward solution. Write it a few times. Get the functionality right. Get the performance right. Profile. Discover where abstractions can be of use and implement with care. Profile again. You know how to profile your project, right? Make conscious decisions based on the reality of your project about which actions and abstractions benefit your. specific. project. That's the only thing that matters. Also, a project driven by a single person will drastically differ from a codebase maintained by a thousand people. It most certainly did not enter this world looking like the latter, for very good and important reasons.
@blubblurb
@blubblurb 16 күн бұрын
When I went to make my CS degree we had a Software Architecture course and of course SOLID was teached. After that I tried to do it right, apply it wherever I can use clean architecture etc. I was so hard trying to do it right that I couldn't get done anything anymore. After a while I stopped caring and just tried to solve the problem with the simplest solution I could bring up. Productivity is way higher, the code is IMHO better too. At least if I work with other people they are able to make changes in my code that's a sign to me that the code is good enough.
@YaserFarid
@YaserFarid 23 күн бұрын
Totally agree with you, I like my program with very minimal classes, otherwise, it gets confusing really fast. I can have classes (as I make the embedded programs most of the time) LCD_Display class, Communication, GPIO, sensors, that is it, I would not add extra things to make it more confusing.
@MrSpyTubes
@MrSpyTubes 25 күн бұрын
SRP means that the module should have one reason to change. Meaning that if the marketing comes with a request for change and the finance comes with another one no single module should need to change for those two requests, but rather two modules
@Daniel_Zhu_a6f
@Daniel_Zhu_a6f 25 күн бұрын
there is a better idea: to organize modules as you need for testing, hot reloading and efficient development in general, without trying to solve unsolvable questions like "what is a single responsibility?". if the program is simple and small (5-10K loc), you can just dump everything in a single module.
@defeqel6537
@defeqel6537 25 күн бұрын
*at least two
@isodoubIet
@isodoubIet 22 күн бұрын
"Meaning that if the marketing comes with a request for change and the finance comes with another one no single module should need to change for those two requests, but rather two modules" That's completely unworkable.
@blubblurb
@blubblurb 16 күн бұрын
@@isodoubIet Exactly. It sounds nice in theory but never happens in practice. And What @Daniel_Zhu_a6f says is also true, define "single responsibility". Sounds easy but it's not. You will abstract way too much to reach that unreachable goal.
@zootsuitpenguin
@zootsuitpenguin 25 күн бұрын
Ive always felt bad that i typically ‘script’ much in the way that i see you’ve done here taking the tradeoff for ease of writing vs strictly adhering to these principles, glad to see I’m not the only one! #gatekeepingprogramming
@PurpleSheeep
@PurpleSheeep 25 күн бұрын
Hey, SOLID isn't a set of laws its a set of principles
@tylerbreau4544
@tylerbreau4544 25 күн бұрын
About SOLID programming being good but preferring to be loose and not a requirement. I think this also applies to programming paradigms in general. Yea, you can program every single thing strictly following OOP. Or you can realize, this little thing is only in used by this 1 class and can be a single function. This little task doesn't even need its own function. Paradigms and these approaches to organizing code or guidelines, they're all tools. A good programming knows which tool to use for a particular task. As a general rule of thumb, yea single responsibility is a good idea. On the job, you're balancing readability, time to write & design, effectiveness, maintainability, performance and whatever other things I missed.
@firetruck988
@firetruck988 25 күн бұрын
Here's my design principles: Make it as simple as possible without compromising function. All other design principles are sub to this, and are used when they support simplicity in a given context.
@defeqel6537
@defeqel6537 25 күн бұрын
If you have 2 pieces of related code with very similar functionality, which is the simplest: to use shared data+code for the similarities, or to implement them separately?
@strider5245
@strider5245 24 күн бұрын
I love Prime, I used to call it: this is over engineering. Or why are you giving me a spoon larger than my soup bowl?!
@TysonLondon
@TysonLondon 25 күн бұрын
Amen, "you abstract when you see the abstraction" 🙏
@LusidDreaming
@LusidDreaming 25 күн бұрын
Imagine getting credit for just creating an acronym for someone elses work. Its like the Maclaurin series in math.
@MarkWilds87
@MarkWilds87 22 күн бұрын
Developers usually tackle their problem with technical first, functional later. Instead it should usually be functional first, technical later. But getting to understand the functional part of your program is really dependent on soft skills, communicating, etc... ughhhhh Basically what Prime says at the end: "Refuse to abstract what you think you need, instead build the thing you know you need". ~Prime: "You abstract when you discover the need of the abstraction."
@joejoesoft
@joejoesoft 25 күн бұрын
This is the classic YouArentGoingToNeedIt argument of Extreme Programing. I used to spout the "gospel" of XP early on until I understood it's major flaw - the refactoring nightmare. A collection of DoTheSimplestThing turns into an unreadable and unmanageable mess so slowly, you often don't see it until the fixes are enormous. The hidden part of "DTST" is that you have to refactor as you go, and knowing when to do this isn't trivial. This is the hard part. SOLID it kind of the opposite. The SOLID approach requires a fantastic base to even work. There are few people that can design a non-trivial API/Library/OO base that's flexible, easy to extend, and doesn't need to be changed. This is the major flaw of the paradigm; bad choices early on tend to become permanent.
@zwerko
@zwerko 25 күн бұрын
#1 Rule of Acronyms: If you encounter one that's way too convenient, 99% of the time it's a reverse acronym (acronym in search of a meaning). You should never follow principles derived from such acronyms.
@spikedgav
@spikedgav 9 күн бұрын
We could totally mess up the authors day (and get them to think about what they're doing) by telling them that on tuesdays, wednesdays and thursdays, customers get a free bookmark with any purchase of 2 or more books. NOW they have to actually think in terms of abstraction and might have to write a new article about business logic
@Sharp-E
@Sharp-E 25 күн бұрын
00:01:22 Robert J. Martin?? It's Robert C. Martin. Article credibility out the window right from the start. 🤦‍♂️
@DanielMPries
@DanielMPries 24 күн бұрын
I teach it like this. Writing software is a lot like music, we learn foundations and guiding principles, structure and theory. Once you developed mastery in those areas, go ahead and break the rules. That's where the magic happens. But I'll be easier to ease back into the foundations if things go sideways than it will be to establish foundations when you started out without the rules in mind. Much like art, negative space is also important. It's ok to leave things out. You don't have to be comprehensive if code is going to be unused. Worse yet though is someone who refuses to know the rules. They can be dangerous contributors and toxic collaborators
@mattetis
@mattetis 24 күн бұрын
Misunderstanding Liskov. **Implementing an interface is subtyping.** Passing an object which implements an interface to a function which expects said interface, and expecting the program to work, is the Liskov substitution principle. It just happens to be that inheritance is also subtyping of the base class. Using abstract classes as the interface is the problem.
@RobRoss
@RobRoss 20 күн бұрын
Designing classes to be inherited from is *hard*. It takes effort and skill. Java has new features that help with this. They have default methods for interfaces. So you can add new API (methods) to an interface, and specify a default behavior (implementation), so you don’t break any classes using the modified interfaces. And now Java has sealed classes, which let you control what classes can inherit from a class. You can lock down your inheritance model to prevent problems down the road with people using your class and being brittle to changes in the inheritance hierarchy. And you can allow one specific class in your hierarchy to be inherited from and you design that one class for inheritance. Josh Block has a chapter on designing classes for inheritance in “Effective Java.”
@wforbes87
@wforbes87 20 күн бұрын
the last year I've been dealing with a project of like 16 microservices in typescript, all using really dense solid patterns... every opportunity to use an interface or a factory was taken, even if there's just a couple entities involved. Want to add a new database table? get ready to write 7 code files to follow the pattern. want to find a bug? get ready to drill down through layer after layer of abstraction. I mean, the code can be scaled out into infinity and beyond, with multiple teams working on it happily... but its a 300 user internal app with a pretty limited scope, and like one or two developers. I've really come to absolutely worship simplicity.
@heavenaldrico
@heavenaldrico 25 күн бұрын
3 seconds in, true.. my only problem with the SOLID principles is that I forgot what they stands for few hours after reading about it
@TurtleKwitty
@TurtleKwitty 25 күн бұрын
Inheritence is really nice for UI/renderable framework, being able to define a simple say 2D renderable rectangle and then let subclasses figure out the rest of the details themselves without the framework doing more work makes implmenting it a LOT easier -- BUT -- inheritence/OO definitely gets shoehorned into a lot of stuff that doesnt belong for sure
@TheTubeYou251
@TheTubeYou251 10 күн бұрын
Liskov doesn‘t say that you want to have a lot of subclasses. It just says that if you write a subclass, you better don‘t do unexpected things there that breaks code which codes against the base class. If you never write any subclass, you trivially follow the principle.
@fabyao
@fabyao 17 күн бұрын
I personally find the SOLID principles useful. When one works in a large team with a large code base, without any design and code quality agreements, the code-base can quickly turn into spaghetti code and mixed concerns. When done properly, SOLID allows you to replace any bottleneck or compromised part of the system with minimum effort. As a concrete example, there was a vulnerability found in a third-party logger library. I believe it was a Java library. With SOLID, replacing the affected library is done in one place with ease. Unfortunately, most developers use logger libraries directly without programming to an interface. This means finding all the instances in your code-base to replace it. As a Software Engineer, I strive to implement code that welcomes changes without going down the rabbit hole of a major code refactor. SOLID is one way to achieve this. Unless your are experimenting and not seriously thinking of a "production ready" code, I would argue that a design principle whatever it might be must be carefully considered. The idea that one can write "dirty code" and refactor later to "clean code" is, in my humble opinion doing the job twice. A good analogy is trying to build a house by having a "quick and dirty" foundation which will be revisited after the house is built. If the house is still standing
@cod3r1337
@cod3r1337 23 күн бұрын
I think SOLID is a useful starting point to teach beginners to start thinking more carefully about the structure of their code. Just be absolutely clear that those "principles" are not to be treated as dogma but rather as little nudges to get the thinking process started.
@ErinCollective
@ErinCollective 25 күн бұрын
the only time i ever use inheritance is encapsulating logging into errors and creating a typed instance of a generic typed interface, like something becomes somethingInt : something
@assombranceanderson6175
@assombranceanderson6175 25 күн бұрын
Currently working on a medium project which would probably be very annoying without inheritance. I'm handling instructions of several types, and operations on these instructions. Avoiding standard inheritance would just lead to emulating inertance by having a type hierarchy hardcoded for each subtype of instructing...
@Asto508
@Asto508 25 күн бұрын
I honestly think the "conflict" comes from people only looking at it from a pure coding point of view vs a maintenance point of view. The more you have to maintain existing code bases, the more (well thought) inheritance pays off and you are glad that you only need to touch this tiny part over here instead of re-writing 50% of the code base over there because your predecessor thought abstraction is just a waste of time.
@vanstanian
@vanstanian 25 күн бұрын
A comment on Liskov principle: is just about behaviour responsiveness. I mean, if you have an interface and multiple implementations on it, you have to expect a consistent behaviour. Sometimes in Java (a fundamentaly broken languaje bc of being older), you have some trouble dealing with some types as Lists. I found that when you use unmutable lists, there are functions that exists in the interface like f.e. .add() which throws an exception, violating Liskov. That becomes a pain in the ass in the moment you realize that the behaviour is different from the ArrayList. Liskov talks about what you should expect with assurance about an abstract type, just to do the life of other developers easier as possible.
@JacobSantosDev
@JacobSantosDev 25 күн бұрын
1. One should not start their design with SRP. Start with DIP or ISP. Or better with an implementation and start seeing where patterns are established and contracts can be formed. 2. All subtypes inherit, including when implementing interfaces. It is just that you can only satisfy LSP when working with interfaces. Just like OCP does not necessarily imply inheritence. 3. Bro needs to find DDD.
@bigpest
@bigpest 26 күн бұрын
Abstractions like the ones SOLID calls for make you *feel* like you’re making things easier and more maintainable. Really, you’re just hiding the actual function of your code underneath a coat of pretty paint.
@playthatsoloboi3705
@playthatsoloboi3705 25 күн бұрын
hmm, that depends actually
@LusidDreaming
@LusidDreaming 25 күн бұрын
I feel like this is very true for single responsibility. One thing that is rarely noted is that separation of concerns is mutually exclusive with locality of behavior. So you look at a small class that does only one thing and think "oh, this is simple to understand." But then you start actually working with the codebase and realize that a single process will span several files and contain several layers of indirection that make it very hard to track the actual control flow (made even worse if you add inheritance). Conversely, procedural code with high locality of behavior often looks ugly and disorganized, but when working with it you realize its very easy to read and understand all the code paths. There are tradeoffs with both, but I personally consider locality of behavior to be the most important, and only move away from that of testability becomes an issue.
@Asto508
@Asto508 25 күн бұрын
That's only true if you're doing it wrong. There is overengineering and pointless abstraction, but there is also the opposite that is equally bad. If an abstraction is not serving a real (foreseeable) purpose, then it's just a useless layer and simply a wrong application of what abstraction is supposed to solve. The hammer isn't bad because you try to drive screws with it tbh.
@broadestsmiler
@broadestsmiler 25 күн бұрын
You robbed my face. Please give it back. :(
@mirkogeffken2290
@mirkogeffken2290 25 күн бұрын
Yes that is the very foundation of the principles. You want to hide complexity and avoid change until you need to dive deeper. There is a difference between algorithmic and domain complexity. You want to make it easy to understand code and avoid change to hard things while keeping comprehension at a high level. This is a hard problem to solve, but optimizing on readability is mostly correct until you need to optimize. His video is spot on to evolve towards this balance. You are 99.99% going to get this wrong up-front. Don’t whiteboard it, build it, then optimize as needed. None of the fundamentals of SOLID are wrong, just know when to apply and a need to know when to violate them. They aren’t prescriptions, they are guiding principles.
@rusmaakatupal4723
@rusmaakatupal4723 25 күн бұрын
Nice voice and tone game. Is this the pilot speaking ? May I ask you the weather forecast for the next video ?
@hanseichel4327
@hanseichel4327 25 күн бұрын
so where can i play this tower defense game? have some ssh credentials or how do you run that? :)
@frydac
@frydac 24 күн бұрын
SOLID doesn't say you HAVE to follow the dogma without critical thought and any violation is inherently bad design, uncle bob or any decent resource on the subject doesn't say this afaik. They are design 'principles', not design laws. I learned a lot by studying SOLID when I was a newbie, they give you a way to think, a way to spot what could be the underlying issue when you start repeating things you shouldn't and introducing dependencies in a way that you feel will make you regret later on, they are a tool to use in certain situations. Before I studied SOLID I felt things were going wrong, but didn't know why or how to deal with them, and solid gives at least some kind of answer (of course it's not complete) that may help in a given situation. They give you a names to use when discussing design with your team, like design patterns: "maybe we can use this or this here? Oh no, this or that requirement probably makes it a bad idea". or "When we do that we are violating this or that principle. Yeah, but it's ok because the chance of this becoming an issue later is very lo. Ah yes indeed." are possible/viable conversations one can have and are probably better informed and get better results when you know about the principles/patterns. 'There are no zero cost abstractions' (by chandler carruth cppcon2019) is also a principle that should be weighed when thinking about introducing an abstraction, everything is a cost-benefit trade of. And of course you don't apply things everywhere, of course, noone sensible ever told anyone that this is the only correct way, which is usually the sense I get from ppl 'against' solid or clean code or design patterns, I think they are reacting to the ppl that interpret these principles as laws/dogma and try to force them on other ppl, and not against the principles themselves, as all of them (afaik) can be applied in a way that makes things better in the right circumstance, and there is significant value in learning about them. Anyway, I got baited again into commenting, so job accomplished I guess... 'sigh'
@joebowbeer
@joebowbeer 18 күн бұрын
The most important principle is to maintain a low cost of change. SOLID attempts to avoid design blunders that can increase the cost of change.
@janwilmans5954
@janwilmans5954 23 күн бұрын
LSP is not just about inheritance, it can also just be the function interface of a strategy pattern; maybe some languages do not handle that very will, but for example in C++ it works really nice.
@dripcode2600
@dripcode2600 25 күн бұрын
code to interfaces -> SOLID -> Software Design Pattern (Why do this? Assists in good automated testing. Why automate test? Automated Test are like the business logic compiler.) Why are good test important? To avoid South West Airline software crash embarrassments and costs.
@OneAndOnlyMe
@OneAndOnlyMe 5 күн бұрын
Nah, definitely should have a separate InvoicePrinter class to handle printing 🙂 In my real world enterprise, SOLID applies very much, especially open/close. Mainly because we are at a point where we can build solutions that leverage utility computing services, so decoupling code for quick and easy extension of a persistence manager is very useful, for example, we might use an AWS implementation of a service today, but next month we want to switch to the GCP implementation, in large enterprise where we're continually looking for cost efficiency, we would do this kind of thing quite often. When you're a long term employee of an organisation and you know how the organisation works, proactive abstraction can be easier and saves time.
@andreaslofkvist25
@andreaslofkvist25 20 күн бұрын
Is there any actual performance advantage to using dependency injection or interfaces instead of just creating objects from classes if that's the only thing the dependency injection does?
@Meteotrix
@Meteotrix 24 күн бұрын
The conclusion sounds like KISS YAGNI to me, i like it because those are my favorite principles :D You can think ahead of time but you shouldn't implement ahead of time, write what you're the most sure you'll need first, don't /commit/ to designs until later once you understand the problem better (it's hard & rare to know the entire problem ahead of time, might as well just code loosely to figure out the problem as you go). But i'm a solo game dev and not building enterprise space stations. Also I looked up SOLID principles recently, and all i concluded was "don't write giga classes" and "use wrappers", but my own xp says "try to stick to 1 abstraction layer max, not 3+".
@efkastner
@efkastner 25 күн бұрын
30:40 this!! it’s the spidey sense that you might want to extend later, but enough experience to hold off. you don’t make it impossible to extend, but you also don’t try to make it extendable in every possible dimension
@szirsp
@szirsp 25 күн бұрын
18:00 Yeah, I agree with this. Preserving locality until you need to break it apart makes the code more readable, easier to understand... and while it makes it harder to test, it also makes it less error prone. Imagine invoice introducing a new field. Now you have to update all your saveToFile and print methods. If it's in a single class, it is relatively easy. If you have interfaces... good luck. If everything is in one project then it's not that hard, but still easy to miss one or two implementations not saving a field. But if other projects can implement their own... you have no control over those. ...unless you design the interface such a way that breaks them: require not just a saveToFile but break it down to saveBook, saveQuantity... (abstract/pure virtual) methods in the interface, and add a new required method to the interface when you add a new field to the data class. And that's pure hell!
@Archheret1c
@Archheret1c 25 күн бұрын
In general principles and "recipes" are good when learning the ropes. It's a bit like making food, if you have very little experience with cooking and want to make a more advanced dish following a recipe to the letter is probably a good thing. When get more experience you can start to deviate, and after a while you start to understand what parts of a recipe you can deviate from and which part is crucial to reach your goal.
@nuKsBe
@nuKsBe 9 күн бұрын
The single responsibility can (and actually should in many case) be to handle the dataflow. This both follows locality of behaviour and SOLID. The point is not to have as many abstraction or unit of code as possible. The point is the opposite, to have one single place per responsibility rather than multiple places per responsibility. Then you have control over the granularity of the responsibility, at long as it is one per unit. It can be a "wide" responsibility or a small one, but it must be properly defined, unambiguous and unique/single. Done right, Single Responsibility Principle and Locality of Behaviour are the same thing. Liskov tells when you can use inheritance, not that you should do it. Composition over inheritance. Inheritance is good for modularity and encapsulation. If others developer want to extend or modify a feature and the original developer want to control to which extent they can do it. Lots of great use cases (UI, plugins, ...) A good way to look at SOLID overall is that you can apply it in non-OOP as well. The paradigm itself doesn't matter as much as the principles themselves. For instance using higher order functions etc. I may understand it feels counterproductive nowadays. I think it is because most of the time it is being understood from a place where things are already being built upon standardized ways / abstractions / frameworks that are actually already following SOLID principles. For instance MVC and all related. Thus there is no need to add SOLID, because it's already being done. A good counter-case for OOP is when you need both targeted and global customization through code (declarative customization alone not being enough for the use case etc.). For instance, in multi-tenancy setup where you may have to be able to slightly change business rules at any point of code depending on the clients. Considering you'll then have to maintain the different codebases in parallel over long period of time as well. This can be done totally fine without OOP, but in any case you'll need a very good design for this. And OOP aims to provide the tooling for that. If you don't have the experience to use it well, and I do think it does take a lot of trial and error before getting OOP the right way, it may induce too much complexity. But the same goes for anything that allows high level of abstraction, ie. higher order functions etc. I do believe you pinpoint a lot of major caveats however and your video has a lot of value. From my perspective the title could very well be renamed "how to do SOLID the right way", rather than SOLID - No Thanks", and it would still work out fine overall.
@acharris
@acharris 25 күн бұрын
This is essentially the programming version of the Platonic Idealism vs. Aristotilian Realism debate
@jasperdunn
@jasperdunn 25 күн бұрын
Procedural programming FTW!!
@0dsteel
@0dsteel 25 күн бұрын
Getting One Guy'd ™ "SOLID is for *programming, akshually ..."
@saritsotangkur2438
@saritsotangkur2438 18 күн бұрын
Open Close principle is great sometimes. Imagine you have this super complicated legacy code that every breaks whenever they modify it. If you restructure the code at the edges to be Open/Closed then you can keep adding new features w/o ever breaking (and having to debug) that mess.
@owenreynolds8718
@owenreynolds8718 25 күн бұрын
That article got me! Since it was giving specific examples from the same project, when it came to "L" I was on the edge of my seat. I know this project doesn't use squares. I'm going to see a new "L" example. But NOOO! I think of all the children, about to make their Square's inherit from Rectangle, being saved by the "L" in solid.
@girlswithgames
@girlswithgames 26 күн бұрын
i hate it how i have to pretend to like all this fluffy bullshit in tech interviews to even get a chance lol
@chamutalzered7468
@chamutalzered7468 25 күн бұрын
Same here. And then, after the interview, they give you a home assignment and you forget to implement it because you're on a time limit and you wouldn't if it was your own code.
@Justin73791
@Justin73791 25 күн бұрын
@@chamutalzered7468 It's because the managers interviewing you only know code from buzz words, and high level concepts.
@actually_it_is_rocket_science
@actually_it_is_rocket_science 25 күн бұрын
Eh I just say why I dislike it and generally it shows you have a better understanding of it then taking a sunshine and roses approach
@alivepenmods
@alivepenmods 25 күн бұрын
Lol I hear a single Solid or OOP design pattern word in an interview and I'm out of the process I don't work for clowns anymore Yeah go ahead and tell me how the Linux Kernel is bad because it doesn't use OOP Clowns
@MikkoRantalainen
@MikkoRantalainen 25 күн бұрын
I totally agree that you shouldn't abstract before actually *feeling* the need for it. Say you abstract your invoice printing from the start to support printing to JSON and stdout. However, when the boss then says you have to support HTML, too, and by the way, HTML needs company header, you have to redo *every abstraction* you already did for the printing stuff so support injecting the extra information to pass the header without using hardcoded header or global configuration values. And the same thing for every other extra dependency what your future data print needs might be. I know I've done lots of unnecessary abstractions during my career and it's not an accident such thing is called astronaut architechture: you try to guess what kind of interfaces you might need if this specific feature would be used by NASA during the Mars mission. And since you cannot possibly guess that correctly, you'll always miss something and have something extra that even the Mars mission is not going to need.
@aybgim3850
@aybgim3850 12 күн бұрын
Liskov only tells how NOT to use inheritance, it doesn't tell you how much to use it. If anything, it prevents you from abusing it in a really bad way. And it applies to implementing interfaces/traits as well, so totally applicable to Go and Rust
@DanielS-cu2ic
@DanielS-cu2ic 25 күн бұрын
Do your best to follow the rules until you have a good reason to break them.
@Altirix_
@Altirix_ 26 күн бұрын
ive seen people take Single responsibility too far in our codebases. for example. there was this part of the project that would transform a grid of points. ie rotation and translate. these are all simple concepts that can be done in a few lines. whoever originally wrote it did every math operation in its own function. every function was a single line. the problem with the idea of single responsibility is the line is ambiguous. because, technically every function had a single responsibility of a single math operation, and doing this made the code much less readable, who could have guessed. end of the day the programmer still has to understand where to draw that line, where abstraction is a benefit and where it is not. in some ways these principles we have do end up feeling like they say a lot of nothing as there is no one size fits all and you end up losing the nuance to the when and why
@ncpeaksean4278
@ncpeaksean4278 25 күн бұрын
Thats not the SRP concept, youre wrong, it's not about to split every task in functions, it's about every function only would have a reason to change, no many reasons.
@TurtleKwitty
@TurtleKwitty 25 күн бұрын
Seems totally fine for your grid math lib to be split in multiple functions though? Unless you meant in the sense that you had a specific set of operations to perform in for the final output nad they split that pipeline up for no reason? IF that's the case then yeah that's wack as hell, that's why I tend to describe my functions in terms of "data op" "pipeline" and "transform" the math operations (rotate, translate, etc) would be a transform and seperate but the pipeline for the final output would be in its own thing (func calc(in){in.rotate(1, 2).translate(3, 4).rotate(5,6)}) and the data op functions would befor getting the in object from a data source and another for sending that off somewhere
@emmanuelbustos2532
@emmanuelbustos2532 25 күн бұрын
SRP is not separation of concerns. They are different things but are confused all the time. Everyone thinks they know what SRP is but no one really does. It's an organizational principle, not directly a code related principle. The way I understand it the best is that you don't want multiple stakeholders requesting things in a single software entity (i.e. but not necessarily a class), as they are likely going to request things that conflict with each other.
@Altirix_
@Altirix_ 25 күн бұрын
@@TurtleKwitty yeah, it was basically taking one 2d coordinate space and mapping it to another. just a linear transform and a rotate i was tasked to convert it from only being used to converted between two hardcoded coordinate spaces to be user controlled at runtime. it did the latter, there were like 16 functions responsible to convert between the two. so it was like func convertToLocationX(x){return x + LOCATION_X_ORIGIN} and below it func convertToLocationY(y){return y + LOCATION_Y_ORIGIN} rinse and repeat
@isodoubIet
@isodoubIet 24 күн бұрын
"I'd argue that you should keep better indentation" Typical tabber code. "You can set the tab width to be whatever you want!" while ignoring that it looks like garbage on any setting except for his.
@chaitanyasharma6270
@chaitanyasharma6270 25 күн бұрын
Liskov principal is generally done using interfaces right? Or am I wrong, i rarely ever see inheritance classes
@defeqel6537
@defeqel6537 25 күн бұрын
LSP applies to all polymorphism
@steamer2k319
@steamer2k319 26 күн бұрын
Will watch later but here's my apriori take on SOLID: I think it has some interesting things to say, but it'd probably be easier to communicate / remind about the principles if someone were to translate them into English. EDIT: HAHA! First line out of Prime's mouth: "I forget what they are all the time" EDIT 2: Just noticed the article is different from the video title too 😄: ~"SOLID in plain English"
@bitwize
@bitwize 25 күн бұрын
SOLID is not what Alan Kay had in mind when he coined the term OOP, either. Seriously, in Smalltalk, the ideal is closer to what you term the "locality of behavior" principle. A class is a template for capturing state and behavior that could be then replicated over and over; nothing more or less. Subclasses are basically a way of compressing modifications to similar templates or variations on a theme -- of saying "this template, but with these changes". There is, for example, no requirement for Liskov substitutability between a class and its subclasses by design. That's more suitable for _subtypes_ -- Number, say, and Integer as a specialization of Number. But even then, it doesn't capture the reality: consider division. Most number types implement the idea that (a / b) * b = a, but this does not hold for integer division! So the important thing is that you capture the reality of the situation in a way that's straightforward to examine and change, not that you follow a book of rules. The language, and the conventions around the language, gave you a set of tools with which to build what you need -- "mechanism, not policy" as the X11 team said. SOLID appears to be aimed as a principle to instill in large teams of inexperienced programmers hired in legion strength, so that they avoid stepping on one another's toes, coupling components too tightly, or creating the feared "God class". But Smalltalk, true to its name, was originally a program meant for single programmers, or programmers working in small groups, to be able to design systems of staggering complexity (for the 1970s anyway). Literal children were writing full, useful applications. There was the 12-year-old girl's animation program and the 15-year-old-boys electronic design suite written in Smalltalk, for instance. And you know if you had bottled that creativity up and tried to enforce enterprise architecture design pattern best practices on it, you would've killed it. Profoundly powerful programming tools -- even more so than 1970s Smalltalk -- are available to the average person, as a free download. And yet the programming wisdom out there is tuned to the least common denominator: the corporate drone working on one tiny piece of a huge puzzle. If I were conspiracy-minded, I'd say that a lot of the "best practices" of today were designed to fill the drone's time with busywork, so they'd have little chance of dreaming bigger. One of the lessons my rinky-dink VIC-20 taught me is that computers are "make dreams come true" machines, and if you have one it becomes even more important to dream big dreams because a computer can put those dreams within reach. Otherwise the machine is just going to waste. That said, learn to freaking dependency-inject. You can save so much time and effort testing one little function at a time over feeding crafted input into a half-completed program.
@robgrainger5314
@robgrainger5314 25 күн бұрын
FPOOP has been around at least the 1960s. OO originally rose from projects in LISP before there were even OO languages.
@Schindlabua
@Schindlabua 25 күн бұрын
I agree that inheritance usually doesn't solve problems well, but the Liskov Substitution principle still applies. It's one of the only principles that's really set in stone imo, it's not only about OOP either and if we squint a little it helps us design our app's types and code. Take a structually typed language like typescript and maybe we have a weird database abstraction because I can't think of a better example: type Database = { query: () => void; } technically speaking, an express app `const app = express()` also has a "query" method so express apps are in fact a subtype of `Database`. When I'm writing functions for my `Database` abstraction I'll not consider the case where someone passes express apps because the two have totally different semantics. And express apps can't safely be substituted for Databases, hence breaking Liskov's substitution principle even though they follow the subtype relation. And I'm saying it's your fault if you pass non-substitutable objects into my function taking a `Database`. At the same time when I have different implementations of `Database` I'll make sure they all follow the contract I've defined for `Database` in my mind.
I Interviewed Uncle Bob
1:11:07
ThePrimeTime
Рет қаралды 266 М.
Clean Code : Horrible Performance | Full Interview
47:13
ThePrimeTime
Рет қаралды 199 М.
GADGETS VS HACKS || Random Useful Tools For your child #hacks #gadgets
00:35
FLIP FLOP Hacks
Рет қаралды 103 МЛН
ШЕЛБИЛАР | bayGUYS
24:45
bayGUYS
Рет қаралды 666 М.
How To Choose Ramen Date Night 🍜
00:58
Jojo Sim
Рет қаралды 58 МЛН
Who Will Eat The Porridge First The Cockroach Or Me? 👧vs🪳
00:26
Giggle Jiggle
Рет қаралды 9 МЛН
Scams In Software Engineering
31:44
ThePrimeTime
Рет қаралды 473 М.
zig is the future of programming. here's why.
9:34
Low Level Learning
Рет қаралды 152 М.
Lets Chat About Unit Tests
15:06
ThePrimeTime
Рет қаралды 87 М.
98% Cloud Cost Saved By Writing Our Own Database
21:45
ThePrimeTime
Рет қаралды 246 М.
C Is Not A Language Anymore
34:29
ThePrimeTime
Рет қаралды 150 М.
The harsh reality of good software
27:28
ThePrimeTime
Рет қаралды 289 М.
The Plight Of Cobol Mainframe Programmers
29:15
ThePrimeTime
Рет қаралды 162 М.
This Is Why Managers Don't Trust Programmers...
28:04
Thriving Technologist
Рет қаралды 135 М.
5 Design Patterns That Are ACTUALLY Used By Developers
9:27
Alex Hyett
Рет қаралды 158 М.
The power button can never be pressed!!
0:57
Maker Y
Рет қаралды 46 МЛН
Save Work Efficiently on Your Computer 18/05/2024
0:51
UNIQUE PHOTO EDITING
Рет қаралды 308 М.