A História da Pizzaria da Ana: Construindo sistemas robustos que escalam de verdade.
A Pizzaria da Ana começou simples: era pequena, um homem só e rápida. Mas o negócio cresceu e o "código espaguete" dominou a cozinha inteira:
O SOLID ajuda a reduzir o acoplamento explosivo e alinhar a coesão, definindo o que cada um faz na cozinha!
"Uma classe deve ter um, e apenas um, motivo para mudar... Ou o Mário bate seu ponto e queima a pizza pra atender o telefone!"
public class PizzariaSystem {
public void AnotarPedidoTelefone() { /* .. */ }
public void AmassarPizza() { /* .. */ }
public void LigarMotoEntregar() { /* .. */ }
}
Se a moto quebrar (bug de delivery), toda a classe para. Ninguém assa mais nada.
public class AtendenteCaixa { ... }
public class PizzaioloMaster { ... }
public class DeliveryMotoboy { ... }
Se precisarmos trocar de iFood pra telefone de novo, o Pizzaiolo continua assando sem nem saber do reboliço.
"Seja Aberto para expansão (cardápio flexível), mas Fechado para modicações drásticas (quebrar paredes) na base do restaurante!"
if (pedido == "Calzone") PrepararCalzone(); else if (pedido == "Brotinho") PrepararBrotinho(); else if (pedido == "Esfiha") ... // Ops, pediram Petisco? // Reescreve o FornosEngine.cs!
public interface IPreparoCozinha { void Assar(); }
public class Calzone : IPreparoCozinha { ... }
public class Churros : IPreparoCozinha { ... }
// A Cozinha apenas comanda:
// itemDeHoje.Assar();
// sem abrir o capô das receitas!
"Se o sistema espera processar uma Pizza comum, injetar um herdeiro falso ou disfuncional fará tudo pegar fogo."
A regra: Subclasses herdadas (do tipo PizzaGourmet ➡️ Pizza) devem se comportar da forma que o pai prometeu à infraestrutura.
Exemplo: A Ana lança oficialmente a sua "Pizza de Picolé Assada".
public class Pizza { public virtual void AssarFornoA400Graus() { ... } }
public class PizzaDePicole : Pizza {
public override void AssarFornoA400Graus() {
throw new Exception("MEU DEUS, ELA DERRETEU E QUEBROU O SISTEMA!");
}
}
"Você não deve forçar as classes a dependerem (e implementarem) rotinas gordas que elas nunca vão usar."
public interface IFuncionarioPizzaria {
void BaterMassaDeTrigo();
void PilotarMotoDeEntrega();
}
public class Motoboy : IFuncionarioPizzaria {
// Código inútil só pro C# parar de reclamar:
public void BaterMassaDeTrigo() => return;
}
public interface IAmassadeiro { void BaterMassa(); }
public interface IMotorista { void PilotarMoto(); }
// O Motoboy apenas herda de Motorista!
// A sanidade mental foi preservada!
"A Pizzaria (Forte) não deveria quebrar ou parar porque o detalhe estrutural (João e a Moto) sofreu uma pausa."
public class PizzariaAna {
// Nós instanciamos a implementação crua! 😭
private MotoboyJoao _mecanismo = new MotoboyJoao();
}
Pior: Teremos que jogar fora a classe se a Ana resolver usar Loggi amanhã de tarde.
public class PizzariaAna {
private IServicoDeLogistica _rota;
public PizzariaAna(IServicoDeLogistica entrega){
_rota = entrega; // Recebeu a tomada pronta do C#!
}
}
Passar iFood, Xbox ou Loggi via construtor agora é apenas plugar e rodar o negócio.
Feche o Figma, abra o seu Code e responda com honestidade: Ele está parecendo o cenário inicial do boteco da Ana?
else ifs em vez de polimorfismo ou interfaces para variações dos dados?README.md como livro caixa e conte qual peso tiramos do código base.Ao realizar as refatorações dessa semana com seu grupo, invista tempo na fundação estrutural.
Tire a carga bruta do seu Service. Tudo que não for responsabilidade central daquele domínio, despache (ex: mande para um JwtAuthCore ou DataParserService).
Desista do vínculo rígido do Classe -> Classe. Promova A abstração (Dependency Injection) usando containers de inversões do Spring, DotNet, NestJS.
// No container mestre de injeções da sua app!
builder.Services.AddScoped<ICompanhiaLogistica, LoggiService>();
// E na vida selvagem do controller...
public PizzariaController(ICompanhiaLogistica servicoDaVez){
// O framework injeta a dependência. ZERO acoplamento!
}