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

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

このコミットは、Go言語の標準ライブラリstringsパッケージ内のreader.goファイルに対する変更です。具体的には、Reader型のUnreadByteReadRuneUnreadRuneメソッドから、それらが満たすインターフェースによって暗黙的に示されるコメントを削除しています。これにより、コードの冗長性が排除され、Goのドキュメンテーション慣習に沿った形に修正されています。

コミット

commit 4c7695126d881b4622ed74238d7ce5c4e6b3b259
Author: Rob Pike <r@golang.org>
Date:   Fri Feb 10 14:45:11 2012 +1100

    strings: delete method comments implied by interface satisfaction
    
    Fixes #2957.
    
    R=golang-dev, bradfitz
    CC=golang-dev
    https://golang.org/cl/5653053

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

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

元コミット内容

strings: delete method comments implied by interface satisfaction

Fixes #2957.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/5653053

変更の背景

この変更は、Go言語のドキュメンテーション慣習と、インターフェースの暗黙的な実装という言語特性に基づいています。Goでは、ある型が特定のインターフェースのすべてのメソッドを実装していれば、その型はそのインターフェースを「満たす」と見なされます。この際、implementsのような明示的なキーワードは不要です。

strings.Reader型は、io.ByteReaderインターフェース(ReadByte()メソッドを持つ)やio.RuneReaderインターフェース(ReadRune()メソッドを持つ)などを満たしています。Goのドキュメンテーション慣習では、インターフェースのメソッドがそのインターフェースの定義によって十分に説明されている場合、そのメソッドの実装側で冗長なコメントを繰り返すことは推奨されません。

このコミットは、Go issue #2957("godoc: don't show method comments for interface satisfaction")に関連しており、godocツールがインターフェースを満たすメソッドのコメントをどのように表示すべきかという議論の結果として行われました。インターフェースのメソッドは、そのインターフェース自体で十分にドキュメント化されているべきであり、個々の実装で同じ説明を繰り返すのは冗長であるという考え方です。これにより、ドキュメンテーションの重複を避け、コードの可読性を向上させることが目的です。

前提知識の解説

Go言語のインターフェースと暗黙的な実装

Go言語のインターフェースは、メソッドのシグネチャの集合を定義します。Goの型は、インターフェースで定義されたすべてのメソッドを実装していれば、そのインターフェースを自動的に満たします。これを「暗黙的なインターフェースの実装(implicit interface satisfaction)」と呼びます。例えば、io.ReaderインターフェースはRead([]byte) (int, error)メソッドを定義しており、このメソッドを持つ任意の型はio.Readerとして扱えます。

io.ByteReaderインターフェース

ioパッケージに定義されているByteReaderインターフェースは、単一のReadByte()メソッドを持ちます。

type ByteReader interface {
    ReadByte() (c byte, err error)
}

このインターフェースを実装する型は、バイトストリームから1バイトずつ読み込む機能を提供します。

io.RuneReaderインターフェース

ioパッケージに定義されているRuneReaderインターフェースは、単一のReadRune()メソッドを持ちます。

type RuneReader interface {
    ReadRune() (r rune, size int, err error)
}

このインターフェースを実装する型は、UTF-8エンコードされたUnicodeコードポイント(rune)を読み込む機能を提供します。ReadRuneは、読み込んだルーン、そのルーンが占めるバイト数、およびエラーを返します。

Goのドキュメンテーション慣習

Goのドキュメンテーションは、godocツールによって生成されます。Goのドキュメンテーション慣習では、エクスポートされた(大文字で始まる)型、関数、メソッド、変数、定数には、その直前にドキュメンテーションコメントを記述します。

特に、インターフェースのメソッドがそのインターフェースの定義によって十分に説明されている場合、そのメソッドの実装側で同じ内容のコメントを繰り返すことは冗長と見なされます。インターフェースのコメントが、そのインターフェースの目的と各メソッドの振る舞いを明確に説明していれば、実装側のメソッドコメントは、その実装固有の詳細や注意点に限定されるべきです。

技術的詳細

strings.Reader型は、文字列を読み込むためのio.Readerio.ByteReaderio.RuneReaderなどのインターフェースを満たすように設計されています。

このコミット以前は、strings.ReaderUnreadByteReadRuneUnreadRuneメソッドには、それぞれのメソッドが何をするかを説明するコメントが付与されていました。しかし、これらのメソッドはそれぞれio.ByteReaderio.RuneReaderインターフェースのメソッドを実装しており、これらのインターフェース自体がそのメソッドの振る舞いを定義し、ドキュメント化しています。

