[インデックス 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をサポートします:
- 子プロセス視点(child.go): CGI子プロセスとして実行されるGoプログラムを支援
- ホスト視点(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")
}
}
この元のコードには以下の問題がありました:
- 変数スコープの不明確さ:
tries := 0
がif文の条件部で宣言されており、変数のスコープが限定的で理解しにくい - 論理構造の複雑さ: if文の条件部での変数宣言と実際の条件チェックが混在
- 可読性の低下: 変数の初期化場所と使用場所が分離されている
変更後のコード分析
tries := 0
for tries < 15 && childRunning() {
time.Sleep(50e6 * int64(tries))
tries++
}
if childRunning() {
t.Fatalf("post-conn.Close, expected child to be gone")
}
リファクタリング後のコードの改善点:
- 明確な変数宣言:
tries
変数が関数レベルで明確に宣言されている - シンプルな制御構造: if文とfor文が独立して理解しやすい
- 線形な読み取り: コードが上から下に論理的に流れる
コアとなるコードの変更箇所
ファイル: 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行削除
コアとなるコードの解説
変更の目的と効果
-
変数スコープの明確化
tries
変数が関数レベルで宣言されることで、その用途とライフサイクルが明確になりました- 条件文内での変数宣言という、初学者には理解しにくいパターンが排除されました
-
制御フローの単純化
- if文の条件部での変数宣言を排除することで、条件チェックのロジックが明確になりました
- 3つの独立した文(変数宣言、forループ、if文)として構造化されました
-
テストの意図の明確化
- 子プロセスが終了するまで最大15回まで待機する処理が分かりやすくなりました
- 各ステップが何をしているのかが明確に表現されています
技術的な背景
このテストは、CGI子プロセスの終了を確認するためのものです:
childRunning()
: 子プロセスが実行中かどうかを判定する関数time.Sleep(50e6 * int64(tries))
: 指数バックオフによる待機(マイクロ秒単位)- 最大15回まで待機し、それでも子プロセスが終了しない場合はテストを失敗させる
Go言語の慣用句との整合性
この変更は、Go言語の以下の慣用句に従っています:
- 単純さの原則: 複雑な制御構造よりも単純で読みやすい構造を優先
- 明確性の原則: 変数の宣言と使用を明確に分離
- 線形読み取り: コードが上から下に論理的に流れる
関連リンク
- RFC 3875 - The Common Gateway Interface (CGI) Version 1.1
- Go net/http/cgi パッケージドキュメント
- Go Language Specification - Variable declarations
- Go Code Review Comments
- Effective Go - Control structures