The Problem with Object-Oriented Programming

preview_player
Показать описание


I stream on my main YT channel: @NeetCode

#neetcode #leetcode #python
Рекомендации по теме
Комментарии
Автор

OMG so true! This drives me nuts in my C++ job! Every time I want to figure out what is happening I have to go up and down the inheritance/interface tree. Nothing does anything. After 3-4 jumps I don't even know what I am looking for.
Alright, then you realized let's say there is no actual implementation in this dependency tree. Great. You search for all classes that implement the interface in question. Excellent, they all do something different. Now you have to find that the piece of code you were originally looking at which implementation was used in the background. But then you can easily find yourself in the same cycle, trying to find what implementation actually got there. Madness.
Even worst when you have interfaces prematurely. There is only a single implementation yet, I need to jump to extra hoops, because we designed the system.

Qwantopides
Автор

The problem is people focus too much on one paradigm. Objects are great, but everything doesn't have to start by inheriting a purely abstract class etc.

psyience
Автор

I’ve worked with too many people who can’t even explain code they wrote four weeks ago because everything is abstracted away behind services, factories and interfaces that do nothing but juggle data around in the most convoluted way possible. Everything is “maximally reusable” but never gets reused.

And then the desire to wrap SQL which is very well readable in massive “builders” where you have no chance to quickly check what SQL is actually being executed.

magicmulder
Автор

I hate when engineers starts to implement design patterns without an actual need. The codebase isn’t even got any bigger yet. And instead of building a momentum to ship product faster, they stuck arguing what design pattern should be used to make it future proof.

yp
Автор

5:40 - Being honest here: please don't mix up the term "premature optimization" with "premature overengineering." Reason being that almost no one these days seem to know what optimization even means, and they just repeat what they hear without understanding. It's so bad that some (most?) programmers these days think that simply avoiding writing slow code in the first place is "premature optimization." For example, if I avoid a triple nested loop and just use a single constant instead, someone will jump down my throat and say I'm "prematurely optimizing" when in reality I just didn't need a triple nested loop. It's almost as if they think we _need_ triple nested loops everywhere, and then we remove them at the end of production in the mythical "optimization phase."

totheknee
Автор

Not everything needs an interface or base class.
Not everything needs to be injected through DI.
Not everything needs its own library.
Not everything needs clean architecture or DDD.
Follow these and you’ll be fine.

LuisAlonzoRivero
Автор

I think this was the biggest mental hurdle I had to overcome when I started programming. I was basically learning how to conform to this weird standard. I also think that's why I appreciate functional programming so much because you get to solving problems a lot faster

That being said, I do think OOP has a place. I don't see why it's bad that we have industry standards in an industry. It gets out of hand at times, sure, but I'd rather have guidelines for everyone to follow rather than everyone doing their own thing

asdasddas
Автор

You're using it right. Abstraction inherently isn't bad (it's obviously what a lot of coding is about), but when you abstract, you start putting up walls and sometimes it's hard to couple those abstractions together in order to work together the right way. So it can be bad to unnecessarily create abstractions before you need them because you end up spending your time connecting them together in the right why and it ultimately makes your code less dynamic.

EDIT: I don't know why everyone has to have a moral judgement on everything. It's a tool in your toolbox, use it at your will. If you don't think you need, don't use it.

Rockyzach
Автор

Although, I agree that generally pre-mature abstraction is bad (that it negatively affects developer productivity) and that quite a lot of organizations like to "abstract" things out to make the code more maintainable and extensible without the need for it, I would, however, like to visit your point about - "code that perfectly solves the problem with some SOLID principle violations". I think we, as engineers, should understand that the problem you are trying to solve is a constantly changing goal-post. If you solve perfectly solve problem A right now even with bad code, you will then probably need to solve problem B, followed by problems C and D. This is a very likely scenario in all (big and small) organizations. That is when writing code with abstraction shines and is very much needed. Understanding the balance of how much abstraction your code needs is what you, as an engineer, should decide. If you over-abstract too soon, or if you do not abstract at all - both these scenarios will bite the engineer later. OOP/Abstraction is not the problem, but a tool, and we should not overutilize it or shy away from it.

obnx
Автор

Regarding Alan Kay's definition of OOP:
As I understand it his idea was very similar to what we call today "actor model" or "actor-based concurrency", which is the core concept behind the language Erlang. The idea is to have "objects"/"actors" that only communicate via messages instead of direct method calls, and just react to messages they receive. Software built like this is very easy to distribute across multiple CPU cores or even devices as the program itself doesn't need to concern itself with how the messages are actually transmitted. It also reduces coupling to a point individual actors can be restarted after a crash without affecting any other part of the program, the worst that can happen are some lost messages. Erlang was designed by a telecommunication company (Ericsson) for minimal downtime of their systems, and this actor-based model allows live updates as well as crash recovery without any downtime. It's so good at what it does that many modern messaging services (e.g. Discord) still use Erlang in the backend.

SaHaRaSquad
Автор

Having grappled with abstraction, SOLID and design patterns for over 20 years all I can say is Hallelujah.

I can't tell you how often I've had to think "wtaf does open for extension and closed for modification really mean and do I really need to follow this rule in the age of modern refactoring tools?". The worm is turning. Over abstracted code is an absolute mindfuck.

I started to push back on pointless abstractions on PR's a while back. OOP and it's rules were a best guess of how it should work at a certain point of time. We've seen the results. Pretty horrible. And as for "clean code". Omfg. Ten shitty 3 line methods does not make code easier to read than one 30 line method.

BeatPoet
Автор

On the other hand, there's the old saw: "There is no problem in computer science that can't be solved using another level of indirection." I remember once trying to program a calculator using only instance variables. How much easier it is to solve a problem like this with the appropriate data structure. Once you have data structures, I think you're starting to move towards OOP.

There's another book I read a bit of called "The Philosphy of Software Design". One refreshing aspect of that book was the author's focus on complexity -- the central problem in software design is supposed to be to minimize complexity. Sometimes all the cruft of OOP increases complexity. Indirection itself is a form of complexity. A hierarchical page table is harder to understand than a simple page table, and a simple page table is harder to understand than a giant array that makes no distinction between physical and virtual memory addresses. But you get so much power out of separating the physical location in which a piece of memory resides from the system you use to identify that physical location!

The difficult thing is developing the foresight to know when making something more complicated in the short run could help to make things simpler in the long run. Sometimes you can get the worst of both worlds, obviously.

firezdog
Автор

This feels like a strawman but I'm not smart enough to say why. Functional and OOP are different tools to solve different problems. Being dogmatic about one or the other being better for everything doesn't really make sense. For example the main programming I do is ETL. It's more important for me to turn solutions around quickly than to get closer to the hardware. Different problems require different solutions.

future
Автор

So I just started learning OOP and so far I really like it. I think issues with it arise when you turn every little thing into a class, similar to how "clean code" says that if a function/method does more than one thing it should be refactored into another function, which is absolute madness. OOP is essentially just building a program out of bricks, but some people go too far and break the bricks down into gravel, and some even break it down into sand. Even the book where it's only lightly touching on OOP paradigms (it's for a specific language, not OOP) goes too far imo... there are parts where it suggests making an object for what should just be code executing in the main program entry point for example.

