Solid Programming - No Thanks

Ғылым және технология

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
    @JayHiza27 күн бұрын

    "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

    27 күн бұрын

    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

    27 күн бұрын

    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

    27 күн бұрын

    spoiler: nobody is that savant

  • @defeqel6537

    @defeqel6537

    27 күн бұрын

    This is a good starting point, another is to abstract platform specifics. Abstraction can just be a C/C++ declaration too though.

  • @Linkario86

    @Linkario86

    27 күн бұрын

    ​​@@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.

  • @PaulPhilp-pe5oe
    @PaulPhilp-pe5oe27 күн бұрын

    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

    27 күн бұрын

    😮 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

    27 күн бұрын

    True! But there are much more software developers out there who are not on this level.

  • @filipg4

    @filipg4

    27 күн бұрын

    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

    27 күн бұрын

    @@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

    27 күн бұрын

    It should be noted that there are also just flat out bad scores that no creative freedom can fix (without entirely replacing the original)

  • @angelcaru
    @angelcaru27 күн бұрын

    liquid programming

  • @hextech687

    @hextech687

    27 күн бұрын

    Ahhh yes the Bruce Lee paradigm

  • @sebastienpautot

    @sebastienpautot

    27 күн бұрын

    Programming with inferior genes

  • @grexpex1807

    @grexpex1807

    27 күн бұрын

    naked programming

  • @iMagUdspEllr

    @iMagUdspEllr

    27 күн бұрын

    Solidus programming

  • @jimgorlett4269

    @jimgorlett4269

    27 күн бұрын

    venom programming

  • @rampantporcupineandfriends3793
    @rampantporcupineandfriends379327 күн бұрын

    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

    27 күн бұрын

    Define "complexity".

  • @rampantporcupineandfriends3793

    @rampantporcupineandfriends3793

    27 күн бұрын

    @@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 kzread.info/dash/bejne/lKGHo7ulpZO0k7w.html

  • @monad_tcp

    @monad_tcp

    27 күн бұрын

    Essential complexity versus accidental complexity.

  • @rampantporcupineandfriends3793

    @rampantporcupineandfriends3793

    27 күн бұрын

    @@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

    27 күн бұрын

    ​@@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
    @AndrewBrownK27 күн бұрын

    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

    27 күн бұрын

    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

    27 күн бұрын

    @@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

    27 күн бұрын

    @@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

    27 күн бұрын

    @@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

    26 күн бұрын

    @@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
    @roberthoople27 күн бұрын

    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

    27 күн бұрын

    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

    27 күн бұрын

    @@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

    27 күн бұрын

    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

    27 күн бұрын

    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

    27 күн бұрын

    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
    @DarylMetzler27 күн бұрын

    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.

  • @SKULDROPR
    @SKULDROPR27 күн бұрын

    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

    11 күн бұрын

    Could you please explaining this in more detail or refer an article that does?

  • @SKULDROPR

    @SKULDROPR

    11 күн бұрын

    @@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.

  • @mgoonga
    @mgoonga21 күн бұрын

    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!

  • @ReneHartmann
    @ReneHartmann27 күн бұрын

    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

    27 күн бұрын

    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

    27 күн бұрын

    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

    27 күн бұрын

    ​@@Dom-zy1qy of single responsibility is so simple why do so many people, including the article in this video get it wrong?

  • @Justin73791

    @Justin73791

    27 күн бұрын

    @@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

    27 күн бұрын

    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".

  • @optimisticenigma283
    @optimisticenigma28327 күн бұрын

    Jesus these bots be saying anything, gosh

  • @FRAMEDSKATEKREW69

    @FRAMEDSKATEKREW69

    27 күн бұрын

    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

    27 күн бұрын

    Thumbnails ok tho 🤣😎

  • @electrolyteorb

    @electrolyteorb

    27 күн бұрын

    i am a BSD enthusiast

  • @penewoldahh

    @penewoldahh

    27 күн бұрын

    Jesus these bots be saying anything, gosh

  • @nikolaygruychev2504

    @nikolaygruychev2504

    27 күн бұрын

    Jesus these bots be saying anything, gosh

  • @DeathSugar
    @DeathSugar27 күн бұрын

    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

  • @grandeau3802
    @grandeau380227 күн бұрын

    There are basically three main (or meta) principles above all: KISS, DRY and No-Principle-is-Sacred.

  • @lifelover69

    @lifelover69

    26 күн бұрын

    I generally agree, but I have worked on codebases that were a nightmare due to taking DRY literally :)

  • @georgehelyar

    @georgehelyar

    26 күн бұрын

    DRY has its own problems and can lead to tight coupling so there's a balance to find there as well.

  • @Nightwulf1269

    @Nightwulf1269

    25 күн бұрын

    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

    25 күн бұрын

    I'd say YAGNI is way more important than DRY

  • @Nightwulf1269

    @Nightwulf1269

    25 күн бұрын

    @@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!

  • @splitpierre
    @splitpierre27 күн бұрын

    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.

  • @ionuttiplea4666
    @ionuttiplea466626 күн бұрын

    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

  • @muslim8622
    @muslim862227 күн бұрын

    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

    14 күн бұрын

    Very well articulated and I agree on your critique.

  • @markemerson98
    @markemerson9827 күн бұрын

    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

    27 күн бұрын

    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

    25 күн бұрын

    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.

  • @ProfMonkeys
    @ProfMonkeys27 күн бұрын

    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.

  • @steamer2k319
    @steamer2k31927 күн бұрын

    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

    27 күн бұрын

    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

    27 күн бұрын

    @@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

    27 күн бұрын

    @@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

    27 күн бұрын

    @@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

    27 күн бұрын

    @@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
    @zbyniew27 күн бұрын

    Your enthusiasm is infectious. Love the content, man

  • @almicc
    @almicc27 күн бұрын

    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

    27 күн бұрын

    Brilliant comment

  • @deloftie3619

    @deloftie3619

    27 күн бұрын

    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

    26 күн бұрын

    ​@@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

    26 күн бұрын

    @@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

    26 күн бұрын

    @@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.

  • @jjurksztowicz
    @jjurksztowicz27 күн бұрын

    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

    27 күн бұрын

    Clean Code actually has a decent section on this: "Data/Object Anti-symmetry"

  • @TECHN01200
    @TECHN0120027 күн бұрын

    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.

  • @andrewshirley9240
    @andrewshirley924027 күн бұрын

    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

    27 күн бұрын

    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

    27 күн бұрын

    Being too stubborn with the "this should be standard everywhere" will absolutely be a terrible idea. You need to be flexible.

  • @defeqel6537

    @defeqel6537

    27 күн бұрын

    Sounds like your understanding of OOP is missing an understanding of the Single Responsibility Principle and Open/Close Principle

  • @AloisMahdal

    @AloisMahdal

    22 күн бұрын

    "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

    22 күн бұрын

    @@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

  • @UNgineering
    @UNgineering27 күн бұрын

    "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

    27 күн бұрын

    Finally someone who gets it. The biggest problem with SOLID is that it is being misunderstood at the most fundamental level.

  • @Sc0nes

    @Sc0nes

    27 күн бұрын

    Gather together the things that change for the same reasons. Separate those things that change for different reasons.

  • @halim7725

    @halim7725

    27 күн бұрын

    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

    25 күн бұрын

    "beholden to a single stakeholder". Have you thought about what that means critically?

  • @shawnington

    @shawnington

    7 күн бұрын

    @@chickenmonkey88 your mom

  • @kashperanto
    @kashperanto26 күн бұрын

    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

    25 күн бұрын

    That's a remarkably useless principle.

  • @rupertsmith6097
    @rupertsmith609727 күн бұрын

    You can do SOLID in functional programming too. Interface = higher order function.

  • @ThundersLeague
    @ThundersLeague26 күн бұрын

    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.

  • @XKCDism
    @XKCDism27 күн бұрын

    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

    26 күн бұрын

    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.

  • @pseudocoder78
    @pseudocoder7827 күн бұрын

    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"

  • @flannn6
    @flannn627 күн бұрын

    It is really cool how you understand the ideas behind each language. As a go developer i feel well represented by you =)

  • @CaptainWumbo
    @CaptainWumbo26 күн бұрын

    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.

  • @ErinCollective
    @ErinCollective27 күн бұрын

    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

  • @ssamani24
    @ssamani2427 күн бұрын

    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)

  • @n8ged8
    @n8ged818 күн бұрын

    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.

  • @ITPMMentor
    @ITPMMentor27 күн бұрын

    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

  • @jaymaj21
    @jaymaj2124 күн бұрын

    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.

  • @YaserFarid
    @YaserFarid25 күн бұрын

    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.

  • @zootsuitpenguin
    @zootsuitpenguin27 күн бұрын

    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

  • @Vendavalez
    @Vendavalez27 күн бұрын

    21:50 Weird. I always took the Liskov's substitution principle to mean that you generally don't want to use inheritance. The test it provides is kind of difficult to pass in any actual practical example and, even when your use-case passes it, how sure that requirements are not going to change?

  • @TurtleKwitty
    @TurtleKwitty27 күн бұрын

    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

  • @Dan_Diaconescu
    @Dan_Diaconescu27 күн бұрын

    your voice is smoother since quitting Netflix, faang bad for health confirmed

  • @sournois90

    @sournois90

    27 күн бұрын

    oh i didn't know he quit

  • @mamneo2

    @mamneo2

    27 күн бұрын

    Incroyable.

  • @TheArrowedKnee

    @TheArrowedKnee

    27 күн бұрын

    He quit?

  • @abelnagy9877

    @abelnagy9877

    27 күн бұрын

    @@TheArrowedKnee yup

  • @efkastner
    @efkastner27 күн бұрын

    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

  • @joejoesoft
    @joejoesoft27 күн бұрын

    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.

  • @blubblurb
    @blubblurb18 күн бұрын

    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.

  • @Archheret1c
    @Archheret1c27 күн бұрын

    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.

  • @MrSpyTubes
    @MrSpyTubes27 күн бұрын

    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

    27 күн бұрын

    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

    27 күн бұрын

    *at least two

  • @isodoubIet

    @isodoubIet

    24 күн бұрын

    "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

    18 күн бұрын

    @@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.

  • @james.lambert
    @james.lambert27 күн бұрын

    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.

  • @wforbes87
    @wforbes8722 күн бұрын

    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.

  • @assombranceanderson6175
    @assombranceanderson617527 күн бұрын

    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

    27 күн бұрын

    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.

  • @saritsotangkur2438
    @saritsotangkur243820 күн бұрын

    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.

  • @heavenaldrico
    @heavenaldrico27 күн бұрын

    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

  • @scoutchorton
    @scoutchorton23 күн бұрын

    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

  • @canepaper967
    @canepaper96722 күн бұрын

    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.

  • @janwilmans5954
    @janwilmans595424 күн бұрын

    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.

  • @firetruck988
    @firetruck98827 күн бұрын

    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

    27 күн бұрын

    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?

  • @vanstanian
    @vanstanian27 күн бұрын

    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.

  • @silak33
    @silak3326 күн бұрын

    I think you should try to read Liskovs substitution principle again. It doesn't try to argue about something you can do with inheritance, it tries to show examples of stuff you definitely shouldn't do with inheritance. The example actually says that a square should NOT inherit from a rectangle since it would break the expected behaviour of a rectangle :)

  • @wtfusernamecrap
    @wtfusernamecrap5 күн бұрын

    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.

  • @salvatoreshiggerino6810
    @salvatoreshiggerino681027 күн бұрын

    Isn’t Liskov just as important for interfaces? For example I see a lot in enterprise Java where something takes an instance of an interface, only for it to throw a ClassCastException or something because what they actually want is one concrete implementation, they just threw the interface into the mix to make it enterprise grade.

  • @TheTubeYou251
    @TheTubeYou25112 күн бұрын

    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.

  • @saheemsiddiqi3220
    @saheemsiddiqi322027 күн бұрын

    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.

  • @tylerbreau4544
    @tylerbreau454427 күн бұрын

    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.

  • @andreaslofkvist25
    @andreaslofkvist2522 күн бұрын

    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?

  • @bigpest
    @bigpest27 күн бұрын

    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

    27 күн бұрын

    hmm, that depends actually

  • @LusidDreaming

    @LusidDreaming

    27 күн бұрын

    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

    27 күн бұрын

    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

    27 күн бұрын

    You robbed my face. Please give it back. :(

  • @mirkogeffken2290

    @mirkogeffken2290

    27 күн бұрын

    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.

  • @ErinCollective
    @ErinCollective27 күн бұрын

    abstractions are more than just classes and interfaces though, like if you want to do ddd then you have additional abstractions (that you need because you already populate them) above the class / interface level eg project level, folders are better for namespacing but the ddd abstraction can be the top level directories too.

  • @spikedgav
    @spikedgav11 күн бұрын

    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

  • @gileee
    @gileee22 күн бұрын

    You might need to print an invoice to a file because some old POS terminal drivers work through the file system. Like it has a "For Print" folder it reads and waits for new files to appear, and after it finishes printing it might move the invoice file to a "Printed" folder.

  • @GhiveciuMarian
    @GhiveciuMarian27 күн бұрын

    This whole abstraction thing reminds of my nightmanre when i was asked to do a quick change to wordpress to add some text in front of products purchased from shop before sending the cart object to paypal. They had factory of factories, settings were spread among 10s of files... everything was tiny functions, and coming from outside project next to impossible to understand it all, and see the hoocks and what i needed to implement my custom functionality, hate paypal pluging with all my fiber!:P

  • @animanaut
    @animanaut25 күн бұрын

    would love to see an article that lays down how solid looks like when you overdo it. might be interesting approach for every topic, not just solid

  • @TysonLondon
    @TysonLondon27 күн бұрын

    Amen, "you abstract when you see the abstraction" 🙏

  • @aybgim3850
    @aybgim385014 күн бұрын

    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

  • @RobRoss
    @RobRoss21 күн бұрын

    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.”

  • @etzabo
    @etzabo26 күн бұрын

    I program until whatever I want to do works with adequate optimization and readability so that I don’t have to determine whether or not the system I’m about to implement fits into some random acronym.

  • @SimGunther
    @SimGunther27 күн бұрын

    Code is data, data is code Feet used to the pipeline dataflow workshop factory model to translate data into different kinds of data, but no side effects unless it's at the beginning or end of the function.

  • @DirkFedermann
    @DirkFedermann27 күн бұрын

    Sometimes I wonder how much time has gone into the acronym vs. what it actually is...

  • @juanjosefarina
    @juanjosefarina22 күн бұрын

    20:00 there is still a bigger problem with touching existing code to add new functionalities, and that is that if a bug arises, it's gonna be harder to troubleshoot where the bug is, it could happen in the code you wrote, or the code that has already been communicating with that older portion of code. If you add the new functionality outside the older code, you can be pretty sure the problem is in the new functionality alone.

  • @owenreynolds8718
    @owenreynolds871827 күн бұрын

    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.

  • @chaitanyasharma6270
    @chaitanyasharma627027 күн бұрын

    Liskov principal is generally done using interfaces right? Or am I wrong, i rarely ever see inheritance classes

  • @defeqel6537

    @defeqel6537

    27 күн бұрын

    LSP applies to all polymorphism

  • @MikkoRantalainen
    @MikkoRantalainen27 күн бұрын

    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.

  • @cod3r1337
    @cod3r133725 күн бұрын

    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.

  • @rikschaaf
    @rikschaaf27 күн бұрын

    For SRP, I usually use this to figure out if I need to follow SRP: do I have a good name for the abstraction? If I can't think of a good name, how could I ever define the scope of that abstraction and how would I be able to explain what it does? Sure it would have only one responsibility, but who knows what it actually does

  • @itermercator114
    @itermercator11427 күн бұрын

    The problem with OOP is that when you write a family of classes, you've crystallised behaviour, it's great if you have minor addition/changes that you want for it entirely or upstream, but you haven't got wiggle room for anything in that crystal. The second part is that the crystal grows, over time you need something so you extend it and so fourth, so everything gradually crystallises (especially as the code becomes forgotten and people don't want to mess about with it, see adapters to pre-existing classes, it's like trying to untie a Georgian knot by hand to do otherwise). OOP works in this sense when you have something you know will absolutely not change or will only change everything (gamedev has a lot of this), but outside of that, it's useless and if anything, a blight as it becomes a monolith crystal. It even goes against agile-based workflows since you build a crystal structure that won't change, in an environment where the entire point is that you're constantly pivoting to your goal. I'll also add that FP has this same issue but the embedded nature of it is arguably worse.

  • @zeez7777

    @zeez7777

    27 күн бұрын

    You clearly didnt understand OOP at all. Not sure if this is because of seeing a bunch of cursed and plainly wrong usages of OOP or just bad teaching. But none of what you said about OOP is true if you do it right.

  • @gabrielfreitas4270

    @gabrielfreitas4270

    27 күн бұрын

    ​@@zeez7777That's always the thing, isn't it? To do it right. I assure you that you can do any paradigm "right", the focus should be how hard is to do it, the amount of friction and how long you'll need to go through trying to achieve that. Honestly, I prefer to follow all "best practices" somewhat loosely after trying them, thinking on how well they fit the context I'm in

  • @somniad

    @somniad

    27 күн бұрын

    @@zeez7777 real oop has never been tried

  • @Asto508

    @Asto508

    27 күн бұрын

    @@gabrielfreitas4270 That's a kinda pointless argument. If you judge everything based on how easy it is to be misused, then you will eventually always end up only with the most fool-proof, but ineffective way of doing things. It's like stating that flying air planes is bad, because most people would instantly crash it.

  • @gabrielfreitas4270

    @gabrielfreitas4270

    27 күн бұрын

    @@Asto508 your analogy is such a strawmen. The whole point of what I said is to consider cost relative to what you'll get in return. It's not about how easy something is to being misused but how much would be the investment to be used correctly or on at an acceptable level. Nonetheless this for sure does not apply to everything, the context here is clear: software development. If you really want to go that route on generalizing into an analogy, a better one would be cargo shipping. For sure flights are great, but costly and may not fit well in many scenarios. As so, that's why we still have maritime and road transport.

  • @Altirix_
    @Altirix_27 күн бұрын

    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

    27 күн бұрын

    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

    27 күн бұрын

    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

    27 күн бұрын

    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_

    27 күн бұрын

    @@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

  • @clementdato6328
    @clementdato632827 күн бұрын

    Liskov substitution is problematic because depending on the variance of the class in the function, it could be in either direction (subclass/class which substitutes which)

  • @rusmaakatupal4723
    @rusmaakatupal472327 күн бұрын

    Nice voice and tone game. Is this the pilot speaking ? May I ask you the weather forecast for the next video ?

  • @mattetis
    @mattetis26 күн бұрын

    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.

  • @hanseichel4327
    @hanseichel432727 күн бұрын

    so where can i play this tower defense game? have some ssh credentials or how do you run that? :)

  • @robgrainger5314
    @robgrainger531427 күн бұрын

    FPOOP has been around at least the 1960s. OO originally rose from projects in LISP before there were even OO languages.

  • @ericm97
    @ericm9717 күн бұрын

    As a Java developer, I’ve always wondered what’s an easy way to find all code implementations of an interface in go? In Java we can simply do a search for implements, what’s it like in Go?

  • @LusidDreaming
    @LusidDreaming27 күн бұрын

    Imagine getting credit for just creating an acronym for someone elses work. Its like the Maclaurin series in math.

  • @DanielMPries
    @DanielMPries26 күн бұрын

    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

  • @ryoriotwow
    @ryoriotwow27 күн бұрын

    Inheritance is very useful. Suppose you have a datastructure that combines multiple tables in a database because there is some validation across them. For instance a case-folder containing multiple documents, having a case-owner and some sort of access-validation scoped by user-session. Maybe you even have something stored in a completely different database, or off-site, like files for the documents in a one-drive or whatever. If you want to present this data in a web-application, you typically want to have API-endpoints returning DTOs of different degrees of implementation. I.e. one DTO that only exposes the most simple fast-accessed properties, and one or more inherited DTOs that expose further properties that the API might have to do a bit of work to retrieve the values for. That way, your front-end web-application can work with these different levels of inheritance and request the object that it minimally needs given the context, to display whatever it needs to display, and you don't have an API working overtime collecting data that is discarded.

  • @ryoriotwow

    @ryoriotwow

    27 күн бұрын

    Of course, you can always solve it differently. You could for instance separate out the properties that is load-heavy into their own structure, maybe it just takes in the case-folder id, and then you retrieve it completely seperately whenever you need it.

  • @worldwideweb7794
    @worldwideweb779427 күн бұрын

    Solid is great, but not when you are dogmatic about it. Always think about YAGNI and KISS whenever you want to abstract. Good devs know solid rules, the better devs also know when to break them.

  • @steamer2k319
    @steamer2k31927 күн бұрын

    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"

  • @ifeoraokechukwu1346
    @ifeoraokechukwu134627 күн бұрын

    Here's my 2 cents on the "S" in "SOLID": Single Responsibility Principle (SRP). I believe (based on my experience) that SRP does a very wonderful and perfect handshake with High Locality of Behavior (LoB). Now, most people like to define LoB as co-locating all the logic in one source file. But, it can also be co-locating logic spread across many source files in one folder (especially for non-trivial software logic). SRP ties perfectly into this by grouping (or co-locating) things that change for the same reason together and separating things that change for a different reason. When using SRP, people organise their codebase by. type instead of by feature - which is wrong. Organising your codebase by feature gives you higher LoB than than organising by type. So, you can only enjoy the true benefits of SRP by organising by feature (so you don't have to hop far around the codebase too much to understand the code). Making use of SRP in your codebase will always suck ass when you organise your codebase by type instead of by feature. Cheers ✌🏽

  • @JacobSantosDev
    @JacobSantosDev27 күн бұрын

    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.

  • @PurpleSheeep
    @PurpleSheeep27 күн бұрын

    Hey, SOLID isn't a set of laws its a set of principles

  • @slavagarshin
    @slavagarshin27 күн бұрын

    Open-closed principle is described the wrong way in the article. It's about interface of class. Not about changing the code. It says on wiki: Keep existing interfaces. Add new if needed.

  • @SimonBuchanNz

    @SimonBuchanNz

    27 күн бұрын

    This makes no sense. Do you mean just keep compatibility to reduce churn?

  • @defeqel6537

    @defeqel6537

    27 күн бұрын

    Wiki might be wrong, OCP is indeed about not touching "working" code when adding new functionality. This, of course, is not always possible.

  • @helium73
    @helium736 күн бұрын

    I wonder if it's possible that when something amazing like PHP comes out that makes programming so incredibly easy that this inspires people to come up with frameworks libraries to make it even easier. And on the other hand no one comes up with frameworks and systems to make incredibly hard things easier.

Келесі