Yes, I've dealt with systems that had bad abstractions.
And I've also dealt with systems where knowledge of highly nameable things - like how to authenticate a user, or how to connect to a database, how to obtain a token to the same API server - wasn't centralized.
Systems of the first kind are certainly bad. It takes a lot of time to understand before you can get ahead and start refactoring. If your organization had low code review discipline at any point, abstractions often become hard to refactor with time, since some developers don't understand the abstractions, and instead of fixing them, just work around them with thread locals or lots of branches.
But systems of the second kind are much worse. Here what happens is that duplicated knowledge invariably diverges with time. It can be developers fix a bug in one place and forget the other, or adding a certain feature in one place and another one the other place. Over time, each implementation of the knowledge has it own unique behavior and bugs, and some parts of the sprawling code base grow to depend on a certain behavior. Or perhaps your code doesn't, but you have other services in other part of the company consuming your API that do and you just have no idea if they rely upon the implementation difference or not.
Yes, I've dealt with systems that had bad abstractions. And I've also dealt with systems where knowledge of highly nameable things - like how to authenticate a user, or how to connect to a database, how to obtain a token to the same API server - wasn't centralized.
Systems of the first kind are certainly bad. It takes a lot of time to understand before you can get ahead and start refactoring. If your organization had low code review discipline at any point, abstractions often become hard to refactor with time, since some developers don't understand the abstractions, and instead of fixing them, just work around them with thread locals or lots of branches.
But systems of the second kind are much worse. Here what happens is that duplicated knowledge invariably diverges with time. It can be developers fix a bug in one place and forget the other, or adding a certain feature in one place and another one the other place. Over time, each implementation of the knowledge has it own unique behavior and bugs, and some parts of the sprawling code base grow to depend on a certain behavior. Or perhaps your code doesn't, but you have other services in other part of the company consuming your API that do and you just have no idea if they rely upon the implementation difference or not.