Live data from Hacker News

Case against OOP is understated, not overstated (2020)

boxbase.org

511–520 of 557 posts

Re: Case against OOP is understated, not overstated (2020)

#511
post #391

Earlier quoted context omitted.

> only exist to mutate state Which part of the state, and when? Is this your program? // change anything, anywhere, in the entire database, the biggest state execute_sql(user_input) You might want controls around that state so not anyone can change it. It might be read only for some users - that is, immutable. Is this your program? log_to_database(financial_event for $5.00) You probably want your financial logs to be…

Try instead this for pure function: thread safe radix trie supporting ins, del, find. Purpose exclude blacklisted ip addresses. Go!

This question was not snark for FP pure functions or otherwise; no ill-will! It needs a legit answer maybe with a small lecture on why radix trees can be FP not pure FP. Hey, I can read and learn.

Other sorts of streaming operations --- message in, transform to new object which is logged or put into a data store most certainly do not need mutation so long as they are cache friendly, performant. FP and friends might even argue: yah ok it's some 10 pct slower but no race conditions, no weird sync. Formal methods are easier there to deploy. Those secondary arguments can be effective too; I'd bite

Re: Case against OOP is understated, not overstated (2020)

#512
post #482

Earlier quoted context omitted.

You are building a straw man from your misunderstanding of the OOP technique. As 'dragonwriter' tried to explain it to you that mathematical model of a square being a kind of a rectangle has nothing to do with OOP modeling. Liskov substitution principle tells you that a rectangle cannot be a super class of a square.

If modeling taxonomies of the world is not OOP modeling, what is exactly? The very reason Barbara Liskov had to point out the damn principle is that people were doing dumb stuff like this. They still do btw. Universities still teach that Mammals have a walk() method that you implement for Dog and Cat, except then you need to add a Whale and now you're screwed. Silly example, but real world cases are much more subtle.…

>If modeling taxonomies of the world is not OOP modeling, what is exactly?

You are still focused on a mathematical property of a square being a special case of a rectangle. Inheritance is not the tool to model such a relationship. Again it has nothing to do with taxonomy.

>Universities still teach,...

The same people teach functional programming with silly recursion examples and linked lists being the most important data structures.

OOP code can be convoluted, but a large imperative mess is worse. I haven't seen any large collaborative project written in a purely functional language, so I can't comment about that.

Re: Case against OOP is understated, not overstated (2020)

#513
post #506

Earlier quoted context omitted.

A1) No. A2) Because it's about 1,000x to 10,000x more efficient. An awful lot of the "ills" of modern development practices boil down to the lack of ingrained rules of thumb related to performance. The difference between a local function call -- virtual or not -- and a network call can easily be a factor of a million . This just isn't in the mental model of most developers. The terms "nanoseconds" or "clocks" are not…

I mean, if you really care about performance, object-oriented is a poor choice as it doesn't map well onto the GPU.

OO runtime dispatch as implemented by C++ via "vtables" of function pointers doesn't even map well to CPUs! The indirection via a data pointer that can change unpredictably is terrible for pipelined architectures. Similarly, this approach generally prevents inlining, especially across dynamic library boundaries.

However, many languages and even C++ with modern compilers can pull tricks to mitigate this. For example, static analysis can often be used to replace virtual calls with direct ones. Similarly, functions can be inlined in many cases, such as a "leaf" class in a hierarchy calling itself.

Languages with "virtual machine" runtimes such as Java and C# can potentially optimise even dynamic scenarios. Java certainly does in some cases.

I think the ideal OO framework would actually be more like what Rust does with traits. Have static dispatch as the default at runtime, but with the traditional OO model of interfaces, classes, derived classes, etc... Dynamic dispatch should be an option, but not the default. Ideally, dynamic dispatch should be used only on the boundary of binary modules such as DLL files or kernel-to-user-mode ABIs.

