6 ms·
I’ve come to loathe inheritance in OOP, favoring composition instead. The idea of creating abstract base classes makes sense in theory, but this eventually lea
by save_ferris 7y ago
I’ve come to loathe inheritance in OOP, favoring composition instead.
The idea of creating abstract base classes makes sense in theory, but this eventually leads to problems regarding inherited behavior (i.e. debugging unexpected behavior of a “duck typed” interface up the inheritance chain)
- nathanaldensr 7y agoAgreed. I love OOP--C# in particular is my favorite language--but I always advise more junior folks to avoid inheritance in favor of composition and DIP. I do wish languages like C# would make it easier to implement the "delegating member" pattern so I don't have to rely on ReSharper to generate all the boilerplate, but it's a small price to pay to avoid the pitfalls of inheritance.
- sdfin 7y agoDid you try F#? If so, what's your opinion about it?
- nathanaldensr 7y agoI haven't, no. If anything I've been trending more OOP by starting to write C++. I just haven't had the opportunity to switch gears that much.
- kjeetgill 7y agoOOP says pretty little on inheritance over composition, but I do agree that inheritance became the focus of a ton of OOP/Java/C++ curriculum and I think we're all feeling some backlash from that.
- stillbourne 7y agoIf we are talking about SOLID the S for SRP implies that we should favor composition of inheritance. Composition makes testing easier and reduces side effects. Not to mention delegation, aggregation, etc. In es/ts if you build small single purpose lambdas you can use things like pipe or compose to chain methods with a single unary input. Like this: private _getJiraDataWithPipe(data: CircuitViewModel[]): string { const pipe = (...fns) => x => fns.reduce((v, f) => f(v), x); return pipe( this._getCsvData, this._splitRows, this._removeDoubleQoute, this._formatLines, this._joinRows, this._setHeaderToBody, )(data); one input 'data' passes down the pipe from left to right transforming the object as is passes down. As each of the methods called in the chain are lambdas with strict typing there are no side effects.
- cpeterso 7y agoReflecting on C++ projects that I've worked over the years, a lot of inheritance (especially inheritance of implementation) was unnecessary or made the code harder to understand. These issues with inheritance are reflected in the designs of new school language like Rust and Go.
- stillbourne 7y agoThat's because the functional way is the correct way.
- imtringued 7y agoThere is more than one "functional way".
- stillbourne 7y agoThey are referring to function composition, that's the point...
- ajross 7y agoThat's sort of the essence of the dispute, though. Inappropriate promiscuous subclassing is a bad idea, but really just a fairly small part of what people tend to call "OOP", most of which is pretty unobjectionable and good: inherent modularity, data-dependent name scoping, unification of typesafety with behavior/interface... no one complains about that stuff, and it's all part of what we picked up in the OO revolution of the 90's too. So we end up in endless strawman arguments about "OO is bad! You should be programming in Flurf instead!" when, no, what makes Flurf special is just its choice of how to eliminate implementation inheritance. You can write great code in Java or whatever too, even while rejecting inheritance promiscuity.
- doboyy 7y agoThe good parts listed as OOP don't seem exclusive to it though. They fall more under just plain, old, good program design regardless of the paradigm. But subclassing, while occasionally useful, does.
- ajross 7y agoIsn't it sort of a truism that any good idea seems like a "plain, old, good" idea once it's become a consensus thing? I mean, sure, other modified paradigms have picked that stuff up, and the features aren't "unique" to OO. But they were certainly popularized by OO, and the languages we talk about as "OO" languages all implement them in mostly the same ways and for the same reasons. So basically this is the no-true-scotsman way to perpetuate the strawman, I guess.
- doboyy 7y agoI'd say one property of good ideas is that they are able to survive much longer than bad, so, yes, they have a higher probability of reaching a general consensus. Bad ideas can also reach consensus. Consensus is not always an indicator of quality, and I don't believe good ideas are destined to reach consensus. I can't really argue with the historical impact of OO, because it's obviously had a ton. OO is always so loosely defined that a no-true-scotsman argument is almost inevitable, but I'd certainly say a subclassing model is one of the defining features of the OO languages we talk about.
- fragsworth 7y agoI disagree. OOP and inheritance is fine, and so is just about every feature/paradigm/language/anything in programming, when used thoughtfully by an experienced developer. For instance, inheritance can often be used nicely at a framework or engine level. Most people are just inexperienced and bad at programming, and bad at managing large projects, and if a lot of bad programmers and managers happen to be using some paradigm or feature or language, it is often the paradigm that takes the blame for their shoddy work because nobody is willing to admit that they are the ones at fault. Functional programming feels nice to everyone right now, because lots of experienced developers are enjoying themselves with it, and writing decent code. But mark my words: that good feeling will end once it gets too popular and adopted by new developers. And then people will blame Functional Programming for all the awful work people do in it. If you think I'm wrong, you are way underestimating how bad new software developers can be. We don't throw away all our hammers just because some bad construction workers use hammers on the wrong things.
- squirrelicus 7y agoI wish I could talk to you 5 or 10 years down the road when you have discovered and internalized the reality that a) there are no good programmers b) the programmers you're complaining about will never go away c) you're one of them My contention against OOP is that it is a pattern that encourages critical mistakes that composition-based systems does not encourage. My contention against FP is that it discourages small amounts of state (e.g. that doesn't leave the scope of the current function) and instead encourages many mental leaps to wrap your head around the transducer or whatever. But if I had to pick one, FP tends to produce higher quality code.
- fragsworth 7y agoI've been programming for 20+ years now, nearly fulltime, and worked with many other programmers for the entire time. There are plenty of good programmers, and they all have a lot of experience. I've learned to tell the difference. It took a long time. Your blanket statement that developers are all bad is simply wrong, there are vast differences between them. Maybe to put it in terms you seem to prefer: some are "less bad" than others. And not everyone is bad in the same way, either. But you're right, the programmers I'm complaining about will never go away, because there will always be new programmers, and old ones will retire or die. My only point was that everyone's impression that FP tends to produce higher quality code is largely based on a selection bias from the code you've read, or based on your own attempt to learn the paradigm after already having had some amount of experience. I witnessed firsthand the rise and fall of many paradigms in programming. I've witnessed it with NoSQL. And Agile. The same thing is likely to happen to Functional Programming, if it becomes too popular too quickly. When you see companies starting to post jobs with "Functional Programming experience required", that's when you're reaching peak, and a bunch of new (bad) developers will come in and ruin everyone's impression of the paradigm.
- julienchastang 7y agoInheritance breaks encapsulation. When you break encapsulation your code becomes difficult to reason about. The OO code I've observed tends to have an abundance of global state in the superclasses.
- 0815test 7y agoImplementation inheritance does more than break encapsulation. It creates inherent fragility because of how it makes code defined in a base class dependent on behavior that may be overridden willy-nilly in a derived class; the possibility of overriding means that the whole bundle of public and protected methods/fields is essentially part of an object's external interface, due to its open extensibility - with method implementations typically calling through that same interface. This is far worse than what you would get with a plain old non-OOP program, even one that doesn't use encapsulation at all! In most cases, implementation inheritance can be treated as simply a bad idea that should be avoided altogether - composition is clearly the better approach.
- imhelpingu 7y agoThe problem with the "abstract" keyword is it's more normative than descriptive. If there's not an actual useful abstraction involved, and/or if the abstract class doesn't actually represent a more abstracted generalization of a mental category, it's just code re-use.
- jayd16 7y agoWell that's not really a critique of OO. A component is an object, no? Inheritance is often overused but its obviously important and useful. When it works it works seamlessly. You don't have to think about all the inheritance in collection libraries, for example.
- username90 7y agoYou can write good collection libraries entirely without inheritance, just use interfaces instead.
- jayd16 7y agoBut you'd still want inheritance in your interfaces even if you didn't rely on base classes that much. IList is an ICollection and an IEnumerable in C# for example.
- madhadron 7y agoI've come to the conclusion that in most languages we refer to as object oriented today, we probably shouldn't use inheritance at all. In Smalltalk it was a way to make generic behavior available to all objects. The prototype chain in Self was the for the same reason. If you're writing a language that doesn't expose that machinery (which lets you reprogram the runtime), I've found that inheritance is usually a poor choice. Yes, Python programmers, I'm saying that you should never use inheritance unless you're doing metaclass programming.