Live data from Hacker News

Classes Considered Harmful [pdf]

web.cecs.pdx.edu

101–110 of 129 posts

Re: Classes Considered Harmful [pdf]

#101

Earlier quoted context omitted.

So rust traits are effectively/functionally abstract classes with restricted functionality and a different implementation?

Sort of. The closest thing in C++ would be concepts. That is, even using traits in this way is the minority case; they're more usually used for monomorphized, statically dispatched code. But, given the case where you want dynamic dispatch, then in a sense, they are, yes.

Right. I suppose in Rust you generally use variants and pattern matching when dynamic dispatching is required.

Re: Classes Considered Harmful [pdf]

#102
post #80

Having used C++, Java, C#, Python, Ruby, NewtonScript, Dylan, Scheme, and various other languages "in anger" I can say that in general I agree with the author's frustrations. My favorite (as in most flexible, least boilerplate) approaches to object-oriented programming have been: - NewtonScript's frames with prototype inheritance. Allows "objects" to consist of very small data structures that point to ROM objects and…

In addition to Dylan, Julia also allows multiple dispatch via generic functions. I have found this approach to multiple dispatch leads to code that's much easier to reason about and maintain. My use case is a tensor library where the tensors have a single interface but various storage backend types, which 'interact' with each other. It doesn't make sense to define these interactions through methods belonging to only…

Also R via the S4 OOP system, which was directly inspired by Dylan

Re: Classes Considered Harmful [pdf]

#103

Earlier quoted context omitted.

Sort of. The closest thing in C++ would be concepts. That is, even using traits in this way is the minority case; they're more usually used for monomorphized, statically dispatched code. But, given the case where you want dynamic dispatch, then in a sense, they are, yes.

Right. I suppose in Rust you generally use variants and pattern matching when dynamic dispatching is required.

You could, but that requires that you know all of the variants ahead of time. The advantage of trait objects is that you don't have to.

It really just depends on what exactly you're trying to do.

Re: Classes Considered Harmful [pdf]

#104
post #96
post #63

Earlier quoted context omitted.

Superior composability with simpler semantics and sounder type systems. Class hierarchies are inherently unfriendly to strong, sound type systems. Interface composition isn't. Composing interfaces is clean and straightforward. Composing classes isn't, and you run into things like the diamond problem.

Classes do not imply inheritance. Classes are a means of defining an interface, albeit a heavy one. The statement that it is better to separate data and behavior is far from self-evident IMO, and I would be very interested to understand why this is such a deeply held belief. Seriously, why?

> Seriously, why?

Personally speaking, it's just a lot easier. I could go on about various theoretical justifications, but at the end of the day it's just easier. This probably has something to do with the fact that you don't really gain anything by defining data and behavior together, but you do lose flexibility by coupling those possibly orthogonal concerns.

Re: Classes Considered Harmful [pdf]

#105
post #96
post #63

Earlier quoted context omitted.

Superior composability with simpler semantics and sounder type systems. Class hierarchies are inherently unfriendly to strong, sound type systems. Interface composition isn't. Composing interfaces is clean and straightforward. Composing classes isn't, and you run into things like the diamond problem.

Classes do not imply inheritance. Classes are a means of defining an interface, albeit a heavy one. The statement that it is better to separate data and behavior is far from self-evident IMO, and I would be very interested to understand why this is such a deeply held belief. Seriously, why?

It's not always true, by any stretch of the imagination. Closures couple data and behavior and most (though not all) functional programmers consider closures to be pretty central to FP. I'd add that closures are hard to use in that way without allocating, which is why I think one potentially reasonable argument against coupling data and behavior is performance-driven, but that's a more subtle argument that ignores compiler performance (and there are times where you lose more from all the extra code taking up your icache than you gain in speed due to not allocating; plus, as C++ and Rust demonstrate, you can have closures without allocation if you're willing to heavily restrict them).

Re: Classes Considered Harmful [pdf]

#106
What is the point of these types of arguments and opinions if they don't have any evidence to back them? I don't give a shit if it's functional or object-oriented or procedural or whatever comes next. I just want a language that is proven, via empirical evidence and reproducibility, to solve my particular use case better than any others.

And, given all the use cases I have, I'd be amazed if one class of language can do it all. I'm guessing it's impossible.

It's way better for my engineering team to know how to use a bunch of different specialized tools, and how to use them together, than to focus on one type of tool.

Re: Classes Considered Harmful [pdf]

#107
The biggest problem with classes is that they conflate two different concepts in a way that limits reusability.

When you have classes, you have subclassing, and subclassing means two different things at the same time. First, subclasses are the subtyping operation. If you want type B to be a subtype of A, B must subclass A. Second, they provide code reuse via inheritance.

Each of those things is useful, but there's no reason to tie them together. In fact, modern best practices in OO say to favor interfaces and delegation over subclassing, and that's precisely because it separates those two concerns.

As far as I can tell, this is what the paper was getting at - separating delegation of implementation from subtyping. Since this is already what OO best practices suggest, why is it controversial?

Re: Classes Considered Harmful [pdf]

#108
Amount of boilerplate one needs to implement "good" OO design is just horrendous. For example, in C++, previously we had rule of 3. Now its rule of 5! Just having a virtual abstract interface means almost half dozen lines of boilerplate! Even in managed languages such as C# or Java, it would require significant effort to create, say, read-only version of collection given a read-write collection. One of the goal for language design should be to eliminate all these forced boiler plate. It is definitely the time for new paradigm in language design. However I'm not sure how the "delegates" would solve this which is proposed alternative in this paper.

Re: Classes Considered Harmful [pdf]

#109

Amount of boilerplate one needs to implement "good" OO design is just horrendous. For example, in C++, previously we had rule of 3. Now its rule of 5! Just having a virtual abstract interface means almost half dozen lines of boilerplate! Even in managed languages such as C# or Java, it would require significant effort to create, say, read-only version of collection given a read-write collection. One of the goal for l…

I believe Objective C's @property declarations brings some level of what you describe to C/C++. They generate the boilerplate for you.

E.g., @property (readonly) NSString* myName;

Re: Classes Considered Harmful [pdf]

#110
post #96

Earlier quoted context omitted.

Classes do not imply inheritance. Classes are a means of defining an interface, albeit a heavy one. The statement that it is better to separate data and behavior is far from self-evident IMO, and I would be very interested to understand why this is such a deeply held belief. Seriously, why?

It's not always true, by any stretch of the imagination. Closures couple data and behavior and most (though not all) functional programmers consider closures to be pretty central to FP. I'd add that closures are hard to use in that way without allocating, which is why I think one potentially reasonable argument against coupling data and behavior is performance-driven, but that's a more subtle argument that ignores co…

> Closures couple data and behavior

The use of closures in functional programming is an implementation detail, not a fundamental aspect of the underlying theory, and closures only "couple" data and behavior in the very literal sense that it is a function that happens to point to some data under the hood, not in the syntactic or semantic sense we're referring to when we say that OOP classes couple behavior and data.

A closure in a pure language can't couple to data any more than a lambda expression without free variables (from the programmer's perspective), because they can have the exact same type and semantics.

In other words, there's no semantic difference between "f = \x . x + 2" and "f = let y = 2 in \x . x + y" even though the latter is a closure in the absence of inlining.

Post reply on HN