Controversy
This generates a bit of controversy because there are those who defend one thing and others who think the opposite. No one has proved what is right, so everyone only has opinions. Some are more grounded than others. Depending on who reads and the prior knowledge of each, who reads will believe one thing or another. I myself have spoken of this in several questions on the subject:
Basically the question has already been answered.
The summary of all this is that there is a school that says that exception is the solution to everything that wasn’t quite what you wanted, or in other words "cure cancer exception" and you should do exactly what you did. In fact in Java there is a tendency to do this, the whole API adopts this.
Java has modernized
But more recently Java has stopped being so dogmatic, repeating the mantra that language is object-oriented, and for the good of all has evolved into a more functional style. I think it’s fantastic that a lot of the community has adopted this style. And he preaches less the use of exceptions. For example they created the Optional
to use an error code instead of throwing an exception when the error is expected.
So modern Java code would not do what was done and adopt an error code that could be better than a checked exception. You inform the inadequacy of what one tried to do so without making a mess in the code, without a huge exception weight.
Java started to adopt the school that preaches that exceptions should not be used for flow control, that they should only be released when something happened that shouldn’t happen, ie programming errors, and environment failures.
Your code is the old way of doing something because it is expected that there is no balance in some situations, it is not a mistake that the programmer committed and it is not something that the environment caused, it is an expected business rule.
Your case
Congratulations for having created a specific exception to this, in general people do not create. But there is still another mistake that almost everyone makes. It basically uses the same structure of Exception
and sends a message that may not be suitable for use in a given situation.
The right thing to do when creating a new exception is to try to do something that only she has. The exception already indicates what the problem was and in each context you capture it may be that the message is different. Perhaps the most appropriate is just to aggregate the balance (not as a message, have a field for it) in the exception for the consumer to use it in a personalized message. But I’m not saying it’s wrong, it depends on the requirement, it may be that neither the balance should put, for security and privacy. Perhaps the value of the loot is in case it is included.
See more in Create more specific or more generic custom exceptions?.
But there’s another problem, when it comes to capturing the exception, it took the most generic possible, and that doesn’t make sense. I will not go into detail because I have answered in: There is some drawback in always catching Exception and not something more specific?. If you get a memory error you’re doing something you can’t imagine.
I don’t like checked exceptions, in the way Java has implemented, in complex systems a lot of wrong things can happen, but if you are going to follow this school of abuse of exceptions, then your exception should be checked since you cannot ignore the indication of failure (at least this is my interpretation for the problem).
And this gives a clue that exception is a difficult mechanism to use. Almost everyone who posts something here is making mistakes with it and in general make the same mistake every time.
Some say your code is perfect (rare), some say you were only wrong to capture Exception
instead of SaldoInsuficienteException
, and also those who will say that you were also wrong to make the exception not checked, and finally those who will say that you should not have used exception.
At my school, which is followed by some of the best programmers in the world, having no balance is not a failure, it is an expected situation that happens and is part of the business rule, and today Java has the right way to treat this.
Workaround
I don’t usually use Java and mainly the new features I don’t have domain, but it would be more or less this:
import java.util.*;
class Conta {
public double saldo;
}
class ContaCorrente extends Conta {
public void deposita(double valor) {
super.saldo += (valor);
}
public Optional<Double> saca(double valor) {
if (super.saldo < valor) return Optional.empty();
super.saldo += (valor - 0.10);
return Optional.of(valor);
}
}
public class Main {
public static void main(String[] args) {
ContaCorrente conta = new ContaCorrente();
conta.deposita(200);
var sacado = conta.saca(300);
if (sacado.isEmpty()) System.out.println("O saldo nao eh suficiente para saque");
else System.out.println("A operação foi concluída e foi sacado " + sacado.get());
}
}
Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.
You can do it even more functionally, I think it’s good not to change the way you learned too much. Do not take as the perfect code, this implementation can be improved.
It may be that the requirement indicates that you can withdraw the available balance instead of denying the entire drawing. This works with this mechanism, except it has like, but it gets weird because it will have given exception, but it worked and would have to carry the value that worked out within the exception. Even if you don’t need to do this in this case, in another you may need it. Using the right mechanism is consistent.
But I have my doubts whether you should do so. Maybe it’s just a matter of returning true or false if the operation didn’t work out, and that Java always had, would look something like this:
import java.util.*;
class Conta {
public double saldo;
}
class ContaCorrente extends Conta {
public void deposita(double valor) {
super.saldo += (valor);
}
public boolean saca(double valor) {
if (super.saldo < valor) return false;
super.saldo += (valor - 0.10);
return true;
}
}
public class Main {
public static void main(String[] args) {
ContaCorrente conta = new ContaCorrente();
conta.deposita(200);
if (!conta.saca(300)) System.out.println("O saldo nao eh suficiente para saque");
}
}
Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.
Attention that there is still another error in the code. And there are other conceptual errors in it.
Very good! very good explanation. thanks.
– André Martins