Note that OO was also designed to reduce compilation times by decoupling implementation from use. So if developer A updates an implementation (class/struct) of an interface/trait, then developer B using that interface can use incremental compilation without having to recompile the usages of the interface! This saves a lot of time for large code bases.

One reason Rust is notoriously slow to compile is because it always recompiles everything -- both implementation and usage of interfaces.

Again, a hybrid approach could work: dynamic dispatch by default for debug builds to enable efficient workflows, and static dispatch by default for release builds for runtime performance at the cost of longer build times.

Re: Case against OOP is understated, not overstated (2020)

#514
post #484

Earlier quoted context omitted.

What have you solved by having squares and rectangles as PODs? Now you won't be able to treat them as same in some way (e.g. IShape, IDrawable, IPrintable, IArea,...) and you will need twice as many functions for doing same things.

If you make a square and a rectangle into IShapes (with no inheritance hierarchy) you still need 2 separate implementations for GetWidth(). Either way, it's simply not true that you can't treat them the same way because you've made them PODs, there are more kinds of polymorphism beyond subtype polymorphism. Even for the latter modern languages split the data (structs) from the behavior (traits/protocols), see Rust or…

Everything you are describing is still OOP. Again, inheritance in not necessarily the best tool to model all relationships.

Re: Case against OOP is understated, not overstated (2020)

#515
Tl;dr: [nothing, really.]

"(Anything)-oriented programming" is obviously stupid: the world doesn't conform to your (anything), whichever you choose. QED, an (anything)-oriented programming language will be the wrong thing most of the time.

A general-purpose programming language needs to provide support for solving actual problems, whatever they are. Any program big enough to be interesting addresses sub-problems of different kinds, that each need their own treatment. Most problems benefit from a mix of approaches.

Once in a while objects are exactly the right thing. Then, if your language has stuff for that, lucky you; otherwise you need to cobble something together. Likewise, when any other formalism matches.

Almost always when people complain about OOP, it is because they want their (other-thing)-oriented language to get respect. That does not end well: the same arguments against OOP apply equally well to their thing, given trivial adjustments.

So, nothing to see here.

Re: Case against OOP is understated, not overstated (2020)

#516

Earlier quoted context omitted.

I completely agree with this. I love writing functional Java. The issue is mutation, not OOP

Would you have any resource on functional Java? My experience with 8 and onward is better for sure. I find myself writing more robust filtering / map-reduce logic. But that’s kind of it. For instance I don’t feel like function are first class citizen still. ( I almost never user higher order function in Java, even if it’s possible )

Effective Java [0] is the single most important book I can recommend for any Java programmer. This article [1] gives an overview of some of the primitives you can use for writing functional Java. Lombok [2] is a very common library that makes writing functional Java much more ergonomic with its `@Value` annotation, but that might not be needed anymore with Java 14's Record types [3].

The book Clean Code [4] helped me a lot to really learn how to write clean Java, and many of these ideas directly translate into writing good functional code. One of the key takeaways was just how small functions should be which incidentally is a great thing to learn when functions are your main unit of composition.

Java isn't a purely functional language, so you obviously will always have some impurity regarding state/mutation. I personally try to do the following: 1. Keep all state in some top-level class and let everything else be immutable 2. Nearly every class I write is immutable 3. Follow common OOP principles like SOLID 4. Write reactive code with heavy use of Optional and Streams

Here's [5] an example repo of board game written using those ideas.

[0] https://www.oreilly.com/library/view/effective-java/97801346... [1] https://www.baeldung.com/java-functional-programming [2] https://projectlombok.org/ [3] https://www.baeldung.com/java-record-keyword [4] https://smile.amazon.com/Clean-Code-Handbook-Software-Crafts... [5] https://github.com/harding-capstone/logic

Re: Case against OOP is understated, not overstated (2020)

#517
post #177

Earlier quoted context omitted.

https://en.wikipedia.org/wiki/Julia_(programming_language)

> Performance approaching that of statically-typed languages like C I might have to give this a try. Is there any language other than assembly that can beat the performance of C?

