A newcomer with about a month of java development is writing to output what he learned by reading Effective Java. I am aiming for an article that is as easy to understand as possible even for beginners, by breaking down my interpretation and explaining it.
Minimizing the scope of local variables improves the readability and maintainability of your code and reduces the chance of making mistakes.
badPractice1
String hoge = "hoge";
int fuga;
double piyo = 0.1;
doSomething(hoge);
... //Some processing
doSomething(fuga); //What is the fuga type? What is the initial value?
... //Some processing
{
doSomething(piyo) //What is the type of piyo? What is the initial value?
}
—— Distracts the reader's attention.
-> I'm trying to understand what I'm doing, but I'm using my brain's resources to remember variables.
—— Readers have difficulty remembering types and initial values when variables are used.
--Wide scope.
-> The wider the scope, the more likely it is to be used in unintended places, with disastrous consequences.
goodPractice1
String hoge = "hoge";
doSomething(hoge);
... //Some processing
int fuga = 10;
doSomething(fuga);
... //Some processing
double piyo = 0.1;
{
doSomething(piyo)
}
--Declare the first time a local variable is used.
-> There is no need to memorize variable types and initial values, and the reader can concentrate on understanding the process.
--Reduce the scope.
-> fuga and piyo have a narrower scope forward, which reduces the possibility of being used incorrectly.
--Local variables basically include initial values.
-> If there is no information to reasonably initialize the variable, it is not the time to initialize it, so it should be postponed until the information is obtained (except for the exception by the try-catch block below).
exception
Hoge hoge = null;
try {
hoge = hogeHoge();
} catch (HogeException e) {
e.hoge();
}
hoge.doSomething();
-> In such a case, rational initialization is not possible.
badPractice2
Iterator<Hoge> i = hoge.iterator();
while(i.hasNext()) {
doSomething(i.next());
}
Iterator<Hoge> i2 = hoge2.iterator();
while(i.hasNext()) { //There is a bug
doSomething(i2.next());
}
--The scope of local variables is wide, which causes bugs.
-> Since there is no problem with the code itself, it compiles normally and it is difficult to notice mistakes.
goodPractice2
for (Iteratro<Hoge> i = hoge.iterator(); i.hasNext()) {
doSomething(i.next());
}
//Compile error-i not found
for (Iteratro<Hoge> i2 = hoge2.iterator(); i.hasNext()) {
doSomething(i2.next());
}
--You can immediately notice the error.
-> Since the scopes of i and i2 are contained in the for block respectively, a compile error will occur if you try to refer to a variable outside the scope.
--No need to avoid duplicate variable names. An example is shown below.
goodPractice3
for (Iteratro<Hoge> i = hoge.iterator(); i.hasNext()) {
doSomething(i.next());
}
for (Iteratro<Hoge> i = hoge2.iterator(); i.hasNext()) {
doSomething(i.next());
}
-> It has a very sophisticated writing style and is easier to read than while.
badPractice4
public int calcTotalAmount(int price) {
double taxRate = 1.1;
... //Processing to calculate the price including tax
... //Processing to calculate shipping costs
int totalAmount = taxIncludedPrice + shippingFee;
return totalAmount;
}
--A local variable that has nothing to do with the process exists in the scope.
A local variable called-> taxRate exists within the scope of the irrelevant process of calculating shipping costs.
goodPractice4
public int calcTotalAmount(int price) {
int taxIncludedPrice = calcTaxIncludedPrice(price);
int shippingFee = calcShippingFee(price);
return taxIncludedPrice + shippingFee;
}
public int calcTaxIncludedPrice(int price) {
double taxRate = 1.1;
... //Processing to calculate the price including tax
return taxIncludedPrice ;
}
public int calcShippingFee(int price) {
... //Processing to calculate shipping costs
return shippingFee;
}
-> Since it does not include unnecessary local variables in the scope, the possibility of bugs can be reduced.