2
respostas

Aula 5 - Alguém sabe explica qual é o sentido dessa aula?

Até entendi o conceido do LSP, o fato que nem sempre herança é usada de forma apropriada

Mas esse exemplo aí... Não entendi!

Tinha uma herança entre ContaComum e ContaEstudante. Cada conta passou a implementar da propria maneira o método rende(), onde no caso de estudante retornava uma exception e atrapalhava a execução do ProcessadorDeInvestimento

Aí se fez uma composição com uma classe de saldo, permitindo reaproveitar código ou até mesmo reescrever o código se necessário, até aqui Ok.

Contudo, no final da vídeo aula o método rende é simplesmente removido do código, retornando ao problema inicial, o bug na execução do ProcessadorDeInvestimento, pois o método rende() deixa de existir e quando ele é jogado no loop do método processa(), como não há método rende() pra classe estudante retorna erro.

Claro que isso poderia ser simplesmente modificado para resolver o problema, só não entendi por que entrou na aula.


Aproveitando também o espaço, concluí o curso e não vi nada referente ao I do solid (Interface Segregation Principle). Gostaria de uma explicação COM EXEMPLO do que seria isso.

2 respostas

Oi Anderson, a ideia da Interface Segregation é limitar o que tá exposto em um objeto para ser acessado, por exemplo, em um método. No blog da caelum, tem um exemplo que considero bom => http://blog.caelum.com.br/qual-parametro-devo-receber-em-meus-metodos/

De fato o problema dentro do processamento persiste, o que eu fiz foi melhorar a forma como a herança ocorre e compor o comportamento do Rendimento com uma interface, dessa forma é possível checar se uma conta é rentável antes de tentar chamar o método rende nela.

Dessa forma o principio de Liskov é preservado, ou seja qualquer subclasse de conta pode ser usada onde uma instância de conta poderia (se não fosse abstrata e não pudesse ter instâncias).

Um exemplo mais real poderia ter criado alguns objetos com algumas regras de negócio, ex.

  • Conta Corrente - Não rende e tem taxas.
  • Conta de Estudante - Não rende, não tem taxas e tem milhas
  • Conta Poupança - Rende e não tem taxas.
  • Conta fácil - Se comporta como um misto da corrente e poupança rendendo, mas com taxas.

Neste cenário todas herdam de conta, os comportamentos como render e cobrança de taxas podem ser aplicados com um strategy, por exemplo, criando uma interface IRendeBehavior com duas classes filhas a RendimentoSimplesBehavior e a SemRendimentoBehavior, assim como a questão da taxa, mas talvez isso já seja complicar demais, o que isso faria no entanto seria evitar duplicação de código com composição ao invés de herança, onde as classes filhas iriam usar estes comportamentos para compor a si mesmas e a classe pai apenas forçaria que elas deveriam possuir um comportamento de cada tipo.

<?php

interface Rende {
    public function rende();
}

abstract class Conta {

    protected $saldo;

    public function __construct() {
        $this->saldo = 0;
    }

    public function saca($valor) {
        if($valor > 0 && $valor <= $this->saldo) {
            $this->saldo -= $valor;
        }else {
            throw new Exception("Valor inválido para o saque");
        }
    }

    public function deposita($valor) {
        $this->saldo += $valor;
    }

    public function getSaldo() {
        return $this->saldo;
    }

    public function isRentavel () {
        if($this instanceof Rende) {
            return true;
        } else {
            return false;
        }
    }

}

class ProcessadorDeInvestimentos 
{
    public function processa() 
    {
        $contas = $this->contasDoBanco();

        foreach($contas as $conta) {
            if($conta->isRentavel()) {
                $conta->rende();    
            }
        }
    }

    private function contasDoBanco() 
    {
        $contas = array();
        $contas[] = $this->contaComumCom(100);
        $contas[] = $this->contaEstudanteCom(200);
        $contas[] = $this->contaComumCom(300);

        return $contas;
    }

    private function contaComumCom($valor) 
    {
        $conta = new ContaComum();
        $conta->deposita($valor);

        return $conta;
    }

    private function contaEstudanteCom($valor) 
    {
        $conta = new ContaEstudante();
        $conta->deposita($valor);

        return $conta;
    }
}

class ContaEstudante extends Conta
{
    private $milhas;

    public function deposita($valor) 
    {
        parent::deposita($valor);
        $this->milhas += $valor;
    }

    public function getMilhas() 
    {
        return $this->milhas;
    }
}

class ContaComum extends Conta implements Rende
{
    public function rende() 
    {
        $this->saldo *= 1.1;
    }
}