isolando_resposabilidade - VWJavascript/Alurapic GitHub Wiki

Isolando responsabilidades

Nossa aplicação consegue incluir e alterar, porém nossa solução ainda não está cem porcento. Veja que tanto para um inclusão quanto para alteração estamos navegando para ListagemComponent. No entanto, queremos que o usuário continue em CadastroComponent caso ele tenha feito uma inclusão permitindo assim que ele cadastre mais fotos.

Outro ponto é que a mensagem de inclusão ou alteração são definidas em CadastroComponent. Se usarmos FotoService em outro local da nossa aplicação teremos que repetir as mesmas mensagens.

Isolando ainda mais reponsabilidades

Uma solução é fazer com que o método cadastra de FotoService passse a retornar um objeto que contenha duas propriedades para guardar a mensagem e e um boleano para indicar se foi inclusão ou não. Hoje nosso método retorna um Observable, com a nossa alteração ele passará a retorna um Observable:

// alurapic/client/app/foto/foto.service.ts 

// código anterior omitido 

cadastra(foto: FotoComponent): Observable<Object> {

    if(foto._id) {
        return this.http.put(this.url + '/' + foto._id, JSON.stringify(foto), 
        { headers: this.headers })
        .map(() => ({mensagem: 'Foto alterada com sucesso', inclusao: false}));

    } else {
        return this.http.post(this.url, JSON.stringify(foto), 
            { headers: this.headers })
            .map(() => ({mensagem: 'Foto incluída com sucesso', inclusao: true})); 
    }   
}

Tanto na alteração quando na inclusão a função map agora retorna um objeto com as propriedades mensagem e inclusao. O primeiro contém a mensagem da operação e o segundo true se for uma inclusão e false se for uma alteração. Você deve ter achado um tanto estranho envolver nosso objeto entre parênteses, mas essa é uma exigência quando retornamos em uma única linha um objeto {}. Se não envolvermos com parênteses nossa arrow function confundirá as chaves do objeto com a chave de um bloco resultando em um erro de compilação.

Agora, vamos alterar nosso CadastroComponent para pegar carona no novo tipo de retorno:

// alurapic/client/app/cadastro/cadastro.component.ts

// código anterior omitido 

cadastrar(event) {

    event.preventDefault();
    console.log(this.foto);

    this.service
        .cadastra(this.foto)
        .subscribe(res => {
            this.mensagem = res.mensagem;
            this.foto = new FotoComponent();
            if(!res.inclusao) this.router.navigate(['']);
        }, erro => {
            console.log(erro);
            this.mensagem = 'Não foi possível savar a foto';
        });
}

Um pouco mais sobre tipagem e o tipo any Temos um erro de compilação no método cadastra de CadastroComponent. O TypeScript é bem enfático e nos diz que res.mensagem e res.inclusao não existem para o tipo Object. Realmente, o tipo Object não possui qualquer um desses métodos. Como resolver?

Em TypeScript podemos usar o tipo any para indicar tipo retornado é qualquer tipo. Na verdade ele foi adicionados aos tipos deste superset do ES6 para possibilitar sua introdução em sistema legados, quando não há uma maneira clara de especificar o tipo. Vamos alterar o tipo de retorno de cadastro em FotoService:

// alurapic/client/app/foto/foto.service.ts 

// código anterior omitido 

    cadastra(foto: FotoComponent): Observable<any> {

       // código omitido  
    }

Com essa alteração nosso código compila perfeitamente, no entanto não temos recurso de autocomplete muito menos checagem de tipos.

⚠️ **GitHub.com Fallback** ⚠️