6 ms·
I hope that, with the assistance of time, we can now adopt a more aristotlean/catholic "and" vs. a platonic/puritan "or" with respect to these various language
by recursivedoubts 4y ago
I hope that, with the assistance of time, we can now adopt a more aristotlean/catholic "and" vs. a platonic/puritan "or" with respect to these various language features.
Object oriented programming is a perfectly reasonable way to organize a code base and the basics provide for good encapsulation. Elaborate object hierarchies and the design pattern maximalism of the early java community that lead to the hilariously germanic ThingDoerFactoryFacadeFactoryInstaniatorService abominations are obviously bad, but the basics of OO do a good job if used reasonably.
Increasingly we are seeing pragmatic integration of different language features: for example using classes/objects for data modeling but using functional-style closures for data structure manipulation. Pragmatic static type systems with 'escape hatches' when needed, or dynamically typed language adding support for some static typing. Etc. This is the right thing.
Not "either/or" but rather "both/and" and using the right tool for the job. The manichaeism of early language discussions can be set aside and, rather than fighting about which language is "the right thing" we can talk about which language feature(s) is/are the right thing for this particular problem.
- thesz 4y agoPlease, define "reasonably". Because these people who created hilariously Finnish ThingDoerFactoryFacadeFactoryInstaniatorService also thought they do a reasonably reasonable job. Per your comment on "use classes for data modeling" I would like to provide you with two historical facts: it took more than 25 years to get Simula (and OO) types right [1] and it took not more than 8 years for Per Martin-Loef to have intuitionistic type theory right [2]. [1] http://lucacardelli.name/Talks/2007-08-02%20An%20Accidental%20Simula%20User%20(ECOOP%20Prize).pdf http://lucacardelli.name/Talks/2007-08-02%20An%20Accidental%... [2] https://en.wikipedia.org/wiki/Intuitionistic_type_theory https://en.wikipedia.org/wiki/Intuitionistic_type_theory Classes are much harder to reason about than other type systems.
- sebastianconcpt 4y agoReasonable in this context I'd understand as: 1. ThingDoerFactoryFacadeFactoryInstaniatorService trying to represent the reality of an abstraction meant to represent a reality (an indirection that isolates the domain in that level of abstraction of an abstraction). 2. ThingCreator. An abstraction named in a way that is closer to direct reality (and that can perfectly hide its own inner complexities using composition and they could be as many or more than the ridiculous example in 1). Note that people that, conscious or unconsciously, exclude the inverted pyramid principle fall into creating 1 and people that, conscious or unconsciously, embrace it, tend to create 2 in "a reasonable" way.
- jkaptur 4y agoDefinition of a reasonable paradigm: millions of developers can successfully use it to build software systems used by billions. Windows, iOS, Android, Photoshop, Excel, Chrome - these are complex products that use object-oriented programming. They exist and work well. They have shipped many new features over the years.
- ihatepython 4y agoThose products don't need to be complex, at their heart they are actually rather simple. They are just written in such a way that they become unnecessarily complex, because they are poorly understood. I would argue that the examples you give don't work well (Windows, Android, Chrome, later versions of iOS). They get worse and worse over time. Even if they start out with a good design, it turns to crap eventually. Just because a piece of software is used by billions doesn't mean that it is well written.
- DeathArrow 4y agoIf by successful you mean slow to develop, slow to run, bug ridden software we have to deal with today, you have built a great definition. This kind of thinking got us Teams and Slack.
- thesz 4y agoMillions of developers also use functional programming, for decades now. Even bigger order of magnitude of developers use relational languages to build systems of various scale. Indirectly, even more millions of developers use constraint programming of various sorts (compilers, databases and user interfaces). Given that, the definition of yours does not provide much to discern between paradigms. But we can compare complexity of logic of different systems and I provided two examples of that. We can even discuss some ordering between different systems. For example, contemporary type system that is powerful enough (not even dependently typed) can model class hierarchy, it is a no big deal [1] from, at least, 2005. So classes are, in some sense, less general than System F that is used above. They also more specific, whether it is good or not. [1] https://www.cs.tufts.edu/comp/150FP/archive/oleg-kiselyov/overlooked-objects.pdf https://www.cs.tufts.edu/comp/150FP/archive/oleg-kiselyov/ov... But in System F in [1] you can have several parallel class hierarchies, without requiring anything else from the system. The same goes to other things like "escape hatches". System with dynamic types cannot prevent (runtime) errors that can be prevented by a system with static types. It is just not possible to have reasonable description of a system without certain kinds of (runtime) errors without reimplementing many things from system with static type checking. On the other side, in system with static types it is quite possible to have over-encompassing type that represents all dynamic values one needs. So, systems with static type checking are, in some sense, more general than systems with dynamic type systems. And, of course, systems with dynamic types are more specific, whether it is good or not.
- rqtwteye 4y ago“Because these people who created hilariously Finnish ThingDoerFactoryFacadeFactoryInstaniatorService also thought they do a reasonably reasonable job.” The people who did this will mess up FP or any other paradigm too. I think OOP was a huge step forward but like with everything in software design, you have to have good taste and recognize when something you do is going off the rails. There is no paradigm that will save you from clueless people or ideologues.
- thesz 4y ago>The people who did this will mess up FP or any other paradigm too. The people who did this will not mess up FP or any other paradigm. I have an example of that somewhere in my career, with Haskell. But it is "he said she said" here and it is not me who started that. >you have to have good taste and recognize when something you do is going off the rails The Liskov substitution principle is not precisely defined, see the "shapes" problem (class Rectangle : Square or vice versa?). Thus, you have to have "a good taste," or, to be more reality grounded, you have to weigh your design choices against current use cases and possible future changes. When you deal with constraints on a type, you don't need hierarchy at all. If you add two values of some variable type in a function, assure function's type to have Num constraints for the type of these two values. Then pass there anything that has Num implemented and be fine. The inheritance in typical OOP program fixes solutions of historical use cases in place and prevents finding more general solutions when new use cases arise. The solutions for new uses cases most often get bolted on instead of being organically implanted. Basically, it is OOP that provokes such concatenative names. When you step outside, you find yourself in no need of these.
- kaba0 4y agoWho said that you have to use inheritance for shapes? I do know that it is an often used example, but similarly to Animal/Bird it has no real world relevance. I would even argue that inheritance is not the most important feature of OOP, but objects are. Inheritance is useful, for example GUI Nodes are famously good fit for it, but object encapsulation is the essential feature, missing that would pretty much disallow large swathes of programs from existing.
- shanebellone 4y ago"Classes are much harder to reason about than other type systems." Strange, I find classes intuitive. Objects lend themselves to physical system analogues; making objects easier to reason about in complex systems. The paradigm specifically helps me build light mental models which in turn helps me retain the associated codebase. Anyone else have a similar experience?
- recursivedoubts 4y agoI find classes extremely intuitive.
- thesz 4y agoI find classes extremely unintuitive. I find type classes and (generalized) algebraic data types to be extremely intuitive.
- recursivedoubts 4y agoI have met a few people like you, and I wish you all well in your programming careers.
- kaba0 4y agoI find both intuitive and one is better for these kinds of jobs, the other for other kinds.
- DeathArrow 4y agoThere are countless articles showing how OOP fails to model the physical world.
- shanebellone 4y agoStraw man. The point of contention regards ease of reasoning not completeness or ability to model the physical world.
- tobyjsullivan 4y agoI implemented a module with objects the other day. Five or ten years ago, in the heart of my object-oriented career, this would not have been noteworthy. The last couple years, however, I've managed to enter what almost feels like a post-OO phase of development steeped in javascript (and typescript) which commonly flows between procedural and functional. Long story short, on this particular assignment, objects made sense. They are short-lived, isolated in a module, and model the domain exceptionally well. This feels like the right balance to me compared to the decade of horrors I was complicit in building "object-oriented codebases". OO should be one tool that is known, studied, and reached for only when needed. I'd go so far as to say that the literature around OO might be more useful if it was written from that perspective. Perhaps too many Java consultants, thought-leaders, and shamans have led the conversation around OO since the 90's.
- pjmlp 4y agoWhat people call Java OO was made mainstream via C++ UI frameworks, that is what consultants, thought-leaders, and shamans were selling before a Oak tree turned into Java. The famous GoF is all about Smalltalk and C++.
- deleted 4y ago[deleted]
- bluetomcat 4y ago> Object oriented programming is a perfectly reasonable way to organize a code base and the basics provide for good encapsulation. It should be understood as what it is - an organisational paradigm over procedural programming. The basic building block of OO programs is still the procedure with some local and global state. OO lets you bundle procedures together in groups, associate them with mutable state, and call them (statically or dynamically-bound) via the static type system.
- kaba0 4y agoI mostly agree (and taming mutations is likely the reason for its widespread adoption), though there is no reason why it can’t be paired with FP, or at least restrict mutations to an object’s internal private state.
- Hermitian909 4y agoI don't think I can agree. OO feels like a tax, where payment is more coupling and layers of indirection in the codebase (and this is the happy case with good OO practices) but no benefits out the other side. Stepping back, an important set of question to ask when introducing any abstraction into a codebase is "What does it get me? What does it cost? Is what it gets me worth the costs?". OO says implicitly says "objects are always worth the cost" and I just haven't found that to be true. (keeping the metaphor going, this is obviously not so great a tax it's going to kill companies, hugely successful companies the world over pay it with out issue, but it irks me!)
- zabzonk 4y ago>more coupling and layers of indirection actually, OO claims less coupling. as to layers of indirection, i don't think it claims anything. > OO says implicitly says "objects are always worth the cost" don't know where you get this "always" from - objects are sometimes, maybe even often worth "the cost" (which is small), but not "always"
- stonemetal12 4y agoIn Java "public final class Math extends Object". So yeah, some parts of OO land went "always". I think that is way to far. As far as I am concerned Objects have their uses. Files in Haskell and the sequence abstraction in Clojure look like objects in everything but name to me.
- zabzonk 4y agoof course it is too far, which is why other languages don't do it, though they use objects elsewhere
- nh23423fefe 4y agoBut thats irrelevant. You can't instantiate that class so what does it matter. How should it be different?
- rqtwteye 4y ago
- photochemsyn 4y agoI've found this Jon Kalb talk immensely helpful - it's about applying best practices to OOP, and doesn't promote it or discourage it, just describes how to minimize excess complexity if you're going to use it. (2020) https://youtu.be/c0lutJECNUA https://youtu.be/c0lutJECNUA He also mentions three popular alternatives: 'object-based, static polymorphism, and functional' which is an interesting breakdown. I don't quite get what the author of this 2002 piece is saying here, however: > "And as a result we find that object-oriented languages have succumbed to static thinkers who worship perfect planning over runtime adaptability, early decisions over late ones, and the wisdom of compilers over the cleverness of failure detection and repair." Static polymorphism bad? OOP should be more on the dynamic side?
- wsc981 4y ago> "And as a result we find that object-oriented languages have succumbed to static thinkers who worship perfect planning over runtime adaptability, early decisions over late ones, and the wisdom of compilers over the cleverness of failure detection and repair." The way I read this is that you first have to think out all the objects and the way they interact with each other up front, before starting the development proces. I would imagine with a procedural style this is much less of a concern. You just have data types (adding fields as needed) and implement each procedure as needed as well, one by one. There's no interaction between objects to think about, just manipulations on some data type. But I also think his perspective is not 100% correct. Alan Kay said the main idea about objects is that they send messages to each other (or something like that). Objective-C (like Smalltalk) have objects that act this way and this allows for very dynamic programming where at runtime decisions can still be made easily (e.g. exchange method implementations at runtime or re-route messages). I would imagine this is harder in many other languages that have objects, since they generally don't adopt the idea of sending messages. From Wikipedia [0]: > One notable difference [with regards to C++] is that Objective-C provides runtime support for reflective features, whereas C++ adds only a small amount of runtime support to C. In Objective-C, an object can be queried about its own properties, e.g., whether it will respond to a certain message. In C++, this is not possible without the use of external libraries. The use of reflection is part of the wider distinction between dynamic (run-time) features and static (compile-time) features of a language. Although Objective-C and C++ each employ a mix of both features, Objective-C is decidedly geared toward run-time decisions while C++ is geared toward compile-time decisions. The tension between dynamic and static programming involves many of the classic trade-offs in programming: dynamic features add flexibility, static features add speed and type checking. --- [0]: https://en.wikipedia.org/wiki/Objective-C https://en.wikipedia.org/wiki/Objective-C
- DeathArrow 4y agoA class with just data is not an object, it's a structure. Inheritance and encapsulation are bad. I fail to see any pro for OOP even if I use it every day. OOP, "clean coding", design patterns and TDD morphed most code bases into monstrosities, hard to reason about, inneficient, hard to change and slow - even if they promised the opposite. I find good old procedural programming and functional programming more fun.
- wsc981 4y agoWhile I submitted this article, cause it raises some interesting points, I still do pretty much all of my programming in object oriented style. But for my next project I want to try the procedural approach. With that said, I've always believed that just a single level of inheritance can be quite useful (e.g. abstract base class and below that the concrete classes). However, adding more levels of concrete classes below this can get confusing. Perhaps there should be some way in programming languages to restrict subclassing to a single level only, perhaps that could be useful. It's kinda funny that when I started programming, so many years ago, I only did procedural programming (TI-BASIC on the TI-99/4A). But after programming object oriented for so many years, it feels kinda hard to make the switch back to procedural style. I do find my Lua / LÖVE 2D programs become much harder to reason about as the codebase grows and I am kinda hoping adopting a procedural style can fix this issue. Though I do know part of the issue is that Lua is not static typed.
- agumonkey 4y agonot a fp vs oo thing but more generally, in fp time made proper shortcuts possible (automatic currying, compositions abstractions) while oo has zero care for syntactic ergonomy, it's one big pain point imo the other point is the features of oo don't either help for modularity (it protects but doesn't help) nor logical mechanics, there should be a way to freely encode what is a valid object state, what transitions are allowed or not, without manually bolting a protocol on every methods (or requiring metaclasses / metaobjects)