I think that one possible problem with the 'O' in SOLID (open closed principle) is spending excess time second guessing future modifications to the code. The examples are always clear cut, but in the real world it sometimes doesn't work out that way.
OTOH I'd say that the 'L' is worthwhile (Liskov substitution principle) as inheritance can be abused as a kind of 'version control' for functionality, and LSP helps guard against that.
Some time ago I worked exposing an API that, given that it was constantly evolving and different partners adapted to it at different paces, we had to support a wide range of versions of it, which was basically what you say as version control.
I'm not gonna say it was pretty, actually from a design perspective it was disgusting, but from the perspective of handling a dozen versions of the same code in the same application, it was certainly very sane.
For example, at some point we supported versions 2.0, 3.0, 4.0, 4.1, 4.2, 4.3 and the freshly new 5.0. They inherited this way: 2.0 -> 3.0 -> 4.0 -> 4.1 -> 4.2 -> 4.3 -> 5.0, easy enough.
One day decide to deprecate version 2.0.
What happens is we consolidate 2.0 code in 3.0:
1. If a method calls super, copy + paste from 2.0 its place.
2. If it's overridden, there's nothing to do.
3. Run unit, regression tests, on the remainder of the versions and fix anything that might have been missed.
4. Delete 2.0 code.
The end.
If we need to fix a bug introduced in 4.1, you fix it there and it gets fixed automatically for the rest of the higher versions.
Sounds reasonable, I should really have said 'informal version control' where it's used to get stuff out the door and piles on technical debt as well :-o
The L really doesn't fit in with the others. It's super weird that people even try to compare it with the other "SOLID rules".
The Liskov substitution principle isn't advice on architecture, it's a statement of what the mathematical requirements are for inheritance to be compatible with a type system. If you violate it, you are no longer in compliance with the expectations your compiler has of you, and your compiler may fail you. It's like allowing UB into your C code. You might very well get away with it, but if you end up with a run-time type error, even though you have an allegedly static type system, well it's your OWN FAULT.
The other principles are all recommendations that have to do with whether or not other future developers will be happy building on your work. It is very easy to imagine a perfect-until-you-maintain-it piece of software that wildly violates every single one of those principles. I'm personally not convinced by most of them, but as someone with only 10-ish years of experience, I'm definitely still learning, and it won't surprise me if I'm absolutely wrong about some or all of S/O/I/D. But either way, they're rules of thumb, not mathematical laws, and they're rules of thumb about future work, not rules of thumb about whether the software will work right this moment.
OTOH I'd say that the 'L' is worthwhile (Liskov substitution principle) as inheritance can be abused as a kind of 'version control' for functionality, and LSP helps guard against that.