Solid Programming - No Thanks

247,313
0
Published 2024-04-25
Recorded live on twitch, GET IN

Article
www.freecodecamp.org/news/solid-principles-explain…
By: Yiğit Kemal Erinç | x.com/erinccodes

My Stream
twitch.tv/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
youtube.com/ThePrimeagen

Discord
discord.gg/ThePrimeagen


Have something for me to read or react to?: www.reddit.com/r/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

All Comments (21)
  • @JayHiza
    "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.
  • @PaulPhilp-pe5oe
    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.
  • 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.
  • @mgoonga
    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!
  • @AndrewBrownK
    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
  • @DarylMetzler
    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.
  • @roberthoople
    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.
  • @SKULDROPR
    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.
  • @grandeau3802
    There are basically three main (or meta) principles above all: KISS, DRY and No-Principle-is-Sacred.
  • @TECHN01200
    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.
  • @TheTubeYou251
    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.
  • @muslim8622
    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.
  • @markemerson98
    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
  • @DeathSugar
    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
  • @UNgineering
    "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 :)
  • @XKCDism
    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.
  • @almicc
    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.
  • @ReneHartmann
    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.