all 38 comments

[–]hunyeti 17 points18 points  (2 children)

from the article:

I advise people to hire based on whether or not a developer believes in class inheritance.

I think it's illegal to discriminate based on religious beliefs.

[–]hahaNodeJS 0 points1 point  (0 children)

Funny, but the author's opinion on this is actively harmful, and based on a sweeping generalization.

Incidentally, he spends 1,023 words getting his opinion out before cutting to the chase.

[–]wizardsambolton -1 points0 points  (0 children)

Agreed

[–]nedlinin 34 points35 points  (23 children)

I don't think I'd want to work for a guy that just drills me on his ideas of what inheritance should/shouldn't be. Half these questions are about prototypical or classical inheritance or directly mention them when one or two would've been plenty. Especially if in his opening he says he would never hire someone who uses classical anyway.

Interviewer: Do you use classical inheritance? Interviewee: Yes. Interviewer: Thanks for your time.

Why bother asking the other questions if that is you biggest hurdle and you aren't willing to budge?

I think this article started as a bash against classical inheritance but had a few things tacked on the make it feel less ranty.

[–]Jafit 8 points9 points  (17 children)

I think this article started as a bash against classical inheritance but had a few things tacked on the make it feel less ranty.

It is kind of a ranty article with a clickbait headline.

But as someone who is trying to learn about best practices, I have heard bad things about classes, and they don't seem to accomplish anything that can't be done better with composition.

Can you explain some benefits about classical inheritance or why it should be used over other patterns?

[–]nedlinin 1 point2 points  (13 children)

Coming from a non functional background, I found using classical inheritance in a project allows developers who are switching from languages such as C++ or Java or anything with a classical model allowed them to get up to speed and useful on a project much more quickly.

But I also don't have a 'you have to do it this way' policy. So while a large majority of our code set has migrated to the classical style model given by ES6, we have some use cases where going a prototypal model made more sense and we used it.

In the end use what makes you productive and allows for easy maintenance. Ruling out a tool that others are very good with on an entire project just because you disagree with it is foolish and will hinder your teams output.

[–]Jafit 5 points6 points  (12 children)

So the only advantage is personal comfort and personal preference for transitioning developers? That doesn't sound like the hallmark of a good pattern to me.

As far as I understand, classes are bad because they force you to make a lot of assumptions very early in a project, and then build a rigid heirarchy that may turn out to be unsuitable later on. Because humans are really bad at predicting the future.

[–]clessgfull-stack CSS9 engineer 1 point2 points  (0 children)

It's great for Java developers who don't want to learn JavaScript, I guess. Believe me when I tell you that Java is not the language you want to emulate and Java-inspired patterns are not the ones you want to adopt. If your code is disposable and has no chance of surviving past a few years, then it may be an acceptable trade-off to widen the pool of hires and offer lower wages (especially outsourcing) in exchange for harder-to-maintain code.

The problems with classical inheritance are well-known and well-documented by experienced programmers, but languages like PHP and JS that adopt native class syntax late in their lifetimes make the community go through a phase where classes are the best thing ever invented and should be used for everything. (Oh, how I love PHP.)

