Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Let me try to list the objections:

1. Inheritance creates dependencies on their parent class

2. Multiple inheritance is hard

3. Inheritance makes you vulnerable to changes in self-use

4. Hierarchies are awkward for expressing certain relationships

All true. But likewise, functions introduce dependencies on their arguments, and data structures introduces dependencies on their fields. You must consider your dependencies carefully when designing any software interface.

The task of software architecture is not to go around categorizing everything into a taxonomies. Inheritance is just one tool in your software interface toolbox.

5. Reference semantics may result in unexpected sharing

This has more to do with reference semantics than objects.

6. Interfaces achieve polymorphism without inheritance.

Interfaces long for inheritance-like features. For example, see Java 8's introduction of default methods, or the boilerplate involved in implemetning certain Haskell typeclasses.



I think that inheritance and composition are not the interesting aspects of object oriented design, or of any language or paradigm. These are tools for code brevity / reuse / elegance. Advanced copying or ctrl-c.

I would also argue that too much elegance in any language or design paradigm faces the same problem, in that elegance is often (but not completely) in tension with modularity or granularity of control, which is an engineering subgoal, because a common engineering situation is to experience system change (feature growth or reorganization of code), and improvements in granularity or modularity makes system restructuring easier.

I think that object oriented design is more essentially about modelling distributed state, because you probably have multiple objects with their own internal state. I believe this means that object oriented design is highly concerned with protocolized communication and synchronization between distributed states, whether via messages or channels or something else.

I believe that in distributed situations, object oriented design can be very harmonious with functional reactive programming strategy. You can easily and usefully have a situation where an object functionally updates its internal state with a typed stream of inputs.


That is a good analysis. While I was reading this article all I could think is "You wanted to do things in a bad way and then you learned how to do it the right way and you don't like the right way?"

His entire problem seems to be he thought OO was a magic bullet he could do whatever he wanted with and then he learned there was more to using OO than the three concepts he cites at the beginning.

And this guy has supposedly been writing in OO languages for decades? What?


> And this guy has supposedly been writing in OO languages for decades? What?

This is the bit i don't get. It's like he learned OOP in the '90s, when everyone thought inheritance was rad and nobody had realised how terrible mutating shared state was, and then fell asleep for twenty years. None of this article, none of it, has any relevance to how OOP is practiced by informed people today.


The keyword there is informed. There are still plenty of shops that practice OOP this way. I'm working at one right now and there are OOP horrors around every corner.

Unfortunately, they seem intent on adding more mutable state rather then eliminating it.


Do you have anecdotes you can share? :D


Quite a few, but the worst would be the custom logger. I got lost trying to trace the inheritance graph. which spans projects, and the dependency graph, loggers within loggers within loggers. I gave up when I ran out of space trying to sketch the relationships in my notepad.

Being encapsulated means you don't actually have any control over the logger, or the threads it spins up. Creating a logger for a new app requires inheriting from a application logger (which is already 3 or 4 layers deep in the inheritance hierarchy.

The distinction other loggers make between the log interface and the appenders are non-existent. If you want to log to a new source (say the event log) you have to add a new layer to the inheritance tree.

Then there's the fact that it's handling the application state, in an "on error resume next" kind of way. And this is a global state, so don't even think about multi threading.

Naturally, actually accessing the logger is done via a singleton.

It causes more problems than it helps resolve, and the ones it causes naturally don't have an diagnostic information available.

There are plenty of others, but it's hard to top this tour de force of OO anti patterns. If only there was some free and stable alternative...


> If only there was some free and stable alternative...

There's no shortage of good-enough loggers out there for major languages.


The ellipsis in this case appears to me to be a sarcasm indicator, not a real wish.


> It's like he learned OOP in the '90s

Well, if he's been doing OOP for decades, isn't that likely to be the case?


People use that crap today. Ever take a shake at wpf for windows? It's a fucking mess.


I read it slightly differently. The author has an internal notion of what "good" programming is, that appears to contain the concepts "compact", "correct", and "uniform".

For compact, a "good" program converts the expression of intent (the source code) into the execution (executable) into a package of data in which both statically (being loaded, being resident) "good" is defined by the minimum use of resources, and dynamically (while running) it minimizes its resource usage (and thus is "fast").

For correct, a "good" program works the same way every time you compile it and run it. Good in this case would be systems which notify you of changes which can affect the existing compiled code.

And for "uniform" the same syntax or tools are applied in the same way for all idioms. "Bad" here is the number of special cases that have to be accounted for (or inversely good is the lack of special cases).

As he wrote, the "promise" of the object oriented approach to programming has not been fulfilled according to a set of criteria that the author came up with internally. That sums to an opinion of dislike based on an internal metric.

That said, since I share what seem to be his unidentified metrics for "goodness" I found myself agreeing with his statements. I recognize though that there are many metrics which others may choose to rank more highly than those so rather than "failed promise" I'd characterize it as "It hasn't worked out to provide a better solution for me."


Actually "right way" is described in article, so don't worry about his knowledge.

I think point of this article is OOP have so many limitations for safe usage, that makes usage of FP more comfortable.


Everything has limits. You're right, there are no magic bullets. OO is easier to code and maintain. That alone is worth it.


There is no good evidence that OO is easier to code and maintain than some alternative. In my experience (which is, of course, only anecdotal), the authors' skills are by far the strongest determinants of maintainability. In the wrong hands, OO features are just additional dimensions for obfuscation.


That has been very far from my experience. Unless by OO you mean something more niche than mainstream Java that I haven't experienced.


You all have missed the point that the author is well aware of what needs to be done to avoid the pitfalls of OO and be productive in an OO language. His point is that OO is still being taught, promoted and justified with the same simplistic claims and assumptions that were made in the 90s.


> 2. Multiple inheritance is hard

It needn't be. The awkwardness of multiple inheritance in C++ comes from the fact that C++ classes try to be both classes and abstract data types, and end up not fulfilling either role in a satisfactory manner. In OCaml, where abstract data types and classes are completely separate and unrelated mechanisms, multiple inheritance is the most natural thing in the world.

> 4. Hierarchies are awkward for expressing certain relationships

Hierarchies are totally fine. The problem is tying vtables to individual objects. This deprives you of the ability to say “this virtual method operates on two objects of unknown types”, because the only type that can be abstracted is that of the object carrying the vtable. Haskell-style type classes and CLOS-style generic methods don't have this problem.

> 5. Reference semantics may result in unexpected sharing

Unexpected sharing is only a problem with mutable data.

> This has more to do with reference semantics than objects.

How many languages that call themselves “object-oriented” don't equip all objects with a first-class identity?


The same can apply to any use of libraries.

1. You depend on the library and its dependencies

2. Version controlling libraries is hard when you depend on A and B both of which depend on C

3. Someone changes something in, say, npm and it breaks everything that depends on it. Also, security is only as strong as its weakest library.

4. Do you put everything in one monolithic library or have libraries require each other? Requiring is also a hierarchical graph.

5. Libraries may want to share pointers to the same objects, but then who owns them?

6. Libraries do things for you but sometimes you need to override or customize something, so that breaks encapsulation.

And so forth.


> 5. Reference semantics may result in unexpected sharing

> This has more to do with reference semantics than objects.

I would argue that these are intertwined. You can't really have objects without aliased identity and therefore reference semantics. Otherwise, you are in "land of the anonymous values" where FP techniques are much more useful, while objects clearly have names. (I'm an OOP fan BTW, but also heavily use FP.)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: