This has nothing to do with tooling, but the fact that pulling the rug under an established code base could have very unintended effects, compared to simply adding and extending functionality without touching what is already there.
By doing as the author suggests you’ll end up with either 500 broken tests or 5000 compiler errors in the best case, or in the worst case an effectively instantly legacied code base where you can’t trust anything to do what it says.
I once had to change an entire codebase’s usage of ints to uuids, which took roughly 2 whole days of fixing types and tests, even though logically it was almost equivalent. Imagine changing anything and everything to “make it do something else”.
And how long would it have taken for the original author to use an IdentifierFactory instead of ints and write meaningful tests for it? Less than two days?
OCP though more commonly refers to: 1. Building small, universally useful abstractions first 2. Extending behavior of that abstraction or system by writing new code rather than changing published code directly.
This is trivial when you have a few patterns under your belt. Template factories, builders, strategies, commands. I mean, while it’s not the best idea in most cases, even just inheriting a parent class and giving a new concrete new behavior is still better than changing something fundamental to the system.
Like has been said 999 times in this thread, software isn’t black and white. You have to make choices about where you go concrete and where you abstract, and gauge that against risk factors. A somewhat complex class you expect to go away in a couple months? Make it a god class that anyone who wants to can scan through. A fundamental class that will be used by hundreds of developers and underpin most operations in a production system where 5 minutes of downtime costs tens of thousands of dollars? It’s worth the upfront cost to build with these standards.
Honestly, if you cannot change your code, you have a problem.
https://drive.google.com/file/d/0BwhCYaYDn8EgN2M5MTkwM2EtNWF...
Flipping it around, if base libraries were to be always open for modification instead of extension, then instead of writing your feature logic in your own codebase, you might be tempted to submit a pull request to React.js to add your feature logic. That sounds ridiculous but that's the equivalent of what I see a lot of new engineers do when they try to fit the feature logic they need to implement anywhere it makes sense, often in some shared library in the same codebase.
That's still a matter of tooling. With type-checking, static analysics, and test suites, changing code doesn't have "very unintended effects".
Back in the day, without those, things were much more opaque.