Earlier quoted context omitted.
> Inheritance is not a banned practice. Maybe it should be. Go and Rust do not provide implementation inheritance, and I think that's for the best. Few language features have led to so much spaghetti code. > It should just be your second choice when there's a better path through composition. Do you see one here? I don't think this logic should be split over a graph of objects at all. This is highly cohesive code; it…
> Maybe it should be. Go and Rust do not provide implementation inheritance, and I think that's for the best. Few language features have led to so much spaghetti code. I agree, but there are reasons inheritance becomes problematic. Just throwing the baby is not helpful. Go, Elixir, Rust are all relatively young languages and although they did away with inheritance, they make use of interfaces/protocols/traits, hintin…
Oh I very much agree, I love interface polymorphism.
> "No Bottle", "One Bottle", [etc] are distinct things and should be represented accordingly
I completely disagree. The problem is to generate a 100-line poem, line by line. Our challenge is to express the rules which govern how to derive a line from its line number in the clearest way possible. Creating an ontology for bottle types makes that overcomplicated. What if there were a special rule for bottle numbers divisible by 3? What if there were a special rule for doubled digits? Would we need to create a DivisibleByThreeWithDoubleDigitsBottle using multiple inheritance to write a line for 66 bottles? Why?
The big gift of OOP is interface polymorphism. The big curse of OOP is the philosophy that objects should model "real distinct things." Object-oriented domain modelling often causes more problems than it solves. Clear dataflow, cohesively represented logic, and loosely coupled modules are much more important than some philosophical notion about what sorts of ideas ought to be given associated objects. That's how you get Joe Armstrong's "gorilla holding the banana and the entire jungle."