6 ms·
> Somehow over the years I've found that the animals/cars analogies given in OO tutorials are one of the few places that fit well with the model. Yes, and I've
by beagle3 5y ago
> Somehow over the years I've found that the animals/cars analogies given in OO tutorials are one of the few places that fit well with the model.
Yes, and I've never actually needed to implement a cat or a cow in any project :)
The other thing for which OO works much better than plain data is GUIs - and I think it is not a coincidence that OO popularity exploded together with the the coming-of-age of GUIs.
The other canonical example of OO - "Shapes" - doesn't actually work well at all; It doesn't work better with "plain data", but it exposes the fallacies of trying to use OO inheritance to model the real world. Every square is a rectangle, so square should inherit from rectangle ... but, you can't stretch width and height independently in a square, so it's not really a rectangle, etc. etc.
- deleted 5y ago[deleted]
- dragonwriter 5y ago> The other canonical example of OO - "Shapes" - doesn't actually work well at all. Shapes work quite well with OO if you design the heirarchy right using is-a relationships, the typically cited problem involves applying is-a relationships which apply to immutable geometric concept of shapes to mutable representations whose mutation contracts don’t support the is-a relationship of the immutable shapes. This would actually be fine if the contracts were written in a way which respects the it's-a relationships properly. E.g., the common Circle-Ellipse problem goes away if the contract for the mutator for, say, the major axis of an Ellipse doesn’t specify what the effect is on the minor axis. For the base class, the two can then be independent with the Circle subclass having them invariably equal under mutation. Alternatively, its not a problem with a Smalltalk like “become”, in which case an unequally stretched Circle becomes an Ellipse with appropriate attributes. Or, the mutable elements arr restricted to things thst don’t change the shape like scale and location, and shape transforms return a new Shape; if Ellipse’s StretchMajorAxis returns an Ellipse and so does Circle’s, there’s no problem, either.
- beagle3 5y agoI should have added "in C / C++ / C#". Everything OOP works well in Smalltalk (and most of it does in Python), but you pay dearly for that in efficiency - which is what this article as about.
- dragonwriter 5y ago> I should have added "in C / C++ / C#". The only part of my response that would have effected was the aside about Smalltalk-style “become”, not the main point about the problem being one of constructing an inheritance heirarchy based on relations of immutable entity and using it for mutable entities with mutation contracts that don’t observe the same is-a heirarchy.
- deleted 5y ago[deleted]
- beagle3 5y agoI agree, but that's the thing: It is non idomatic to write immutable Shape-style classes in C++. Possible, yes. Idiomatic, no. IIRC in Stroustroup's book (the one I read a decade ago, anyway), he concludes that Rect:Square and Circle:Ellipse can not inherit from each other in either direction, and did not suggest switching to immutable everything.
- slifin 5y agoOO is a tree and html (UI) on a page is a tree The problem is when you want to go to page two and want to display the same data as page 1 but in a different configuration OO is suddenly terrible because the data is the wrong shape, you should hold your data as a graph then derive trees out of it to satisfy views OO is not good for UIs unless you have one page and the contents on that page is static and doesn't change it's placement outside the statically defined tree shape of OO
- beagle3 5y agoI Was referring to the lower level GUI world, that in which you implement "Button" and "TextField" - OO was, and still is, a great win there. The Win32 / Cocoa / Xt level. But even inside the browser, the fact that even div/span/thing is an object, to which you can attach listeners, and otherwise apply methods, works rather well - I'm not familiar with a better alternative for implementation and dynamic control of this layer
- dragonwriter 5y ago> OO is a tree Inheritance heirarchies in single-inheritance languages are trees. In MI they are DAGs. But neither of those constrains data representations, OO can support arbitrary data graphs. > OO is suddenly terrible because the data is the wrong shape, you should hold your data as a graph then derive trees out of it to satisfy views How does this make OO terrible? What you describe is exactly standard OO GUI practice (specifically, in MV<whatever> architecture, the model layer is an arbitrary graph representing the data, from which the view is derived.)
- kaba0 5y agoOO can be a tree, as well as pretty arbitrary graphs. As has been said for over a decade, prefer composition over inheritance. There are cases where inheritance is really cool, but the main point of OOP is encapsulation. It can enforce class invariants.
- purplerabbit 5y agobeen thinking about this comment since I read it and really love it (even though OO isn't always a tree). This graph <> tree relationship seems central to the successes and failures of many implementation approaches I've seen over the years. Thanks for sharing.
- acje 5y agoI’m on thin ice here. A systems complexity can be measured in the number of tops it has. As in different ways to see it as hierarchical. Could it be that OO favors systems with one top? The tomato example comes to mind. Is it a fruit or vegetables? According to American law it was classified as vegetable at some point to meet a political need to limit imports. Of course botanically it’s a fruit but usually perceived as a vegetable. So three tops identified just in this example. Depends on context; import, science or consumers.
- divs1210 5y ago> The other thing for which OO works much better than plain data is GUIs This cannot be further from my experience. Switching from Java/AWT/Swing to ClojureScript/Reagent/Re-frame has been suoer liberating. Every GUI programmer must fiddle with reagent once: https://reagent-project.github.io/ https://reagent-project.github.io/
- iforgotpassword 5y agoWell, you really picked the worst representative with awt/swing. I'd say Qt or even classic VB6/Delphi are great examples for OOP gui development.
- MaxBarraclough 5y agoHow about JavaFX? Swing has been old hat for years now.
- iforgotpassword 5y agoI haven't touched java gui code in almost a decade, but didn't they suddenly pull a 180 on JavaFX a few years ago?
- MaxBarraclough 5y agoNot exactly, they moved it out of the core Java standard library. The main effect of this seems to have been that many developers are now uncertain of whether JavaFX can be relied on, but it is still maintained.
- astrange 5y agoCocoa has been a great OOP-based UI framework forever. The key is that it doesn't use inheritance and has messaging (https://wiki.c2.com/?AlternateHardAndSoftLayers https://wiki.c2.com/?AlternateHardAndSoftLayers).
- 5y ago
- dnautics 5y ago> The other thing for which OO works much better than plain data is GUIs I think the absolute dominance of React and its functional style (especially among juniors) is pretty good evidence against this belief.
- kaba0 5y agoIt is pretty much an MVC separation that was mainstream in OOP-based GUI frameworks since the 90s at least. But instead of “state”, you have a model, which uses the Observable pattern to notify the view of changes.
- TeMPOraL 5y ago> The other thing for which OO works much better than plain data is GUIs - and I think it is not a coincidence that OO popularity exploded together with the the coming-of-age of GUIs. Yeah, and I think the reason has nothing to do with objects per se. I've recently been coming to conclusion that the one thing that makes OOP last is that it's neatly packaging an important feature that other programming paradigms struggle with or ignore: late binding (aka. dynamic linking). Is it better to write a class Foo with a method Bar(stuffs), or a struct Foo and a function Bar(Foo&, stuffs)? I don't care. They're literally the same thing. But say I want to change the system so that, in some cases, it calls Baz instead of Bar - but I don't want to rip the system apart and change every call site. With OOP, I just make a class Quux inheriting from Foo, have it override Bar(stuffs) to do Baz code, and shove a Quux object into the system. Done. Dynamic linking ensure that my new implementation gets called for Quux objects. Meanwhile, in most programming languages, you can't pull that same trick with a struct. Not without having to manually reimplement dynamic dispatch - at which point you may as well use an OOP language. Dynamic dispatch is a super useful thing to have. You can minimize its use - and probably should, for performance reasons - but when your language doesn't support it as a built-in feature, these few cases in which you need it get very painful to write.
- ric2b 5y ago> But say I want to change the system so that, in some cases, it calls Baz instead of Bar - but I don't want to rip the system apart and change every call site. With OOP, I just make a class Quux inheriting from Foo, have it override Bar(stuffs) to do Baz code, and shove a Quux object into the system. Done. Dynamic linking ensure that my new implementation gets called for Quux objects. Functional programming does this with pattern matching, it is just as easy and avoids the dangers of sub-classing.
- beagle3 5y agoThere’s another side, which is that from a source code management perspective, modern pattern matching forces you to group implementation by operation (to get all the benefits), modern OO let’s you group by “class”. There’s no right or wrong answer here. For GUIs, it appears grouping by class is more effective. But many other times, it’s not.
- prionassembly 5y agoI have a word for you: https://plato.stanford.edu/entries/mereology/ https://plato.stanford.edu/entries/mereology/
- Sohcahtoa82 5y ago> The other canonical example of OO - "Shapes" - doesn't actually work well at all; It doesn't work better with "plain data", but it exposes the fallacies of trying to use OO inheritance to model the real world. Shapes work well, but people do the wrong things with them, as you state... > Every square is a rectangle, so square should inherit from rectangle ... but, you can't stretch width and height independently in a square, so it's not really a rectangle, etc. etc. A square is a just a rectangle where the length and width happen to be the same size and shouldn't be its own class. Books and websites teaching inheritance should stop trying to use it as an example.