Executando verificação de segurança...
Em resposta a [Não disponível]
1

Então, esse tipo de coisa parece ser meio roia e sem noção no começo, por que basicamente é um projeto inicial e pequeno para maioria dos casos.

Design patterns começam a fazer sentido quando o projeto começa a crescer e você precisa de determinada utilidade que só o uso da linguagem em si é capaz de prover.

Por exemplo que o Filipe Deschamps usa no vídeo dele que é interessante, é o caso de testes onde você não pode subir um "banco de dados real" para testar teu código, então a injeção de dependência cria um falso para "substituir o banco de dados" e então confirmar que o software funciona perfeitamente.

Outro que vou pegar diretamente do blog AkitaOnRails é o caso do porque o strategy é usado.

Digamos que temos as entidades Voyage e Cargo, tipo viagem e mercadoria, onde uma viagem tem muitas mercadorias. O Eric descreve um sistema que tem responsabilidade de associar cada mercadoria com uma viagem, gravar e rastrear esse relacionamento. Até aqui tudo bem. Em algum lugar do código vamos ter um método como esse:

public int makeBooking(Cargo cargo, Voyage voyage) {
    int confirmation = orderConfirmationSequence.next();
    voyage.addCargo(cargo, confirmation);
    return confirmation;
}

Mas porque existem cancelamentos de última hora, uma prática padrão da indústria de entrega é aceitar mais mercadorias do que é possível numa única viagem. É o que se chama de "overbooking". Algumas vezes é usado um percentual simples, como 110% da capacidade, em outros casos tem regras mais complexas.

Isso é uma estratégia básica no domínio de entregas que é conhecido de qualquer empresário dessa indústria, mas normalmente nós, programadores, não sabemos disso. O requerimento que vem pra nós poderia ser algo como "Permitir 10% de overbooking", o diagrama de classes poderia ficar parecido com isto e o código seria atualizado da seguinte forma:

public int makeBooking(Cargo cargo, Voyage voyage) {
    double maxBooking = voyage.capacity() * 1.1;
    if ((voyage.bookedCargoSize() + cargo.size()) > maxBooking)
        return -1;

    int confirmation = orderConfirmationSequence.next();
    voyage.addCargo(cargo, confirmation);
    return confirmation;
}

Ou seja, no código determinamos quanto é o novo máximo com 10% a mais de overbooking e vemos se a mercadoria que queremos adicionar ultrapassa esse máximo. Mas isso cria um problema: agora temos uma regra de negócio escondida, como uma cláusula de guarda, no meio do método da aplicação.

Segundo o Eric, essa regra de overbooking é uma política. Política é outro nome pra um design pattern conhecido como Strategy. Em resumo, esse novo código poderia ser refatorado pra ter uma classe separada de OverbookingPolicy e no método de adicionar a mercadoria na viagem, chamar o método "isAllowed" dessa nova classes, e assim separar a política numa entidade separada, que documenta melhor essa regra em vez de deixar misturada e escondida com o código anterior.

public int makeBooking(Cargo cargo, Voyage voyage) {
    if (!overbookingPolicy.isAllowed(cargo, voyage))
        return -1;
    int confirmation = orderConfirmationSequence.next();
    voyage.addCargo(cargo, confirmation);
    return confirmation;
}

