I just don’t see an API reducing all those dependencies
Because it doesn’t. Uncle Bob is wrong there. Let me list some reasons for this:
The very first thing is, Uncle Bob doesn’t seem to think in terms of design trade-offs. It seems to be always in absolutes, like the UI must always be separated from the business, database and all other technologies must all be separated from each other, etc. Just take a look at Uncle Bob’s code to see how unmaintainable that is.
Architecture is heavily dependent on the requirements. That means you can’t make a trade-off “in general” without even looking at what that application is for.
Second, introducing an additional abstraction is not free. Putting a box in a diagram might be easy, but you’re bringing a lot of complexity on board. This is also not acknowledged.
Third, it doesn’t even decouple anything necessarily. Uncle Bob leaves out all the details about that one additional box. Like, is that API a data-oriented API, like Uncle Bob usually defines them? Because if it is, both sides have to know what that data is and how it works. That would mean that if the “services” change, the “users” have to change anyway, because of the changed semantics and/or protocol. What if the workflow changes, the meaning of some data elements, etc.?
He might mean, that you don’t exactly need to know which service you need to call, because you’re calling a central thing. That might help you in some situations, but that’s a pretty small part of the whole thing.
In general though, I agree with the conclusions. TDD will not get you a good design automatically, it is not a design practice. It is still all up to us.