I've also only just barely learned about inheritance and I can already see that being a nightmare if you don't really use restraint and only use it where it saves you from writing pages of boilerplate. Basically OOP seems like a very, very good model for breaking down programs, avoiding global state, and protecting code from other code while still allowing the pieces to interact, but it also seems very easy to go overboard with.

datguy
Автор

OOP is trash, instead I always use 12 levels of "if else" statements.

qwe
Автор

There is a HUGE misunderstanding about the Dependency Inversion Principle.

It indeed says to rely on abstractions rather than implementations.
But that's only the second part of the principle.
If you apply only this part, it will lead to code that is too abstract and unmaintainable.

The key is the first part that says : High Level Code (business/domain) should not depend on Low Level Code (details), both should depend on abstractions.

That is, separating only the low-level concerns (Persistence, UI...) from the high-level policies (Use cases, Domain Model).

That's the core of Hexagonal Architecture / Clean Architecture, and what I teach to my students.
With the notable benefit of being able to test your Domain Model independently from the low-level technical concerns.
And being able to swap out your ORM/Database Engine if necessary.
And being able to run your code locally or inside an airplane with no internet access, since the gist of your code is implementation independant.

The only caveat is how your code is a little bit more difficult to navigate because from your domain model point of view, you can't know which implementation will be called.
In practice you rarely have more than two implementations (in memory & concrete) so it's seldom a problem.

That's a good trade given all the benefits you gain (testability, reusability...).

ancyracademyfr
Автор

The problem with Blow is that his statements are weak and don't solve anything. Yeah, sure, you can just focus on solving the problem, but it doesn't automatically mean that the problem solution will be easy to maintain and to reuse. That's why paradigms and software-architectures were invented in the first place.

SnakeEngine
Автор

I think the main take away is that only HUMANS care about objects. It's more in line with how we model the environments around us. But an "object" from our heads can only ever be _grafted onto_ problems in computer space. I think OO offers itself really well to situations where there is a real-world system already in place that your program is modeling and "objects" in your code line up with actual real objects in that system. It's also pretty good for setting up guide rails for other developers, but if those guide rails are bad then new devs will inherit bad practices.

For solving a single well-defined problem, I think sticking with procedural programming is the way to go. Starting with OO will cause you to set up arbitrary walls to stay confined in when you should just be focusing on raw problem solving. Procedural lets your solution change shape at will so you can really explore the problem space.

benbowers
Автор

These tidbits of information have persisted from among the elder members of the programming community, they are exceptionally valid here. Abstractions should be useful, classes are abstractions. Prefer the free function unless you have something you actually need to encapsulate. There is nothing wrong with accessing a class/struct data member without getters/setters if you don't need them.

multiHappyHacker
Автор

In my 13 years of professional programming, I have never once had a problem that OOP made easier. But I've had plenty that it made harder. It doesn't remove complexity, it just scattered it to the winds and makes it impossible to reason about.

ycombine