Jefferson Mariano de Souza
Resolver situações e problemas de negócio
Situação: Persistir dados para envio de e-mail de uma obrigação
Situação: Código possui classes em português e em inglês
Situação: Para resolver determinada situação, a solução pensada é apagar uma coluna da tabela
Situação: Alteração em tabela existente
Situação: Já estava assim, me baseei em outro lugar
SOLID é um acrônimo que contempla princípios da programação orientada a objetos e design de código identificados por Robert C. Martin (Uncle Bob)
class Order {
public calculateTotalSum(){/*...*/}
public getItems(){/*...*/}
public getItemCount(){/*...*/}
public addItem(item: Item){/*...*/}
public deleteItem(itemId: number){/*...*/}
public printOrder(order: Order){/*...*/}
public showOrder(order: Order){/*...*/}
public load(orderID: number){/*...*/}
public save(order: Order){/*...*/}
public update(order: Order){/*...*/}
public delete(order: Order){/*...*/}
}
class Order {
public calculateTotalSum(){/*...*/}
public getItems(){/*...*/}
public getItemCount(){/*...*/}
public addItem(item: Item){/*...*/}
public deleteItem(itemId: number){/*...*/}
}
class OrderRepository {
public load(orderID: number){/*...*/}
public save(order: Order){/*...*/}
public update(order: Order){/*...*/}
public delete(order: Order){/*...*/}
}
class OrderViewer {
public printOrder(order: Order){/*...*/}
public showOrder(order: Order){/*...*/}
}
class ContratoClt {
public salario(): number {/*...*/}
}
class Estagio {
public bolsaAuxilio(): number {/*...*/}
}
class FolhaDePagamento {
protected saldo: number;
public calcular(funcionario: Funcionario) {
if ( funcionario instanceof ContratoClt ) {
this.saldo = funcionario.salario();
} else if ( funcionario instanceof Estagio ) {
this.saldo = funcionario.bolsaAuxilio();
}
}
}
Ao alterar uma classe já existente para adicionar um novo comportamento, corremos um sério risco de introduzir bugs em algo que já estava funcionando.
interface Remuneravel {
public remuneracao(): number;
}
class ContratoClt implements Remuneravel {
public remuneracao(): number { /*...*/ }
}
class Estagio implements Remuneravel {
public remuneracao(): number { /*...*/ }
}
class FolhaDePagamento {
protected saldo: number;
public calcular(funcionario: Remuneravel) {
this.saldo = funcionario.remuneracao();
}
}
Se para cada objeto o1 do tipo S há um objeto o2 do tipo T de forma que, para todos os programas P definidos em termos de T, o comportamento de P é inalterado quando o1 é substituído por o2 então S é um subtipo de T
se S é um subtipo de T, então os objetos do tipo T, em um programa, podem ser substituídos pelos objetos de tipo S sem que seja necessário alterar as propriedades deste programa
public class Passaro {
public voar() {};
}
public class Pato extends Passaro { /*...*/ }
public class Avestruz extends Passaro {
public voar() {
throw new Error("Avestruz não voa!");
};
}
public class Passaro {};
public class PassaroVoador extends Passaro {
public voar(){};
}
public class Pato extends PassaroVoador {}
public class Avestruz extends Passaro {
//avestruz não voa!
}
interface Ave {
public setLocalizacao(longitude, latitude);
public setAltitude(altitude);
public renderizar();
}
class Papagaio implements Ave {
public setLocalizacao(longitude, latitude) {
//Faz alguma coisa
}
public setAltitude($altitude) {
//Faz alguma coisa
}
public renderizar() {
//Faz alguma coisa
}
}
class Pinguim implements Ave {
public setLocalizacao(longitude, latitude) {
//Faz alguma coisa
}
public setAltitude(altitude) {
//Não faz nada... Pinguins são aves que não voam!
}
public renderizar() {
//Faz alguma coisa
}
}
interface Ave {
public setLocalizacao(longitude, latitude);
public renderizar();
}
interface AveVoadora extends Ave {
public setAltitude(altitude);
}
class Papagaio implements AveVoadora {
public setLocalizacao(longitude, latitude) {
//Faz alguma coisa
}
public setAltitude(altitude) {
//Faz alguma coisa
}
public renderizar() {
//Faz alguma coisa
}
}
class Pinguim implements Ave {
public setLocalizacao(longitude, latitude) {
//Faz alguma coisa
}
public renderizar() {
//Faz alguma coisa
}
}
Módulos de alto nível não devem depender de módulos de baixo nível. Ambos devem depender da abstração
Abstrações não devem depender de detalhes. Detalhes devem depender de abstrações
class PasswordReminder {
private dbConnection: MySQLConnection;
constructor() {
this.dbConnection = new MySQLConnection();
}
}
interface Connection {
public connect() {}
}
class MySQLConnection implements Connection {
public connect() {
// ...
}
}
class OracleConnection implements Connection {
public connect() {
// ...
}
}
class PasswordReminder {
private dbConnection: Connection;
constructor(Connection dbConnection) {
this.dbConnection = dbConnection;
}
}
Apresentação disponível em: https://studiojms.github.io/sw-dev-good-practices-presentation/