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.
Free and paid products to turn ideas into a foundation you can actually ship.
13 products availableContinue exploring similar topics
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.
A 47-point checklist to find bugs, security risks, and performance issues before launch.
Production-tested templates trusted by developers. Save weeks of setup on your next project.