1. 7
  1. 18

    I find this article & much of the FP community somehow completely misses the point of OO.

    I’m not an expert of OO to provide great claims, but I can say that working in ruby made me see it really is a beautiful way to handle state in certain cases & has value.

    How can you completely write-off an entire paradigm/philosophy?

    In general there’s a lack of respect for many languages that don’t fit the cool/obscure criteria. Most languages were designed for quite a long period of time, if nothing else give some respect to all the time spent & try to understand the design choices that were made. People don’t add or omit features purely out of ignorance of FP or types.

    Not every language needs to protect people from mistakes. Not every language needs to have a sound type system or one at all. Not every language even has to have a novel feature.

    But every language will have a vision, which I think more often than not is not purely semantics/feature based. Ecosystems are part of the language. The philosophies of the creator is part of the language. Etc.

    It is extremely rare that any feature is strictly better than any other feature.

    1. 8

      I once wrote that there are three kinds of programmers: problem solvers, puzzle solvers, and artists. A lot of times language criticism comes from someone who is in one camp against the other. “Why would I care if a Monad is a monoid in the category of endofunctors when I can make a website in PHP in a weekend of Red Bull?” “Why would I use PHP when the code will be an unmaintainable mess in three years?” “Why would I use a type system that can’t encode all my code’s invariant conditions?” Etc.

      1. 3

        There are similar variations on the “three kinds” argument. On the one hand, it’s important to recognize that different languages have different design goals and different audiences. On the other, the OP summarizes common critiques of classical OO that, perhaps due to a failure of my imagination, do not solve problems for any audience, for example:

        • the brittleness of inheritance and artificial taxonomies in general
        • how prominent shared mutable state is in OO language design
        • how encapsulation does not really solve problems with shared mutable state
        • the awkwardness of “records with overinflated egos” and the “kingdom of nouns” vs. using verbs (functions) to operate on nouns (anything)

        It could be that because OO never clicked for me that I haven’t been motivated to look for useful patterns that are unique to classical OO outside what I encounter in my day job. In any case, my hope is that, as so many languages evolve into a multi-paradigmatic soup, the OO inertia will dissolve and the choice will be amongst better or worse application design patterns rather than programming language tribes.

      2. 2

        Strong static typing+ADTs+pattern matching makes for a pleasant programming experience for most problems. But I don’t get OO bashing at all. It’s just another approach to data abstraction[0, 1]. Doesn’t fit the problem, don’t use it. OO did turn into a cult and made a lot of noise during the 90s and early ’00s and that did not help. In the meanwhile a ton of research happened on FP and when hardware got faster and cheaper most of these ideas got implemented and took over modern general-purpose programming. OO still has uses: UI stuff maps well, even OS kernels are inherently OO (devices, VFS etc) although they all use horrible kludges to implement the model. I was secretly hoping that @david_chisnall would somehow inject a Smalltalk/Objective-C runtime into the FreeBSD kernel to replace the KOBJ stuff but it looks like he has moved on (and that is a good indicator btw!).

        [0] https://web.cecs.pdx.edu/~black/OOP/slides/Cook%20on%20DataAbstraction.pdf

        [1] https://www.cs.utexas.edu/~wcook/Drafts/2009/essay.pdf

        1. 2

          OO did turn into a cult and made a lot of noise during the 90s and early ’00s and that did not help.

          I think OO became popular because they were a nice way of handling GUIs. And they made genuine attempts at solving a bunch of business logic problems.

          In the meanwhile a ton of research happened on FP and when hardware got faster and cheaper most of these ideas got implemented and took over modern general-purpose programming.

          I’m aware that some FP concepts have been implemented in Java and .NET, but from what I can see the dominant model is still some form of OO. Java, .NET, Python and Ruby are OO. Is JS more FP than OO? Maybe depends on how you squint?

          I still see FP as rather niche, especially as the proponents of FP push languages like Haskell and Ocaml that have so far failed to take the world by storm.

          1. 2

            Pure FP may be niche but value-oriented programming (ADTs + pattern matching + functions/closures), as opposed to a class hierarchy, is not IMO. JVM has Scala and Clojure, .NET has F# with C# picking up features from it regularly. JS has Typescript. Haskell and Ocaml have eaten into dynamic language territory, may or may not be in the enterprise. Even C++ too is slowly moving away from (a bad) OO towards (a bad) ML Swift and Rust, I’m sure would have enough features to enable programming with values. It is just a matter of time before “programming with values” becomes the standard approach.

            1. 1

              Well, that’s interesting, but it just tells me that the most successful languages are amalgamations of the concepts from more “pure” languages that actually have real-world value.

              After all, purists will say that Java isn’t “real” OO because it’s not Smalltalk. But Java is a massive success, and Smalltalk is a footnote in history.

              In 20 years greybeards will complain that JavaScriptXS isn’t “real” FP because it’s not Haskell.

      3. 14

        The PersonnelRecord isn’t OOP and exhibits a widespread misunderstanding:

        class PersonnelRecord {
          char* employeeName() const;
          int   employeeSocialSecurityNumber() const;
          char* employeeDepartment() const;
          char  name[100];
          int   socialSecurityNumber;
          char  department[10];
          float salary;

        As written, the PersonnelRecord class will inevitably lead to code duplication, tightly coupled classes, and other maintainability issues. An improvement that’s still not OOP, but exposes a more flexible contract, resembles:

        class Employee {
          Name name() const;
          SocialSecurityNumber socialSecurityNumber() const;
          Department department() const;
          Name name;
          SocialSecurityNumber socialSecurityNumber;
          Department department;
          Salary salary;

        OOP is more about the actionable messages that objects understand to carry out tasks on behalf of other objects. Wrapping immutable data exposed via accessors reaps few benefits. Rather, OOP strives to model behaviours that relate to the problem domain:

        class Employee {
          void hire();
          void fire();
          void kill();
          void raise( float percentage );
          void promote( Position position );
          void transfer( Department department );
          Name name;
          SocialSecurityNumber socialSecurityNumber;
          Department department;
          Salary salary;

        This allows for writing the following code:

        employee.transfer( department );

        I don’t know how to “transfer” an employee given the code from the article, but it would not be nearly as elegant.

        1. 10

          This waffled on a lot so I skipped to the end for the “mathematic explanation for why OOP sucks a big time”:

          You’ll see the Java and C# […] make it inconvenient to write abstract variables and convenient to throw in few ints and floats, although these are quite close to the machine implementation


          In functional programming you just say “a” if it’s something that goes through your system intact. That’s as abstract as it can be

          This is nothing to do with functional-vs-OOP; it’s about type genericity. A functional language can still require you to specify parameter types (sure, many don’t and have generic functions, but that’s not the point unless you’re comparing specific languages rather than programming paradigms).

          I feel like the whole piece is fluff.

          1. 7

            Anyone who knows some PLT has long moved on from this debate, what we are seeing is new people joining old discussions that haven’t been cleaned up properly (so the new people are being “wrong on the internet” and hopefully they will receive the support needed to move on to being wrong about something new).

          2. 7

            Frankly hater pieces such as this are unhelpful. They are unhelpful to the author who shows ignorance in the topic he is talking about, and unhelpful to the wider community who apparently are mostly doing it all wrong. Most of all it is unhelpful to beginners who might be prejudiced against a paradigm together with particular languages/frameworks/methodologies and practices without due reason.

            1. 3

              I’m not an expert on OOP or FP, but I’ve used both and greatly prefer FP. I just FP programs so much easier to understand than OOP programs. However, I think some concepts from OOP such as encapsulation have some merits and can also be implemented in a FP style. I think there has been enough debate on FP vs OOP and we should accept that ideas from both paradigms are very valuable. While I personally hate dislike OOP and believe FP is the way forward, I will never flame someone for using OOP.

              1. 10

                OOP and FP have the opposite problem:

                With OOP, methods are tied to data in such a way that it’s hard to extend an abstract data type with a new behaviour because it requires extending every class that implements that data type with the new method.

                With FP, functions are specialised over data in such a way that it’s difficult to extend an abstract data type with a new concrete representation because it requires modifying all implementations of functions that operate over the data type.

                Which is more of a problem depends on your problem domain.

                Real-world code on either paradigm addresses these problems in similar ways: by defining a core set of methods / functions that are implemented by every instance of an abstract data type and building higher-level abstractions on top. My favourite example, NSString, provides a rich representation-agnostic set of methods that all depend on a concrete implementation providing at least two methods (get the length, get the character at an index) and ideally a third (copy a range of characters), with a fallback implementation of the first in terms of the first two for representations that don’t care about performance. In an FP style, these would be functions that you’d need to provide overrides for and the other string functions would be implemented to call only these three functions with whatever generic type you provided it as the string type.

                OOP does have one significant advantage over FP in terms of usability: noun-verb interfaces are more discoverable than verb-noun ones (‘I have a thing, I want to enumerate the things I can do with it?’ is a more common learning pattern than ‘I want to do a thing, what can I do the thing with?’) and OO languages are intrinsically noun-verb (you have an object, you call a method on it [or send a message, if you’re an OO purist]). This has nothing to do with the underlying semantics and a lot to do with the language syntax. Even in FP languages, the documentation tends to be organised in a noun-first style.

                1. 3

                  I very much agree with the last paragraph, and in my humble opinion, that namespacing is something which is the prime selling point of “OOP” while still fully compatible with “FP”. It just happens not to be in the popular OO languages of the 90s and early 2000s.