DEV Community

Cover image for Masturbatory Code in OOP
Adam Nathaniel Davis
Adam Nathaniel Davis

Posted on • Edited on

Masturbatory Code in OOP

From Merriam-Webster:

Masturbatory: : excessively self-absorbed or self-indulgent

I've done a lot of OOP work in Java and C#. Some of it I enjoyed. Some of it... not so much. I'm not so much interested in the Coding Holy Wars of OOP-vs-functional-vs-whatever. But now that I seem to have escaped the OOP world (for awhile, at least), I can't help but rant about a particular practice that still prevails in OOP that drives me nuts: Absolutely pointless getters and setters.

This is an example that you will find lurking in almost any of the dark corners of an OOP codebase:

public class Person {
    private int age;

    public int getAge() {
        return this.age;
    }

    public void setAge(int newAge) {
        this.age = newAge;
    }
}
Enter fullscreen mode Exit fullscreen mode

If you have any computer science background - even if you're "only" a JavaScript or PHP or Python developer - you probably know what's going on here. We have a basic class Person which has a private variable age. age is private because the coder presumably wants to adhere to the OOP principle of encapsulation.

In other words, we don't want other parts of the application to instantiate Person and then update the age property outside the control of the Person object. If age is going to be updated, then we want it to happen precisely the way that it's prescribed in the Person class.

This is all fine-and-good. I'm not bothered by the concept of public/private variables. It can be extremely powerful and, generally speaking, it's a very good thing. The problem arises when the OOP Acolytes mindlessly adhere to this concept of encapsulation, even when it makes no got-dang sense.

Obviously, the code above is just a simplistic demo. But I've seen code just like this time and time again in real-life applications. The process is very simple:

  1. Dev creates a new class that he presumes will need a dozen different class properties.

  2. Dev knows, from all of the OOP dogma that's been beaten into his skull, that creating public class members violates encapsulation. (Egads!!!)

  3. Dev sets each of the dozen class properties to private.

  4. Dev proceeds to set a dozen getters for each of the dozen class properties, that do nothing but blindly return the value to the caller.

  5. Dev then proceeds to set a dozen setters for each of the dozen class properties, that do nothing but blindly set the value of the property to whatever value was passed in.

  6. Dev then pushes away from the keyboard and ogles his gorgeous, OOP-compliant code that satisfies all the dogmatic dictates that he learned in college.

But all of this boilerplate is syntactic garbage. It serves absolutely no purpose (other than to make someone feel smug-and-secure about their faithful adherence to OOP principles).

What the OOP Acolytes don't want to acknowledge (or admit), is that in the code sample above, age is... wait for it... a public variable.

Oh, sure... it doesn't say it's a public variable. It has that warm, comforting private keyword in front of it. But it's extremely public. It's functionally equivalent to this:

public class Person {
    public int age;
}
Enter fullscreen mode Exit fullscreen mode

If you set a variable to private, and then you give it a getter that does nothing to alter the value before it's retrieved, and then you give it a setter that does nothing to alter the value before it's set, then there's nothing really "private" about it. You've handed complete control of that variable over to the caller. In other words, you've just created a very-public variable - with a lot more boilerplate code attached to it. Umm... yay???

Masturbatory Code

I call this "masturbatory code" because it's code that effectively serves no purpose. Well... that's not entirely true. The "purpose" it serves is solely to make the coder feel good. Every time they write a superfluous set of getters/setters, it's like they're envisioning their comp sci instructor, or their hardcore OOP friends, smiling over their shoulder and nodding. They're silently checking that box that says, "See!! I'm a real OOP coder. And I knows shit!"

I realize that the userbase on this site seems to be largely rooted in frontend dev. Most of them spend their days writing in JavaScript, TypeScript, PHP, Python, or some other procedural language. So maybe this post seems a bit indulgent on my part.

But "masturbatory code" isn't limited to the grimy underside of OOP. There are masturbatory practices to be found in every language, in every coding paradigm, and in every development community. Furthermore, if we're being honest with ourselves, we've all engaged in these masturbatory practices at one time or another.

I'm not even trying to say that these silly little practices are always empirically "wrong". Maybe you have a firm reason (in your mind) why these practices are good-and-necessary. But there's value in understanding them for what they are. Because if you don't appreciate the true masturbatory nature of these practices, you're more likely to become "that guy".

You know "that guy". The one who's not content to simply indulge in his own masturbatory techniques - but feels compelled to shout you down or code-shame you because you haven't embraced the same techniques. The one who's more interested in ensuring that you are coding according to his religious convictions.

Don't be "that guy".

Cross-Platform Masturbatory Code

I can think of several examples of "masturbatory code" that I've seen in JavaScript or PHP. But I'd rather hear from you. What have you seen in your codebase/language/environment that qualifies as "masturbatory"???

