Introdução

As assertivas foram incorporadas no Java a partir da versão 1.4 sendo portanto uma palavra reservada do Java. As assertivas surgiram com o intuito de ajudar o programador nos testes em tempo de desenvolvimento evitando assim que o programador utilize outros meios como captura de exceções que podem nunca ocorrer, uso de escritas em console que podem ser complicados de capturar em alguns ambientes. Esses meios alternativos de depuração ainda exigem que todo o código (tanto usando a manipulação de exceções como a escritas em consoles) seja totalmente apagado após o teste ser concluído, causando menos produtividade, mais lixos espalhados pelo código e maior probabilidade a falhas.

Visão Geral

Para dar uma visão mais geral e concreta aos leitores, aqui será utilizado um exemplo bastante simples, mas que ajuda a ilustrar a ideia das asserções. Imagine que o analista especificou que uma determinada funcionalidade nunca deveria receber um número negativo, sendo assim apenas números maiores ou iguais a zero. Dessa forma, dado a especificação o programador implementou um método que siga esse requisito e além disso o programador fez algumas suposições no código para certificar que tudo está funcionando perfeitamente conforme foi especificado. Portanto, ter-se-ia o código abaixo:

Listagem 1: Exemplo de método testado em desenvolvimento


    private void recebeDoacao(int quantidade) {

        if (quantidade >= 0) {
            //Faz alguma coisa
        } else { //Quantidade deve ser menor que zero
                 //Atenção, nunca devemos chegar neste código!
            System.out.println(" Atenção! Número negativo chegou aqui!");
        }
     }

O leitor consegue identificar o problema com o código acima? Imagine se esse código fosse testado e executado com perfeição, isso indicaria que o código que precede esse método está correto, ou seja, ele verifica de maneira correta se o programa não chamará esse código acima passando um número negativo. Agora que o programador certificou-se de que o código está correto deve-se tirar todos os testes utilizados no método acima, compilar novamente e mandar para produção. Pode-se observar o desgaste nesse processo. Agora imagine se tivesse mais de 40 testes na mesma funcionalidade ou na classe em questão.

As assertivas permitem ao desenvolvedor testar as suposições durante o desenvolvimento, porém, seu código efetivamente desaparece quando colocado em produção (ou quando o programa é distribuído), não deixando portanto nenhum código de depuração ou que precise ser removido. Agora pode-se novamente reescrever o código acima, porém utilizando essa nova funcionalidade incorporada no Java 1.4 e utilizada de maneira muito mais produtiva, limpa e elegante:

Listagem 2: Exemplo de método testado em desenvolvimento com assertivas


    private void recebeDoacao(int quantidade) {

        assert(quantidade >= 0) //Caso retorne false lança uma exceção
                                //AssertionError

        //Faz alguma coisa, pois a quantidade é maior ou igual a zero

     }

Nota-se como o código fico muito mais limpo, claro e menor utilizando as assertivas. As assertivas, a menos que sejam postas em ação como será visto mais adiante, serão executadas como se o código fosse escrito dessa maneira:

Listagem 3: Exemplo de método em produção


    private void recebeDoacao(int quantidade) {

        //Faz alguma coisa, pois a quantidade é maior ou igual a zero

     }

Veja que no código acima as assertivas desaparecem.

Portanto, pode-se concluir que as assertivas levam em conta que a condição é sempre verdadeira. Se a condição for verdadeira o código prossegue com a execução. No entanto, se a condição for falsa uma exceção (Erro) AssertionError é lançada de modo que o programador tenha que corrigir a falha.

Uma dica muito importante é: Exceções de assertivas nunca devem ser tratadas. Lembre-se disso, nunca capture ou trate essas exceções. Assertivas servem única e exclusivamente para alertar você de um problema que não deveria ocorrer e ocorreu.

Tipos de Assertivas

Existem dois tipos de assertivas. A primeira, bastante simples, foi vista acima. No entanto, existe ainda uma outra assertiva que adiciona uma segunda expressão que é separada da primeira por dois pontos (:). Esse segundo parâmetro é utilizado para acrescentar mais informações ao rastreamento da pilha. Ambas as versões lançam a exceção AssertionError, porém na segunda versão o desenvolvedor terá um pouco mais de ajuda na depuração, enquanto na primeira apenas há um aviso que a suposição é falsa.

Teremos então na segunda versão das assertivas uma String sendo passado ao segundo parâmetro que irá gerar uma mensagem que será exibida no rastreamento da pilha para fornecer mais algumas informações de depuração.

Implementação

Segue abaixo um exemplo utilizando a segunda versão das assetivas dentro de um sistema real.

