Logotipo do ConstructiCat
CodeBust.
Explorar a seção ▾

Interface inchada.

Interface inchada é um antipadrão em que uma única interface acumula tantas operações que cada cliente depende de métodos que nunca usa.

Interface inchada (em inglês, interface bloat) é um antipadrão em que uma única interface – a API pública de uma classe, uma interface Java ou C#, as funções exportadas por um módulo – acumula muito mais operações do que qualquer um de seus clientes precisa.

Definição

A palavra “inchaço” (bloat) é usada para vários problemas de design de software, inclusive interfaces de usuário sobrecarregadas de recursos e opções. No design de APIs, uma interface está inchada quando reúne sob um mesmo tipo várias responsabilidades sem relação entre si: consultas, persistência, administração, notificações. Toda implementação precisa fornecer todas elas, e todo cliente depende de operações que nunca chama, de modo que uma mudança em qualquer uma delas obriga a recompilar, retestar ou reimplantar clientes que nada têm a ver com ela.

Sinais típicos de uma interface inchada:

  • implementações que deixam métodos vazios ou lançam UnsupportedOperationException;
  • dublês de teste que precisam simular uma dúzia de métodos para um teste que usa só um;
  • grupos de métodos usados por clientes diferentes e que mudam por motivos diferentes.

Princípio da segregação de interfaces

O remédio é o princípio da segregação de interfaces (o “I” de SOLID): nenhum cliente deve ser forçado a depender de métodos que não usa. A interface inchada é dividida em várias interfaces pequenas, cada uma dedicada a um papel. Uma mesma classe ainda pode implementar todas elas, mas cada cliente enxerga apenas o papel de que precisa.

A refatoração Extrair Interface costuma ser o primeiro passo. Por trás de uma interface inchada muitas vezes há um objeto deus ou uma classe grande, que também precisam ser divididos.

Exemplo

Este UserRepository mistura consultas, persistência, consultas administrativas e e-mails de redefinição de senha. Uma página de perfil que só chama byId continua dependendo dos sete métodos, e cada objeto falso usado em seus testes precisa implementá-los.

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 papel, cada cliente depende apenas do que chama:

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; // depende apenas do que usa

    ProfilePage(UserLookup users) { this.users = users; }

    String title(int id) { return users.byId(id).name(); }
}

Uma única classe JdbcUsers ainda pode implementar UserLookup e UserStore; o que diminuiu foram as dependências dos clientes.

Adaptado do artigo da Wikipédia “Interface bloat” (revisão 1304469164), disponível sob a licença CC BY-SA 4.0; o texto foi traduzido e editado, e exemplos foram adicionados.