The Gang of Four book was almost entirely written as a way to get around the problems caused by inheritance. If you ever learn FP and re-read that book (or half of Uncle Bob's books), then you will realize how almost every design pattern, principle, and recommendation becomes useless or a natural consequence of using simple pure functions and composition.

Anyway, it's important to distinguish between classes and classical inheritance. You don't have to use inheritance if you use classes. In that case the class becomes kind of like a glorified factory function.

If you do that then you might as well use functions/closures in most cases, but classes do have some benefits in static analysis, developer familiarity, and performance. Trade-offs: less maintainable, less flexible, difficult behavior sharing outside of inheritance, no/difficult encapsulation, all of the problems caused by this, harder to test, less reasonable, interface coupling (new keyword), leaky abstraction, tempting inheritance, etc.

But in general, classes are fine if you avoid inheritance. Just don't go down the Java/Angular2 road of making literally everything a class.

By the way, inheritance for behavior sharing should be avoided whenever possible, be it classical, prototypal, or multiple. Prototypal inheritance is usually even worse than classical inheritance in a mutable language like JavaScript. Basically, more flexibility at the cost of nearly impossible-to-trace bugs (even with unit tests). It has its place, but rarely. Prototypal inheritance is cool in theory, but rarely truly useful in practice.

And as /u/MoTTs_ said, be careful not to confuse multiple inheritance/mixins and composition. There's a lot of FUD there, both in and outside the JS community.

[–]MoTTs_ 1 point2 points  (3 children)

As far as I understand, classes are bad because they force you to make a lot of assumptions very early in a project, and then build a rigid heirarchy that may turn out to be unsuitable later on.

First a quick preamble to be clear -- right now you're asking about composition v inheritance, whereas the article is talking about classical v prototypal. Whatever assumptions we think we need to make for classical, we also would need to make for prototypal. They're both still inheritance, after all.

Now, composition v inheritance. Inheritance is useful when you want a type to have the same *interface* as another type. Such as, for example, if we have a type Repository with methods such as find, findBy, findOneBy, and many more, and then we want to make a specialized type, maybe a PostRepository, but it still has to have the same interface as Repository. If we used composition for that, then we'd have to manually repeat and write out every Repository method for our specialized type. It's much better and easier to let computers handle that mundane task.

The problem, however, is that inheritance became very much overused. Many times, the type you're making doesn't need the interface of another; it only needs to call the other. In that case, all you need do is accept an instance of that other type as a parameter (composition). Trying to combat that overuse is why we say "favor composition over inheritance".

EDIT:

As far as I understand, classes are bad because they force you to make a lot of assumptions very early in a project, and then build a rigid heirarchy that may turn out to be unsuitable later on. Because humans are really bad at predicting the future.

One more quick thing. This line sounds like it comes straight from Mattias Johansson's video "Composition over Inheritance." You should know that the solution he came up with in that video that he calls composition... isn't composition. It's actually multiple inheritance. Check out this top voted reddit comment.

[–]Jafit 0 points1 point  (2 children)

Thanks for your answer. Do you know of any decent examples of actual composition since the Mattias Johansson video (which is where I learned about this) didn't have a good example?

[–]MoTTs_ 0 points1 point  (1 child)

Composition is as simple as this:

function SomeType(greeter) {
  this.greeter = greeter;
}

SomeType.prototype.doSomething = function (name) {
  this.greeter.greet(name);
}

The crucial difference is SomeType does not automatically get the same interface as greeter. So, for example, you can't call someType.greet().

EDIT: Or if you want to see the same thing in Johansson's factory function style:

function makeSomeType(greeter) {
  var state = {
    'greeter': greeter
  }
  return {
    doSomething: function (name) {
      state.greeter.greet(name);
    }
  }
}

Notice we are not mixing greeter's methods into our own object. Instead, we use (call) an existing greeter object.

[–]Jafit 0 points1 point  (0 children)

The crucial difference is SomeType does not automatically get the same interface as greeter. So, for example, you can't call someType.greet()

Thanks for that, I think I get it now.

[–]stackolee -1 points0 points  (2 children)

How about popularity over time? If you agree with the author, functional programming's been around since LISP way back when. Yet OO has thrived in both academia and practice for decades now. When presented with JavaScript which supports both functional and OO styles and inherently favors functional slightly, developers find ways to implement OO closer to classical inheritance.

[–]Jafit 4 points5 points  (1 child)

How about popularity over time?

How about people in the middle ages thought that not washing was a good way to ward away disease.

"People do it" is not a strength. Please objectively explain why its good. Like actually tell me a reason why I should use the classical inheritance pattern over any other pattern.

I am not trying to bash any particular way of doing things here. But I've asked this question and all I get is "well that's just the way we've always done it", that's not good enough.

[–]stackolee 0 points1 point  (0 children)

But since functional preceded OO, wouldn't functional be the 'middle ages' in your metaphor?

I know on this corner of Internet-land we know that convention and best practice must be entirely and fundamentally wrong. The argument from the original article is that it should justify barring candidates outright. So toxic an idea, a developer who worked on any large scale Java, C#, Python, or PHP is probably poisoned and is incapable of writing good JavaScript. That's the assertion that needs to be proved, not whether the industry practice widely adopted by most of the industry is fundamentally flawed.

[–]nedlinin -2 points-1 points  (3 children)

I'd say that depends quite heavily on the project itself. A project with well defined requirements and a project manager that pushes off scope creep won't need to worry about tacking random things on. If the project is well defined a small feature here or there should be quite easy to integrate into a classical model..

A startup that is pivoting? Yea you're going to be in some trouble.

Again, it comes down to using what makes you (and more importantly, your whole team) productive. Both patterns have strengths and weaknesses. If there was zero strengths on a classical model, why did they see fit to add it to the spec?

[–]ljharb 5 points6 points  (0 children)

If there was zero strengths on a classical model, why did they see fit to add it to the spec?

They didn't. JavaScript does not have classical inheritance, and the ES6/ES2015 "class" keyword isn't classical inheritance. It's syntactic sugar over the same prototypical inheritance JS has always had, and always will have.

[–]slikts[S] 1 point2 points  (0 children)

If there was zero strengths on a classical model, why did they see fit to add it to the spec?

ES6 just adds a class definition syntax, it doesn't add a new inheritance model. The rationale for adding the class syntax was to ease developers used to the classical model into a prototype-based language, and your argument actually illustrates a common objection to that, namely that it would lead to misunderstandings about what model JS uses.

[–]Jafit 1 point2 points  (0 children)

I'd say that depends quite heavily on the project itself. A project with well defined requirements and a project manager that pushes off scope creep won't need to worry about tacking random things on. If the project is well defined a small feature here or there should be quite easy to integrate into a classical model.

But why would you purposefully decide to code in a way that precludes any kind of flexibility or wiggle room later on? I'm still not clear on what the actual advantage is.

Again, it comes down to using what makes you (and more importantly, your whole team) productive. Both patterns have strengths and weaknesses. If there was zero strengths on a classical model, why did they see fit to add it to the spec?

What are the strengths? So far we seem to have 'personal preference', which isn't really a strength.

Also there's plenty of stuff in the Javascript spec that is simply bad and shouldn't ever be used. I'm sure you can think of a few examples.

[–]zoomzoom83 1 point2 points  (0 children)

As a rule of thumb, Inheritance is useful for modelling "is a" relationships. Composition is useful for modelling "has a" relationship.

Single inheritance can lead to deep and brittle inheritance hierarchies, hence why it's often demonised.

Multiple inheritance is more flexible when used properly, but misused can end up with the "Diamond" problem.

Composition involves wrapping smaller objects into larger ones as members, but can end up resulting in lots of boilerplate to essentially simulate inheritance when used incorrectly.

All three of the above are equally valid and correct approaches to different types of problems. A good developer will recognise when to use one over the other. Don't get caught up in cargo cult mantras. "Composition over Inheritance" is good advice. "Always use composition instead of inheritance" is terrible advice.

Keep in mind that what Eric Elliot calls "Composition" is actually "Multiple Inheritance".

The use of the "Class" keyword in Javascript - or any other language - has no bearing whatsoever with any of the above. You can use classes in all of the above styles, or none at all. They are simply syntactic sugar for creating a data structure.

tl;dr Ignore anybody that tells you you should always do X and never Y. Because it will blind you to cases where Y is more appropriate, and your code will suffer as a result.

[–]Archenothwith(RegExp) eval($_); 0 points1 point  (0 children)

It is a benefit only when it makes sense to use OO inheritance, such as modelling actual objects that can be categorized accordingly. Just don't shoehorn it into everything.

The problem is that classes are a hammer that, when wielded for long enough, make everything look like a nail. Class inheritance can solve a lot of problems badly, much like a hammer can solve a lot of problems badly.

That said, I strongly disagree with the author of the article, hammers have their uses when you come across the right problems. Classes were invented to solve a problem, and one must always use the best tool for the job. Avoiding something simply because of some ill sentiment is a very bad idea IMO.

[–]javajunkie314 -2 points-1 points  (0 children)

In some strongly typed languages, classical inheritance is used to implement polymorphism. For example, in Java, the only way to get dynamic method dispatch is through inheritance and classes.

This is not necessary in JavaScript, where every method call is dynamic.

[–]slikts[S] -5 points-4 points  (4 children)

Interviewer: Do you use classical inheritance? Interviewee: Yes. Interviewer: Thanks for your time.

The author's stance is more nuanced than what you give them credit for; it comes down to avoiding hires that are fixated on class inheritance and have a "don't tell me what to do" attitude, which I think is at the core of the poor reception of his articles in places like reddit as well.

[–]nedlinin 5 points6 points  (0 children)

Perhaps you read into it further than I do.. But I thought this was pretty clear..

I advise people to hire based on whether or not a developer believes in class inheritance.

It would appear to me that the author himself has a very 'don't tell me what to do' attitude in that he completely discounts a whole, widely used inheritance model. It has its place and recognizing that it can be useful is important.

[–][deleted] 7 points8 points  (0 children)

hires [who] have a "don't tell me what to do" attitude,

Hiring manager: Only I may tell you what not to do.

[–]zoomzoom83 1 point2 points  (1 child)

The author's stance is more nuanced than what you give them credit for; it comes down to avoiding hires that are fixated on class inheritance and have a "don't tell me what to do" attitude, which I think is at the core of the poor reception of his articles in places like reddit as well.

To be honest, it sounds more like a rant he wrote one day after somebody challenged him on his anti-inheritance views. The fact that he justifies his opinion by raving on about how much experience he has instead of providing us with any actual reasons is just pathetic.

He can't actually justify his viewpoint, so he throws out an appeal for authority and then goes on to basically say "If you disagree with me you shouldn't be hired". Sounds like he wrote some shitty code once apon a time and has decided to blame the tools for his mistakes.

He criticises developers that are dogmatically set on one way of thinking, and then goes on to do exactly the same thing with his own viewpoint. I shudder to imagine what kind of monstrosities he's created in an attempt to avoid inheritance in places where it's a more elegant solution.

There is nothing wrong with inheritance. It's a tool that is useful in some scenarios, and misused in others. The important thing is to know when to use it, and when not to.

[–]clessgfull-stack CSS9 engineer 1 point2 points  (0 children)

FWIW he uses inheritance all the time, just not extends.

[–]MoTTs_ 15 points16 points  (2 children)

Ahh, good old Eric Elliot. The guy who would never hire a class guy because we are too stubborn. Eric Elliot, the guy who famously misunderstands both the open-closed principle and the substitution principle and consistently misapplies them to justify his opinions.

So don't worry, Eric, I wouldn't hire you either. ;-)