Top comments (8)

Collapse
 
peerreynders profile image
peerreynders

"Those Who Do Not Learn History Are Doomed To Repeat It"

Alan Holub: Why getter and setter methods are evil (javaworld.com, 2003)

Tell, Don't Ask (2013) - pdf (2003)

Constructor Initialization (2006) vs Setter Initialization.

There is also the notion of an opaque data type. Even if the internal structure is publicly accessible the convention is to only interact with a type instance via publicly available functions.

That way the type's "clients" stay decoupled from the internal structure of the type (anything may be restructured, added, or removed in the future) and whether or not the result is computed or stored (cached).

// file: person.mjs
export function makePerson(age) {
  return {
    first: age
  };
}

export function age({first}) {
  return first;
}
Enter fullscreen mode Exit fullscreen mode
import {makePerson, age} from './person.mjs';

const p = makePerson(25);
console.log('Age:', age(p));
Enter fullscreen mode Exit fullscreen mode
Collapse
 
bytebodger profile image
Adam Nathaniel Davis • Edited

I certainly appreciate the feedback. But I'm not sure exactly what you're inferring in your response. so my reply might, admittedly, miss the mark. But here goes:

Even if the internal structure is publicly accessible the convention is to only interact with a type instance via publicly available functions.

I think my entire objective on this is to rail against "convention". Convention has its place. And I'm not claiming we shouldn't care at all about convention. But the whole point of this article is to point out the silliness of convention-for-the-sake-of-convention.

I'm not against the idea of having getters and setters. And I understand the theory of why getters/setters are encouraged. But if you're creating getters/setters just to tick off some checklist in your computer science class, you're missing the whole point.

I fully understand that, sometimes, you create a whole batch of getters/setters because you're essentially wireframing new code. And you know that, at some point in the near future, there will be additional logic inside those getters/setters. So you create them as a kind of scaffolding and, fairly soon, you end up adding the logic to them.

But if you're "scaffolding", for some kind of assumed future expansion of the code, but you don't know that you'll be building out that portion of the code, then you're just creating unnecessary complexity for the purpose of satisfying some theoretical programming professor.

One way to identify a "code smell" is to find those places where the coder has written a whole bunch of boilerplate code to account for some unforeseen eventuality that may not ever occur. When someone insists on never creating a public variable and always couching every class member in getters/setters (even if those getters/setters don't do anything), then they are committing this same sin.

I think you've read several of my articles, so you might've started to understand this theme from me now: I don't much care whether you love getters/setters - or whether you hate them. What I care about is dogma. I care about the OOP acolytes who get all up in their ivory tower to preach the gospel of getters/setters - even when those getters/setters are a complete waste of time.

Collapse
 
peerreynders profile image
peerreynders

And I understand the theory of why getters/setters are encouraged.

From my perspective that practice has been a code smell for at least the past 17 years - unless you're dealing with a DTO.

What is encouraged is to hide access to instance variables behind methods so that implementation details like validation, computation and storage can be hidden away and remain subject to change without impacting the object's public API.

Mindless getters and setters on the other hand hint at lack of design, revealing too much about the object's internal structure which causes its collaborators to be too tightly coupled to it.

Don't ask for the information you need to do the work; ask the object that has the information to do the work for you.

Thread Thread
 
bytebodger profile image
Adam Nathaniel Davis

That was exactly the point of this whole article.

Collapse
 
efpage profile image
Eckehard

Hy Adam,

It´s true, you can write Masturbatory Code in any language, but why should you do that? A=A ist also useless. I assume, it´s not THAT funny.

Getters and setters are just a language feature you can use or not. In OOP it´s generally not the best style to expose a class variable to the public, so a getter and setter can give you more control. You could add a value check or initiate any action before or after the value was changed. So, your class can handle a state change while the user of the class justs sets a variable.

I assume you will find useless code very often. Maybe someone just added a setter and getter out of routine and did not think about. Or he wanted to add more code later, or... . So, this is not a bug, but useless code. But does this mean, setters and getters are useless? I suppose, that´s not what you ment.

Collapse
 
phpfui profile image
Bruce Wells

The proper OO way to do age is the store birth date. Then have an age() function that does the math. You can't set an age, it can only be reported as it is not something you control.

Here is my take on this topic:

blog.phpfui.com/getters-and-setter...

Collapse
 
isaachagoel profile image
Isaac Hagoel

P.S
You are waiting for someone to say Redux, aren't you?

Collapse
 
bytebodger profile image
Adam Nathaniel Davis

Bwahahahaha! Love his rant.

And, P.S.
As you've noticed from my previous posts, I'm no fan of Redux. But I wouldn't actually call it "masturbatory". It does something. It just does it in a big, convoluted way that could be done so much better with other tools.