> The interface shouldn't really be implemented by anyone outside of YARN
This is the heart of the problem. We don't have a way to say (via the audience annotations) that an interface is for read-only use only - and not for users to implement. An interface may be @Public @Stable from the point of view of a user who wants to call it, but that doesn't mean that folks should implement it themselves, since for interfaces like the one we are discussing we might want to add a new method, say (note that such a change is compatible with @Stable). Adding a new method is fine for the first type of user, but not for the second, since their implementation breaks.
In this case, I think it's likely we'll add more methods. For example, it would be useful to add a waitForState method to YarnClient (which is also an interface), which waits for a given application to reach a particular YarnApplicationState. If YarnClient were a class then this would be a compatible change, but if it's an interface then it is not.
I think we should do one of the following:
1. Change YarnClient and AMRMClient to be concrete implementations.
2. Leave the interface/implementation distinction and make the interfaces @Public @Unstable.
I prefer 1. since these classes are helper classes - they are not a tightly-defined interface.