isyumi_netブログ

isyumi_netがプログラミングのこととかを書くブログ

再代入は初期化の直後に限ろう

下のコードのように一度変数に値を代入した後に別の値を代入することを再代入という。

例:

 

 

func main() {
i := hoge()
i = "iii"
log.Print(i)
}

まず、極力再代入を減らすように心がけよう。再代入を減らすとバグが減るしデバッグの手間も減る。このブログで何度も言ってきたことだが、変数はとにかく早く値を確定させよう。下のコードは悪い例だ。関数の上のほうで定義された途中で書き換えられていることに気づいただろうか。

 

func main() {
i := hoge()
a = 3 * 7
b = a % 2
c := fuga(i)
if c == 0 {
a = functionA(d * c)
i = "iii"
}
for x := 0; x < 10; x ++ {
piyo(len(i) * x)
}
log.Print(i)
}

 このようなコードはiの値はなんだっけと考えてしまう。変数を最初に宣言してから最後に代入するまでの間は脳のワーキングメモリを消耗しながらコードを読んでいると考えてほしい。逆に、その間の距離を極力短くすることができれば疲れないコードになったといえる。さらに、変数の再代入を一切排除できればそれだけいいコードといえる。下はいい例だ。

func main() {

i := hoge()
if c == 0 {
i = "iii"
}
// この時点でiの値は確定している

fuga(i)
a = 3 * 7
b = a % 2
if c == 0 {
a = functionA(b * c)
}
for x := 0; x < 10; x ++ {
piyo(len(i) * x)
}
log.Print(i)
}
 

上のコードのように最初にiが宣言されてから即座に再代入をしていればあまり心が消耗することがない。このルールを適用すべき場面として二つあげたい。

  • デフォルト値を入れる
  • for文で計算する

一つ目のデフォルト値だが、関数を実行して戻り値を得るがもしエラーになったらデフォルト値を入れるというコードを書くことは多い。その場合も

i, err := hoge()
if err != nil {
i = ""
}

 

 のように即再代入をすることを心がけよう。決して隙間にほかの処理を挟まないようにしてほしい。

i, err := hoge()
// ここに処理を一切書かない
if err != nil {
// ここにデフォルト値を入れるために必要な処理以外を一切書かない
i = ""
// ここに処理を一切書かない
}

 

二つ目のfor文だが、for文で変数の値を順番に書き換えることは多い。その場合も、書き換える専用のfor文を用意しよう。

i := 0
for x := 0 ; x < 100 ; x ++{
i += x
}

 

このようにこの四行以外に余計な処理が一切なければコードを読んだ人は「ああ、この四行一固まりでiの値が確定するんだ」と理解できる。これも同じようにコードの隙間に別の処理を差し込まないようにしたい。

i := 0
// ここに処理を書かない
for x := 0; x < 100; x ++ {
// ここにiを上書きするために必要な処理以外を書かない
i += x
// ここに処理を書かない
}

 ぜひ心掛けてほしい。