1. 21
  1. 36

    OOP feels like what happened to Agile: people were so concerned about doing it “right”, that they stopped thinking about the real goal: delivering products and services. Consequently, people appear out of the woodwork when there’s money to be made to tell people about that “right” way.

    1. 17

      This is my feeling.

      And right now the same is happening to functional programming: developers will stop other developers from producing perfectly fine working code because

      • it isn’t functional,
      • isn’t functional the correct way
      • or isn’t functional the right way in the right framework.
      1. 15

        If it’s any consolation, in a few years I expect somebody to make waves with a new twist on functional programming that helps augment records with functions already bound to operate on those records, so you can pass them around more easily through data pipelines, and also a defined mechanism for letting those records call up to a default set of functions so you don’t have to keep specifying them for records that are one-off similar.

        Also, joke’s on everyone: with microservices, everybody is doing Kay-style OOP whether they want to or not.

      2. 5

        It’s almost like incompetence ruins things, not paradigms. 🙂

        1. 2

          people were so concerned about doing it “right”, that they stopped thinking about the real goal

          The whole point of methodologies is to be productive. If you are being less productive either you are not “doing it right” or the methodology is flawed.

          The problem with OOP is that people often overuse inheritance, create unnecessary classes, overuse abstraction and so on.

          there’s money to be made to tell people …

          I’ve never met a travelling “OOP consultant”. OOP is hardly a profitable idea. I’s just a popular buzzword.

          1. 4

            I’ve never met a travelling “OOP consultant”.

            I remember OOP consulting being hot shit in the mid- to late 80s.

            (Edit I wasn’t actively developing, but I read a ton of Byte magazine issues).

            1. 1

              I’ve never met a travelling “OOP consultant

              Here’s one: Sandi Metz

              1. 1

                I never met him…

          2. 17

            I skimmed it and saw the following things that were factually wrong:

            • Simplicity is the same as reliable
            • OOP requires procedures or imperative programming
            • OOP languages weren’t “properly designed” and didn’t “come out of a research institution”
            • OOP cannot have a theoretical foundation
            • OOP code is nondeterministic, while FP code is always deterministic (what does this even mean?)
            • The human brain thinks in “doing things” (sounds like “not even wrong” neuroscience)
            • FP is in contrast with OOP
            • Alan Kay invented objects
            • Kay’s original OOP vision didn’t intend to have polymorphism or inheritance
            • Messages are in contrast with method calls
            • Erlang systems have 99.9999999% reliability (Ericsson completely disavows the claim)
            • Design patterns are just an OOP thing
            • The author can juggle two balls.

            Those are just some things I noticed that are factually wrong, as in not-up-for-interpretation wrong. And I didn’t really try to dig into his claims, just the stuff I saw that was obviously factually wrong. As it is, it’s a pretty sloppy hit piece.

            1. 2

              That’s a great presentation, thanks.

              1. 2

                I mean, juggling two balls in one hand is a thing. But otherwise, right on the money.

                1. 3

                  He thinks he can “probably” juggle two balls, which is pretty good evidence he thinks “two balls” means 31 and not 40. Most people can do the first without practice, but not the second.

              2. 15

                I agree that mainstreamed OOP is awful. Mainstreaming FP will go the same way. We’re at the point with Functional Programming now that Object-Oriented Programming critics saw OOP being at a quarter of a century ago. Everyone knows that it’s The Solution and cannot understand why anyone would use anything else. Let’s check back in twenty-five years from now to find out why mainstreaming FP was a quadrillion-dollar disaster that people should have seen coming.

                1. 5

                  Sadly, enough buzzword-based management and consultants can turn anything into a disaster.

                  1. 12

                    This is all a symptom of the immaturity of the industry. We still don’t have a reliable way to measure our work, which means that we as an industry are vulnerable to groupthink and cultish trends.

                  2. 3

                    When the pendulum swings back what the industry (or at least, the cheerleaders and consultants who make money on these things) still won’t want to admit, but what many people have said for a long time, is that people can, and will, write shitty code in any language / framework / paradigm.

                    1. 4

                      Again with the relativism! Some languages are better than others. Some paradigms make it harder to write shitty code and inherently promote good practices. I believe FP fares better according to this measure.

                      1. 3

                        I didn’t say some languages aren’t better than others, I said that it’s possible to write shitty code in any language. Maybe it’s only shitty relative to great code written in that same language, but I stand by the claim.

                    2. 1

                      So much this. Some problems (lots of structure but don’t have the data yet) lend themselves to OO as a reasonable method. Others (I need to repeat the same thing on a bunch of existing data) make really good sense with functional.

                      Using either as a magic bullet that is THE ONE TRUE WAY is going to result in a very bad time.

                    3. 12

                      Long winded rant with little end in sight. I agree with the general message but think this post is a poor ambassador.

                      I wish people would at least get rid of subclassing. It’s easy enough to implement but causes substantial problems when reading and debugging code.

                      1. 18

                        Is this the place for a pet theory? Here’s mine based on the history of programming languages:

                        Adoption of FP, in the early industry, was hindered by two things: one overt and one hidden. Together, they created a space which allowed OO to flourish, but now FP is set to gain market share, and it is.

                        The overt thing is something that people often comment on: FP forces mathematical reasoning on programmers to a greater extent than OO or procedural programming. I won’t belabor this one. The hidden thing is that execution speed was an issue for a long time in our industry. That has changed in the past two decades but, early on, it was seen as impractical to implement closures for any sort of commercial system. A function call for every item in a loop? That was just seen as madness.

                        So, procedural languages and their OO successors were late to the party. It took a long time for them to add lambdas, closures, and blocks. Smalltalk and Obj-C were exceptions. For languages like C++ and Java it took decades. Once you have closures, you start to think about higher-order functions. When you are thinking that way, you start to investigate functional. That’s what has happened recently.

                        We can get upset about OO, but it served its purpose. It enabled the creation of many large systems with somewhat lower skill than functional requires. Now, we have a clear choice. We can build large systems the (now) traditional way with OO, or we can aim for higher quality (and less code) with FP.

                        1. 10

                          A function call for every item in a loop? That was just seen as madness.

                          An equally-hidden corrolary: compilers have gotten WAY better since, say, the early 90’s. A lot of this is because we just have more CPU and memory to throw at them, and a lot of it is because piles of work have gone into large existing frameworks like GCC and LLVM. The mythical Sufficiently Smart Compiler is now a difficult but essentially commodity system with a handful of good choices on the shelf.

                          I mean, what kind of compiler WOULDN’T aggressively inline a map or fold where it can? One I’d prefer to avoid, is what.

                          1. 3

                            All this compiler cleverness has their own issues though: the code you write is no longer the code that the computer runs, and having the correct program behaviour relies on the Sufficiently Smart Compiler being bug-free enough.

                            There’s also the issue of developer ergonomics: I personally compile all my C code with tcc when developing as that’s so much faster than gcc or clang; even with -O0 gcc takes about 2 minutes to compile all of Vim on my system. With tcc it takes about 4 seconds.

                            1. 2

                              All this compiler cleverness has their own issues though: the code you write is no longer the code that the computer runs, and having the correct program behaviour relies on the Sufficiently Smart Compiler being bug-free enough.

                              Does this matter, other than in a philosophical sense?

                              For example, if I ask the computer to take an average of a set of integers, and it does some weird optimization magic, and returns the same result as if I’d done the calculation by hand, that means it’s doing the right thing - even if it’s doing something I’ve never even thought of.

                              I guess if you’re trying to prove a mathematical thesis with computer-assisted proofs, it’s relevant. But for day-to-day programming, other errors dwarf any issues with the compiler.

                              1. 1

                                Does this matter, other than in a philosophical sense?

                                I’d say yes, it does. This is basically how you get Undefined Behavior in C, C++ and Rust: the compiler is allowed to assume the language works a certain way so it can perform more optimizations, which is a subset of what the language can actually do. Dereferencing a null pointer in C, making an infinite loop in C++, creating invalid references in Rust. So the language the compiler is compiling is different from the one the programmer is writing, but it’s up to the programmer to know the difference.

                                …other errors dwarf any issues with the compiler.

                                This is certainly true. We do things like make Undefined Behavior because it improves things for the average case at the cost of the worst case. So, the question of “does it matter” becomes a philosophical one. ;-)

                          2. 3

                            OOP used to be about message passing, but then it became programming with classes and inheritance. Functional programming used to be about programming with functions, and then it became about monads and functors.

                            1. 2

                              Object Oriented Programming has been about a lot of things. Check out this comment by hwayne for a nice history lesson.

                            2. 3

                              In C++, the functional paradigm, or rather a feeling of it, emerged rather much sooner than you think, I would not say “Decades”. If you consider templates or the standard library, namely <algorithm>, there is a bunch of stuffs that are oriented with functions to be passed as value parameters. They have been incorrecly called functors standing for function objects (not synonym of Functors like in Haskell/Category Theory). They were available since the first standard ISO C++98. For example std::transform, is closely resembling the map function in Haskell. There’s this link for some historic stuff: https://www.modernescpp.com/index.php/functional-in-c-98 And anyway you could already pass function pointers even in C ;-) ! though I would not call that functional programing yet, that’s ok ;-)

                              1. 4

                                Thanks. I’d forgotten. Reminds me of the joke question of which was the most baroque unintentional functional programming language: XSLT or C++ templates?

                                1. 3

                                  Argh :-) I dare the answer: having used C++ so long, of course I’m biased when I say that XSLT is too much complicated. But I would not dare a competition of readability between a real production XSLT file and a real C++ library meta-programming template error. I think (without exagerating) that once I have had a 400 lines error message. 400 lines, that was the length of the C++ templated type description. I said once. Hopefully c++20 concepts (which I feel like an approach toward Haskell typeclasses) will makes those nightmare error messages disappear.

                            3. 9

                              The article seems like a trillion dollar disaster itself, wasting a good title. There’s quite lot of craptalk throughout. Also appeals to authorities spread across the post… Seriously think that Linus Torvalds doesn’t do any mistakes and him avoiding OOP would not be one such mistake? Research institutions favored over industry practices? What the heck dude? You still trust everybody after this mess?

                              Then there’s the bull about functional programming as a remedy in the middle. When you bring it over to mean coding in Javascript, it becomes the same turd with the label in the can replaced by an another. Yeaah.. Sell it to us!

                              Warning you ahead: There’s the classical “complexity is bad” -talk mixed in. Complexity down. Ohwait what is meant with complexity here? The guy/gal tells it’s shared mutable state and errorneous abstraction, low signal-to-noise. All those things common in OOP. Maybe the worse problem you have would be that nothing you ever wrote is actually correct? People find bugs in your stuff decades afterwards, and others add their own bugs in! Things have to get quite complex to actually do the things you want them to do and there’s nothing you can do about that. Terabytes of memory in your system. How would you expect that your software could even be simple in the same way it was when you had 32 kilobytes of available memory?

                              And this dogma about mutable state.. Little they do know that latest theorem provers like Idris2 are ok with mutable state and handle it well because of progression into affine/linear logic, and you don’t have problems with reasoning over mutable state with that tool. Then there’s that thing “Separation logic” for reasoning about traditional programs. Mutability or parallellism in OOP aren’t the things that make it bad. They’re merely just things that OOP doesn’t do jack shit about. It’s completely ineffective in handling those things, just like the “FP” is, it’s just that with “FP” you aren’t even able to do anything with mutable state so the problem’s solved?

                              All that incense over message passing is old stuff. It was there when I started coding. Too bad it doesn’t work because messages really provide very little in terms of what you can predict about program’s behavior, often things go over multiple steps before they accept the same message again, meanwhile everything can go wrong. Even Haskell doesn’t help because you still do typo or forget precedence rules somewhere such that it passes the type checker without being noticed and introduces a new case that isn’t catched by any of your seven test suites because it’s a new way to get it wrong.

                              There’s lot of things you can argue spread around there. Encapsulation as global state? OOP modeling real world through its inheritance? All of those factories and MonaLisaProviders being complexity? Bit of intertextual references to classical texts (kingdom of nouns, that was fun to read years ago).

                              Too bad(good?) to the author of that post. People are going to get back into dragging them to your level and arguing with you, just refuting what you say. Unit testing must be great because we test things in real world to make sure they qualify! It can’t be bad with coding?! That time surely isn’t wasted like you claim. Controlling your private parts is important so why not private/protected/public is important too. Surely packing things together must be an abstraction and that’s necessary to write software at all.

                              Meanwhile, your whole industry is a fraud in the progress. You even already know it and feel something that your peers call “impostor syndrome”. Sigh.

                              Nothing of OOP does anything because it attacks the false problem in the first place just like many other software solutions do. You blame yourself about missing targets but you aren’t even aiming at the target when you press fire. Things such as static or dynamic doesn’t mean anything at all. You should foremost care about what you know with certainty of program’s behavior before it runs.

                              The history is indeed repeating itself, and this dude is repeating it. This time with FP.

                              1. 1

                                Nothing of OOP does anything because it attacks the false problem in the first place just like many other software solutions do. You blame yourself about missing targets but you aren’t even aiming at the target when you press fire.

                                Indeed. A problem well-stated is half solved. We did not spend enough time on investigating what is the real problem, and what actually makes the problem hard, but spend far too much time on arguing arbitary solution. Here are some problems I find fascinating:

                                • How to make developer perceive the global architecture when we only have a dark screen of 80 characters scrolling over thousands of files?
                                • How to make developer perceive what is actually going on when we only have “console.log” as a tiny torch lighting up the cave?
                                • If somewhat mutable state is inevitable, how to make “variable” or something with “identity” easier for human cognition? Is mutability the problem, or we are simply having too many states, especially too many ungrounded, local, transient states?
                                • It is well-known attention is single threaded, and developer can only do informal reasoning with attention. How to make software source code read like “single threaded” but actually exploit parallesim in the runtime?
                                • Why re-use is more successful in certain area, but not in other? Is it because there is a missing common ground to make the inter-changable parts economy flourish?

                                I don’t know exactly when people invent OOP or FP, what kind of problem do they have in mind. It will be more constructive when we can start discussion from the problem.

                              2. 6

                                Any one of these articles which concludes with “…therefore, functional programming” should be thrown in the bin.

                                First: Implementation inheritance is like null. We pretty much all agree it’s a bad idea and we wish it hadn’t been done. That being said, there aren’t really a lot of systems forcing you do use it.

                                Second: mutable state is a problem when it’s not controlled properly. It’s also a hard requirement somewhere in the process if you want to do something other than heat rooms. All business value (at least when computation is the means, not the goal) comes from mutating state.

                                As far as “paradigm problems” - There’s a bunch of things which are nice and easy to do in OOP with virtual methods. There’s a bunch of things that are hard to do in this paradigm. These things that are hard to do in the OOP paradigm are easy to do in the functional paradigm. And the things that are easy to do in OOP are hard to do in functional. Neither one of these can or will ever be a blanket “is better” answer, and anybody telling you otherwise is confused, or lying to you.

                                1. 2

                                  It’s also a hard requirement somewhere in the process if you want to do something other than heat rooms.

                                  Good post overall but I really love this line :)

                                  1. 1

                                    All business value (at least when computation is the means, not the goal) comes from mutating state.

                                    “The interior state of the program” and “the state of the outside world” are two different definitions of the word “state”. It should be a goal of any programming tool to simplify working with the former, and FP generally does that by focusing on the flow of immutable data through the program. However, you seem to be conflating that with the latter.

                                  2. 3

                                    My first CS class was AP Computer Science in high school. It teaches Java with an orthodox OOP. It took my a decade to get out of using implementation-by-inheritance, deep class hierarchies, and all that stuff. Now I try to use a mix of composition and functional concepts. I’m sure in 10 years I’ll have a different opinion.

                                    1. 7

                                      I’m not sure you will. :) I’ve been using mainly composition and functions, with classes of depth ~1 as ADTs when that’s how the language does it, for >30 years, and it’s always worked just fine. (Most of my serious work has been in C, 1990s C++, C#, Ruby, and lately some Go.)

                                      Even Java doesn’t require freakish levels of OO — it just became particularly fashionable there for some reason.

                                      1. 3

                                        That’s basically how I did it, too. OOP just for data structures and information hiding. Functions/procedures were always good enough for me. State machines, too.

                                        1. 1

                                          aww, you guys are missing async-message-passing :)

                                          1. 1

                                            I did it for distributed in some project. I held off on learning it until I could make it safe-ish. I’ll be looking deep into Erlang and/or Pony some time in the future. Just not ready yet.

                                    2. 4

                                      Haven’t we all read this rant a thousand times before (though perhaps with different wording)? However, I feel the author got a few things wrong:

                                      1. Erlang gains its famed robustness not by its OOP implementation, but by its solid VM and the crash-only principle (working even in the face of errors)
                                      2. Functional programming is not the solution, it’s overshooting in the other direction. The problem with procedural and OOP programming is shared mutable state, not any mutable state. I personally think that Rust offers a very good solution that gives us much of the benefits of functional programming, but much less of the cost.
                                      1. 2

                                        I feel like I’ve had some of the articles opinions about OOP before, but a few years ago my employer sent me to one of Sandi Metz’ courses based on 99 Bottles of OOP. Hearing from someone who loves OOP and seeing why was kind of eye-opening.

                                        Another book that altered my views about OOP was Game Programming Patterns. I’m not a game developer, but the code examples and descriptions of why OOP (and the often-associated Gang of Four patterns) can be useful were enlightening.