OOP is TRWTF



  • @dkf Very little in this case, of course. But it does play nicely with . and associates somewhat nicely.

    So you can build up chains like...

    result :: [Maybe Char] -> Maybe Char
    result = fmap upperCase 
           . head
           . reverse
           $ myList
    

    for a contrived example. I think in practice, most haskellers choose to use $ over parens because they can just add functions to the chain and "chase the types" with little syntactic futzing.


  • ♿ (Parody)

    @dkf said in OOP is TRWTF:

    @Captain I'm curious what $ gains in this case; it's the same number of characters either way because parens can sit tighter to the code.

    Syntax hipster points.


  • Discourse touched me in a no-no place

    @Mason_Wheeler said in OOP is TRWTF:

    Currying is still :crazy: though.

    Not really. It's just partially binding the arguments to a function (a very powerful technique that I really miss when writing C or Java!) and it's significantly more convenient to do partial binding with functions that return functions than with arguments as a tuple.


  • Considered Harmful

    @Captain I assume that's jQuery?



  • @dkf Perhaps I should have been more clear. Currying everything by default is :crazy:. If you really need it, it's trivial to do in any language with proper support for lambdas. For example, in C#:

    static Func<T1, Func<T2, Func<T3, TResult>>> Curry<T1, T2, T3, TResult>  
        (Func<T1, T2, T3, TResult> function)  
    {  
        return a => b => c => function(a, b, c);  
    }
    

    (source: Jon Skeet)


  • Discourse touched me in a no-no place

    @Mason_Wheeler Well that's what you get with a more verbose and clumsy type system. (It's not that you can't do currying in C# or Java, but rather that you've got all that extra machinery in the way.)



  • @dkf said in OOP is TRWTF:

    @Mason_Wheeler Well that's what you get with a more verbose and clumsy type system.

    One man's "verbose" is another man's "readable". This example makes it explicit and makes it clear what's actually going on, instead of having a bunch of voodoo behind the scenes (by default!) for something that's only actually useful in a small minority of cases.

    As for "more clumsy", what do you even mean by that? Haskell can't even do classes! have you seen the kinds of knots you have to tie the type system in to get anything resembling OO out of it?



  • @Mason_Wheeler said in OOP is TRWTF:

    As for "more clumsy", what do you even mean by that? Haskell can't even do classes! have you seen the kinds of knots you have to tie the type system in to get anything resembling OO out of it?

    Wut? Nobody in Haskell-land wants inheritance. And we already have type classes, so we can do the template pattern.

    And we have Functors, so we can do the Factory Pattern.

    And we have monads, so we can do client-server.

    And we can do the fun data-types a la carte if we need run-time sum types.
    Where's the problem?



  • @Captain said in OOP is TRWTF:

    Nobody in Haskell-land wants inheritance.

    As I've said multiple times before: :crazy:



  • @Mason_Wheeler What is it, 1990? Even in OO land, people prefer composition over inheritance.



  • @Captain That statement is nonsensical gibberish that has never made any more sense than telling a carpenter to "prefer drills over saws." They're two different tools used for different purposes, and the only people who take the notion seriously tend to almost invariably be FP ideologues.



  • @Mason_Wheeler Yeah, FP ideologues like the Gang of Four...



  • @Mason_Wheeler said in OOP is TRWTF:

    Currying is still :crazy: though.

    Not unless you use too much chili in the curry.


  • Discourse touched me in a no-no place

    I did a little bit of reading up…

    … and found this sentence:

    Simon Peyton-Jones has objected to the introduction of functional dependencies in Haskell on grounds of complexity.

    The idea of objecting to something going into Haskell because it is too complicated just amuses me so much.


  • Discourse touched me in a no-no place

    @HardwareGeek said in OOP is TRWTF:

    Not unless you use too much chili in the curry.

    You know it is too much when the neighbours complain to the cops about the manufacture of what they believe is pepper spray…



  • @HardwareGeek said in OOP is TRWTF:

    Not unless you use too much chili in the curry.

    Ugh. Curry is just... wrong. I'm not sure why, but even the smell of it can make me nauseous, to the point where I literally can't go into an Indian restaurant or I'll get all queasy in minutes.


  • BINNED

    @dkf said in OOP is TRWTF:

    @HardwareGeek said in OOP is TRWTF:

    Not unless you use too much chili in the curry.

    You know it is too much when the neighbours complain to the cops about the manufacture of what they believe is pepper spray…

    I can’t find it credible that @anotherusername hasn't had this happen yet.


  • BINNED

    @pie_flavor said in OOP is TRWTF:

    :whynotboth:
    Huh, that's not an emoji yet. Paging @kazitor

    oop, almost missed this. Yeah, I ought to get around to finishing that last set huh…



  • @M_Adams said in OOP is TRWTF:

    @dkf said in OOP is TRWTF:

    @HardwareGeek said in OOP is TRWTF:

    Not unless you use too much chili in the curry.

    You know it is too much when the neighbours complain to the cops about the manufacture of what they believe is pepper spray…

    I can’t find it credible that @anotherusername hasn't had this happen yet.

    They definitely weren't standing right outside my window that one or two times when I had to air out the kitchen...



  • @topspin said in OOP is TRWTF:

    What? So, given a function f(x), the Functor allows me to map over a list (i.e. F(f)([x,y,z]) = [f(x), f(y), f(z)]). And now the applicative allows me to "lift on pure values, too"? But couldn't my original function already do that?

    No, because they don't fit in the type constraint. Functor allows you to lift a -> b for some arbitrary type a and b, which means these types will fit (for all types s, t and u):

    • s -> s, by a = s and b = s
    • s -> t, by a = s and b = t
    • s -> t -> u, by a = s and b = t -> u
    • (s -> t) -> u, by a = s -> t and b = u
    • ...

    However s will not fit into a -> b for some s, so you cannot lift it. We say that s has a different kind to a -> b: they have different shapes at the type level.

    This distinction may seem silly but there are structures that is a Functor but not an Applicative, e.g tuples, simply because of the edge case that the type contained in the tuple has no possible values. In this case you cannot "lift" a value ((undefined, 0) would be absurd).

    There's also an example of combinator calculus: if you want to implement a DSL out of combinators, you can lift functions as basic combinator terms, you can apply one term to another term, but you should not lift a plain value that would defeat the entire purpose of combinator DSL: to compose functions instead of evaluation. (The evaluation should be done at the end with a function that resolves the conbinators, which would give you an actual function to apply to plain values.)

    Hence when you implement combinator calculus, its intended usage dictates that it is at least as powerful as a Functor, but not as powerful as an Applicative as you do not intend to expose pure for others to lift pure values to ruin your DSL. (Actually it's Apply.)



  • @anotherusername said in OOP is TRWTF:

    They definitely weren't standing right outside my window that one or two times when I had to air out the kitchen...

    Was it right after you put in some spice?

    0a212b2f-814d-4708-8496-1cc0f2f0cb40-image.png



  • @TimeBandit One time in particular was right after I accidentally spilled something in the oven.



  • @TimeBandit said in OOP is TRWTF:

    @anotherusername said in OOP is TRWTF:

    They definitely weren't standing right outside my window that one or two times when I had to air out the kitchen...

    Was it right after you put in some spice?

    0a212b2f-814d-4708-8496-1cc0f2f0cb40-image.png

    The spice must flow!


  • Banned

    @Mason_Wheeler said in OOP is TRWTF:

    @Captain That statement is nonsensical gibberish that has never made any more sense than telling a carpenter to "prefer drills over saws."

    Or maybe you just not understand it.

    They're two different tools used for different purposes

    Wrong. Class inheritance serves the same purpose as mixins. Every class hierarchy can be translated to interface + mixin hierarchy. It's just two techniques for doing the same thing, with different pros and cons. And except for very few situations like making custom GUI controls, class inheritance has much more cons than pros compared to mixins or other composition designs.



  • @Gąska said in OOP is TRWTF:

    They're two different tools used for different purposes

    Wrong. Class inheritance serves the same purpose as mixins.

    :rolleyes:

    Every class hierarchy can be translated to interface + mixin hierarchy.

    Yes, badly. Sorta like how a carpenter could theoretically use a drill to perform the same work as a saw... badly.

    It's just two techniques for doing the same thing, with different pros and cons.

    They're different techniques for doing different things. It's possible to abuse composition to do the same thing as inheritance (badly), but it's kind of a dumb idea.

    And except for very few situations like making custom GUI controls, class inheritance has much more cons than pros compared to mixins or other composition designs.

    ...such as?



  • In my experience, every time I've tried to use class inheritance beyond two specific cases, it's only made things worse, and reframing it as objects containing other objects and passing method calls that way has made it better and easier to maintain.

    The two scenarios are:

    1. very shallow hierarchies for dealing with API requirements (ie they give an abstract base class and you implement it).
    2. GUI frameworks. And most of those are :wtf: in their own right.

    Note: This does not apply to interfaces. Those are fine. And the iOS frameworks (for Swift at least) have moved much more towards conforming to interfaces rather than inheritance except for GUI widgets.



  • @Mason_Wheeler said in OOP is TRWTF:

    ...such as?

    The ton of implicit code coupling that happens. The ton of implicit assumptions that get made and are hard to back out of.


  • Banned

    @Mason_Wheeler said in OOP is TRWTF:

    @Gąska said in OOP is TRWTF:

    They're two different tools used for different purposes

    Wrong. Class inheritance serves the same purpose as mixins.

    :rolleyes:

    Is this your brain's loading animation?

    Every class hierarchy can be translated to interface + mixin hierarchy.

    Yes, badly.

    Almost everything you can do with class inheritance, you can do with just interfaces and mixins with just a few more lines of code - but you end up with greater separation of concerns, higher reusability, and an architecture that's easier to modify.

    Sorta like how a carpenter could theoretically use a drill to perform the same work as a saw... badly.

    Class-inheritance-4lyfe programmers are like carpenters who do all their sawing with a hammer because that's all they know.

    It's just two techniques for doing the same thing, with different pros and cons.

    They're different techniques for doing different things.

    Reusing methods and fields you've already written once, as opposed to reusing methods and fields you've already written once.

    It's possible to abuse composition to do the same thing as inheritance (badly), but it's kind of a dumb idea.

    You keep repeating that but you haven't provided a single reason why.

    As for reasons why mixins are better than inheritance: you can have more than one of them at once, and it works exactly as you expect. They also have precisely defined interface, so you don't have to guess which methods you should override and which you shouldn't and when you should call super method and when you shouldn't and whether you should do it before or after your code. Also, the derived class isn't bound to implement the mixin's interface exactly - the mixin can be a private member and the outside interface can be completely different. This gives you much more flexibility, and because mixin is self-contained, you won't break its behavior by doing funny things on the outside.

    And except for very few situations like making custom GUI controls, class inheritance has much more cons than pros compared to mixins or other composition designs.

    ...such as?

    You can only derive one class. All of the base class's public members must appear in your signature too, and they must work in the same way. Many languages do funny things during initialization of class hierarchies, especially related to overridden methods called in constructor (which to a seasoned programmer means "you cannot use non-private methods in the constructor; so much for code reuse"). And many more language-specific issues.

    Compare to mixin, which is just a regular object, or a regular object behind thin syntactic sugar.



  • @Captain said in OOP is TRWTF:

    @Mason_Wheeler said in OOP is TRWTF:

    ...such as?

    The ton of implicit appropriate code coupling that happens.

    FTFY. Coupling things that legitimately belong together greatly increases readability, debuggability, and performance.

    The ton of implicit assumptions that get made and are hard to back out of.

    Again, such as? FP advocates are always saying things like this, and they're always vague, hand-wavey assertions with nothing to back them up.



  • @Mason_Wheeler said in OOP is TRWTF:

    Again, such as? FP advocates are always saying things like this, and they're always vague, hand-wavey assertions with nothing to back them up.

    As for reasons why mixins are better than inheritance: you can have more than one of them at once, and it works exactly as you expect. They also have precisely defined interface, so you don't have to guess which methods you should override and which you shouldn't and when you should call super method and when you shouldn't and whether you should do it before or after your code. Also, the derived class isn't bound to implement the mixin's interface exactly - the mixin can be a private member and the outside interface can be completely different. This gives you much more flexibility, and because mixin is self-contained, you won't break its behavior by doing funny things on the outside.

    You can only derive one class. All of the base class's public members must appear in your signature too, and they must work in the same way. Many languages do funny things during initialization of class hierarchies, especially related to overridden methods called in constructor (which to a seasoned programmer means "you cannot use non-private methods in the constructor; so much for code reuse"). And many more language-specific issues.

    Oh, and there's no diamond dependency problem.


  • BINNED

    @Gąska said in OOP is TRWTF:

    You can only derive one class.

    Depends on the language, I'd say.


  • Banned

    @Mason_Wheeler said in OOP is TRWTF:

    @Captain said in OOP is TRWTF:

    @Mason_Wheeler said in OOP is TRWTF:

    ...such as?

    The ton of implicit appropriate code coupling that happens.

    FTFY.

    Doesn't matter if it's appropriate or not - it's still implicit. And implicit contracts are bad because it's very easy to get them wrong. And you won't even know you've got them wrong until a particular code path in foreign code runs.

    Coupling things that legitimately belong together greatly increases readability, debuggability, and performance.

    Readability? Depends. Debuggability? No, it's irrelevant. Performance? Yes, kinda, sorta, maybe, sometimes, and usually it doesn't matter because you're using bytecode VM anyway.

    The ton of implicit assumptions that get made and are hard to back out of.

    Again, such as?

    That the Formatted part of the class FormattedFileOutput extends FileOutput will only ever be used in conjunction with the File part and you'll never want to use it for anything else.



  • @Gąska said in OOP is TRWTF:

    Almost everything you can do with class inheritance, you can do with just interfaces and mixins with just a few more lines of code - but you end up with greater separation of concerns,

    What's the point of separating things that inherently belong together?

    higher reusability,

    How so?

    and an architecture that's easier to modify.

    Not really. Extreme decoupling is often sold that way, but in practice what happens all too often is that you lose TCIYF and so you end up overlooking things and it becomes much more difficult to modify things correctly.

    As for reasons why mixins are better than inheritance: you can have more than one of them at once, and it works exactly as you expect.

    I expect multiple inheritance to be a disaster that blows up in your face in subtle and hard-to-debug ways. If this is supposed to be equivalent, then... yeah.

    They also have precisely defined interface, so you don't have to guess which methods you should override and which you shouldn't and when you should call super method and when you shouldn't and whether you should do it before or after your code.

    Who's "guessing" these things? If you have to guess then you don't know what you're doing, and if you don't know what you're doing in one scenario, why will you be any more competent in a different scenario that's supposed to be equivalent?

    Also, the derived class isn't bound to implement the mixin's interface exactly - the mixin can be a private member and the outside interface can be completely different. This gives you much more flexibility, and because mixin is self-contained, you won't break its behavior by doing funny things on the outside.

    ...and being able to play clever tricks like that is worth giving up the massive benefits of Liskov substitution?

    You can only derive one class. All of the base class's public members must appear in your signature too, and they must work in the same way. Many languages do funny things during initialization of class hierarchies, especially related to overridden methods called in constructor (which to a seasoned programmer means "you cannot use non-private methods in the constructor; so much for code reuse"). And many more language-specific issues.

    Yes, that is a highly language-specific issue, a victim of C++'s broken model where it initializes objects bottom-up rather than top-down. It's a problem that doesn't exist on better-designed languages.


  • Banned

    @topspin said in OOP is TRWTF:

    @Gąska said in OOP is TRWTF:

    You can only derive one class.

    Depends on the language, I'd say.

    Even in languages that do allow multiple inheritance, people run away from it like it was some kind of disease. Because it never works as advertised, and causes more problems than it solves. And I'm not talking just about the diamond problem.



  • @Mason_Wheeler said in OOP is TRWTF:

    ...and being able to play clever tricks like that is worth giving up the massive benefits of Liskov substitution?

    Liskov is a weak substitionality criterion...


  • BINNED

    @Gąska said in OOP is TRWTF:

    @topspin said in OOP is TRWTF:

    @Gąska said in OOP is TRWTF:

    You can only derive one class.

    Depends on the language, I'd say.

    Even in languages that do allow multiple inheritance, people run away from it like it was some kind of disease. Because it never works as advertised, and causes more problems than it solves. And I'm not talking just about the diamond problem.

    I'm using it (at least if I understand you correctly) the way you use mixins. Privately inheriting from completely orthogonal classes. Not using composition in that case is only a way to reduce the amount of hand-written delegation boiler-plate (or maybe additional member-indirection). I'd probably not need that at all with what @pie_flavor mentioned earlier (again, if I understand correctly), where the compiler auto-generates a set of delegates.


  • BINNED

    @Mason_Wheeler said in OOP is TRWTF:

    Yes, that is a highly language-specific issue, a victim of C++'s broken model where it initializes objects bottom-up rather than top-down. It's a problem that doesn't exist on better-designed languages.

    The alternative comes with its own set of problems.



  • @Captain said in OOP is TRWTF:

    @Mason_Wheeler said in OOP is TRWTF:

    ...and being able to play clever tricks like that is worth giving up the massive benefits of Liskov substitution?

    Liskov is a weak substitionality criterion...

    And yet it's conquered the world.

    The bottom line is, if OOP didn't work, it wouldn't work. People wouldn't have used it to conquer complexity and build the software we rely on every day. But they did, because it does, and nothing else does so nearly as well. And the main "secret ingredient" that makes it so good is the combination of inheritance, polymorphism, and virtual methods (AKA Liskov substitution).


  • ♿ (Parody)

    @Mason_Wheeler said in OOP is TRWTF:

    The bottom line is, if OOP didn't work, it wouldn't work.

    Like riding horses!

    No one is saying that it doesn't work. Why do you insist on making such a strawman? People are just suggesting that there are better ways.



  • @Mason_Wheeler And yet it's conquered the world.

    lol no it hasn't. People have been running away since 1995's Design Patterns, where the Gang of Four told us to prefer composition over inheritance.


  • BINNED

    @Captain said in OOP is TRWTF:

    @Mason_Wheeler And yet it's conquered the world.

    lol no it hasn't.

    Sure it has, but so have Perl and Javascript.


  • Banned

    @Mason_Wheeler said in OOP is TRWTF:

    @Gąska said in OOP is TRWTF:

    Almost everything you can do with class inheritance, you can do with just interfaces and mixins with just a few more lines of code - but you end up with greater separation of concerns,

    What's the point of separating things that inherently belong together?

    It makes it easier to refactor when it turns out they don't inherently belong together after all. You're asking the wrong question. You shouldn't ask what's the point of decoupling. You should ask what's the point of coupling. Because coupling doesn't help you in any way and only causes things to be harder to untangle when need arises.

    higher reusability,

    How so?

    When you have decoupled, more or less autonomous units, then taking one of these units and adapting it somewhere else is much easier than if they were more tightly coupled, because you'd have to start with decoupling them.

    and an architecture that's easier to modify.

    Not really.

    Yes really. Breaking class hierarchies is one of the hardest refactoring tasks. It's much easier to just remove one mixin from inside the container or split interface in two.

    Extreme decoupling

    Who said anything about extreme decoupling? I never suggested anything like that. Don't put words in my mouth. I was just saying that it's good to avoid class inheritance wherever possible.

    As for reasons why mixins are better than inheritance: you can have more than one of them at once, and it works exactly as you expect.

    I expect multiple inheritance to be a disaster that blows up in your face in subtle and hard-to-debug ways. If this is supposed to be equivalent, then... yeah.

    It's not an equivalent. Not even close. It just accomplishes the same task. In a completely different way that doesn't share even a single problem that multiple inheritance has.

    How about you read up on the thing you're talking about before saying anything? Because it's pretty clear you have no fucking clue about what you're talking about.

    They also have precisely defined interface, so you don't have to guess which methods you should override and which you shouldn't and when you should call super method and when you shouldn't and whether you should do it before or after your code.

    Who's "guessing" these things?

    Everyone who ever had to derive a library class because the library demands you to derive those classes.

    If you have to guess then you don't know what you're doing

    And that's exactly the problem. Class inheritance, thanks to all the implicit contracts that must hold but are rarely documented, very often leads to a situation where you don't know what you're doing.

    and if you don't know what you're doing in one scenario, why will you be any more competent in a different scenario that's supposed to be equivalent?

    Because mixins have explicit interfaces defined in the language itself (so you must get them right or your code won't compile), and because mixins are isolated from the container except for the interface (so you don't even have the opportunity to do the wrong thing).

    Also, the derived class isn't bound to implement the mixin's interface exactly - the mixin can be a private member and the outside interface can be completely different. This gives you much more flexibility, and because mixin is self-contained, you won't break its behavior by doing funny things on the outside.

    ...and being able to play clever tricks like that is worth giving up the massive benefits of Liskov substitution?

    THAT'S THE THING. THE CONTAINER ISN'T THE MIXIN. THEY AREN'T BOUND BY THE MIXIN INTERFACE. LSP DOESN'T APPLY BECAUSE YOU CANNOT PASS THE CONTAINER AS ARGUMENT WHERE THE MIXIN IS EXPECTED (unless the callee expects an interface and both the mixin and the container implement that interface but then you explicitly declared your container to implement that interface so of course it must implement it correctly; but you can choose not to implement the interface and it's fine and you still get all the other benefits of mixins, such as code reuse.)

    You can only derive one class. All of the base class's public members must appear in your signature too, and they must work in the same way. Many languages do funny things during initialization of class hierarchies, especially related to overridden methods called in constructor (which to a seasoned programmer means "you cannot use non-private methods in the constructor; so much for code reuse"). And many more language-specific issues.

    Yes, that is a highly language-specific issue

    Sorry, I wasn't clear enough. All of the above are language-independent issue that appear everywhere you have class inheritance. And on top of all that, you have language-specific issues.

    a victim of C++'s broken model where it initializes objects bottom-up rather than top-down.

    Java initializes top-down and you have initialization problems too when you call overridden methods in constructor. They're just different problems.


  • Banned

    This post is deleted!

  • Banned

    @Mason_Wheeler said in OOP is TRWTF:

    The bottom line is, if OOP didn't work, it wouldn't work.

    The bottom line is, if PHP didn't work, it wouldn't work.

    The bottom line is, if Oracle DB didn't work, it wouldn't work.

    The bottom line is, if North Korea didn't work, it wouldn't work.


  • BINNED

    @Gąska said in OOP is TRWTF:

    The bottom line is, if Germany didn't wörk wörk wörk

    🇩🇪TFY



  • @Gąska
    The bottom line is, if work didn't work, it wouldn't work. :kneeling_warthog:



  • @Gąska said in OOP is TRWTF:

    It makes it easier to refactor when it turns out they don't inherently belong together after all.

    No, it really doesn't. It makes it that much more difficult.

    You're asking the wrong question. You shouldn't ask what's the point of decoupling. You should ask what's the point of coupling. Because coupling doesn't help you in any way and only causes things to be harder to untangle when need arises.

    This is literally the opposite of the truth. You appear to be completely unfamiliar with the TCIYF principle.

    When you have decoupled, more or less autonomous units, then taking one of these units and adapting it somewhere else is much easier than if they were more tightly coupled, because you'd have to start with decoupling them.

    Nothing is truly autonomous in a system of non-trivial complexity. "More-or-less autonomous" units tend to be less than you think. When they're explicitly coupled, and then you have to change something, it's explicit what you have to change. When they aren't, you still have to change the same things, but now they're harder to find.

    Yes really. Breaking class hierarchies is one of the hardest refactoring tasks.

    Only when it's something that shouldn't be broken up in the first place.

    Extreme decoupling

    Who said anything about extreme decoupling? I never suggested anything like that. Don't put words in my mouth. I was just saying that it's good to avoid class inheritance wherever possible.

    That is extreme decoupling.

    It's not an equivalent. Not even close. It just accomplishes the same task. In a completely different way that doesn't share even a single problem that multiple inheritance has.

    It has its own problems. Like, what if you're supposed to perform an operation that returns a value? With multiple inheritance, you can have trouble figuring out which one to call; with multiple mixins, you can just call all of them... and then you have trouble figuring out which return value is the one you want.

    How about you read up on the thing you're talking about before saying anything? Because it's pretty clear you have no fucking clue about what you're talking about.

    ...says the guy advocating for throwing out the most powerful programming technique we've managed to develop in favor of a mess of mixins and containers everywhere!

    all the implicit contracts that must hold but are rarely documented

    Oh look, more vague hand-waving.

    Because mixins have explicit interfaces defined in the language itself (so you must get them right or your code won't compile), and because mixins are isolated from the container except for the interface (so you don't even have the opportunity to do the wrong thing).

    And of course there are never any undocumented/poorly-documented internal details that turn out to be crucial to the proper usage of a mixin. :rolleyes:

    THAT'S THE THING. THE CONTAINER ISN'T THE MIXIN. THEY AREN'T BOUND BY THE MIXIN INTERFACE. LSP DOESN'T APPLY BECAUSE YOU CANNOT PASS THE CONTAINER AS ARGUMENT WHERE THE MIXIN IS EXPECTED (unless the callee expects an interface and both the mixin and the container implement that interface but then you explicitly declared your container to implement that interface so of course it must implement it correctly; but you can choose not to implement the interface and it's fine and you still get all the other benefits of mixins, such as code reuse.)

    ...where are you getting "container" from? You're going off on a massive YELLING RANT about containers and mixins when I never said "container" and neither did you. 😕

    Sorry, I wasn't clear enough. All of the above are language-independent issue that appear everywhere you have class inheritance.

    More vague hand-waving. People always talk about the supposed "virtual methods in constructors problem", but they never give any real-world examples of it. Occasionally they'll accompany it with a super-contrived example that looks nothing like real-world code, but it's something I've never actually run into, not even once, in 20 years of doing OOP.


  • BINNED

    @Mason_Wheeler said in OOP is TRWTF:

    You appear to be completely unfamiliar with the TCIYF principle.

    So does google. Care to spell it out?
    My acronym-guesstimator-unit thinks "tight coupling is your friend", but I'm just pulling that out of my endofunctor.



  • @topspin said in OOP is TRWTF:

    @Mason_Wheeler said in OOP is TRWTF:

    You appear to be completely unfamiliar with the TCIYF principle.

    So does google. Care to spell it out?
    My acronym-guesstimator-unit thinks "tight coupling is your friend", but I'm just pulling that out of my endofunctor.

    The Compiler Is Your Friend.

    It means that when you actually do change something, it's going to break other things that are directly dependent on it, and if all of the links and dependencies are explicit and clear (aka "tightly coupled") rather than being handled through indirections, then the set of things you need to change to make this work and the set of compiler errors you get, showing you exactly what needs to change and where, will be identical.


  • Considered Harmful

    @topspin You do understand correctly; it auto-implements the interface by delegating to all of the variable's methods, which does not prevent you from overriding the methods manually.


Log in to reply