News for hackers. Stuff that matters.
Re:The Case Against OOP Is Wildly Overstated by AnimalMuppet on Friday July 31, 2020 @02:11PM (#24011685)
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 invariant is violated. But if it's an object, if the code is bound to the data (in the way OOP normally calls encapsulation), then only the member functions can modify the structure. So if you want to add a component, you have to use the object's addComponent method, which (in a properly debugged object) isn't going to forget to update the total cost.

Now, you could say that the structure could have a code library to go with it, and that could have an addComponent function. That's true. But the user doesn't have to use that function - they can mess with the list directly, if they think they know what they're doing. Whereas with OOP encapsulation, they have to use the existing function. That function can guarantee that the object's invariants are maintained.

Re:The Case Against OOP Is Wildly Overstated by correct_horse on Friday July 31, 2020 @04:17PM (#24013443)
This is generally accurate, but I want to highlight the awesomeness of opaque structs. In C you can declare a struct in a header file, but not its fields ie struct point;. Then in the corresponding c file you can write out the whole definition ie struct point {x: float; y:float;};. Any code that includes the header can pass pointers to struct point (or pointers to pointers, etc) but can't directly pass points around because the compiler doesn't know their size.

All this said, this is basically OOP in C, and the code is still bound to the data, only it is bound by naming (point_add()) not by a scope (point.add()).

Re:The Case Against OOP Is Wildly Overstated by thebruce87m on Saturday August 01, 2020 @08:25AM (#24019943)
Isn’t this the way C++ operates under the hood, with the “this” pointer hidden?

I love opaque structures, but the one downside in embedded is they can’t be truly opaque since you want to avoid dynamic memory allocation - and therefore the place you instantiate the struct needs to know the size, and therefore members of the struct.

Re:The Case Against OOP Is Wildly Overstated by mhoad on Friday July 31, 2020 @06:45PM (#24015124)
This might sound stupid but I have ONLY ever known OOP in the Ruby / C++ / Java sense before but this idea blew my mind as such an interesting and different way of thinking about it and I can't tell if it is just my own bias but my initial thought is that it seems like such an additional level of mental overhead that you would always have to carry around on top of everything else you already have to think about. I assume that becomes easy with time?
Re:The Case Against OOP Is Wildly Overstated by lmm on Friday July 31, 2020 @09:59PM (#24016668)
It's the opposite - you can spend less time worrying about the details because you know they're opaque. It's like how in Java it can actually be easier to work on a generic datastructure (e.g. a tree) than a more concrete implementation (e.g. a tree of integers) - the generics force you to cleanly separate the structure-specific parts and the value-specific parts and not get them mixed up.

You can achieve the same kind of hiding in Java by using an existential type. E.g. you could have a library that looked like:

    interface Cursor<T> {
      T start();
      T nextStep(T currentState, int move);
      void finish(T);
    }
    class DataStructure {
      Cursor<?> traverse();
    }
And then you don't know what the internal state of the cursor is because the T type is hidden from you, but the compiler checks that you always call nextStep() with the same state you got back from start(), and you can't possibly mix up the state from two different cursors.
Re:The Case Against OOP Is Wildly Overstated by thu2111 on Saturday August 01, 2020 @06:53AM (#24019461)
It's just an attempt to make C slightly more OOP without using C++. A very common design pattern in GNOME, for instance.
Re:The Case Against OOP Is Wildly Overstated by ghayes on Friday July 31, 2020 @02:32PM (#24012006)
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).
Re:The Case Against OOP Is Wildly Overstated by zozbot234 on Friday July 31, 2020 @03:06PM (#24012569)
"Abstract data types and non-exposed constructors" is enough to give you object-based code, which is not too far from a definition of "the good parts" of OOP. Though some could quibble that "object-based" doesn't include sensible ideas such as composition, interface inheritance, delegation etc.
Re:The Case Against OOP Is Wildly Overstated by chriswarbo on Friday July 31, 2020 @03:42PM (#24013021)
Classes can be used as modules, as namespaces, as datatypes, for encapsulation, etc. The problem is they're not particularly great at those things, and those concerns often become conflated.
Re:The Case Against OOP Is Wildly Overstated by tsimionescu on Friday July 31, 2020 @02:55PM (#24012399)
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 by camgunz on Friday July 31, 2020 @03:35PM (#24012937)
I think people in general are pretty OK with the data hiding part of encapsulation. Scattering application state across objects as part of encapsulation, and polymorphism and inheritance are the source of a lot of debate though. Bob Nystrom wrote the best description of the polymorphism vs. pattern matching tension I've ever read [1], and I think problems w/ inheritance are all pretty well known (method resolution, programmers becoming taxonomists, etc.)

[1]: https://craftinginterpreters.com/representing-code.html#the-...

Re:The Case Against OOP Is Wildly Overstated by joshuamorton on Friday July 31, 2020 @02:35PM (#24012070)
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.

Re:The Case Against OOP Is Wildly Overstated by TimMurnaghan on Friday July 31, 2020 @02:51PM (#24012350)
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 by joshuamorton on Friday July 31, 2020 @03:08PM (#24012596)
There are a few answers for this: you might include common ones in the same file as the struct (see rust for how this looks, usually).
Re:The Case Against OOP Is Wildly Overstated by zozbot234 on Friday July 31, 2020 @03:09PM (#24012607)
> This maintains the invariant without state.

Yes, but this is not possible in general. For instance, what if you want to endow your List with a "MaxTotalCost", set at creation. You can't ensure that your list respects that invariant, other than by encapsulating it behind some custom interface.

Re:The Case Against OOP Is Wildly Overstated by joshuamorton on Friday July 31, 2020 @03:24PM (#24012814)
That's true, although it raises a question: is the maximum you're willing to spend a trait of your bill of materials (I'd argue no), or of some other thing, for example your overall project. In that case you could have a method that validates your BOM against your project requirements.