Ok, I get it. Mature Ruby codebase sucks. Integer division changes are surprising. But what does it have to do with object-orientedness?
> break functionality into lots of small objects
> use immutabile objects as much as possible (e.g. using thin veneers over primitives or adamantium)
are the guidelines that I'm using in C#.
> separate business logic into collections of functions that act on said objects (service objects)
minimize mutation and side effects to as few places as possible
How does separating out functions minimize mutation?
> thoroughly document expected type arguments for object instantiation and method invocation with unit tests (mimickry of a static type system)
The point is that OOP was introduced so people could continue coding with globals (i.e. states), where the globals now lives inside different namespaced containers instead the global container.
The effect is still the same though, your code is just the same old Rube Goldberg machine.
Very few of their arguments seem to relate to OOP. One of the nastiest gotchas there is that importing a library can change how division works - or, in the general case, that which code has run before my code can affect how my code executes.
Plenty of Object-Oriented Languages do not allow you to rewrite existing code in other modules like this. In fact, most of them don't. Encapsulation is a hallmark of OOP, and it's typically non-OOP languages that allow you to do things like this. Just because Ruby says to you "I'm OOP", and you don't like a feature of Ruby, does not mean you do not like OOP!
Rust has a nice solution to this problem: You can modify an existing class, such as integers, but that modification only applies within the scope of code where you apply it. It can't bleed out into all code that runs after the patching.
> break functionality into lots of small objects > use immutabile objects as much as possible (e.g. using thin veneers over primitives or adamantium)
are the guidelines that I'm using in C#.
> separate business logic into collections of functions that act on said objects (service objects) minimize mutation and side effects to as few places as possible
How does separating out functions minimize mutation?
> thoroughly document expected type arguments for object instantiation and method invocation with unit tests (mimickry of a static type system)
Yet another argument for static typing...