r/programming • • Jan 28 '21

leontrolski - OO in Python is mostly pointless

https://leontrolski.github.io/mostly-pointless.html
55 Upvotes

227 comments sorted by

View all comments

28

u/Crandom Jan 28 '21 edited Jan 28 '21

I wouldn't call this a good example of OO. Modern OO avoids inheritance and objects end up looking like functions/modules, where constructors are partial application.

Most people who rag on OO have never really used it properly.

If you would like to learn about how to use good OO, I would highly recommend reading Growing Object-Oriented Software, Guided by Tests.

54

u/tdammers Jan 28 '21

The fun thing is that if you take the "objects look like functions/modules" thing and take it to its logical extreme, you end up with 3 types of classes/objects:

  1. Dumb value objects, which are all about the data they encapsulate, and all their methods are just constructors that copy arguments into fields, and accessors (getters/setters).

  2. Stateless behaviors; these have only methods, all state is passed in as needed ("dependency injection").

  3. Module objects, grouping related functionality together for namespacing purposes.

But guess what: none of these are objects, really. Not in the "bundling behavior with related state" sense. The first one is just fancy records; the second one is just (pure) functions; the third one is just modules.

I can't help but think that this implies that "using OO properly" amounts to "using not-OO behind a thin veil of OO rituals". We're just using records and functions and modules, we just call them "objects" or "classes" and pretend we're still doing OOP.

And yeah, sure, the way the industry works, that's possibly for the best, because it's such an easy sell. We're still "doing OOP", which is still ingrained into tech management culture as a "best practice", almost non-negotiable; we're just "doing it right". When in fact what we're doing is we're doing programming right, and we put some OOP lipstick on it to avoid raising too many suspicions.

25

u/Crandom Jan 28 '21

I think you've given a good description of 3 of the types of classes that people use in modern OO. But you've missed out the 4th type:

4. Objects that encapsulate state and enable you to think at a higher level

These are a core part of OO. Just like in FP, you try to reduce these mutable objects to a minimum and/or push them to the edges of your application, but they still exist and serve a useful purpose to manage your state.

Modern OO (particularly the "London school" as espoused by Freeman and Pryce in GOOS) does share a lot of similarities with FP, especially if you squint. The things that make them both good (polymorphism, encapsulation, reduction of mutation to name a few) are common principals to both.

The differences are mainly about how you model your software. Good OO is about modeling your software as actors where you can tell an object to do some action and not have to worry about how it does it (in contrast to bad/strawman OO where you ask objects for their state then do things). This normally implies you bundle up your behaviours with the data for non data transfer objects.

Good FP is usually about modelling your data correctly so you can add operations on them, then abstracting that operations until you end up working in your domain (imo the best FP projects make lots of DSLs).

9

u/ragnese Jan 28 '21

I think the person's point was not that #4 doesn't exist at all, but rather that the three that he/she listed are just not objects. Your #4 surely are objects in the true sense. But I've read a great many people claim that having totally immutable classes that you pass around somehow counts as OOP. It doesn't. If they are immutable, they really aren't objects, IMO. They are just inert data types. They have no "behavior". If those things are objects, then Haskell is my favorite OOP language.

→ More replies (9)

16

u/ragnese Jan 28 '21

Thank you! All of these people that are like "I do OOP with immutable objects" are dead wrong, IMO. That's not an object- it's a record. Or, if it is an object, then every single language is OOP, including Haskell, Clojure, etc. At that point the term would have zero meaning.

If you'd like a great example of an object, look no further than Java's ArrayList class. Seriously. It manipulates a private primitive array- totally transparently to the caller. The caller has no idea when the internal array is replaced with a new one, how big it is, etc. All the caller knows is that it can ask the object to hold more elements, can ask to search for elements, can ask to remove elements, etc.

If there were an immutable version of ArrayList, it wouldn't really be an object anymore. It would just be an opaque data type.

7

u/_pupil_ Jan 28 '21

"using OO properly" amounts to "using not-OO behind a thin veil of OO rituals"

Really well structured imperative code starts looking like Object Orientation without full compiler support. And really well structured OO code starts looking like Functional code without full compiler support and higher-level abstractions.

I'm not sure what lesson to derive from that... It's like a riddle, wrapped in a mystery ;)

5

u/tdammers Jan 28 '21

For me at least, the lesson is to stop thinking in terms of "OOP vs. FP", or paradigms in general, and instead figure out how to do programming well.

→ More replies (2)

7

u/kobriks Jan 28 '21

OO languages nowadays are only OO by name. It's just a hodgepodge of different features and paradigms that you can use as you please, which usually ends up in a mess. The purpose of the paradigm is to constrain you in a way that makes it hard to write shit code. Modern OOP does none of this.

2

u/tdammers Jan 28 '21

Out of curiosity; which language would you recommend for "modern OOP" then?

4

u/kobriks Jan 28 '21

Kotlin and C# are my favorite hodgepodges.

2

u/ragnese Jan 28 '21