[deleted]

Re: Case against OOP is understated, not overstated (2020)

#518

Earlier quoted context omitted.

> Were there ever any real objective [hah] studies done about how much it improved software development? And did they show a significant improvement? I think years of hard experience across the industry found out that, for example, multiple inheritance and operator overloading caused more problems than they solved. Both features were taught and advocated back in the day, and now "there be dragons" signs have sprung u…

> operator overloading caused more problems than they solved [citation needed] Just because operator overloading can be abused doesn't mean that it isn't a massive boon in certain problem spaces (e.g. math libraries, SIMD libraries, etc.)

I mean, the standard way to do IO in C++ involves spamming the left shift operator (1. translating format strings to other languages is extremely difficult because the position of expressions in the message is fixed.

2. modifying how things are printed requires modifying global state, and it's easy to forget to reset the flags on std::cout after setting the precision of floats or something.

There's also the famous question of "what does the multiplication operator do on vectors?" problem, but that's something that could be solved by simply having a standard "vector" interface that defines it in a particular way. Overall I don't fully disagree, but seeing as it happened once with C++, I can imagine it can happen again in some equally widespread language (Javascript with it's + operator on strings maybe?).

Re: Case against OOP is understated, not overstated (2020)

#519
post #269
post #51

Earlier quoted context omitted.

Games are actually moving away from OOP by separating out state into a data oriented system.

But aren't they doing that mostly for performance via better memory layout and thus better cache locality? ie: arrays of objects vs objects of arrays. It's a sacrifice of code architecture for performance. I feel like games are actually a good example where OOP makes sense, since there is inherently so much state and encapsulation is useful.

It's every game dev's first mistake to start adding, say, weapon types to their game by first creating an Item class, then creating a Weapon subclass, Sword inherits that, Shortsword inherits that... And so on. Makes sense, right? It's exactly what OO is for.

Except games rarely have that rigid a structure, and maybe you want a sword that also has laser gun features, or an axe that's also a magic staff. That's a lot of subclassing and further dividing up your game objects into rigid hierarchies that become difficult to modify later without unintentionally breaking stuff (was it the logic in the Sword class that grants that damage bonus, or in the Weapon class?)

It's nicer to be able to say "I have a weapon entity, I'm going to attach the `SliceDamage" component, the "MagicAttack" component, and so on, and call it a magic axe. It's easier to maintain, it can change at runtime, and the behaviour code only exists in a component file that only does that behaviour, rather than nestled in some lowest common denominator of a hierarchy of classes.

Re: Case against OOP is understated, not overstated (2020)

#520

Earlier quoted context omitted.

> No major game engine has a finished ECS system yet. The major engines may not have ECS built in, but some of them are supported by ECS systems that are readily available. Your implicit restriction of professional gamedevs to include only people who both use a major game engine but don't use third party components not supplied by the engine is, I think, overly restrictive.

I expect the programmer who liked working with an ECS system would have a hard time making a business case for taking on the additional risk of a third party ECS foundation. A traditional OO architecture will provide all the performance you need to create a modern Simcity style game without having to take on the additional problems of potential bugs in the underlying code, training everybody to understand and use it,…

There are a tonne of open source, MIT licensed ECS libraries in pretty much every language you can write a game in. And, at the end of the day, ECS frameworks aren't all that complicated at their core, it's not hard to roll your own, though libraries will have better querying features and optimisations.

The benefit is to the developer, arguably the most important part of the game development process. It can save a lot of headaches that OO hierarchies can create, makes things more easily concurrent, allows for more flexibility in behaviour and emergent gameplay.

ECS helps to prevent bugs in game object logic, by keeping state and behaviour separate from its corresponding entity. If I'm looking for some behavior, I don't have to start thinking about which ring of the inheritance chain it ended up on, I just find the component or system that does that thing. It encourages you to write state and behaviour in a way that works with any entity and can be attached to anything at any time without crashes and state mutation problems or race conditions.

Post reply on HN