9

Steve yegge wrote an article called "Execution in the Kingdom of Nouns" back in 2006, 14 years later I still find the points he made valid. For example, "Action is what gives life its spice... (but) Object Oriented Programming puts the Nouns first and foremost ... nouns are things, and things are prized beyond all actions in the Kingdom of Java".

The example he used still resonates with me. Most of time when I write the a piece of codes to do a task, it normally consists of a serial of actions. Using his example of taking out the garbage to illustrate the the point,

  /*To take out the the garbage*/
  get the garbage bag from under the sink
  carry it out to the garage
  dump it in the garbage can
  wash my hands
  get back to my couch
  ...

what I need here are a serial of actions, not a serial of nouns like

A GarbageDisposalStrategy nouns, 
A GarbageDisposalDestinationLocator nouns for finding my way to the garage, 
A PostGarbageActionCallback nouns for putting me back on my couch.
...

I have seen too many codes with all kinds of manager classes, with public methods like run(), execute() or dothis().

And let me give a more realistic example to further illustrate my point. People always say choosing the right paradigm for the right problem. So let's take web development as an example. In web development we have lots of OOPs and frameworks, not just in java. But even since I use nodejs (express) to do web development I never use OOP, never miss it. Express's middleware is just a function chain.

So both OOP and procedural design work well for web development. But with express I feel far more easier, I spend more time in developing the "real" code instead of learning the frameworks and all the design and twist in the framework.

What is the "right" paradigm for web development?

What are the disadvantages of OOP, especially in java (in web development & in general)? Does OOP overemphasize the importance of noun and thus put action/verb in the less importance position ?

I also need to emphasize that my question is not to discuss/promote functional programming or to start a language war. I am fully aware that my question maybe seen as opinion-based or too broad. But the fact that 14 years later the problem is still here makes me ask this question.

---- update ----

One more vote and my post will be deleted. But please, the future readers, don't vote to delete it, it has been closed, why delete it? I do think it raises a valid concern, why delete it?

Although my question was closed (as I expected) I want to point out that there was a same question at stackoverflow (before I changed my question title), which was also closed https://stackoverflow.com/questions/2853316/disadvantage-of-oop

There are some good answers there so if you have interest take a look. An answer I quite agree is (maybe because many of my codes are transformative processing)

OOP works best with large-scale, multi-developer, multi-module projects. For "development in the small" - such as scripting or transformative processing, it can require a good deal of overhead without necessarily adding value.

...

transformative processing is quite amenable to the functional style of programming

PS, if you think Steve yegge's article is gibberish, you may check Joe Armstrong(father of erlang) article Why OO Sucks, much shorter, straight to the points and yet basically made the same arguments, like "Data structure and functions should not be bound together."

2 Answers2

17

One of the problems with OOP is not what OOP is, but how it is taught.

Alan Kay, who coined the term "Object-Oriented Programming" has made it very clear on multiple occasions that Messaging is the most important thing in OOP. He has even said that he regrets called it Object-Oriented and should have called it Message-oriented instead.

So, even from the very first days of OOP, the focus has been on the Interaction, not on the Thing.

However, the very first technique for object-oriented analysis being taught is "underline all the subjects, verbs, and objects in the use case; the subjects become classes, the verbs methods, and the objects fields."

Note how this methodology does not even focus on objects, it focuses on classes.

But even if we assume that this methodology is a good methodology, you can still end up with widely differing designs, depending on how you formulate the use case.

One of my favorite examples is banking. The BankAccount is one the most-widely used introductory examples in OOP. And "everybody knows" what a BankAccount is, right?

class BankAccount {
    private Money balance;
void deposit(Money amount) {
    balance += amount;
}

bool withdraw(Money amount) {
    if (balance < amount) { return false; }
    balance -= amount;
    return true;
}

}

Easy-peasy. Now, add the transfer method. Oh, wait, what object does it belong to? Does A transfer to B or does B transfer from A? And what about concurrency?

class BankAccount {
    Money balance;
void deposit(Money amount) {
    balance += amount;
}

bool withdraw(Money amount) {
    if (balance < amount) { return false; }
    balance -= amount;
    return true;
}

bool transfer(Money amount, BankAccount target) {
    if (balance < amount) { return false; }
    withdraw(amount);
    target.deposit(amount);
    return true;
}

}

"Everybody knows" that "balance" is data and "transfer" is an action. Right? RIGHT?

Well, turns out that's not how it works. In fact, it has never worked that way, all the way back to when bank transfers were first invented.

What happens when you make a transfer is that the clerk writes a transaction slip, and at the end of the business day, all the transaction slips for the account are tallied up, and this yields the new balance. Then, the transaction slips are sent to the receiving bank, where the same thing happens.

So, in the "real world" (which every OOP tutorial teaches us we are supposed to model), the transaction is actually data and the balance is actually an operation!

record Transaction(BankAccount source, BankAccount target, Money amount)

class BankAccount { Money balance() { // find all transaction slips which have this as either source or target // add all the amounts which have this as target // subtract all the amounts which have this as source return result; }

void deposit(Money amount) {
    TransactionLog.append(new Transaction(CASH, this, amount));
}

void withdraw(Money amount) {
    TransactionLog.append(new Transaction(this, CASH, amount));
}

}

Note that all of our concurrency problems go away: BankAccount is immutable, Transaction is immutable, we only need an "almost-immutable" append-only TransactionLog. We also get a full audit-trail for free, and can recover from partial data loss.

That is not actually surprising if you consider that this is how banking has been done since the times when moving transaction slips via horse courier between branches and banks was risky and may have taken days. This has exactly the same problems and properties as a distributed electronic banking system.

So, as you can see, we can flip the roles of nouns and verbs for the exact same problem just by approaching the problem differently.

Also, note how the complexity of the problem and the context requires having multiple independent concurrent actors, namely at least the two branches of the bank. That is what OOP is supposed to be: multiple independent actors collaborating by exchanging messages while keeping their own workings hidden from the rest of the world.

Jörg W Mittag
  • 104,619
5

It's normal for people to think about a "series of actions" when thinking about a problem. It's easy, and anything and everything is under your complete control. Nothing wrong with that, it is just a way of thinking.

OO requires a completely different thinking though. Instead of command-and-control, you are actually encouraged to think of work as a cooperation among colleagues. It's not about "things", it is about living things. You give up control yourself in order to delegate tasks to other beings (i.e. objects).

To answer your question: The linked article is BS of course, or rather, it is a strawman. Sure, if you are doing OO very badly, plus you're overcomplicating everything, it will look pretty bad. Even if that applies to some frameworks or libraries, it's not OO at fault here, just people's wrong interpretation of it.