5 ms·
It's a good article, but it reminds me that sometimes I feel like with protocol-oriented programming we're just reinventing class hierarchies with a new kind of
by WoodenChair 7y ago
It's a good article, but it reminds me that sometimes I feel like with protocol-oriented programming we're just reinventing class hierarchies with a new kind of polymorphism and finding a way to do things with composition instead of inheritance, just because that's the new right way to do everything. Other than value types vs reference types, what would be the downside of FileImporter being a base class with a few subclasses for each file type? The base class could have a factory method that returns one of the subclasses.
And could we achieve much of what we want with protocol-oriented programming crossed with value types if structs could have inheritance? I know that sounds strange.
In short, I totally get the elegance of protocol-oriented programming, but I wonder if for most of its applications a traditional class hierarchy would be more than good enough. I'm not sure inheritance is as bad a word as people make it out to be.
- nicoburns 7y ago> What would be the downside of FileImporter being a base class with a few subclasses for each file type? This model doesn't support a single class having multiple base classes very well, whereas this is supported very well by the Swift/Rust approach. Base classes typically also allow shared state between base and derived classes, which can make code brittle and difficult to follow.
- WoodenChair 7y ago> This model doesn't support a single class having multiple base classes very well, whereas this is supported very well by the Swift/Rust approach. Totally agree, but you can have a single base class that adopts multiple protocols or subclasses that adopt multiple protocols. It doesn't have to be an either/or. Inheritance can work together with protocols.
- 0815test 7y agoThe controversy over inheritance has to do with implementation inheritance, where any method that's defined on a base class can depend on methods that may have been overridden in some derived class, or rely on some non-codified invariants that a derived class might break: this is known as the "fragile base class" problem. By using composition over inheritance, this is not something that can happen by default, because there is no provision for a method call on some "base" method to dispatch on the object's "actual" type, or more broadly to rely on anything but what's defined in the base object itself. You can recover that dispatch-like behavior ("open recursion"), but it's something you have to code yourself and opt into explicitly. This is good for rigor and auditability, as well as just being all-around simpler and easier to understand. Implementation inheritance is too general of a feature, and just not a good abstraction.
- WoodenChair 7y agoI'm very aware of the fragile base class problem. But it's a non-problem for many of the small class hierarchies that protocol-oriented programming examples are often used as examples of replacing. Surely, there would be no fragile base class problem here with a total of 1 base class and 3 subclasses. If you're doing something like the Swift standard library, protocol-oriented programming is a huge win. If you're doing a small class hierarchy as you would be to do this example, I don't see the big win.
- julius_set 7y agoInheritance is usually bad since extending from a base class puts you at risk for shared and a centralized dependency for your subclass implementations. I would even argue a protocol witness approach here makes more sense than protocol oriented.