Live data from Hacker News

The Case Against OOP Is Wildly Overstated

medium.com

171–180 of 312 posts

Re: The Case Against OOP Is Wildly Overstated

#171
post #3

Earlier quoted context omitted.

That sounds snarky. Not sure if that was intended or not, but regardless I read your comment as: "OOP is good when you use the object oriented structure as a tool to organize your code and data to solve a problem, but not when you try to wrap your solution or your conception of the problem itself around OOP." It's 2020, and after 50+ years of programming language research I think it's safe to say that there is no "on…

i would make a distinction that data and state are two different things and argue that a lot of the mess people create with OOP is due to confusing the two. data is what exists externally to your program while state is strictly internal to your program. inputs and outputs of your program are data and not state by definition. applying OOP principles to data is an unmitigated disaster and is the source of most of the p…

I concur, at most state and data should be related is by viewing incoming data as your initial state.

Data is immutable.

Re: The Case Against OOP Is Wildly Overstated

#172

Earlier quoted context omitted.

I'm not the one you're asking. But... Here's a data structure that represents a bill of materials. It has a list of components, and a total cost, which is the sum of the costs of the components on the list. That's the invariant - that the total cost is the sum of the costs of the components in the list. If it's just a structure, then someone can add or remove a component, and forget to update the total cost, and the…

Actually my response would be that you just have a plain-ish vanilla list of `Component`, and a function `TotalCost(List[Component]) -> float`, which is implemented as, approximately, lambda arr: sum(x.cost for x in arr). This maintains the invariant without state. There's a potential performance cost here, but that usually doesn't matter a whole lot.

That's true - but where do you put the function? In a complex system I can end up with loads of these totalling functions scattered about. I might have gross and net versions of the total and, given human nature, they get created near the use of them. The variants then get duplicated. The objects give you a modular structure which means you can see the interface.There is a disconnect when you have to shift to the object - but you can also see when to refactor.

Re: The Case Against OOP Is Wildly Overstated

#173
There is a lot that is problematic with OO, especially if it is adhered to with dogma. The worst idea and the one I've experienced most issue with, is the `extends` keyword in Java, and more generally, the concept of inheritance.

Inheritance is terribly overused, and tends to lead to code spaghetti and testing nightmares. Hierarchy is a mental trick we pull on ourselves to make sense of the world, but it rarely works out nicely in systems.

Re: The Case Against OOP Is Wildly Overstated

#174

Earlier quoted context omitted.

Essentially, yes, but in a way that sounds more careful than what you saw in that Fortran program. If it absolutely has to be stateful, like with a db connection for example, then there's no getting around that, but what you can do is (1) not bury it in a bunch of stateful objects that didn't have to be stateful, which can cause cascading errors when either one of them misbehaves and also makes it difficult to isolat…

More concretely, for every bit of state in the program I'm interested in two big questions, each with two subquestions: 1.) Who can access this state, and which of those accesses allow writes vs. which are read-only? 2.) What is the lifetime of that state, and what portion of that lifetime is mutable vs. read-only? Java-style OOP can control #1, but makes no distinction between reads & writes. C++ const correctness a…

Pure functional languages are capable of this, although they likely aren't modeling it as you envision. Pure record constructors let you do perform arbitrary mutation on the stack (e.g. calling other functions to build field values), but once the constructor is called the returned reference is immutable.

This is likely cleaner than sharing a reference which is sometimes mutable and sometimes not. Rust of course allows for both mutable and immutable borrows, and that's a very powerful tool but it'd be complex if all you needed was field initialization.

The consensus across languages that's emerged is that initialization shouldn't be a group effort, with references escaping in various stages of partial initialization. Be it RAII in C++ or functional record constructors, the common theme is that initialization should be a single operation that can succeed or fail as a whole.

Re: The Case Against OOP Is Wildly Overstated

#175

Earlier quoted context omitted.