Goのドキュメンテーションの哲学では、インターフェースのメソッドがそのインターフェースの定義によって十分に説明されている場合、そのメソッドの実装側で同じ説明を繰り返すことは冗長であり、メンテナンスの負担を増やすと考えられます。例えば、io.ByteReaderReadByte()メソッドの機能は、io.ByteReaderインターフェースのドキュメントで明確に定義されています。strings.ReaderReadByte()がそのインターフェースを満たす以上、そのメソッドが「バイトを読み込む」という基本的な機能を持つことは自明です。

したがって、このコミットでは、インターフェースによって暗黙的に示される機能に関するコメントを削除することで、ドキュメンテーションの重複を排除し、コードをより簡潔に保っています。これにより、godocで生成されるドキュメントもより洗練され、ユーザーはインターフェースのドキュメントを参照することで、そのメソッドの基本的な振る舞いを理解できるようになります。

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

--- a/src/pkg/strings/reader.go
+++ b/src/pkg/strings/reader.go
@@ -50,9 +50,6 @@ func (r *Reader) ReadByte() (b byte, err error) {
 	return
 }
 
-// UnreadByte moves the reading position back by one byte.
-// It is an error to call UnreadByte if nothing has been
-// read yet.
 func (r *Reader) UnreadByte() error {
 	if r.i <= 0 {
 		return errors.New("strings.Reader: at beginning of string")
@@ -62,11 +59,6 @@ func (r *Reader) UnreadByte() error {
 	return nil
 }
 
-// ReadRune reads and returns the next UTF-8-encoded
-// Unicode code point from the buffer.
-// If no bytes are available, the error returned is io.EOF.
-// If the bytes are an erroneous UTF-8 encoding, it
-// consumes one byte and returns U+FFFD, 1.
 func (r *Reader) ReadRune() (ch rune, size int, err error) {
 	if r.i >= len(r.s) {
 		return 0, 0, io.EOF
@@ -81,9 +73,6 @@ func (r *Reader) ReadRune() (ch rune, size int, err error) {
 	return
 }
 
-// UnreadRune causes the next call to ReadRune to return the same rune
-// as the previous call to ReadRune.
-// The last method called on r must have been ReadRune.
 func (r *Reader) UnreadRune() error {
 	if r.prevRune < 0 {
 		return errors.New("strings.Reader: previous operation was not ReadRune")

コアとなるコードの解説

上記の差分は、src/pkg/strings/reader.goファイルから以下の3つのメソッドのコメントが削除されたことを示しています。

  1. UnreadByte() メソッドのコメント削除:

    // UnreadByte moves the reading position back by one byte.
    // It is an error to call UnreadByte if nothing has been
    // read yet.
    

    UnreadByteio.ByteScannerインターフェース(ReadByteUnreadByteを持つ)の一部として期待される機能です。このコメントは、メソッドの基本的な動作とエラー条件を説明していましたが、io.ByteScannerインターフェースのドキュメントで同様の情報が提供されるため、冗長と判断されました。

  2. ReadRune() メソッドのコメント削除:

    // ReadRune reads and returns the next UTF-8-encoded
    // Unicode code point from the buffer.
    // If no bytes are available, the error returned is io.EOF.
    // If the bytes are an erroneous UTF-8 encoding, it
    // consumes one byte and returns U+FFFD, 1.
    

    ReadRuneio.RuneReaderインターフェースの主要なメソッドです。このコメントは、メソッドの目的、EOF処理、不正なUTF-8エンコーディングの処理について詳細に説明していました。しかし、これらの情報はio.RuneReaderインターフェースのドキュメントでカバーされるべき内容であり、strings.Readerの実装固有のコメントとしては過剰と見なされました。

  3. UnreadRune() メソッドのコメント削除:

    // UnreadRune causes the next call to ReadRune to return the same rune
    // as the previous call to ReadRune.
    // The last method called on r must have been ReadRune.
    

    UnreadRuneio.RuneScannerインターフェース(ReadRuneUnreadRuneを持つ)の一部として期待される機能です。このコメントも、メソッドの基本的な動作と前提条件を説明していましたが、io.RuneScannerインターフェースのドキュメントで同様の情報が提供されるため、削除されました。

これらのコメントの削除は、Goのドキュメンテーション慣習に従い、インターフェースによって提供される機能のドキュメントはインターフェース自体に集約し、実装側のコメントは実装固有の振る舞いや注意点に限定するという原則を徹底するためのものです。これにより、コードの重複が減り、ドキュメンテーションの一貫性が向上します。

関連リンク

参考にした情報源リンク