The complexity of a program has to go somewhere. Everybody's got different ideas about where it should go.

Old-school Unix guys would prefer that you divide it all up into lots of differently-focused languages, tools, and such based on the ethic of 'doing one thing, well'. Which is fine and all, but it forces everybody new to learn a hundred little tools and languages to make anything significant.

The great thing about using a language/framework is that all your tools can share the same semantics. With OOP, you can model all sorts of interactions between domain concepts and do it in an iterative fashion.

But most OOP languages are insufficiently powerful, as the article says. It's difficult to move complexity around because OOP languages tend to not be dynamic enough to really be fluid like you need.

If you ask me why I think everyone hates OOP, it's because they haven't really understood Ruby's object model.

Ruby makes most everything an object that needs to be an object. A primitive is just a syntax for creating a built-in object. All of them ultimately inherit from BasicObject, which is separate from Object because it allows you to create entirely new hierarchies.

A block is not an object, but it can be turned into a Proc, which is.

All of this fluidity makes it so you can push around the complexity of your application to wherever you feel it needs to be. The ability to see exactly how complex your OOP programs is is a feature, not a bug. How can you remove duplication if you can't see it? How can you see the dividing lines of your emerging domain model if there's no way to make your code model anything, if it's obsessed with data rather than relationships between abstract concepts?

With Ruby, you can write the long complex methods, then gradually DRY them up into a bunch of methods, then collect those methods into classes, slowly deciding what needs to be class behavior and what needs to be object behavior, then meta-program the creation of those classes and objects with a DSL/front-end, then finally turn the whole thing into a tool you use declaratively which generates whole new concepts on the fly.

It works the way the human mind works, we take concepts and model them and their relationships in our heads and try to reason about edge cases. Once it's all well-defined, you can just add new cases as data rather than as code. Your business users think in terms of classes and objects, your boss thinks in those terms.

If you don't have a domain model you're at least trying to work out, then it will be that much more difficult to get them involved in the process. You want them involved because otherwise you have to understand the domain yourself. Your boss will have to come to you whenever the promo generator isn't quite working because he won't really understand the semantics behind it.

If you have an object model you're hacking on, you can just hand it to him and be like, "OK point to where you think the problem is". But if it's just a bunch of functions focused on data, that might make it easier for you to trace the data through your pipelines and find the bug, but you're going to spend a lot of time translating between the domain model your boss and business users are already and informally using anyway to understand the application and the way you understand that it's actually working. They're already using a domain model, so it would behoove you to create a canonical model and get it as reflective as possible of the business needs.

You don't use OOP because it makes it easier for you to understand. It doesn't. Clarifying a domain model is hard work. You do it because that complexity has to live somewhere, it should be the domain model, because other people besides programmers are involved in the system too.