Item 57 Minimize the scope of local variables

Premise

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.

[Roughly]

Minimizing the scope of local variables improves the readability and maintainability of your code and reduces the chance of making mistakes.

[Bad example 1]

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.

[Let's write this]

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.

[Bad example 2]

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.

[Let's write this]

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.

[Bad example 3]

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.

[Let's write this]

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.

[Summary]

  1. Declare a local variable the first time it is used.
  2. When declaring a local variable, basically the initial value should be included.
  3. Use a for loop rather than a while (only if you don't need the loop variable after the loop ends).
  4. Make the method smaller to make it more focused.

Recommended Posts

Item 57 Minimize the scope of local variables
Item 57: Minimize the scope of local variables
[Basic knowledge of Java] Scope of variables
[Ruby] Display the contents of variables
Item 72: Favor the use of standard exceptions
Item 63: Beware the performance of string concatenation
[Rails] Check the instance variables and local variables of the file you are browsing
Item 44: Favor the use of standard functional interfaces
Variables / scope (ruby)
Talking about the merits of database bind variables ((1) Introduction)
[Introduction to Java] Variable scope (scope, local variables, instance variables, static variables)
SSL in the local environment of Docker / Rails / puma
I want to be aware of the contents of variables!
Judgment of the calendar
The world of clara-rules (4)
The world of clara-rules (1)
The world of clara-rules (3)
Features of Static variables
Glossary: Member Variables / Local Variables
The world of clara-rules (5)
The idea of quicksort
Master the [Rails] scope!
The idea of jQuery
JSP-About the MVC model of Servlet, redirect forward, and scope