Why OOP Exists

(mathspp.com)

21 points | by lumpa 3 days ago

22 comments

  • reaanb2 1 hour ago
    This article describes the OOP approach that leads to object-relational mapping, boilerplate code, database schema duplicated in code, navigational data access and the impedance mismatch. It defines OOP around data modeling and taxonomy, rather than around responsibilities. Principles such as "Tell, don't ask" and "Single responsibility" are just ignored. What responsibility does a book have in a library management system? It doesn't, it's just a subject of recorded facts, and a better approach would be to identify the behavioural components of the solution space, construct those as classes/objects, and let facts be encapsulated in or communicated between objects.
    • omnibrain 55 minutes ago
      "Object thinking" by David West was eye opening about this back in the day. The gist is to model the objects not along the line of real world entities, but along the line of "behaviour" like you mention.
  • mickeyp 1 hour ago
    OOP is fine. Not using OOP is fine too if your architecture / design demands it.

    What people forget -- much like the design patterns in the gang of four book -- is that languages and frameworks evolve.

    A decorator pattern was a niche but useful abstraction in the 1990s. In Python today you can @decorate stuff just like that. It's evolution.

    The same holds for OOP. Encapsulation and co-located methods with the encapsulating slots was an incredibly powerful upgrade over basic structs. Now most languages have first-class functions and lexical scoping so you can build your own encapsulation that way.

    It's all good. Just use whatever fits best.

    • kodoman 42 minutes ago
      I agree.

      I used to be OOP hater, but realized that it has it's place and some problems are OOP shaped and OOP is a wide range of techniques. I do think that python is a sloppy language and generally don't like it.

      Functional programming has it's place and I love it and is probably what my mind goes to the most, but often in Functional languages I find you can 'over fit' to a particular way of doing things, And with OOP your get more degrees of freedom with things you can do with a class and things can be modified easier, think sort of problems like a board game just as an example treating the pieces as an object can make it easier to modify any section of the logic of the game and add new pieces then the typical functional approach.

    • hereonout2 1 hour ago
      I often have to teach basic OOP concepts to junior - mid level developers.

      Many who've entered the career in the last decade or so seem to have missed what I 'd consider to be quite a fundamental grounding.

      Not even advanced concepts from the gang of four book - though I have taught these too - but often just an un-awareness of OOP in general, even simple things like understanding encapsulation.

      Frameworks and languages do evolve, but never being taught basic things like encapsulating state or exposing dependencies seems an issue. Very differnt from my own time as a junior when this stuff was constantly hammered home.

      • mickeyp 54 minutes ago
        You're probably right. But they most likely know more about functional programming, logic programming (if they studied CS), and have some awareness of advanced concepts that generally weren't widely known when we were young.

        I think it's just a shift in how development works: epicycles and all that. Luckily most OOP stuff they need to know can be taught quite quickly. And perhaps not knowing about GoF is a minor win for cyclomatic complexity in your codebase :-)

        If you're a Typescript developer doing React you're probably not going to reach for classes, for example, as it's just not a common paradigm in most modern React/TS codebases.

        • iamflimflam1 44 minutes ago
          I’ve met a lot of juniors who have no idea what functional programming is.
    • slopinthebag 1 hour ago
      OOP hate is definitely a popular way to signal that you aren't just a "common grunt programmer". And there are personalities who have made it a big part of their appeal.

      But I also spent some time with modern Spring Boot, and I get where the hate is coming from. There is a lot of complexity that just doesn't seem necessary at all.

      • danielbarla 1 hour ago
        > But I also spent some time with modern Spring Boot, and I get where the hate is coming from. There is a lot of complexity that just doesn't seem necessary at all.

        I'm sure there is some (very high) level of inherent project complexity where the massive number of abstractions and tools that Spring Boot gives you (and forces on you) actually starts turning into a net positive... And I'm also fairly sure that most projects don't quite break even, and would be better off with something more lightweight.

        • slopinthebag 19 minutes ago
          the functionality is often necessary and useful the question is if they're required to be implemented in the way that they are or if there is a simpler approach.

          also a lot of oop hate is 1) hatred of compile-time hierarchies attempting to match the domain model and 2) all the complexity in oop systems which isn't really inherent to OOP but made possible by it. oop doesn't require a PrototypeFactoryInjectorFactoryBean but it doesn't prevent you either :)

          on the flip side I've seen functional codebases which are also full of complexity because of how fragmented everything is, like 20 functions all applied when it could have been a single imperative one making it hard to keep track of what is happening.

          and of course everything in between

      • js8 1 hour ago
        Well, I just wrote a comment that could be considered an "OOP hate". I was debating whether to do it.

        The point is not to be snug about it. Functional programming (and monads) are actually simpler. You just need to resist the urge to "make it more understandable".

        Abstract math doesn't have good analogies to the real world. By trying to make an analogy with the concrete ("monads are mappable") you lose simplicity.

        • kodoman 35 minutes ago
          Monads might be simple but it's easy to create confusing large stacks of monad transformers in the haskell world, At least I have found and can often become not the most pleasant to work with aliasing complex monad stacks and all the rest, It can really lose elegance. Some problems beautifully fit as Monads and single monad code can be nice indeed but a few transformers and you can end up with a lot of mess. I do think there is some things that functional programming paradigm struggles with like games programming and other things, I really do think OOP is a better choice for some problems.
        • ImHereToVote 1 hour ago
          In the end you will be passing messages between entities when your codebase becomes complex anough.
          • js8 37 minutes ago
            That relates to another misunderstanding. These ideas like "everything is a function" or "everything is a category" are not there to help you understand complex system better.

            They are supposed to help you build better foundations; the abstractions to better understand your complexity you need to build (or at least pick) yourself.

            Good foundations then help you relate the abstractions. For example, the categoric dual of a product is a sum. We can apply it to relation (relational algebra), and we get that sum is data inheritance.

            So that gives you understanding of how functions (foreign keys), product (relation) and sum (inheritance) fit together. This sometimes helps to build abstractions in a consistent way.

      • mickeyp 1 hour ago
        Oh, I agree. But there's value in people who set out to do things a certain way, even if that approach ends up not working well in the long term.

        We're collectively shaking a lot of trees when we build frameworks, languages and tools. What works? What does not? What is the right level of abstraction? How much developer ergonomy do we want to sacrifice?

        Sadly we only seem to know in hindsight what works well. But that is also how we learn and grow; it was just meant to be this way.

    • jongjong 1 hour ago
      Some problems don't require OOP, but most large complex problems do, IMO.

      Most complex codebases I've seen which were pure Functional Programming were spaghetti code; unmaintainable.

      What I saw every single time was that the project was syncing a huge amount of state in a central place and then passing it through a large number of components and sub-components. The top level component basically had to have full awareness of everything going on inside the system in order to do its job and there were no separation of responsibilities because none of the components had sovereignty over the state they needed to do their job independently. It's just components micro-managing components all the way down.

      React with Redux is probably the best FP implementation I've seen thus far but even it is kind of a mess. I have nightmares about Redux Saga. The Redux Saga logo is literally a stylized drawing of entangled spaghetti.

      Had Redux + Saga been presented to people as part of React at the time it was introduced, React would probably not have become so popular. Because people would have understood that it creates too much unnecessary baggage which isn't worth it. React was used as a gateway drug to Redux which was itself a gateway drug for Saga! And what I observed in practice is that most React apps are glitchy AF; and those glitches are usually difficult to reproduce and fix, even if you know all the ins and outs of the framework!

      • hurril 1 hour ago
        Component is not a term out of the FP schoolbook. I am sorry to be making what smells like a true scottsman here, but you seem to be describing a React codebase since they call themselves functional with that Redux stuff, you think this is functional programming. A graph of "components" all talking amongst each other. Functional. Programming. Come one, man :)

        What you are describing is OOP. Passing messages between identities over calling pure functions with values.

        • jongjong 54 minutes ago
          In the newer versions of React with Redux, the components are all pure functions and state is centralized and passed down into the components. IMO it's as close as a codebase can be to pure functional programming whilst still functioning.
          • pyrale 40 minutes ago
            > IMO it's as close as a codebase can be to pure functional programming whilst still functioning.

            You know, people have put functioning codebases using pure functional programming languages like Haskell, Elm, Purescript, etc. I really don't see what in your opinion is too close to FP to work.

            • kodoman 26 minutes ago
              Not a frontend developer and my frontend skills are lacking, but the argument I think that is being made is that a react component should generally be written with no side effects and rely on signal for state change and do reactive programming. While of course something like Elm is more so this model and actually is functional from the get go. In js/ts react you are writing a lot of code that aims to be side effect free.

              Most programs code bases of course need some way of doing side effects and not being 100% pure so many haskell projects would not be classed as 100% pure.

          • hurril 22 minutes ago
            That is just not the case. I have worked, full time, as a functional programmer coming up to 15 years, in different langauges. Actual functional programming and not merely doing web programming with React.

            "[...] pure functional programming whilst still functioning."

            I mean, what is this?

            When I read what you are saying here, you are saying that an "advanced codebase", whatever that means, using functional programming leads to centralized state and distributed components. And you know this because the codebase you are thinking about has this software architecture.

            I have been in such codebases too, they tend to be frontend and maybe that is just the way you have to do it, maybe not. But this is not a property inherent to functional programming. Solving problems with a component or object concept as a central abstraction for "a thing" is the OOP way. I know this because this is how I spent the first half of my career. You think you need a _substantive_ onto which you perform verbs. Nothing wrong with this though, I am not picking a fight with OOP.

            I can offer what I refer to when I talk about FP so that we can at least have a real thing to disagree over :)

            1. model the domain and interactions with it with strong types such that neither interactions nor state can represent values outside of the domain.

            2. parse, don't validate

            3. Use modules, stateless collections of declarations, to organize stateless functions. No this. No self.

            4. No magic code. I.e.: no null checks, no magic number checks, no arbitrary logic in four places that together make up the fact that prices can have taxes. Abstract it and "store" these runtime decisions using typed values, use functions that accept these typed values to force use of the aforementioned types.

            5. Control the side effects. This does not mean that you have to use Haskell or monads or anything like that. Just that managing it is a good thing.

            6. #5 implies keeping track of state. I.e.: no, you may not just willy-nilly read it from the persistent store, cache or file.

      • jppittma 1 hour ago
        > none of the components had sovereignty over the state they needed to do their job independently. It's just components micro-managing components all the way down.

        Isn't one of the tenants of FP that nothing is mutable anywhere?

        • jongjong 53 minutes ago
          Correct, technically they pass copies of the state; which gets cloned at every component/module/function boundary. This protects you from 'spooky action at a distance' which is a real problem which can happen when mutable state is shared by different components but FP can introduce other issues related to passing around a lot of state which can become outdated as it traverses the many layers of spaghetti code.
      • mrkeen 54 minutes ago
        Don't forget to define OOP before requiring it!
      • slopinthebag 1 hour ago
        ya ive seen the same but in OOP codebases, where the state is all distributed and incapsulated and it's just impossible to reason about how the entire system works because despite it's separation of responsibilities everything is still intrinsically coupled together. and then you have all sorts of hidden mutations and other shenanigans.

        to me the best way to design large systems is sort of like an ecs. you don't separate components by state + behaviour, you separate systems and state.

        • jongjong 40 minutes ago
          I've seen some ugly OOP codebases, but I've seen some very nice ones too. I haven't seen any nice FP codebase yet besides basic APIs.

          There's a reason why 99% of video games are OOP. That level of complexity is just too much for FP.

          • slopinthebag 16 minutes ago
            video games are oop for historical reasons mostly. ue6 is built on verse which is a crazy functional language. carmack himself flirted with haskel and racket. but games are so perf oriented that for a long time the only options were c or c++ (c style ofc).

            the current trend are ecs's which are distinctly not classical oop

  • tarix29 1 hour ago
    Nothing in this article is even OOP-specific. You can do all of this with structs and static dispatch. The code in a language like Go or Zig that supports the dot-notation would look pretty similar too.
  • eru 2 hours ago
  • mrkeen 1 hour ago
    Admittedly I read this pretty quickly, but this is just structs.

    The "behaviours" being modelled here were data access. Writing .name() instead of .name.

    You can save yourself the time of manually packing these structs by writing out a constructor in full. Which the article called "automatic".

    (You don't even need to write out the constructor for a struct in C99. Probably any other modern language too)

  • Ekaros 38 minutes ago
    Sometimes or even quite often considering objects as records is reasonable approach. It has set of fields. And maybe functions helpful to manipulate these fields or even use them. Even more complicated things are just records.

    And then sometimes it is useful to extend these functionalities for specific special cases.

    Maybe OOP is often taught going too abstract. And trying to model wrong things. But thinking of it as grouping fields and then adding functions to manipulate or use those and things related to them is useful.

  • seanmcdirmid 41 minutes ago
    The article feels a bit late since we have come full circle: OOP attempted to force natural language ontologies into deterministic code, while LLMs can now process natural language ontologies directly. Prose has become the source code humans write (or at least read), and model weights are the new compiler that extract objects (or functions) and relationships directly from a written specification to generate Python. OOP hasn't disappeared; it has finally been supplanted by the natural language it always tried to mimic.
  • bronlund 1 hour ago
    Someone learning programming it seems :D
  • slovenlich 1 hour ago
    And then you start adding some real world books that have some of the attributes missing or uncertain, have several authors, go by different titles or uses some kind of exotic notation to their titling, and this OOP structure kind of crumbles?
  • groomlake 2 hours ago
    Wayback link since the site was hugged to death: https://web.archive.org/web/20260827081007/mathspp.com/blog/...
  • renke1 46 minutes ago
    OOP is fun if we could treat everything to be readily available in memory and retrievable infinitely fast.
  • js8 1 hour ago
    Well, what I don't understand is the SW engineering propensity towards cargo culting and doing things the harder way than mathematicians do.

    I see it with OOP, XML, design patterns, and other things, now with LLMs. (LLMs - you really want to build complex systems in badly specified natural language, compiled or interpreted with an inscrutable algorithm and possibly indeterministic?)

    Is it the excitement from a new analogy? Or are engineers naturally empiricists, while the rationalism/empiricism distinction doesn't work in computer science?

    I think we would be better off if we just learned functional programming and few abstract concepts (categories, monads). Simpler than OOP.

    • mickeyp 1 hour ago
      But functional programming and OOP are intrinsically the same, but expressed using different primitives.

      The thing that empowers first-class functions and closures (lexical binding) is the exact same method by which encapsulation works, even if the latter opts for heap vs stack. The fundamentals are the same.

      Here's a simple one in Emacs Lisp:

          (defmacro send (object method &rest args)
            "Sends a METHOD to an OBJECT with ARGS."
            `(funcall ,object ',method ,@args))
      
          (defun make-animal (name)
            ;; 'hunger' is entirely private (encapsulated)
            (let ((hunger 5))
              ;; here's our lambda using lexical binding
              (lambda (method &rest args)
                (cond
                 ((eq method 'get-name) name)
                 ((eq method 'feed) 
                  (setq hunger (max 0 (1- hunger)))
                  "Yum!")
                 (t (error "Animal does not understand: %s" method))))))
      
          (let ((good-boy (make-animal "Rex")))
            ;; "call" (via our macro) the "get-name" method; then feed. hunger does down 1.
            (send good-boy get-name)
            (send good-boy feed)
            ;; pretty-print the "object" good-boy
            (pp good-boy))
      
          ;; this is the state of it after the two calls.
          #[(method &rest args)
            ((cond ((eq method 'get-name) name)
                   ((eq method 'feed) (setq hunger (max 0 (1- hunger))) "Yum!")
                   (t (error "Animal does not understand: %s" method))))
            ((hunger . 4) (name . "Rex"))]
      • js8 32 minutes ago
        Yes, you can express everything using lambda calculus. Kinda.. so why not use a thing that already exists? Why invent a new language (encapsulation) when previous (binding) suffices?
    • ivan_gammel 1 hour ago
      OOP is not about doing things harder, it‘s about doing them efficiently. The key elements of software engineering are abstraction and encapsulation: we, humans, cannot load the entire domain into our memory and reason about it at all levels of detail at once. We need to zoom in and zoom out, decompose problems into smaller pieces, then reassemble, treating those pieces at surface value. OOP isn‘t rocket science, it just adds one more piece — the hierarchy of concepts with inheritance and polymorphism. And it‘s just a technique: most programs are written in a mix of styles anyway. The foundational style is procedural, because that‘s how computers work. FP and OOP just build on top of it and translate to it.
  • kstrauser 36 minutes ago
    > “That's because I thought it made sense to represent a book as a sequence of Unicode code points stored along with the cumulative lengths of the individual fields. But you don't have to worry about it, since the auxiliary functions book_xxx are the ones that represent the interface that users should interact with.”

    I’m not saying you should ever fire a coworker out of a cannon. I’m just saying that I wouldn’t always hold it against you.

  • yxhuvud 1 hour ago
    > If you think you already know OOP, this article will change the way you think about programming

    No, it won't. I'm especially sad that this, like so many OOP guides before it, did not go into how it interacts with data structures and bigger picture stuff. It had the perfect chance to do that as it could have made a Catalog class and then had a discussion about what belongs to that and what to the books. Instead it started to abstract on author, in the stupidest way possible (no, no one will ever look up a book using the author birth date).

    • fjcururuvy7 1 hour ago
      The older I get the more I realize the stuff I learned in university was just plain wrong.

      It's incredibly difficult now dealing with zoomers in the workplace that think I'm some old boomer that never learned "proper computer science".

      No, sorry Timmy, it's not because I don't understand microservices, it's because I actually do.

      • kodoman 5 minutes ago
        Craft and expertise are worth a lot, but so are the facts of computer science and so are people wanting to debate and try new things some mistakes repeat (and computing seems to repeat it's self so many times.), But those zoomers might have the theory fresher in their minds and they might have studied something you have not or did not know.

        If what you learned in university was plain wrong that does not sound good because computer science has eternal truths to it, If an architect said everything he learned in university was wrong I would be very worried and not trust his judgement because he should have learned facts not just theories of practice. If he only learned theories of practice I would be worried, if he learned both theories of practice and science and starts to disagree with the science I would be worried.

      • mrkeen 48 minutes ago
        Well did you learn proper computer science or did you learn plain wrong computer science?
        • left-struck 25 minutes ago
          Well maybe they learnt proper computer science after university.
  • projectileboy 1 hour ago
    A good book for appreciating the OO mindset is Object Thinking by David West.
  • Zak 1 hour ago
    This seems like a beginner-level OOP-in-Python tutorial, and I'm disappointed the author didn't demonstrate a functional abstraction for `find_by`.
  • phplovesong 1 hour ago
    There is good OOP, there is bad OOP, and then there is PHP(OOP).
  • victorbjorklund 2 hours ago
    Site died.
  • wolvesechoes 1 hour ago
    OOP, like most stuff discussed in dev-related web, exists so that permaonline people can have another reason to create their own tribes and fight each other.
  • echelon 1 hour ago
    OOP is perfectly fine.

    Rigid class-based inheritance (especially multi-inheritance) is what sucks. This over-engineered complexity really only benefits things like window toolkits where you want super rigid modeling of widget types. But even that's a stretch.

    Traits do OOP the right way. Complete flexibility.

        Dog goes "woof"
        Cat goes "meow"
        Bird goes "tweet"
        And mouse goes "squeak"
    
    Does not need classes.
    • garretraziel 1 hour ago
      Not sure if intentional, but I read it in Ylvis’ “What does the fox say?” and now I can’t get it out of my head, thank you very much.
    • dnautics 1 hour ago
      Nah even traits are kinda bad because it increases the indirection necessary for code reading
  • OtomotO 2 hours ago
    OOP exists to add a quadrillion of layers to otherwise perfectly understandable business code in an attempt to obfuscate meaning and intent and guard against malicious extraction of valuable trade secrets.

    Oh, it also helps me to pay my bills, because someone has to untangle the mess.

    And it helps my therapist, because he has to keep the madness that grows inside of me in check.

    Jokes aside: I was taught OOP at university.

    I was also taught functional programming, answer set programming and other forms such as logical programming.

    Focus was definitely on OOP though.

    I mainly see OOP as a way to (dis) organizer code and a way for hardware manufacturers to sell more hardware.

    • TonyStr 1 hour ago
      OOP is sold on the promise that everything is modular. Since everything is neatly encapsulated with clearly defined API surfaces, you can easily swap out any part for any other. This should make developers interchangeable, because anyone can go in to the code and swap out parts as needed.

      In reality this seems to make coupling even worse. Now you have to dig 8 classes deep just to find the business logic for a particular feature. Changing it is even harder because the rest of the program expects this part to behave in a very specific way.

      • OtomotO 4 minutes ago
        The same is true about FP, just that it doesn't promise this.

        I agree with the reality.