Interfaz inflada.
La interfaz inflada es un antipatrón en el que una interfaz acumula tantas operaciones que cada cliente depende de métodos que nunca usa.
Una interfaz inflada (en inglés, interface bloat) es un antipatrón en el que una sola interfaz —la API pública de una clase, una interfaz de Java o C#, las funciones que exporta un módulo— acumula muchas más operaciones de las que necesita cualquiera de sus clientes.
Definición
La palabra «inflado» (bloat) se usa para varios problemas del diseño de software, entre ellos las interfaces de usuario sobrecargadas de funciones y opciones. En el diseño de API, una interfaz está inflada cuando agrupa bajo un mismo tipo varias responsabilidades sin relación: consultas, persistencia, administración, notificaciones. Cada implementación tiene que proporcionarlas todas y cada cliente depende de operaciones que nunca llama, de modo que un cambio en cualquiera de ellas obliga a recompilar, volver a probar o redesplegar clientes que no tienen nada que ver.
Señales típicas de una interfaz inflada:
- implementaciones que dejan métodos vacíos o lanzan
UnsupportedOperationException; - dobles de prueba que deben simular una docena de métodos para una prueba que usa uno;
- grupos de métodos que usan clientes distintos y que cambian por motivos distintos.
Principio de segregación de interfaces
El remedio es el principio de segregación de interfaces (la «I» de SOLID): ningún cliente debe verse obligado a depender de métodos que no usa. La interfaz inflada se divide en varias interfaces pequeñas, cada una dedicada a un rol. Una misma clase puede seguir implementándolas todas, pero cada cliente solo ve el rol que necesita.
La refactorización Extraer interfaz suele ser el primer paso. Detrás de una interfaz inflada a menudo hay un objeto todopoderoso o una clase grande, que también conviene dividir.
Ejemplo
Este UserRepository mezcla consultas, persistencia, consultas administrativas y correos de restablecimiento de contraseña. Una página de perfil que solo llama a byId depende igualmente de los siete métodos, y cada objeto falso de sus pruebas tiene que implementarlos.
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);
}
Divididas por rol, cada cliente depende solo de lo que llama:
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; // solo depende de lo que usa
ProfilePage(UserLookup users) { this.users = users; }
String title(int id) { return users.byId(id).name(); }
}
Una única clase JdbcUsers puede seguir implementando UserLookup y UserStore; lo que se ha reducido son las dependencias de los clientes.
Adaptado del artículo de Wikipedia “Interface bloat” (revisión 1304469164), disponible bajo la licencia CC BY-SA 4.0; el texto ha sido traducido y editado, y se han añadido ejemplos.