1. 10
  1.  

  2. 11

    Ten years from now we’ll be flooded with takes that FP is wildly overrated and the One True Way To Program is to use… I dunno, zarbomographic programming. And people will have to write “The case against FP is wildly overstated”. The pendulum swings eternal.

    The gap between theory and practice has fueled the interest in design patterns. As OOP became more popular, programmers looked to them for help with their achitecture. Unfortunately, design patterns can easily become a way to smuggle in overly complex OOP design under a veneer of respectability.

    People conflate design patterns with OOP, but every paradigm has design patterns. Should you use free monads or monad transformer stacks?

    1. 7

      I largely agree with you, but I wonder if part of the problem with OO was actually the marketing machine behind it. Sun dumped so much money into Java and put so much “thought leadership” into the world that the pendulum swung hard in the other direction. I don’t think there is as much force behind functional programming right now. That could change, of course.

      1. 9

        Java played a big role here, but OOP was already becoming dominant well before Java appeared. The Gang of Four book was originally written in Smalltalk and C++. Java’s main impact was to shrink the field to C++ and Java, killing competitors like Smalltalk, Beta, SIMULA, and Eiffel in the process.

        1. 3

          Yeah, I think shrinking the design space being explored could have had a part in that. You have a language with big claims, you denigrate and destroy alternatives, and just wait. It’s a recipe for backlash.

      2. 7

        I don’t object to your prediction, but how can you tell whether this is a pointless hype cycle or forward progress? Maybe these new paradigms do improve on the previous iteration and maybe zarbomographic programming will indeed be even better.

        1. 3

          Most of the OOP is okay vs OOP is not okay debate revolves around whether Inheritance was a good idea or not. And oddly most of the time everyone agrees we’d be better off it wasn’t used most of the time. All the rest of the arguments devolve into the classic koan about closures and objects being the same thing and people talking past each other.

        2. 17

          Requires a sign-in to read. Unread.

          1. 8

            Is there a way to filter content by domain? I never want to give medium.com my eyeballs

            1. 2

              Fair enough, and I agree.

              But if you like you can work around the problem by telling your browser not to accept cookies from medium.

              1. 2

                I opened this page both in Firefox for macOS and Firefox for Android, and both browsers showed me the full article without me having to sign in. I was able to view the article despite not even having a Medium account.

                Maybe your problem is related to this message I see at the top of the page:

                You have 2 free stories left this month. Sign up and get an extra one for free.

                Try opening the page in a Private Browsing window?

              2. 9

                The case against OOP is not that it is impossible to write good OO code, but that OOP encourages people to abuse bad design and bad patterns, which the author seems to concede. The article makes an argument similar to someone who says it’s possible to write eg Ruby without type errors: of course it’s possible, but the language makes it harder than other languages, which is the whole brunt of the criticism.

                1. 9

                  That only holds if you’re defining OOP to be something like Java circa 2000.

                  If you want to say “Java circa X encourages bad design”, I would concede that (see my other comment in this thread).

                  I would not concede “OOP encourages bad design”, because the space is so big and there are simply too many programs under that umbrella.

                  You could similarly define FP to be the subset of FP that allocates too much memory, is slow, and hard to modify, but that wouldn’t make much sense either.


                  I’ll point back toward the same comment: OOP and FP have largely converged – they are both about being principled about state and I/O, and not littering it all over your code.

                  https://lobste.rs/s/lwopua/functional_code_is_honest_code#c_twssec

                  “Immutable objects” were a thing 15 years ago and continue to be – and to not acknowledge that is like not acknowledging anything that’s happened in functional programming in 15 years (e.g. think Haskell or OCaml 15 years ago).

                  I understand that some people are still working with bad old codebases designed before that period. I think that is just the curse of “being used”, a la Bjarne Stroustrop (there’s 2 kinds of languages: the ones people don’t complain about and the ones people use).

                  1. 4

                    That only holds if you’re defining OOP to be something like Java circa 2000.

                    I think it holds pretty true of Rails in 2020 as well - idiomatic rails is a giant conflation of behavior and state where every model/controller/etc inherits from a framework class.

                    1. 2

                      OK I don’t have any experience with Rails, but that doesn’t surprise me too much. I am more of a Python person, and Ruby code definitely seems to lean more on classes/objects, for a better or worse.

                      I like this comment: https://news.ycombinator.com/item?id=24012090

                      If there is anything in CS which should be renamed simply because people have completely incorrect assumptions from the name, it’s OOP. Everyone has someone different they think about it, and almost none of it has anything to do with late-binding, encapsulation, or message passing.

                      Basically I think it is more useful to criticize Java or Rails specifically, rather than OOP, which is a big nebulous concept. (And ironically I don’t even agree that those are the 3 main things about OOP :) )

                      Although Java and Rails may share some problems with regard to maintainability, I also think they have completely distinct problems as well. Putting dynamically typed OO and statically typed OO under the same umbrella and making statements about them does seem like a stretch to me.

                      1. 2

                        Basically I think it is more useful to criticize Java or Rails specifically, rather than OOP, which is a big nebulous concept. (And ironically I don’t even agree that those are the 3 main things about OOP :) )

                        Those things quoted are not the 3 main things about OOP. The main things about OOP are inheritance, polymorphism, encapsulation and abstraction. (https://www.oreilly.com/library/view/vbnet-language-in/0596003080/ch04s02.html) At some point when you start defining OOP as not-these-things you’re just committing a “no true Scotsman” fallacy. And it’s entirely fair to criticize a language based on its dominant idioms and paradigms: writing code based around mutable state and subtype polymorphism isn’t just something you CAN do in Java or Ruby, it’s what you’re largely expected to do. The fact that even these languages have recently provided mechanisms to avoid doing this isn’t a counterargument to “OOP is bad”, it’s evidence that even mainstream OOP languages can’t sustain large professional codebases with the design patterns foisted by the overwhelming tendency of the respective ecosystems.

                2. 5

                  The differences between functional and OO might not be as big as you think. My favourite object-oriented language is Erlang. It’s not OO, you say? Processes encapsulate state and work through message passing; that’s basically an actor system. (Indeed, a lot of OO languages are essentially architecting distributed systems without the distributed…)

                  1. 1

                    In fact I would state that programming mutable OO vs Functional is an optimization choice.

                    OO to me is about type safety and program proving.

                    Mutable is an optimization trade off to be made only if required.

                    By default I make my constructors immutably bind instance variable names to a collection of values in a manner that guarantees that all instances of this class have certain properties and behaviours.

                    Making my objects mutable is an space / time optimization trade off to be made only if needed.

                    Inheritance is useful when I have a collection of classes that shared with a weaker, but still useful guarantee.

                    Yes, I do check and enforce this.

                  2. 5

                    Just gonna take one potshot at the new merged article:

                    Are you sure about polymorphism? First of all you took it from type theory and that’s itself getting popular featuring stable forms of parametric polymorphism, while your version of polymorphism is shifting shape like crazy.

                    You have it backwards. ML cited CLU’s type system as inspiration, which cited SIMULA as inspiration. Parametric polymorphism may be more elegant in typed FP, but from a historical engineering perspective it migrated from OOP to FP.

                    1. 1

                      Type theory itself is older than either ML or Simula, but it’s worthwhile to add this in. I’ll put a note in there sometime soon.

                    2. 4

                      The venerable master Qc Na was walking with his student, Anton. Hoping to prompt the master into a discussion, Anton said “Master, I have heard that objects are a very good thing - is this true?” Qc Na looked pityingly at his student and replied, “Foolish pupil - objects are merely a poor man’s closures.”

                      Chastised, Anton took his leave from his master and returned to his cell, intent on studying closures. He carefully read the entire “Lambda: The Ultimate…” series of papers and its cousins, and implemented a small Scheme interpreter with a closure-based object system. He learned much, and looked forward to informing his master of his progress.

                      On his next walk with Qc Na, Anton attempted to impress his master by saying “Master, I have diligently studied the matter, and now understand that objects are truly a poor man’s closures.” Qc Na responded by hitting Anton with his stick, saying “When will you learn? Closures are a poor man’s object.” At that moment, Anton became enlightened.

                      https://wiki.c2.com/?ClosuresAndObjectsAreEquivalent

                      1. -1

                        Haha :) nice username ~

                      2. 3

                        My take is that the claimed advantages are not really delivered by OOP. From the website:

                        • Encapsulation: Most OOP languages leak trivially avoidable implementation details to the caller (like whether some member is a field or a no-arg method).
                        • Inheritance: Usually not that useful.
                        • Polymorphism: Parametric polymorphism is often superior to OOP’s subtype polymorphism.

                        I don’t have anything against OOP, but it is definitely oversold.

                        In the end, just stop making everything mutable, and I can largely live with it.

                        1. 0

                          In the end, just stop making everything mutable, and I can largely live with it.

                          I largely agree with this sentiment, but I feel that since objects are essentially a behavior/mutable state combination, this sentiment is also very anti-OOP.

                          1. 4

                            Object-oriented design does not imply mutability, but rather most implementations of OO feature it as the fusion of behavior and mutable state. As you mentioned, this creates the perception that OO must be implemented this way. (In fact, few languages even take mutability seriously enough until very recently!)

                            OTOH, most languages feature immutable String classes in their standard library, and there’s nothing non-OOP-y about them. They’re fundamentally values, and have the semantics of values by being immutable. OOP is not opposed to value semantics. IMO, the sweet spot of OOP is defaulting to values everywhere, with a few islands of mutable state loosely connected together (see Gary Bernhardt’s Boundaries talk for further discussion).

                        2. 2

                          I’d be curious what you think of this talk.

                          It includes clips of interviews from decades ago from some of the originators of OOP as we know it today, talking about what their goals were and how they aimed to achieve them.

                          https://youtu.be/6YbK8o9rZfI

                          1. 1

                            There’s that thing again.. It’s more of a wording issue but eventually translates into a thinking issue. Functional programming doesn’t erase or “remove” side effects. It just separates side effects from reduction rules.

                            Also after I watched this video and thought on it a bit, a question arose: Is the modern stuff OOP at all? Has the definition been extended to cover every use of class-like structures?

                          2. 2

                            This is a defense of OOP by redefining OOP, essentially “Yes, inheritance and trying to model the world with classes are bad, but that’s not what OOP means, OOP means DRY and YAGNI and the law of demeter continuous refactoring and valuing simplicity above all else” seems like sophistry to me. The OOP moniker has no claim to DRY and YAGNI and refactoring and simplicity above any other paradigm.

                            1. 1

                              I agree that those things you listed are not especially related to OOP, but the author doesn’t say they are:

                              Unfortunately, design patterns can easily become a way to smuggle in overly complex OOP design under a veneer of respectability. […] How do you avoid this trap? Focus on the rock-solid principles of good programming [that you listed].

                              The author says those principles are ways to guide yourself to apply OOP in a good way instead of in a bad way. They don’t say OOP consists of those principles.

                              What does the author say OOP consists of, then? I think their view is represented by these quotes:

                              An object is a programming construct that lets you pack together data and functionality in a somewhat reusable package.

                              Object-oriented languages give you a set of tools for using objects (formalizing their interactions with interfaces, extending them with inheritance, and so on). But they don’t say much about how you should apply these objects to a problem.

                            2. 1

                              Very good article. I agree with the “original sin” of trying to model the real world. That may work in some particular cases (CAD programs), but doesn’t apply to most of code I’ve seen and worked with.

                              Roughly, I think about writing the most straightforward procedural code, and then refactoring it so state and I/O are explicit (dependency inversion). That naturally creates good class boundaries for the code.

                              In systems code, distinguishing between I/O and computation, and code and data, is very important. For one, parallelism essentially forces you to distinguish code and data (to prevent races). Instrumenting systems code often means instrumenting I/O.


                              This part:

                              An object is a programming construct that lets you pack together data and functionality in a somewhat reusable package. Some objects may be structs by another name. Other objects may simply be libraries of related functionality.

                              echoes something I’ve said and I haven’t heard anywhere else:

                              https://lobste.rs/s/lwopua/functional_code_is_honest_code (Functional Code is Honest Code)

                              I use “functions and data” (a la Rich Hickey).

                              Except my functions and data are both CLASSES. Data objects are basically structs, except they can do things like print themselves …

                              Function objects are simply classes with configuration passed to constructors.


                              Java also has some particular deficiencies that have been cleaned up by newer languages:

                              • Kotlin adds “data class”, which are values (equality, hashing, printing)
                              • I think Scala case classes are pretty similar
                              • Python also added dataclass late in its life. This was also a deficiency, but Python at least has tuples and dicts, and free functions, so you weren’t forced to put everything in a class. Java didn’t have this.
                              • Java lacks free functions. It confuses classes and namespaces, which is extremely miseadling and leads to bad design (which I’ve seen many times in real life). In the way I use Python and C++, classes and namespaces are very much distinct and orthogonal.

                              So as the article says, there are lots of real problems with OO, but people are learning.

                              The situation is analogous to Evolution of a Haskell Programmer – within the same language / paradigm there are dozens of ways to express yourself, some good and some bad. (Which the article also says)

                              1. 1

                                Yah I just think it gets used in a lot of places where the code should be polymorphic instead.

                                1. 1

                                  I think a bit problem with OOP is that it’s very vague. Either you have that box of things that relate to OOP (the four pillars from the article) when you come out of school. Or you have more a Smalltalk style understanding of OOP or it’s about concepts and use object oriented approaches to solve problems in languages that are not labeled object oriented, for example regular C.

                                  So in discussions people end up meaning different things.

                                  Another more generic problem that is not at all only true for OOP, but pretty much for all instances of trying to define “good code” is that people will simply make use of things like language features or blindly making everything a singleton, huge class hierarchies, etc. So even when there is a well-intended suggestion by an experienced developer or some blog article it can result in over-use and hard to read, maintain and debug code.

                                  Other examples of this are blindly following code linter output, working around them in non-idiomatic ways and not fixing underlying and systemic issues that might even lead to the linter output. Or overusing, potentially misusing language features, gorutines in Go, lambdas in every language getting them or promises in JS for non-async code or very complex iterative .map()-calls relying on side effects for example.

                                  I think a reason for this being such a big topic in the case of OOP is that it is taught in universities, often as one of the first things and frequently using Java (and sometimes Python). Nearly everyone who went through some kind computer science class will have been through this, even if they end up in a different field or in a very specific subset of the field.

                                  In the end it will be the thing people will agree on, because that was what they did back in school. And programming at university of course has a tendency to focus on something that makes it easy to check if certain, individual concepts have been understood. Depending on where you head after that initial contact, that might even out, but that’s certainly not everyone.

                                  After all designing and implementing software is a challenge and when the target might be moving or not clear at all one clings to those easy rules that even when they apply in many or even the majority of cases might be the very wrong path for the particular case and especially when there is time pressure, no prototyping and the problem is not well understood even the best programmers and even whole groups of them might end up making big design mistakes early on.

                                  Maybe OOP (and individual parts) should be taught later and/or there should be more explanation of it being a tool in a large set of tools. Also it might be a good idea to point out there have been quite a lot of studies about how different programming paradigms (and languages btw.) don’t appear to have significant differences in quality - by various definitions of quality.

                                  1. 4

                                    I think a bit problem with OOP is that it’s very vague.

                                    One could easily say the same of functional programming, which clearly means different things to different people. To some people, any language or even any style of programming rooted more in the Church approach than the Turing/von Neumann approach to computation is “functional”. To other people, only typed lambda calculus counts. To still other people, only languages with tail-call optimization and a culture of forcing every function to be tail recursive count. To yet other people, only type systems with very specific features count. Or immutability. Or lazy evaluation. Or… on and on and on we could go.

                                    So if you think it’s a problem that you can’t get everyone to agree on a definition of OOP, how do you feel about the fact that getting five functional programmers in a room would net you at least twelve mutually-incompatible definitions of FP?

                                    1. 1

                                      Vague definitions are a problem everywhere.

                                  2. 1

                                    Is it just me or are this and the article this replies to, essentially arguing for the opposite nor that their titles claim?

                                    1. 1

                                      Previous discussion of The Case Against OOP is Wildly Overstated on Lobsters: https://lobste.rs/s/bmzgvz/case_against_oop_is_wildly_overstated. It looks like the posting of another response article, Case against OOP is understated, not overstated, was merged into that Lobsters story as well.