Conceitos de SOLID
Principios de SOLID aplicados ao projeto Batcaverna-PV
Construir o BatCaverna Editor é uma tarefa de alta responsabilidade. Se o Batman vai usar esse software para registrar investigações ou analisar dados da Wayne Enterprises, o código precisa ser tão robusto e à prova de falhas quanto o próprio cinto de utilidades.
Aplicar os princípios SOLID vai garantir que o seu editor seja fácil de manter, testar e expandir. Vamos traduzir esses cinco princípios para o contexto do seu projeto (usando TypeScript/C# como base conceitual).
1. SRP - Princípio da Responsabilidade Única (Single Responsibility Principle)
O Conceito: Uma classe deve ter apenas um motivo para mudar. No BatCaverna Editor: Não misture a lógica de interface do usuário, manipulação de texto e salvamento de arquivos na mesma classe.
❌ O Jeito Errado (Classe Faz-Tudo):
class BatDocument {
public text: string;
public formatText() { /* Negrito, itálico... */ }
public saveToBatComputer() { /* Lógica de acesso ao disco... */ }
public printToBatPrinter() { /* Lógica de impressão... */ }
}
✅ O Jeito SOLID: Divida as responsabilidades. Se a rede do Batcomputador mudar, você só altera a classe de salvamento, sem o risco de quebrar a formatação de texto.
class BatDocument {
public text: string;
}
class DocumentFormatter {
public format(doc: BatDocument) { /* ... */ }
}
class DocumentStorage {
public save(doc: BatDocument) { /* ... */ }
}
2. OCP - Princípio Aberto/Fechado (Open/Closed Principle)
O Conceito: O código deve estar aberto para extensão, mas fechado para modificação. No BatCaverna Editor: Se você quiser adicionar um novo formato de exportação (ex: exportar para PDF, ou para um formato criptografado da WayneCorp), você não deve precisar alterar a classe principal que gerencia as exportações.
✅ O Jeito SOLID: Use interfaces ou classes abstratas.
interface IFileExporter {
export(text: string): void;
}
class PdfExporter implements IFileExporter {
export(text: string) { console.log("Exportando PDF..."); }
}
class WayneCorpEncryptedExporter implements IFileExporter {
export(text: string) { console.log("Criptografando nível militar..."); }
}
// A classe abaixo nunca precisará ser modificada quando um novo formato surgir!
class ExportManager {
public exportDocument(text: string, exporter: IFileExporter) {
exporter.export(text);
}
}
3. LSP - Princípio da Substituição de Liskov (Liskov Substitution Principle)
O Conceito: Classes derivadas devem poder substituir suas classes base sem quebrar o sistema. No BatCaverna Editor: Se você tem um documento “Somente Leitura” (ex: um dossiê finalizado do Coringa), ele não deve herdar de uma classe que o force a ter um método de edição que lance um erro.
❌ O Jeito Errado:
class Document {
public write(text: string): void { /* ... */ }
}
class ReadOnlyDossier extends Document {
public write(text: string): void {
throw new Error("Não é possível editar um dossiê finalizado!"); // Quebra o princípio!
}
}
✅ O Jeito SOLID: Crie abstrações que façam sentido.
interface IReadableDocument {
read(): string;
}
interface IWritableDocument extends IReadableDocument {
write(text: string): void;
}
class DraftDocument implements IWritableDocument { /* Lê e Escreve */ }
class ReadOnlyDossier implements IReadableDocument { /* Apenas Lê */ }
4. ISP - Princípio da Segregação de Interfaces (Interface Segregation Principle)
O Conceito: Nenhuma classe deve ser forçada a depender de métodos que não usa. No BatCaverna Editor: Imagine que você quer criar um sistema de plugins para o editor. Não crie uma interface gigante que obrigue todo plugin a ter botões na UI e atalhos de teclado se alguns plugins rodam apenas em background.
✅ O Jeito SOLID: Quebre as interfaces em partes menores e mais específicas.
interface IBackgroundPlugin {
executeInBackground(): void;
}
interface IUIPlugin {
renderToolbarButton(): void;
}
// Um plugin de Auto-Save só precisa da interface de background
class AutoSavePlugin implements IBackgroundPlugin {
executeInBackground() { /* Salva a cada 5 minutos */ }
}
5. DIP - Princípio da Inversão de Dependência (Dependency Inversion Principle)
O Conceito: Dependa de abstrações, não de implementações concretas. Módulos de alto nível não devem depender de módulos de baixo nível. No BatCaverna Editor: A interface principal do editor não deve instanciar diretamente o banco de dados ou a API da nuvem. Ela deve receber a dependência “injetada”.
✅ O Jeito SOLID:
interface IDatabase {
saveLog(log: string): void;
}
class OracleCloudDatabase implements IDatabase {
saveLog(log: string) { /* Envia para os servidores da Oráculo */ }
}
class EditorCore {
private db: IDatabase;
// A dependência é injetada via construtor. O Core não sabe QUAL banco está usando,
// apenas sabe que ele obedece à interface IDatabase.
constructor(database: IDatabase) {
this.db = database;
}
public performAction() {
this.db.saveLog("Ação realizada pelo Batman.");
}
}
Aplicando essas regras, o núcleo do seu editor ficará imune a “efeitos colaterais” quando você precisar adicionar novas funcionalidades ou trocar tecnologias no futuro.