Jails – módulo Throwable

Fala povo!

Demorei pra postar, mas estou aí. Bom, este post é uma sequência, ele é uma continuação do anterior que trata sobre tratamento de erros no javascript.

Uma vantagem de trabalhar com algum framework é a previsibilidade que ele te dá, sendo consistente nos seus próprios padrões.

Isso te dá uma visão macro da aplicação sem ter de pensar muito e te permite criar novas soluções de forma mais rápida e objetiva. Sendo assim, com o Jails como framework,  criei um módulo bem básico e ainda beta, chamado Throwable.

Propósitos

A idéia geral deste módulo é garantir que se uma controller Jails lançar alguma excessão em produção, este irá garantir que as outras controllers continuem funcionando.

Existem outras finalidades também. O módulo Throwable também fornece uma api que facilite encapsular alguma função em try/catch caso esta função tenha algum risco de falhar, que não dependa da nossa lógica, algo externo ao nosso escopo.

O terceiro propósito é desacoplar da lógica da aplicação, detalhes de implementação no caso de algo falhar. Isso permite que sua controller fique realmente fácil de entender mais compacta e concisa.

Configuração

Para habilitar no projeto é bem simples, basta usá-lo como middleware, carregando como dependência do projeto.

require.config({
    baseUrl :'js/',
    deps    :['jails', 'throwable', global.page],
    paths   :{
        jails       :'//rawgit.com/jails-org/Jails/master/source/jails.min',
        throwable   :'//rawgit.com/jails-org/Modules/throwable/throwable'
    },
    callback :function( jails, throwable ){
        throwable({ debug :false });
        //Use true for debug
        jails.start();
    }
});

Ele simplesmente implementará o try/catch na classe controller e no método .init() dela. Só esta linha já garante que um módulo não quebre outro.

O Throwable vai fazer um bypass nos eventos de erro do browser, ou seja, você não irá mais receber erros no console, a não ser que os erros sejam de sintaxe. Erros de sintaxe não são possíveis de tratar, estou considerando que no seu processo de build, você já barre qualquer erro de sintáxe do código =).

Capturando eventos de erros globais

Como não receberá mais o alerta no console, o módulo Throwable dispara eventos dos erros capturados. Você pode dessa forma dar um console log, ou fazer uma lógica um pouco mais automatizada para mostrar os erros em produção.

define([
	'jails'
], function( jails ){

	jails.controller('minha-controller', function( html, data ){

		this.init = function(){
			this.subscribe('throwable', log);
			undefinedMethod();
		};

		function log(err){
			console.log('Erro!', err);
		}
	});
});

No caso acima, a controller se inscreve no evento throwable , que é o evento global para qualquer tipo de erro. O código vai levantar uma exceção porque existe uma função não definida sendo chamada.

Capturando erros em uma controller

É possível capturar erros lançados de uma determinada controller. Isso permite que deixemos a lógica de tratamento de erro fora da nossa controller. No script acima não fica claro a vantagem do Throwable, mas perceba a vantagem disso no script abaixo:

minha-controller.error.js

define(['jails'], function( jails ){

    jails.subscribe('throwable@controller:test', function( error ){

        switch( error.message ){

            case 'link:no-title':
                console.error('No attribute [title] was found for that link');
            break;

            default : console.error('Uncaught Error', error);
        }
    });
});

Esse é o arquivo de erro externo de tratamento de erro da controller. Ele consegue capturar os erros que vem de uma controller específica, fazendo um .subscribe em : throwable@controller:nome-da-controller.

No caso acima ele possui um comportamento padrão caso não consiga tratar o erro, apenas logando no console. Existe um erro que ele está tratando que é um link sem title. Mais adiante vou mostrar um método útil para encapsular uma função específica em um try/catch.

O método .try()

Por padrão, o throwable trata no try/catch apenas situações criticas, ou seja, a execução do mixin e a inicialização dele através do método init(). Isso porque não seria nada performático aplicar o try/catch em todos os métodos.

Então cabe a você definir onde são os pontos críticos específicos da sua aplicação. Como identificar estes pontos? Imagine uma função de soma, nunca haverá excessões, apenas erros de cálculo.

Agora numa divisão, se está recebendo duas entradas, o divisor e o dividendo, dependendo das entradas sua função poderia levantar uma excessão numa possível divisão por zero. Ou seja, você não sabe quais dados serão inputados, fatores externos à sua função podem fazer com que ela levante uma exception.

Identificado o ponto que pode levantar a exception, você pode então usar o .try() para poder encapsular um método e tratar em outro arquivo a excessão.

define([
    'jails',
    'errors/minha-controller.error'
], function( jails ){

    jails.controller('minha-controller', function( html, data ){

        this.init = function(){
            this.on('click', 'a', this.try( message ));
        };

        function message(){

            var title = this.title;

            if( title )
                alert( 'Hey, it works! The title is :' + title );

            else throw 'link:no-title';
        }
    });
});

Um exemplo bem besta e quase que inútil, mas apenas para perceber que em determinada situação, você apenas quer dizer na sua controller que aquele ponto pode lançar um erro, e o tratamento deste erro não importa para a controller.

O módulo Throwable estende a classe controller, por isso no código acima você percebe o uso de this.try(), que não existe nativamente nas controllers do Jails.

A forma como organiza os erros é por sua conta, dependendo do projeto podem existir erros recorrentes que podem ser resolvidos ou podem ser tratados de uma mesma forma. Nesta situação seria interessante criar um módulo de tratamento de erro que poderá ser reutilizado em várias controllers.

Um erro muito comum é o erro de resposta ajax. Você poderia criar um padrão para os tipos de erros, e mostrar um feedback, tanto na controller do seu módulo, ou criar uma controller de notificação como temos nos sistemas operacionais por exemplo, para avisar ao usuário de que tal operação falhou.

Este é o tipo de erro que terá de tratar em vários módulos, em várias telas, faz todo sentido do mundo tratá-los de forma independente, e deixar a lógica da sua controller apenas para as regras de negócio, para as regras da sua aplicação. Assim, qualquer problema de lógica pode ser facilmente detectado, porque sua lógica de tratamento de erros e outras coisas não irão atrapalhá-lo ao visualizar sua controller.

O módulo Throwable está pronto e documentado no repositório oficial de módulos do Jails.

https://github.com/jails-org/Modules/tree/master/throwable

Se não for útil do jeito que é, tomara que sirva pelo menos para te dar uma idéia diferente e ajudar a pensar em uma forma de como abstrai os erros em suas aplicações =).

É isso, um grande abraço.

Anúncios

2 comentários sobre “Jails – módulo Throwable

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s