class OverbookingPolicy {
    public static double OVERBOOKING = 1.1;
    public boolean isAllowed(Cargo cargo, Voyage voyage) {
        double maxBooking = voyage.capacity() * OVERBOOKING;
        return ((voyage.bookedCargoSize() + cargo.size()) <= maxBooking;
    }
}

O vídeo do Akita em si é para não usar design patterns adoidamente, mas aqui o seu caso parece o contrário. O design pattern nesse caso tem a função de "expor" uma funcionalidade sem que ela fique hard-code no código. Até porque dá forma que você citou até dá para fazer rodar, só que fica mais díficil de realizar a manutenção dele


Os vídeos do Fabio Akita sobre modelagem de dados e do Deschamps sobre Factory e Injeção de Dependências ilustram bem isso:

Carregando publicação patrocinada...
1
1

Porque você teria a lógica de implementação e a lógica de negócios misturado.

Algo que quebraria algumas regras de legibilidade e faria com que você perdesse mais tempo procurando onde corrigir ou alterar algumas lógica do que realmente resolvendo o problema

1

Não entendi.

Vamos imaginar que eu tenha essas funções:

function isAllowedOverbooking() {}

function isAllowedSomethingElse() {}

function makeBooking(isAllowedFn) {
    if(isAllowedFn()) {}
}

como isso ficaria misturado? que regras de legibilidades são essas?
e porque separar numa classe essa política? sendo que não está sendo utilizada em nenhum outro lugar?
se tiver um bug no makeBooking, como separar essa política vai ajudar a encontrar o bug? acredito que testes já resolveriam isso.

1

vamos por dúvidas:

como isso ficaria misturado?

Vou usar esse exemplo javascript para demonstrar

Bad pratice

function makeBooking(cargo, voyage) {
    // Lógica de negócios e implementação misturadas
    let maxBooking = voyage.capacity * 1.1;
    if ((voyage.bookedCargoSize + cargo.size) > maxBooking)
        return -1;

    let confirmation = orderConfirmationSequence.next();
    voyage.addCargo(cargo, confirmation);
    return confirmation;
}

Neste exemplo ocorre a mistura da lógica de implementação e da lógica de negócio, o que dificultaria cada parte do código de ser testado. Ao mesmo tempo que fere o principio do S.O.L.I.D que é explicado nesse vídeo do Deschamps.

Outro problema é que provavelmente você queira usar este trecho do código em outras partes do código mas com ele hard-code fica dificil.

Do outro lado temos este código seguindo a good pratice

class OverbookingPolicy {
    constructor(overbookingRate) {
        this.overbookingRate = overbookingRate;
    }

    isAllowed(cargo, voyage) {
        let maxBooking = voyage.capacity * this.overbookingRate;
        return ((voyage.bookedCargoSize + cargo.size) <= maxBooking);
    }
}

function makeBooking(cargo, voyage, policy) {
    if (!policy.isAllowed(cargo, voyage))
        return -1;

    let confirmation = orderConfirmationSequence.next();
    voyage.addCargo(cargo, confirmation);
    return confirmation;
}

Este código já automaticamente deixa o código menor, mais testável e mais reusável que o anterior já que eu consigo reutilizar a classe em outros pontos.


Que regras de legibilidades são essas?

Essas regras são o que chamamos de Clean Code baseado num livro de mesmo nome.

Essas regras de legibilidade tentam tornar o código mais simples de entender para outros programadores, normalmente quando você está escrevendo o seu código tudo parece muito mais fácil de entender do que quando um terceiro vai tentar ler ou mesmo você no futuro.

E acredite, clean code não é a única regra de legibilidade. Existe o D.R.Y que é sigla para Don't repeat Yourself, K.I.S.S que é sigla para Keep It Simple Stupid, Y.A.G.N.I que é sigla para You Ain't Gonna Need It, entre outros ... dependendo claro de projeto a projeto.

Bad Pratice

function clc(a, b, c, d) {
    var res = a * b + c - d;
    return res;
}

var r = clc(2, 3, 4, 1);
console.log(r);

Good Pratice

function calculateResult(multiplier, multiplicand, addend, subtrahend) {
    var result = (multiplier * multiplicand) + addend - subtrahend;
    return result;
}

var finalResult = calculateResult(2, 3, 4, 1);
console.log(finalResult);

e porque separar numa classe essa política? sendo que não está sendo utilizada em nenhum outro lugar?

Quanto se separa uma classe em uma política (no caso de strategy), você aumenta a testabilidade do código e começa a seguir um principio chamado príncipio de responsábilidade única. Ao mesmo tempo que encapsula sua lógica fazendo com que a lógica de negócio fique independente da lógica de implementação.

se tiver um bug no makeBooking, como separar essa política vai ajudar a encontrar o bug? acredito que testes já resolveriam isso.

Você está correto na parte do que testes já resolveriam isso, mas separar a lógica ainda ajuda no quesito de que você simplifica a refatoração e aumenta a testabilidade independente de cada um dos componentes

-2

SOLID é mais genérico do que remédio de farmácia. Esse princípio não ajuda em nada.

Além disso eu dei um exemplo de código pra você me explicar o que tinha de errado mas você usou o seu exemplo anterior.