Inheritance was invented as a performance hack (2021)

catern.com

194 points by aquastorm a month ago


roenxi - a month ago

I'm not sold the evidence is there to show inheritance is a good idea - it basically says that constructors, data storage and interfaces need to be intertwined. That isn't a very powerful abstraction, because they don't need to be and there isn't an obvious advantage from doing so over picking up the concepts separately as required. And inheritance naturally suggests grouping interfaces into a tree in the way that seems of little value because in practice a tree probably doesn't represent the fundamental truth of things. Weird edge cases like HTTP over non-TCP protocols or rendering without screens start throwing spanners into a tree of assumptions that never needed to be made and pull the truth-in-code away from the truth-in-world.

All that makes a lot of sense if it was introduced as a performance hack rather than a thoughtfully designed concept.

dang - a month ago

Discussed at the time:

Inheritance was invented as a performance hack - https://news.ycombinator.com/item?id=26988839 - April 2021 (252 comments)

plus this bit:

Inheritance was invented as a performance hack - https://news.ycombinator.com/item?id=35261638 - March 2023 (1 comment)

smallstepforman - a month ago

There is this wonderful presentation by Herb Sutter talking about how the C++ concept “class” covers over 20 other abstractions, and that Bjarne’s choice for C++ was the right choice since it offers so much power and flexibility and expressive power in a concise abstraction.

Other languages (just like the article) only saw the downsides to such a generic abstraction that they added N times more abstractions (so split inheritance, interfaces, traits, etc) and rules for interactions that it significantly complicated the language with fundamentally no effective gains.

In summary, Herb will always do a better job than me explaining why the choices in the design of C++ classes, even with multiple inheritance, is one of the key factors of C++ success. With cppfront, he extends this idea with metaclasses to clearly describe intent. I think he is on the right track.

virgilp - a month ago

I find that structural typing is the most useful thing and unfortunately few languages support it. I'd like a language where:

- If I have a class Foo and interface Bar, I should be easily able to pass a Foo where Bar is required, provided that Foo has all the methods that Bar has (sometimes I don't control Foo and can't add the "implements Bar" in it).

- I can declare "class Foo implements Bar", but that only means "give me a compilation error if Bar has a method that Foo doesn't implement" - it is NOT required in order to be able to pass a Foo object to a method that takes a Bar parameter