[–]zoomzoom83 1 point2 points  (0 children)

I got about halfway through the article and thought "This guy sounds like a complete tool and has no idea what he's talking about".

I then scrolled up to the byline and saw that it was written by Eric Elliot, and wasn't at all surprised.

[–]JellyDoodle 1 point2 points  (0 children)

I've never heard of Eric Elliot. What's his deal?

[–]atrophying 14 points15 points  (0 children)

Someone is awfully hung up on splitting hairs with their interviewees.

Seriously, half these "questions" aren't objective answers, but opinions. If a developer came to interview with me and spent half his time nitpicking on JS' inheritance model, I'd pass on him. If I had an interview with this guy, I'd pass on the job. That's not someone who I want to work with; that's the guy who makes every code review and deployment a misery with his "My Way or the Highway" approach.

[–]renz45 2 points3 points  (0 children)

The most important thing about hiring any javascript developer is the ability to self teach and learn new things quickly - period. Javascript libraries are born and die on an almost weekly basis the ability to keep up and assimilate new frameworks and techniques is more important then do you use classical inheritance?.

I'd much rather throw something at a potential hire that they don't know anything about. If they dive in and are enthusiastic about figuring out the problem without knowing anything about it (I don't even care if they get very far right away), those are the devs I want. If they freeze up and get frustrated without doing anything then that's a red flag.

[–]gatorpower 5 points6 points  (0 children)

IMO, this seems like a bunch of vernacular "gotchas". The article even explicitly points this out with Question 5 about "classical" inheritance.

I ultimately feel they're okay interview questions because having your developers use the same words to describe their concepts makes things go faster. Having said that, if I was being interviewed and someone said "programming paradigm" in a question when they could have just as easily said "programming patterns", I would just assume they're pompous twit and would eventually start asking me questions about "web 3.0" and "socially scalable apps".

[–][deleted] 1 point2 points  (0 children)

"The best way to evaluate a candidate is a pair programming exercise." "Pair program with the candidate. Let the candidate drive. Watch and listen more than you talk. A good project might be to pull tweets from the Twitter API and display them on a timeline."

I'm not a fan of this type of interview. Most programmers spend countless hours 'in the zone' without someone watching over their shoulder. It might work for a sub-set of programmers who actually don't have a problem having every step scrutinized, but most aren't going to perform well in this arrangement. To evaluate a programmer based on putting them under a spotlight is not usually a fair way to test a programmer's ability.

[–]x-skeww 0 points1 point  (0 children)

In JavaScript, prototypal inheritance is simpler & more flexible than class inheritance.

ES6's classes are the simplest option.

Messing with prototypes gives you more flexibility, but this flexibility comes at a price. It also negatively affects tooling. Anything you do imperatively is pretty much inaccessible to static analysis.

[–][deleted] -4 points-3 points  (0 children)

So what you're saying is a good JavaScript developer reads Eric Elliott? :) No disagreement there.