TL;DR
The shape correct to deal with exceptions that should not occur is not to use them in the first place.
Deducting the scenario
You must have the code something like this:
Produto obterProduto(Loja loja, int numeracaoProduto) {
if (loja == null) throw new LojaNulaException();
...
}
This is a common practice and I have worked in companies that used exception to treat all "exceptional" cases of methods (there was even an excel spreadsheet to generate exceptions automatically, size was the number of classes).
Analyzing the Exceptions
There are at least two reasons why exceptions should not be used:
1. This case is not really exceptional.
Treating nulls is not something that is part of the planned system flows. You would not create a diagram or flowchart to treat each parameter that can be null.
By this I do not mean that the parameters should not be checked, on the contrary. Every good developer checks well the incoming entry.
However, parameter checking is something known as preconditions. Preconditions are requirements that need to be met for a routine to actually perform.
As I will show below, there are other mechanisms to treat these preconditions.
2. This generates an unnecessary "dumbness"
All the unnecessary bureaucracy makes development worse. People don’t like it, you spend more time on things that don’t make sense and you don’t solve any problems.
Specifically in this case, do you really want to create specific exceptions to all the possible problems that your program might have? Why not create an exception for each field that is not populated.
I know many argue that this helps the developer to know that he can’t pass a null but this could simply be documented in the method.
"Ah, but if you don’t follow the documentation?". Well, that’s what tests are for. If a developer can put into production a code that has never been executed, passing an invalid argument, you have a serious problem in the development process.
And at the end of the day, even in difficult cases where you don’t get an obvious mistake like this, it doesn’t make much of a difference if the program stops with a LojaNula
or NullPointer
. The user will not be happy. And with the stack you can easily find the problem in both cases.
Alternatives to treat preconditions or cases that "should not occur"
More general exceptions
There is a reason why the exceptions have a message. They can be reused, but it seems that many architects forget this.
If a parameter has an invalid value, you can do this:
if (tamanho < 0)
throw new IllegalArgumentException("Tamanho deve ser positivo!");
If you want to avoid null parameters, a simple alternative is to launch:
if (parametro == null)
throw new NullPointerException("Parâmetro XYZ não pode ser nulo!");
If by chance you have any special treatment for your null parameters (which I doubt), you can do something like this:
throw new ParametroNulo("XYZ");
And in the exception constructor you only receive the parameter name and generate a more friendly message.
I’m always amazed to see how people forget that they can extend Exception
and add attributes and arguments to the constructor.
Assertions
Another way to treat unexpected behavior is through assertions.
The point here is to draw a line between known errors and the unexpected.
- An expected problem can be easily dealt with with with an exception. You know that that is a situation that has a legitimate probability of occurring. Still check if there is no longer an exception made for this.
- An unexpected problem does not need an exception, you can simply make an assertion like: this should never occur, but if by chance it does occur, throw an error.
Java has good assertion support and they basically work as unverified exceptions.
Guava is a library known to reinforce good practices. One of them is to use assertions to treat preconditions.
Example:
checkArgument(tamanho > 0, "Tamanho deve ser positivo: %s", count);
checkNotNull(loja, "Loja deve ser informada");
The above examples should use import static
to import class methods Preconditions
and will issue exceptions in case the check fails.
This makes your code easier to read and requires less typing, decreasing the tangle of if
s if there are many cases
Considerations
Every project should draw the line between exceptional treatment and preconditions.
Hundreds and thousands of exceptions do not make the development better, so I suggest forgetting the old and known bad practice of creating standard exceptions for each entity of your CRUD (sometimes I think people do this just to feel in control or to get the impression that they are having more productivity).
In fact, in all cases where you have virtually generated code, maybe even a code generator, it’s best to think and rethink ten times if it wouldn’t be better to create a unified code that can be reused.
And if you’ve fallen into a trap like this and are now having trouble maintaining code, get together with the team and create a mini-code cleaning project. In a project like the one mentioned in the question, I would spend a day or two removing all the specific exceptions and replacing them with more generic ones and perhaps assertions. If you have many cases, a replacement with Regex can do much of the job, if not all.
You can’t quite understand what you want. Perhaps the problem is already in the so-called methods. Perhaps these exceptions should not even exist. You say you have a build error, but you don’t say which one. Put a
throw e
within thecatch
is the last thing you should do. This way of "treating" exceptions is the worst possible. The only guarantee this gives is that problems will occur. Put more information and I try to give an answer.– Maniero