Princípios de Projeto Orientado a Objetos

Prof. Marcelo Cohen

Coesão

Quantas responsabilidades?

public class Gerenciador {
    ...
    public void cadastrarCliente(...) { }
    public void cadastrarProduto(...) { }
    public void gerarNotaFiscal(...) { }
    public void listarCompras(...) { }    
}

Alto acoplamento

public class Cadastro {
    private ArrayList<Usuario> lista;
    ...
    public ArrayList<Usuario> getLista() {
        return lista;
    }
}

Conclusão?


Discussão (longa) sobre coesão e acoplamento
Reducing Coupling (Martin Fowler)

SOLID

Um termo que descreve uma coleção de princípios de projeto para código de qualidade, criado por Robert C. Martin (também conhecido como Uncle Bob).

Só porque você pode, não significa que você deve!

Single Responsibility Principle

interface IEmail {
    public void setSender(String sender);
    public void setReceiver(String receiver);
    public void setContent(String content);
}

class Email implements IEmail {
    public void setSender(String sender) {// set sender; }
    public void setReceiver(String receiver) {// set receiver; }
    public void setContent(String content) {// set content; }
}

Qual é o problema aqui?

Single Responsibility Principle

interface IEmail {
    public void setSender(String sender);
    public void setReceiver(String receiver);
    public void setContent(IContent content);
}

interface IContent {
    public String getAsString();
}

class Email implements IEmail {
    public void setSender(String sender) {// set sender; }
    public void setReceiver(String receiver) {// set receiver; }
    public void setContent(IContent content) {// set content; }
}

Separando as responsabilidades...

Open/Closed Principle

public class GerenciadorVoos {
    private ArrayList<VooDireto> listaDiretos;
    private ArrayList<VooEscalas> listaEscalas;
    ...
    public boolean adicionaVooDireto(VooDireto v) { .. }
    public boolean adicionaVooEscalas(VooEscalas v) { .. }
}

Qual é o problema aqui?

Open/Closed Principle

public class GerenciadorVoos {
    private ArrayList<Voo> listaVoos;
    public enum TipoVoo { DIRETO, ESCALAS };

    public boolean adicionaVoo(Voo voo) { .. }

    public void processaVoos() {
      for(Voo v: listaVoos) {
        if(voo.getTipoVoo() == TipoVoo.DIRETO) { ... }
	else if(voo.getTipoVoo() == TipoVoo.ESCALAS) { ... } 
        ...
     }
}

E agora, melhorou?

Open/Closed Principle

public class GerenciadorVoos {
    private ArrayList<Voo> listaVoos;

    public boolean adicionaVoo(Voo voo) { .. }

    public void processaVoos() {
      for(Voo voo: listaVoos) {
        voo.processa(); // polimorfismo!
     }
}

É fácil definir e usar mais uma classe derivada de Voo?

Liskov Subtitution Principle (LSP)

public class Rectangle {
    private double height, width;

    public double area() { ... }

    public void setHeight(double height) { ... }
    public void setWidth(double width) { ... }
}

public class Square extends Rectangle {
    public void setHeight(double height) {
        super.setHeight(height);
        super.setWidth(height);
    }
    public void setWidth(double width) { setHeight(width); }
}

Qual é o problema?

Liskov Subtitution Principle (LSP)

public static void exibe(Rectangle r) {
    System.out.println("Área: "+r.area());
}

public static void main(String args[]) {

    Rectangle r1 = new Square();

    r1.setWidth(20);
    r1.setHeight(10);

    // 20 x 10 => 200
    // Mas como é um Square... o resultado é 100!
    exibe(r1);
}

Violação do LSP!

Dependency Inversion Principle (DIP)

public interface Reader { char getChar(); }
public interface Writer { void putChar(char c); }
 
class CharCopier {
 
  void copy(Reader reader, Writer writer) {
    char c;
    while ((c = reader.getChar()) != EOF) {
      writer.putChar();
    }
  }
}
 
public Keyboard implements Reader { ... }
public Printer implements Writer { ... }

É fácil criar uma nova implementaçao de Reader ou Writer?