- Conversely, I should be able to also declare "interface Foo implementedBy Baz" and get a compilation error if either one of them is modified in a way that makes them incompatible (again - this does not mean that Baz is the _only_ implementor, just that it's one of them)

- Especially with immutable values - the same should apply to data. record A extends B, C only means "please verify that A has all the members that B & C have, and as such whenever a B record is required, I can pass an A instead". I should be able to do the reverse too (record B extendedBy A). Notably, this doesn't mean "silently import members from B, and create a multiple-inheritance-mess like C++ does".

(I do understand that there'd be some performance implications, but especially with a JIT a feel these could be solved; and we live in a world where I think a lot of code cares more about expressiveness/ understandability than raw performance)

cturner - a month ago

We use the word inheritance to refer to two concepts. There is implementation-inheritance. There is type-inheritance. These ideas are easily confused, which should be cause to have distinct words for them. Yet we don't. (Although Java does, effectively)

chuckadams - a month ago

I think a lot of the arguments against inheritance come from C++'s peculiar implementation of it, which it clearly, ah, inherited from Simula. Slicing, ambiguous diamond inheritance, stuff like that are C++ problems, not inheritance problems. This isn't to say inheritance isn't problematic, but when you're making a properly substitutable sub-type of something, it's hard to beat.

rakejake - a month ago

IMHO Inheritance (especially the C++ flavored inheritance with its access specifiers and myriad rules) has always scared me. It makes a codebase confusing and hard to reason with. I feel the eschewing of inheritance by languages such as Go and Rust is a step in the right direction.

As an aside, I have noticed that the robotics frameworks (ROS and ROS2) heavily rely on inheritance and some co-dependent C++ features like virtual destructors (to call the derived class's destructor through a base class pointer). I was once invited to an interview for a robotics company due to my "C++ experience"and grilled on this pattern of C++ that I was completely unfamiliar with. I seriously considered removing C++ from my resume that day.

impure - a month ago

Huh, I was always told that inheritance hurt performance as it requires additional address lookups. Thats why many game engines are moving away from it.

I guess it could simplify the GC but modern garbage collectors have come a long way.

shadowgovt - a month ago

Fascinating.

Interestingly enough, my first non-class-related experience with "intrusive lists" was in C, and we implemented it via macros; you'd add a LINKED_LIST macro in the body of a struct definition, and it would unspool into the pointer declarations. Then the list-manipulation functions were also macros so they would unspool at compile time into C code that was type-aware enough to know where the pointers lived in that individual struct.

Of course, this meant incurring the cost of a new definition of function families for each intrusive-list structure, but this was in the context of bashing together a demo kernel for a class, so we assumed modern PCs that have more memory than sense. The bigger problem was that C macros are little bastards to debug and maintain (especially a macro'd function... so much escaping).

C++, of course, ameliorates almost all those problems. And replaces them with other problems. ;)

wonderwonder - a month ago

Favorite part of this is that I had no idea if this article was going to be about biology, code or money. I love a good surprise

juped - a month ago

All of what we take for granted in modern computing architecture was invented as a performance hack by von Neumann in 1945 to take advantage of then-novel vacuum tube tech.

wy2010344 - a month ago

I think inheritance should be completed in one go like SQL database operations, but the code needs to be maintained and records the entire transformation history, so I can't figure out the intention of my predecessors and dare not change it easily.

dboreham - a month ago

Before my time but I reject the idea that inheritance was "invented" in the context of a particular high level programming language. It was used widely in assembly/machine code programming. It's essentially a manifestation of two things: categorization of things (at least thousands of years old); and pointers to data structures (at least as old as the Manchester Mk1).

ogogmad - a month ago

What do folks think of the OCaml/SML style approach with its signatures+modules+functors? It's a bit obscure, and some people find it inconvenient. Inheritance in their approach can be approximated using functors.

austin-cheney - a month ago

I always thought this was common knowledge. I guess it isn’t.

The only reason inheritance continues to be around is social convention. It’s how programmers are taught to program in school and there is an entire generation of people who cannot imagine programming without it.

Aside from common social practice inheritance is now largely a net negative that has long outlived its usefulness. Yes, I understand people will always argue that without their favorite abstraction everything will be a mess, but we shouldn’t let the most ignorant among us baselessly dictate our success criteria only to satisfy their own inability to exercise a tiny level of organizational capacity.

simonebrunozzi - a month ago

I know we're on Hacker News, but I would have preferred a more explicit title (programming language, not wealth across generations).

Lirael - a month ago

[flagged]

curtisszmania - a month ago

[dead]

vangphong - a month ago

[flagged]

adornKey - a month ago

Performance is not a hack. Title is wrong... ;-)

Interfaces are indeed much nicer, but you have to make sure that your program language doesn't introduce additional overhead.

Don't be the guy that makes Abstract Factory Factories the default way to call methods. Be aware that there are a lot of people out there that would love to ask a web-server for instructions each time they want to call a method. Always remember that the IT-Crowd isn't sane.

steviee - a month ago

This title is so wild when you read it without the context of software development...

masfoobar - a month ago

I think many developers, especially in the range on 1999-2020, has gone through many pitfalls in programming. More specifically.. OOP.

As someone who was blessed/lucky to learn C and Pascal.. with some VB6.. I understood how to write clean code with simple structs and functions. By the time I was old enough to get a job, I realised most (if not all) job adverts required OOP, Design Patterns, etc. I remember getting my first Java book. About 1,000 pages, half of which was about OOP (not Java directly)

I remember my first job. Keeping my mouth shut and respecting the older, more experienced developers. I would write code the way I believed was correct -- proper OOP. Doing what the books tell me. Doing what is "cool" and "popular" is modern programming. Hiding the data you should not see, and wrapping what you should in Methods... all that.

Nobody came to me and offered guidance but I learned that some of my older codebase with Inheritence, Overrides.. while it was "proper" code, would end up a jumbled mess when it required new features. One class that was correctly setup one day needed to be moved about, affecting the class hierarchy of others. It brings me back to thinking of my earlier programming days with C -- and to have things in simples structs and functions is better.

I do not hate on OOP. Afterall, in my workplace, am using C# or Python - and make use of classes and, at times, some inheritence here and there. The difference is not to go all religious in OOP land. I use things sparingly.

At work, I use what the Companies has already laid out. Typically languages that are OOP, with a GC, etc. I have no problem with that. At home or personal projects, I lead more towards C or Odin these days. I use Scheme from time-to-time. I would jump at the opportunity to using Odin in the workplace but I am surrounded by developers who dont share my mindset, and stick to what they are familiar with.

Overall, his Conclusion matches my own. "Personally, for code reuse and extensibility, I prefer composition and modules."