Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 10392] ファイルの概要

コミット

コミットハッシュ: 4bd15ae1b72c5488a06ea1365d0090d76699770c 作者: Brad Fitzpatrick bradfitz@golang.org 日付: Mon Nov 14 13:12:08 2011 -0800 コミットメッセージ: cgi: make test code more readable

このコミットは、Go言語の標準ライブラリnet/http/cgiパッケージのテストコードの可読性を向上させるためのリファクタリングを行っています。

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/4bd15ae1b72c5488a06ea1365d0090d76699770c

元コミット内容

commit 4bd15ae1b72c5488a06ea1365d0090d76699770c
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date:   Mon Nov 14 13:12:08 2011 -0800

    cgi: make test code more readable
    
    R=rsc
    CC=golang-dev
    https://golang.org/cl/5375089
---
 src/pkg/net/http/cgi/host_test.go | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

変更の背景

2011年当時、Go言語の標準ライブラリは急速に発展しており、コードベースの可読性と保守性の向上が重要な課題となっていました。特に、テストコードの可読性は開発者の生産性や新しいコントリビューターの参加しやすさに直結する重要な要素でした。

このコミットは、net/http/cgiパッケージのhost_test.goファイルにおいて、変数の宣言と初期化のパターンを改善することで、テストコードの可読性を向上させることを目的としています。

当時のGoのコードレビューシステムであるGerritを使用しており、https://golang.org/cl/5375089でコードレビューが行われていました。レビュアーはrsc(Rob Pike)で、golang-devメーリングリストにも報告されています。

前提知識の解説

CGI(Common Gateway Interface)とは

CGI(Common Gateway Interface)は、WebサーバーとWebアプリケーションとの間でデータを交換するためのインターフェース仕様です。RFC 3875で定義されており、Webサーバーが外部プログラムを実行し、その結果をクライアントに返すための標準的な方法を提供します。

Go言語でのCGIサポート

Go言語のnet/http/cgiパッケージは、以下の2つの視点からCGIをサポートします:

  1. 子プロセス視点(child.go): CGI子プロセスとして実行されるGoプログラムを支援
  2. ホスト視点(host.go): WebサーバーとしてCGIプロセスを起動・管理

変数宣言とスコープ

Go言語では、変数の宣言方法がいくつかあります:

  • var varName type = value: 明示的な型指定
  • var varName = value: 型推論
  • varName := value: 短縮宣言(関数内のみ)
  • var varName type: ゼロ値での初期化

スコープとライフサイクルの管理は、コードの可読性と保守性に大きく影響します。

技術的詳細

変更前のコード分析

if tries := 0; childRunning() {
    for tries < 15 && childRunning() {
        time.Sleep(50e6 * int64(tries))
        tries++
    }
    if childRunning() {
        t.Fatalf("post-conn.Close, expected child to be gone")
    }
}

この元のコードには以下の問題がありました:

  1. 変数スコープの不明確さ: tries := 0がif文の条件部で宣言されており、変数のスコープが限定的で理解しにくい
  2. 論理構造の複雑さ: if文の条件部での変数宣言と実際の条件チェックが混在
  3. 可読性の低下: 変数の初期化場所と使用場所が分離されている

変更後のコード分析

tries := 0
for tries < 15 && childRunning() {
    time.Sleep(50e6 * int64(tries))
    tries++
}
if childRunning() {
    t.Fatalf("post-conn.Close, expected child to be gone")
}

リファクタリング後のコードの改善点:

  1. 明確な変数宣言: tries変数が関数レベルで明確に宣言されている
  2. シンプルな制御構造: if文とfor文が独立して理解しやすい
  3. 線形な読み取り: コードが上から下に論理的に流れる

コアとなるコードの変更箇所

ファイル: src/pkg/net/http/cgi/host_test.go 関数: TestCopyError 変更行: 22-30行目

変更内容の詳細

-	if tries := 0; childRunning() {
-		for tries < 15 && childRunning() {
-			time.Sleep(50e6 * int64(tries))
-			tries++
-		}
-		if childRunning() {
-			t.Fatalf("post-conn.Close, expected child to be gone")
-		}
-	}
+	tries := 0
+	for tries < 15 && childRunning() {
+		time.Sleep(50e6 * int64(tries))
+		tries++
+	}
+	if childRunning() {
+		t.Fatalf("post-conn.Close, expected child to be gone")
+	}

この変更により、以下の改善が達成されています:

  • 行数の削減: 9行から7行に削減(-2行)
  • 挿入: 7行追加
  • 削除: 8行削除

コアとなるコードの解説

変更の目的と効果

  1. 変数スコープの明確化

    • tries変数が関数レベルで宣言されることで、その用途とライフサイクルが明確になりました
    • 条件文内での変数宣言という、初学者には理解しにくいパターンが排除されました
  2. 制御フローの単純化

    • if文の条件部での変数宣言を排除することで、条件チェックのロジックが明確になりました
    • 3つの独立した文(変数宣言、forループ、if文)として構造化されました
  3. テストの意図の明確化

    • 子プロセスが終了するまで最大15回まで待機する処理が分かりやすくなりました
    • 各ステップが何をしているのかが明確に表現されています

技術的な背景

このテストは、CGI子プロセスの終了を確認するためのものです:

  • childRunning(): 子プロセスが実行中かどうかを判定する関数
  • time.Sleep(50e6 * int64(tries)): 指数バックオフによる待機(マイクロ秒単位)
  • 最大15回まで待機し、それでも子プロセスが終了しない場合はテストを失敗させる

Go言語の慣用句との整合性

この変更は、Go言語の以下の慣用句に従っています:

  • 単純さの原則: 複雑な制御構造よりも単純で読みやすい構造を優先
  • 明確性の原則: 変数の宣言と使用を明確に分離
  • 線形読み取り: コードが上から下に論理的に流れる

関連リンク

参考にした情報源リンク