But that paper also finally clarified for me why OOP is so awkward and unnatural sometimes. Why should an entire program be composed only of codata types? One would think data types (which are traditionally seen more in functional languages than OOP languages) would be more natural for most problems.
The specific combination of late binding and equi-recursive codata types that is approximated by OOP only makes sense when you're solving a problem that is naturally expressed in terms of those features, but in my mind the majority of problems are not.
The other major problem I have with OOP is that it's not a straightforward manifestation of an underlying mathematical calculus, but rather a hodgepodge of (not universally agreed upon) programming ideas that are best applied on a more à la carte basis. These ideas should be used when appropriate rather than taken as an indivisible paradigm to be applied wholesale to every programming problem. That's why I prefer to think of OOP as a design pattern rather than a programming paradigm: useful in some situations, but not to be used for every situation.
[1] https://www.microsoft.com/en-us/research/uploads/prod/2020/0...
How do you reach the conclusion that "the majority of problems are not"? But more importantly, the right question is not about the majority of problems, but the most common tricky parts of software, or, more precisely reduce the effort where it is largest, and the majority of tasks does not comprise the majority of effort.
I am skeptical about any programming paradigm making a big difference, largely because evidence suggests none so far does, or, at least, that there are diminishing returns, but even if some programming paradigm could make a difference, I doubt FP would be it, and not only because empirically FP so far hasn't. The reason is that FP "helps" when the task is easy to begin with, and once you start dealing with interaction, it "devolves" into classical imperative programming. If any style could help, it would be a style that specifically helps with the hard parts, not the easy parts. An example of a more radical approach would be synchronous programming, that at least aims to make interaction/concurrency easier.
However to what extent the move to OOP rather than FP (or logic programming) for instance is accidental rather than rational is a question one may ask. Javascript has nothing special but is wildly used just because it benefited from its quasi-monopoly on web scripting.
I think the problem is efficient, easy, correct: pick two.
With "easy" meaning not only "easy to program with" but also "easy to learn" and "easy to hire people".
Programming paradigms are false dichotomies. One can do pseudo-OOP with a procedural language, imperative in FP, FP-style in OOP. Not to mention the existence of multi-paradigm languages. Paradigms are merely about which programming style a language make easier, what is supported "out of the box".
The problem is then for the user to pick the right main paradigm for the task at hand. This is where programming becomes a craft - just like a proof strategy in mathematics is not dictated by the formalism, but is chosen based on intuitions (that is, expertise).
If there is no silver bullet, then maybe, from a programming language perspective, one can have a language that let us chose different pairs in (efficient, easy, correct) at different times. It is well-known that dynamic scripting languages make prototyping easier, but may not be viable in terms of efficiency and correctness for a finished product (Gradual typing tries to reduce this gap, it seems). Automatic memory management (garbage collectors) and more recently, languages with built-in concurrency features (instead of direct manipulation of OS threads) makes it easier to make less incorrect programs at the expense of some efficiency.
If we admit there is no silver bullet, then can we however to build silver bullet factories?
I'm not saying it's not possible to help, just that in a world of diminishing returns, it means that finding stuff that helps is very, very hard, and I think we're at a point where we can say that FP and OOP are not "the answer" to getting us further than where we already are, and start looking for other things.
> If we admit there is no silver bullet, then can we however to build silver bullet factories?
I would say that the answer is no, for a similar reason we can't build halting-problem-deciding factories. If we had silver-bullet factories, then unless picking the right bullet is very hard -- in which case we've solved nothing -- then we have a silver bullet. There are some fundamental reasons for that, and I tried to cover some of them here: https://pron.github.io/posts/correctness-and-complexity
The one unanswered question is how far are we from the best we can do?
Second, mathematical reasoning has its limits, especially as we're dealing with intractable problems. It doesn't matter if you can somewhat more easily reason about a simple three-line program in one paradigm than in another if most important programs are six orders of magnitude bigger. Unfortunately, program correctness (aside from some very simple properties) does not compose tractably (i.e. even if reasoning about components A1...An is "easy", reasoning about the composition A1 ∘ ... ∘ An can be more difficult than any computable function of n. So I would not put ease of mathematical reasoning about simple cases as necessarily the main priority, let alone the only one.
The problem domain that is naturally expressed in terms of OOP is GUI development (windows, toolbars, buttons, forms, and so on).
The tendency to entangle the actual problem you're trying to solve with the problem of developing a user interface for your solution seems to be the main driver of the growth and extension of OOP languages over the past several decades. Various patterns (MVC, MVVC, etc.) for disentangling these while still using the same programming language have become popular, as have multi-paradigm / mixed-paradigm languages. Perhaps what was needed instead were multilingual programs, which is sort of where we ended up anyway, in an ad hoc manner (eg. HTML+CSS+JS+SQL+Python, etc.).
This is opposed to datamodelling, which is the better approach to actually implementing complex stateful systems.
I can't see how - the idea of using patterns was that they would provide a common language of design and a "best practice" for common situations that would allow easier consumption of the services provided by other developers. Seems pretty aligned with OO to me!
- "Objects and Classes, Coalgebraically" (1995) http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.29.6...
- "Codata in action" (2019) https://www.microsoft.com/en-us/research/publication/codata-...
Coalgebras fit very well with the "hidden internal state" that characterizes objects in OOP.
Even if they were, I don't see why it matters. The nature of the basic mathematical building blocks doesn't have much of an impact when the problem described is intractable to begin with. Not a very good example, but the n-body problem is just as intractable, and no easier to simulate, using Newtonian mechanics than when using epicycles (well, it is, but not because Newtonian mechanics is more mathematically simple). My point is just that when dealing with intractable systems, simplifying the basic mathematical building blocks is not necessarily where we should spend our optimisation efforts.