segunda-feira, 30 de setembro de 2013

Tratamento de erros em java


Tratamento de erros pode parecer tão simples mas são muitos fatores a se considerar, a entrada pode estar errada o dispositivo pode falhar, é responsabilidade do programador certificar-se que o código não trave com esses erros. O tratamento de erro domina completamente muitos códigos fonte, ou seja, se torna praticamente impossível ver oque o código faz devido a tantos tratamentos espalhados pelo código. O tratamento é um recurso importante, mas se ele obscurecer a logica, está errado.

Uma coisa interessante sobre exceções com try-catch-finally é que elas definem um escopo dentro de seu programa, que ao executar a parte do try você declara que aquela execução pode ser cancelada a qualquer momento, e então, continuar no catch. Vejamos um exemplo. Precisamos criar um código que acesse um arquivo e consulte alguns objetos em série. Começamos com um teste de unidade que mostra como capturar uma exceção se o arquivo não existir.

@Test (expected = StorageException.class)
public void retrieveSectionShouldThrowOnInvalidFileName() {
	sectionStore.retrieveSection(“invalid – file”);
}

O teste nos leva a criar esse stub:

public List<recordedgrip> retrieveSection(String sectionName) {
	// retorno fictício até que tenhamos uma implementação real
	return new ArrayList<recordedgrip>();
  Nosso teste falha porque ele não lança uma exceção. Em seguida, mudamos nossa implementação de modo a tentar acessar um arquivo inválido. Essa operação lança uma exceção:

public List<recordedgrip> retrieveSection(String sectionName) {
	try {
		FileInputStream stream = new FileInputStream(sectionName)
	} catch (Exception e) {
	  throw new StorageException(“retrieval error”, e);
	}
	return new ArrayList<recordedgrip>();
}
Nosso teste funciona agora porque capturamos uma exceção. Neste momento podemos refatorar. Podemos reduzir o tipo de execução que capturamos para combinar com aquele que realmente é lançado pelo construtor FileInputStream: FileNotFoundException:

public List<recordedgrip> retrieveSection(String sectionName) {
	try {
		FileInputStream stream = new FileInputStream(sectionName);
		stream.close();
	} catch (FileNotFoundException e) {
	  throw new StorageException(“retrieval error”, e);
	}
	return new ArrayList<recordedgrip>();
}
 Agora que definimos o escopo try-catch, podemos construir o resto da lógica que precisamos, que será adicionada na criação do FileInputStream do close e poderá fingir que nada de errado aconteceu.

Não se esqueça de criar mensagens de erro informando a operação e tipo de falha que ocorreu, pois cada exceção lançada deve fornecer contexto suficiente para determinar a fonte e a localização de um erro.

Existem muitas formas de classificarmos erros seja pela origem: de onde vieram, ou pelo tipo: são falhas do dispositivo ou da rede ou de erros de programação. Geralmente, uma única classe de exceção esta bom para uma parte especifica do código. Use classes diferentes apenas se houver casos em que você queira capturar uma exceção e permitir que outra passe.

Se você retornar um null basicamente esta jogando o problema em cima dos seus chamadores, basta esquecer uma verificação de null para que o programa se perca. Pior do que retornar null é passar null como parâmetro. A menos que esteja trabalhando com uma API que esteja esperando por null.

Por: Bruno Lima.


BIBLIOGRAFIA [Martin]: Agile Software Development: Principles, Patterns, and Practices, Robert C. Martin, Prentice Hall, 2002.

Nenhum comentário:

Postar um comentário