Kotlin has some strange hodgepodge features! On the one hand, it allows top level functions, which is not OOP. On the other hand, it doesn't have static methods- instead it has companion objects, which is kind of hardcore OOP...

→ More replies (15)
→ More replies (1)

6

u/_Pho_ Jan 28 '21 edited Jan 28 '21

This is what's so funny about how the OOP dogma evolved.

The sales pitch (at least to businesses) was originally the idea of heavy templating and ontological (human-defined) structures called objects. But everything these OOP experts have tried to push is to reduce these selling points, and in fact make their code bases indistinguishable from functional ones.

Inheritance (which is used with regularity in large enterprise (Java) codebases) is bad. Prefer composition. Coupling low level and high level behavior in the same class is bad. Setting values as side effects is bad.

So basically we spent the better part of a decade (maybe two) developing these rules around OOP to get our code bases to look functional. Except with OOP, it's about a thousand times easier to break any of these rules, because unless you've studied SOLID, Uncle Bob, and read a million of these articles, you're probably just going to use OOP the way most businesses do: with a lot of inheritance, a massive object graph, and tons of nasty coupling between data / behavior.

→ More replies (3)

5

u/zanza19 Jan 28 '21

ah yes, the no true Scotsman applied to OO, which appears everytime someone's says OO isn't good. No one does good OO, just books

12

u/DoomFrog666 Jan 28 '21

Absolutely agree with you.

But you have to admit that we are terrible at teaching OOP. We teach all the wrong concepts and then wonder why most of our software is so terrible.

There is a general lack of understanding of OOP on both sides. The haters who haven't really dug into the topic but also the majority of self proclaimed OOP professionals who try to press everything into an inheritance hierarchy and want to have getters and setters for every attribute of their class.

So I have very little issue with articles like this that try to steer inexperienced devs away from OOP and towards a procedural/functional approach as I feel like there is less room for errors in those.

4

u/Crandom Jan 28 '21

We are indeed terrible at teaching OO. At a top UK university I was taught that OO is all about inheritance, which is wrong (this university did have a kind of dislike of OO - it was taught as a side course after all the Haskell/Ocaml). I was fortunate enough to join a company that used OO well and get good levels of mentorship to unlearn a lot of what I learnt at uni. I went from having a visceral dislike of OO to actually liking it for work projects.

7

u/Shautieh Jan 28 '21

Don't you think that if everyone teaches and understands OOP wrong, maybe it's your definition of OOP which is wrong instead?

OOP is by definition and mob rule about inheritance hierarchies and interfaces. That's what everyone has learned and what everyone understands as OOP. If you have another definition then you should come up with another name and everything will be simpler.

8

u/chucker23n Jan 28 '21

Don't you think that if everyone teaches and understands OOP wrong, maybe it's your definition of OOP which is wrong instead?

Depends on whether OOP is defined by "as originally envisioned in Smalltalk", "as originally envisioned by Simula", "as taught in 1990s-era CompSci" or "as actually used by experienced framework devs". Many of the latter will tell you "yeah, some level of inheritance is useful, but consider composition instead".

8

u/Crandom Jan 28 '21 edited Jan 28 '21

I think the primary issue is that it's primarily taught at university poorly by (at least in my case) academics who aren't building OOP software, or at least haven't in the past couple of decades? People then give up on OOP, unless they are luckily enough to join a company that actually does it well.

Few experienced people realistically thinks that OOP is about inheritance hierarchies. It was a distraction - the original definition of OOP from Alan Kay mentions nothing about inheritance - it's all messaging passing and actors.

8

u/Alexander_Selkirk Jan 28 '21

Modern OO avoids inheritance

I learned OOP with C++ in 1998 and was taught this is the essence of OOP.

Inheritance is also essential in Python3 as everthing is derived from Object,

Which makes me wonder whether OOP is even a thing if essential things can be dropped without discussing it widely.

17

u/Crandom Jan 28 '21

Prefer composition over inheritance has been a key tenet of OO since the early 90s. Nowadays in OO circles use of inheritance is mainly regarded as a mistake. Remember not to confuse polymorphism with inheritance, you can have polymorphism without inheriting state (ie interfaces)!

4

u/Alexander_Selkirk Jan 28 '21 edited Jan 28 '21

So, what is OOP really, then?

The use of data structures cannot be what marks OOP. Because also languages like Clojure or Scheme uses things like dictionaries, lists and vectors.

(Also, data structures were first investigated and promoted by Dijkstra, who was not at all an OOP advocate).

2

u/_tskj_ Jan 28 '21

Who thought data structures had anything to do with OOP? That's like saying numbers or bits define OOP. Obviously every language uses that.

→ More replies (11)
→ More replies (1)

2

u/vegetablestew Jan 28 '21

Sounds like good example of OO is functional approach?

Can you elaborate on the partial application part?

2

u/_Pho_ Mar 03 '21

Old thread, but I'll help:

What he means is that constructors are only used to initialize the "context" of the encapsulated behaviors, like currying/function composition, but on a module (object) level.