Live data from Hacker News

A Healthy Hatred of OOP, or the principles of my message-driven framework

bythehilt.com

61–70 of 98 posts

Re: A Healthy Hatred of OOP, or the principles of my message-driven framework

#62
post #4

Your essay is arguing against a strawman of what "good" OOP is supposed to be. Your examples... >Objects just aren't supposed to be reaching into each other with 'getters' and 'setters' and messing with information. The getX() and setX() is an anti-pattern of good OOP. >Instead of using objects for compartmentalizing functionality, they were just used as a holding pen for loosely related functions. No, good OOP has c…

> The getX() and setX() is an anti-pattern of good OOP. No it isn't, it provides encapsulation, which the most important aspect of OOP. I agree with the rest.

It can very easily break the encapsulation though. Now external processes are dependent on direct access to the internal state of your object, and if the object is refactored in the future you need to reprogram those getters and setters to return something that is still correct but may not represent the internal state of the object at all and may in fact be complex now.

An example of where this can all go wrong is if you have a TCP object that opens a connection to a remote server and then lets you read and write the socket. Someone decides that they need to find out what IP address the object used when it connected and create a get_ipaddr() method that returns a s_addr type. But then the TCP object is updated to support IPv6 and now the author needs to figure out how to return a V6 IP address to external methods that only expect V4.

The proper way to implement it might have been to move whatever logic was examining the IP address into the TCP object itself. Of course this is how you end up with horrendously complex objects with hundreds of methods all used exactly once somewhere in the code or exactly once in the code of some other project.

Re: A Healthy Hatred of OOP, or the principles of my message-driven framework

#63
post #26

Earlier quoted context omitted.

> The getX() and setX() is an anti-pattern of good OOP. This needs to be tattooed in reverse on many developers foreheads so it's the first thing they read when brushing their teeth in the morning.

Problem is developers take that as an excuse to make state public, which is even worse.

It doesn't matter whether you make the state public via a getter or via variables (modulo some compiler specific reasons to use accessors).

If your design is allowing some external actor to work with multiple parts of the state of a behavior driven object (ie not a record) accessors are not going to help you, you've still exposed the state.

Re: A Healthy Hatred of OOP, or the principles of my message-driven framework

#64
post #4

Your essay is arguing against a strawman of what "good" OOP is supposed to be. Your examples... >Objects just aren't supposed to be reaching into each other with 'getters' and 'setters' and messing with information. The getX() and setX() is an anti-pattern of good OOP. >Instead of using objects for compartmentalizing functionality, they were just used as a holding pen for loosely related functions. No, good OOP has c…