I think the key differentiater is that OOP (in some versions) wants to hide the data and not just implementation details. For example, a hash map data structure hides the details of how the hash map is implemented, but it doesn't hide the data. In some versions of OO, the object should not only hide the implementation details but also the data. Any function that needs that data MUST be a method of that object. That's…

In what versions of OO does a hash map hide the data? The definition of a map requires that you can access the data.

The data is accessed through an interface, a set of functions associated with the data structure. You don't dig through internal memory structures to get the data - you call these functions. That is what "hidden" means in this context.

A better example might be a linked list. With information hiding, you manipulate the list through functions like push and pop. Without information hiding, you manipulate the pointers directly. For instance, I've worked on C codebases where linked list manipulation isn't even hidden behind macros.

Re: The Case Against OOP Is Wildly Overstated

#176
post #163

Earlier quoted context omitted.

I'm not the one you're asking. But... Here's a data structure that represents a bill of materials. It has a list of components, and a total cost, which is the sum of the costs of the components on the list. That's the invariant - that the total cost is the sum of the costs of the components in the list. If it's just a structure, then someone can add or remove a component, and forget to update the total cost, and the…

For what it’s worth, with ADTs and non-exposed constructors you can achieve the same result (i.e. only the creating module can actually _build_ such a list but other modules can read the data).

Sure, there are usually equivalent mechanisms in all languages, because it is a good pattern. And yes, especially in OOP purism, it can also go over board, but there are absolutely use cases where tightly binding data and code is very useful (whether you do it with private members, ADTs, forward structure declaration, name mangling etc is less relevant, I think).

Re: The Case Against OOP Is Wildly Overstated

#177
post #55

The author flatly says "do not use inheritance." Without inheritance and polymorphism, what is left in OOP? If you look at the author's 4 pillars, the only thing left is encapsulation (and "Oversimplified Hot Takes") It seems like the author himself has proven why OOP is bad. You can have encapsulation without OOP. People were doing it in C 40 years ago. And people are doing it in Go right now. No one would call Go a…

Is OOP just syntactic sugar once you remove bad practices? I don't think so, but there's definitely an argument there. But on the issue of inheritance, what I'm trying to say is "not a good idea for the average business developer, but still a great tool for careful, ambitious developers designing the OO frameworks that business developers will use."

Re: The Case Against OOP Is Wildly Overstated

#178

Earlier quoted context omitted.

You might want to consider examining another programming language for clues here. Perhaps look to a language that has a more modern approach to state such as Clojure.

My understanding is that Clojure is basically lisp implemented inside the Java ecosystem. I'm not sure how that makes it "modern" given that the only higher level language older than lisp is the original version of Fortran.

Once you have some understanding of the state management facilities native to Clojure, you might be willing to concede the "modern" adjective.

Re: The Case Against OOP Is Wildly Overstated

#179
Pretty good takes here in the comments (shout out to references to "pit of success")

There are two things worth mentioning, though.

1) the best pragmatic programming recommendation is "semantic compression" by Muratori [1]. Incidentally, I find it to be an effective "takedown" of the sort of dogmatic oop that anyone criticizing oop is criticizing

2) Muratori might disagree with this, but for me the whole point of a new class (type) is new invariants [2]. If you need a new invariant, you make a new type. Sticking to this principle has helped me keep classes small and focused without really thinking about other things like "single responsibility". There are a few exceptions (eg you might need a new type to work with a particularly clunky API, like some Map Reduce ones), but it's really that simple.

As a bit of an aside, the worst code I have written hasn't been purely OO nor purely functional. It's been when I've mistakenly tried to add new ideas to existing code that break the paradigm.

[1] https://caseymuratori.com/blog_0015

[2] https://en.m.wikipedia.org/wiki/Class_invariant

Re: The Case Against OOP Is Wildly Overstated

#180
OOP is perhaps not the best abstraction for distributed computing where you want maximize data flow and minimize distributed state. The slowdown of Moores Law for a single core/node means performance improvements will distribute computing among a large number of such units.
Post reply on HN