Listagem 1: Exemplo de assertivas e exceções em Java


	public Collection lista(TratamentoED tratamentoED) throws SQLException, Exception {

		assert(tratamento ED != null) : “Recebeu um tratamentoED nulo”;
		
		ResultSet rs = null;

		try {
			ArrayList list = null;

			String sqlQuery = montaSql(tratamentoED);

			rs = Query.getResultSet("SistemaDS", sqlQuery, 101);

			list = new ArrayList();
			while (rs.next()) {
				TratamentoED tratamentoEDVolta = new TratamentoED();
				tratamentoEDVolta.setNroIntTrat(rs.getInt("NRO_INT_TRAT"));
				tratamentoEDVolta.getPaciente().setNroIntPac(rs.getInt("NRO_INT_PAC"));
				tratamentoEDVolta.getPaciente().setNomePac(rs.getString("NOME_PAC"));
				tratamentoEDVolta.getMedBase().setNroIntMedBase(rs.getInt("NRO_INT_MED_BASE"));
				tratamentoEDVolta.getMedBase().setTpMedBase(rs.getString("TP_MED_BASE"));
				tratamentoEDVolta.getMedBase().setCodMedBase(rs.getInt("COD_MED_BASE"));

				list.add(tratamentoEDVolta);
			}



			return list;
		} catch (SQLException sqlExc) {
			//lança uma exceção
		} catch (Exception exc) {
			//lança uma exceção
		} finally {
			if (!Query.liberaConexao(rs)) {
				Log.fatal("não foi possível liberar a conexão", null);
			}
		}
	}

Observe acima o uso da assertiva para uma simples conferência. Plode-se notar que no inicio do método há uma assertiva atestando se o que foi passado não está nulo. Essa assertiva indica que o desenvolvedor deste método espera que o objeto que está sendo passado para este método não esteja nulo. Também observe o uso das exceções para tratar outros problemas do método, problemas diferentes das assertivas.

Mais uma dica que pode ser dada aqui é que você não precisa retirar as assertivas do seu código. Inclusive, alguns programadores deixam as assertivas para que o desenvolvedor que está mexendo num determinado método ou classe saiba o que esse método deve ou não aceitar. Isso se assemelha bastante com a idéia do Design By Contract que será tratado em outro artigo.

Ativando Assertivas

Agora que as assertivas já foram colocadas no código estamos prontos para utiliza-las. Para ativar as assertivas no tempo de execução usa-se o comando java -ea pacote.Classe ou ainda java -enableassertions pacote.Classe

Muito simples, o comando acima ativa as assertivas, provavelmente o desenvolvedor fará isso em ambiente de desenvolvimento, quando estiver testando o código.

No comando abaixo as assertivas serão desativadas:
java -da pacote.Classe ou ainda java -disableassertions pacote.Classe

Lembrando que as assertivas estão desativadas por padrão.

As vezes é útil também desativar as assertivas para uma classe específica e manter ativadas para as outras classes, nesse caso usa-se o comando abaixo onde a classe chamada Classe terá a sua assertiva desativada: java -ea -da:pacote.Classe

Outra situação útil seria ativar as assertivas num determinado pacote e seus subpacotes: java -ea:pacote

Caso esteja utilizando o Eclipse clique com o botão direito do mouse na área do projeto e vá em Run Configuration. Por fim coloque o argumento como indicado na tela abaixo:

Exemplo de como habilitar assertivas no Eclipse

Figura 1: Exemplo de como habilitar assertivas no Eclipse

Basta agora dar um Run e sua assertiva está habilitada.

Boas Práticas

Seguem algumas boas práticas para o bom uso das assertivas:

  • Não use assertivas para validar argumentos de um método public: Use exceções para validar métodos públicos, lembre-se que um método public é chamado por métodos de diversos lugares que você não tem controle, afinal ele é público, ou seja, visível por todos. Assertivas podem ou não estar ativadas, assim elas não garantem que os parâmetros de um método público serão validados ou restringidos por elas, normalmente se quer uma garantia maior para esses métodos.
  • Use assertivas para validar argumentos de um método privado: Agora se tem um controle maior de quem chama este método, portanto assertivas são bastante utilizadas nesses métodos afim de testá-los validando a sua lógica.

Muitos desenvolvedores perguntam quando usar exceções e quando usar assertivas. Como uma última dica use exceções sempre que você estiver interando com o usuário ou quando você precisa recuperar o sistema de uma situação excepcional que ele se encontra devido alguma ação incorreta do usuário. Asserções são também utilizadas para checagem de pré-condições, pós-condições e invariantes, para prover um relatório para a sua equipe sobre um determinado método, além das dicas já mencionadas no artigo.

Conclusão

Neste artigo procurou-se demonstrar alguns conceitos, implementações e boas práticas de como funciona e como utilizar a assertivas. Infelizmente ainda são poucos os desenvolvedores que conhecem as assertivas, conhecendo-as você pode ganhar bastante em produtividade, rastreabilidade, depuração e clareza de código. Alguns desenvolvedores já explicitaram o seu ganho usando essa funcionalidade vindo do Java 1.4. Se tiverem opiniões, sugestões ou casos de sucesso utilizando essa funcionalidade não deixe de me escrever. Ficarei no aguardo.

Bibliografia

  • Katherine Sierra, Bert Bates, SCJP Sun Certified Programmer for Java 6 Exam 310-065. McGraw-Hill Osborne Media; 1 edition (2008).