In a sense the OP is making a point about which paths are paved in most OOP languages. That said, one of the problems I often see in user interfaces is "runaway metaphors". The "objects" and "messages" in question are _metaphors_ and it's important not to let a concept be taken hostage by the metaphors used to describe it. The main reason controllers exist isn't (or shouldn't be) because of a failure of OOP as a conc…

how fast can that player run? Is asking about internal state. When can you get to X is not.

The internal vs. external separation can often greatly simplify things. A player does not care where another players feet are they care where the best place to toss the ball is.

PS: In an actual game there is a lot of communication going on. You don't want to throw a ball at someone looking in the wrong direction. So, at some level you're stuck dealing with innate complexity.

Re: A Healthy Hatred of OOP, or the principles of my message-driven framework

#65
The same thing happened with REST, TDD and Microservices, etc. The term gets hijacked by people that are less than skilled at executing it. And unfortunately there are more unskilled than skilled people in software; so usually the hijacked term wins the contest. It then takes decades of the "original guy" sending out a BBS message / IRC message / vBulletin post / Blog post / Tweet / HN comment / etc to try to correct people's understanding by saying "actually, that's not canon!".

Re: A Healthy Hatred of OOP, or the principles of my message-driven framework

#66
post #51

>> When I started learning C++ I was shocked. Instead of using objects for compartmentalizing functionality, they were just used as a holding pen for loosely related functions. Instead of communicating between themselves, objects were operated on by some bigger parent object. I found it absurd and fought it for a long time. This has nothing whatsoever to do with C++. It's like blaming a microwave oven because your ki…

The Linux kernel is written in C, not C++. C has static typing, but it is definitely not strong static typing.

Re: A Healthy Hatred of OOP, or the principles of my message-driven framework

#67
post #4

Your essay is arguing against a strawman of what "good" OOP is supposed to be. Your examples... >Objects just aren't supposed to be reaching into each other with 'getters' and 'setters' and messing with information. The getX() and setX() is an anti-pattern of good OOP. >Instead of using objects for compartmentalizing functionality, they were just used as a holding pen for loosely related functions. No, good OOP has c…

> The getX() and setX() is an anti-pattern of good OOP. No it isn't, it provides encapsulation, which the most important aspect of OOP. I agree with the rest.

>No it isn't, it provides encapsulation,

The extensive use of getters()/setters() is a common misunderstanding of "encapsulation". It's an example of following the "letter of the law but not the spirit of the law".

Let's separate the idea of "encapsulation" into 2 categories:

(1) syntax encapsulation: private int x; public getX(); public SetX(); // letter of the law

(2) conceptual/semantic encapsulation: Object.DoSomething() that works on x internally // spirit of the law

It's the idea presented in (2) that follows the ideals of OOP design and helps reduce cognitive load. The common coding practice of (1) doesn't really provide "encapsulation" that helps make large scale programs more understandable. I also think (1) was exacerbated by codegen tools such as ORMs and GUI data binding frameworks. Therefore, inexperienced programmers thought that having a ton of gets()/sets() in their own manually handcrafted classes was "correct OOP".

Re: A Healthy Hatred of OOP, or the principles of my message-driven framework

#68
Comment on the code:

As a Lua aficionado I hate to see stuff like this:

  Ball = {}
  Ball.__index = Ball

  function Ball.new (x, y)
    local table = {}
    setmetatable(table, Ball)
    table.x = x
    table.y = y
    return table
  end
Explicit setmetatable() call and manual __index setting? You can automate this and hide all the metatable magic = less code to write, less potential for bugs.

E.g. in my own Lua object system the above would be:

  Ball = Class()

  function Ball:Properties(x, y)
    return { x = x, y = y }
  end

Re: A Healthy Hatred of OOP, or the principles of my message-driven framework

#69
post #64

Earlier quoted context omitted.

In a sense the OP is making a point about which paths are paved in most OOP languages. That said, one of the problems I often see in user interfaces is "runaway metaphors". The "objects" and "messages" in question are _metaphors_ and it's important not to let a concept be taken hostage by the metaphors used to describe it. The main reason controllers exist isn't (or shouldn't be) because of a failure of OOP as a conc…

how fast can that player run? Is asking about internal state. When can you get to X is not. The internal vs. external separation can often greatly simplify things. A player does not care where another players feet are they care where the best place to toss the ball is. PS: In an actual game there is a lot of communication going on. You don't want to throw a ball at someone looking in the wrong direction. So, at some…

Of course there's innate complexity, but pursuing encapsulation for its own sake adds complexity you don't need (just like using functional programming techniques for intrinsically non-functional use-cases adds complexity for no good reason).

Again, "messages", "objects", etc. -- these are metaphors. They should be abandoned as soon as they stop being helpful.

Re: A Healthy Hatred of OOP, or the principles of my message-driven framework

#70
post #41

Earlier quoted context omitted.

Good points except saying that getters and setters are an anti-pattern of OOP. Actually, you contradict this a few lines blow: > No, good OOP has class/object with both private state If a class has state, you have to be able to read that state or it's useless. It's a good practice overall to tell classes what to do but eventually, you need to get information from them. That's where getters come into play.

>If a class has state, you have to be able to read that state or it's useless. ... That's where getters come into play. No, having a bunch of getABC(), getXYZ(), getEtc() is a code smell . If the class has many getters()+setters() or has the equivalent of many public data members, it means that related actions requiring those variables are happening outside of the class/object instead of inside the class. The more ge…

You don't seem to realize it but your countLines() method is a getter.

At the end of the day, you need to get values from your class, otherwise, they are useless (and they do side effects).

Post reply on HN