Interface Segregation Principle (ISP) diz: clientes不应该 ser forçados a depender de interfaces que não usam. Traduzindo para o dia-a-dia: não crie contratos que carregam 47 campos quando o consumidor precisa de 3.
Esse princípio, que parece óbvio, é quebrado sistematicamente em sistemas médios e grandes. O resultado é acoplamento fantasma: mudar um campo quebra consumidores que nem usam aquele campo.
interface User {
id: string;
name: string;
email: string;
avatar: string;
bio: string;
followersCount: number;
followingCount: number;
postsCount: number;
isVerified: boolean;
preferences: UserPreferences;
settings: UserSettings;
// ... 30+ campos
}
async function getUserAvatar(userId: string): Promise<string> {
const user = await api.users.get(userId);
return user.avatar;
}
O endpoint /users/:id retorna User obesa. Para mostrar avatar, você busca 30 campos. Banco faz query pesada, rede transmite JSON grande, JS parseia objeto gigante, e você usa 1 campo.
interface UserSummary {
id: string;
name: string;
avatar: string;
}
interface UserProfile extends UserSummary {
bio: string;
followersCount: number;
followingCount: number;
postsCount: number;
}
interface UserSettings {
preferences: UserPreferences;
settings: UserSettings;
}
// Endpoint específico
app.get('/users/:id/summary', async (req, res) => {
const user = await db.users.findSummary(req.params.id);
res.json(user);
});
app.get('/users/:id/profile', async (req, res) => {
const user = await db.users.findProfile(req.params.id);
res.json(user);
});
Cada endpoint retorna só o que precisa. Cliente escolhe granularidade.
{
user(id: "123") {
name
avatar
}
}
Cliente pede exatamente o que precisa. Backend entrega. ISP nativo.
// ❌ Errado
function UserCard({ user }: { user: User }) {
return <div>{user.name}</div>;
}
// ✅ Certo
interface UserCardProps {
name: string;
avatar: string;
}
function UserCard({ name, avatar }: UserCardProps) {
return (
<div>
<img src={avatar} />
<span>{name}</span>
</div>
);
}
// Uso
<UserCard name={user.name} avatar={user.avatar} />
Componente declara exatamente o que precisa. Não força caller a buscar User inteira.
const selectUserName = (state: RootState) => state.user.name;
const selectUserAvatar = (state: RootState) => state.user.avatar;
function UserCard() {
const name = useSelector(selectUserName);
const avatar = useSelector(selectUserAvatar);
return <div><img src={avatar} />{name}</div>;
}
Componente depende de selectors mínimos. Mudança em state.user.bio não rerenderiza UserCard.
ISP tem custo. Aplicar sempre pode gerar overengineering.
ISP não é dogma. É heurística útil para evitar acoplamento fantasma. Quando você tem dúvida se deve segregar, considere o custo da segregação versus o custo do overfetching/acoplamento.
Na dúvida, comece segregado. Refatore para unificar se a segregação causar mais fricção que benefício.
Produtos gratuitos e pagos para transformar ideias em uma base que você consegue executar.
13 produtos disponíveisContinue explorando tópicos similares
Guia robusto para aplicar Dependency Inversion Principle com ports and adapters, React Context, contract tests e observabilidade de adapters em produção.
A rule, an AI suggestion, and a human agent's decision, for the same synthetic ticket: only one of them can ever change the ticket's state. From that constraint, DeskPilot gains a typed…
DeskPilot's tests were green. A synthetic provider outage, an actual local restore, and a release review exposed what those tests did not establish: whether a support agent can safely use the pilot.
Checklist de 47 pontos para encontrar bugs, riscos de segurança e problemas de performance antes do lançamento.
Templates testados em produção, usados por desenvolvedores. Economize semanas de setup no seu próximo projeto.