Interface Bloat.
Interface bloat is an antipattern in which one interface piles up so many operations that every client depends on methods it never uses.
Interface bloat is an antipattern in which a single interface – the public API of a class, a Java or C# interface, the exported functions of a module – accumulates far more operations than any one of its clients needs.
Definition
The word “bloat” is used for several problems in software design, including user interfaces overloaded with features and options. In API design, an interface is bloated when it bundles several unrelated responsibilities, such as lookups, persistence, administration and notifications, behind one type. Every implementation then has to provide all of them, and every client depends on operations it never calls, so a change to any one of them forces unrelated clients to be recompiled, retested or redeployed.
Typical signs of a bloated interface:
- implementations that leave methods empty or throw
UnsupportedOperationException; - test doubles that must stub a dozen methods for a test that uses one;
- groups of methods that are used by different clients and change for different reasons.
Interface segregation principle
The remedy is the interface segregation principle (the “I” in SOLID): no client should be forced to depend on methods it does not use. A bloated interface is split into several small, role-specific interfaces. One class may still implement all of them, but each client sees only the role it needs.
The Extract Interface refactoring is the usual first step. A bloated interface often sits on top of a god object or a large class, which then need to be split as well.
Example
This UserRepository mixes lookups, persistence, administrative queries and password-reset e-mails. A profile page that only calls byId still depends on all seven methods, and every fake used in its tests has to implement them.
interface UserRepository {
User byId(int id);
User byEmail(String email);
void save(User user);
void delete(int id);
void rename(int id, String name);
List<User> admins();
void sendReset(int id);
}
Split by role, each client depends only on what it calls:
interface UserLookup {
User byId(int id);
User byEmail(String email);
List<User> admins();
}
interface UserStore {
void save(User user);
void delete(int id);
void rename(int id, String name);
}
interface PasswordReset {
void sendReset(int id);
}
class ProfilePage {
private final UserLookup users; // depends only on what it uses
ProfilePage(UserLookup users) { this.users = users; }
String title(int id) { return users.byId(id).name(); }
}
A single JdbcUsers class can still implement UserLookup and UserStore; only the dependencies of the clients have shrunk.
Adapted from the Wikipedia article “Interface bloat” (revision 1304469164), available under the CC BY-SA 4.0 license; the text has been edited and examples added.