Categories
Mozilla Programming Rants

Object-Oriented Masturbation

Doing some research for an upcoming installment of an infamous series of blog posts (to be released at an undetermined date) I’ve come to notice this annoyance. In general I like object-oriented programming. I think it allows you to take a complicated problem and produce simple, more reusable and easier to maintain code. Assuming the programmer is sane individual, and that sometimes is a leap of faith.

I’m not sure if there are programmers who feel the need to complicate things just for the sake of showing off (oh, look at me!), or if they legitimately don’t know any other way. I suspect a little of both. Perhaps the programmer thought it was possible the code would grow in complexity in the future, and just wanted to prepare in advance. I don’t know. But it annoys me.

I consider this abuse of Object-oriented programming to be Object-oriented masturbation since the only one who gets any enjoyment out of it is the developer who does it. Here’s a slightly exaggerated (though not far off) example of Object-oriented masturbation typical of what I’ve seen many times before:

Objective

Sum two numbers and print the result in the format “The answer is: X” where X is the sum of the two numbers.

Correct (sane) Answer

// This is the simple, obvious answer
function sum(x,y){
    document.write(‘The answer is: ‘ + (x+y));
}
 
// To run:
sum(1,1);

Arguably, you could do the math and store in a variable if you are squeamish to doing math in any line containing an output method. Regardless, this is dead obvious and simple. And yes, this technically still does use OOP since it uses document.write().

Insane (masturbatory) Answer

function MathLib(){
    this.answer = null;
}
 
MathLib.prototype.sum = function (x,y){
    this.answer = x + y;
}
 
MathLib.prototype.getAnswer = function(){
    return this.answer;
}
 
function Printer(){
    this.preText = ;
}
 
Printer.prototype.setPreText = function(str){
    this.preText = str;
}
 
Printer.prototype.out = function (str){
    document.write(this.preText + str);
}
 
// To run
var math = new MathLib();
var print = new Printer();
math.sum(1,1);
print.setPreText(‘The answer is: ‘);
print.out(math.answer);

I did the exact same thing in 1 logical line of code (3 if you include the function itself) up above. What was gained from the object-oriented design? I argue nothing. Rewriting the first example would take a minute should something need changing. If there were a need to localize that string, I could pull it out and either make that a 3rd parameter, or some global string the function can use. There’s no benefit here. This is over engineering. There’s nothing truly reusable here. The closest is the Printer.out() method, and in reality it’s a wrapper for document.write().

The bonus joke is that the object-oriented implementation is significantly slower.

Run 1: 0.0266, 0.0451
Run 2: 0.0314, 0.0464
Run 3: 0.0329, 0.0462
Run 4: 0.0268, 0.0468
Run 5: 0.0274, 0.0475
Avg: 0.02902, 0.0464

The first example is also 62.5% faster in Firefox 3.0.4 since the all that overhead is gone. If you have FireBug installed you can check that out here.

object-oriented masturbation
ob-jikt | o·ri·ent-ed | mas⋅tur⋅ba⋅tion

  1. the stimulation or manipulation of one’s own ego by way of using object-oriented code in places where it has no advantage instead resulting in unnecessary complication and bloat.

If your guilty of doing this, please cut it out. It’s annoying. Thank you.

No I will not single out links to the pages that inspired this, but rest assured it litters the web.

16 replies on “Object-Oriented Masturbation”

@Arpad Borsos: math.answer is a perfectly valid property and can be used. math.getAnswer() is simply a method to fetch the property and remains unused in the code. The method in it’s current state is somewhat pointless, but could be useful in the future should getting the answer require more than just reading that property. Regardless, it didn’t fail. It works.

It’s a mating display, like a peacock’s tail. Instead of lovely feathers we are supposed to boggle over the number of levels of abstraction the author is presumably able to hold in his brain at the same time. (See also: “I’ve suffered for my art; now it’s your turn.”)

Abi: are you kidding? There’s code like this EVERYWHERE. See the Netflix oAuth library, for starters:

http://oauth.googlecode.com/sv.....t/oauth.js

I kinda agree but it’s not really as clear cut as your convoluted example and quite often the reverse can be true. What happens when your example needs to output in a different format, support multiple languages etc? Almost every mature programmer has ended up maintaining large codebase and wishing there’d been some basic underlying design or OO encapsulation.

It’s a matter of style and we’re often making educated guesses as to what is appropriate for some future milestone.

I bought the book, “Refactoring,” by Fowler, sight unseen, as it was highly recommended. As I read through it, it seemed as if the goal was to convert straight-forward code into code exact as described in this complain. Yes, refactoring is good, but it can be carried too far, and it seemed like Fowler carries it too far.

OOW Has hit the nail on the head. Add the requirement “Support multiple languages” or “Allow several different operations to be performed” to your problem and suddenly an OOP solution starts to make more sense.

This is why maybe you should wait to feel the burn from not using OO, before you start using it. Same goes for development methods, huge frameworks whatever. Feel compelled first.

@Ryan: Not really. You could add support for multiple languages by simply abstracting the localized text into a variable. It’s easy.

Writing a one liner as OO is wasteful no matter how you look at it. If you need to handle several operations it doesn’t take any longer to rewrite into OO than to add the functionality to the OO form of it. Prematurely turning every line of code into an object is the wrong way to program.

#include
#include
#include
 
using namespace std;
 
int fap(long CockInHand, int Hornyness);
 
int main()
{
    int Kleenex = 1, IsHorny = 9000;
    bool gotPorn = true, IsAlone = true;
    long Unit = 0;
 
    if((IsAlone || gotPorn) == true)
    {
        IsHorny  ;
 
        if(IsHorny > 9000)
        {
            Kleenex = fap(Unit, IsHorny);
        }
    }
 
    if(Unit < IsHorny)
    {
        cout << "FAP HARDER BOY!!\n\n";
        Kleenex = fap(Unit, IsHorny * 2);
    }
 
    cout << "oh — Oh — OH — OOOOOOOOOOOOOOHHHHHHHHH!!!!\n";
    return 0;
}
 
int fap(long CockInHand, int Hornyness)
{
    bool splooge = false;
    int rub = 0, FingerInAss = 0;
    long double result = 0, eJack = (sizeof(CockInHand) * Hornyness);
    int climax = ((sizeof(Hornyness) * eJack) / (Hornyness / (sizeof(CockInHand))));
 
    if(splooge == false)
    {
        for(rub = 0; rub <= climax; rub  )
        {
            FingerInAss = 1;
 
            while(FingerInAss == 1)
            {
                cout << "fap! ";
                FingerInAss = 0;
            }
        }
 
        splooge = true;
        cout << "\n\n";
    }
 
    if(splooge == true)
    {
        result = sqrt(eJack);
    }
 
    return result;
}

fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap!

FAP HARDER BOY!!

fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap! fap!

oh — Oh — OH — OOOOOOOOOOOOOOHHHHHHHHH!!!!

I personally believe that OOP is a good approach when used correctly. I’m working with a large code base and I think I would loose my sanity if I did everything procedurally and not encapsulate. It does give your code structure and does future proof your applications, if designed properly from the start.

@Howard: It’s essential in many cases. My point is that it’s sometimes abused and used in cases where it has limited or no advantages and lots of disadvantages. In this case performance, readability, and code size. The advantages: none.

@ferricguy: you forgot to build the **** and Ball classes, which should be inherited from the abstract base class Genitalia. also, you’ll need a Hand class to write the Hand.fap(Genitalia g) and Hand.fondle(Genitalia g) methods. polymorphic fapping ftw.

Leave a Reply to Allen Cancel reply

Your email address will not be published. Required fields are marked *