https://www.youtube.com/watch?v=SKXNAdk3ot0
今回から新たに、Swift 公式のガイドライン API Design Guidelines
に入っていきます。
これまでに見てきた Swift.org の About Swift
が終わって、当初からの題材である The Swift Programming Language
を眺めてみようかと思ったのですけれど、その前に API Design Guidelines
を確認しておくとより有意義な機会になるような気がして、まずはここから初めていこうと思います。よろしくお願いいたしますね。
—————————————————————————————————— 熊谷さんのやさしい Swift 勉強会 #12
00:00 開始 00:49 この勉強会の趣旨 01:58 この勉強会における心持ち 03:30 Swift API Design Guidelines 05:28 Objective-C っぽさ 06:50 目的 09:06 Cocoa の命名規則 11:33 Objective-C との相互運用 13:41 基本事項 14:25 使用時の明瞭さを最重視 15:41 API は短さよりも明瞭さを意識 18:06 名前付の文化の違い 22:21 文字列の長さ表現にみる文化の違い 25:04 ドキュメントコメント 26:39 コメントとドキュメントコメント 27:49 ドキュメントコメントとクイックヘルプ 31:14 ドキュメントコメントは API の設計に良い影響を与える 33:53 ドキュメントコメントの概要 35:39 ドキュメントコメントの例 38:01 コメントは実装の道しるべ 48:00 何をするのか、何を返すのか 48:30 Swift の関数は原則、戻り値を返す 50:59 添字構文における概要説明 52:57 イニシャライザーにおける概要説明 53:31 その他における概要説明 54:45 シンボル・ドキュメンテーション・マークアップ 58:32 次回の展望 ——————————————————————————————————
Transcription & Summarize : 熊谷さんのやさしい Swift 勉強会 #12
今日から新しいトピックですね。「APIデザインガイドライン」です。これを見ていると面白いし、理解するとSwiftが気軽に書けるようになる感じがして、なかなか良い題材かなと思います。この勉強会では、もともとは「The Swift Programming Language」をゆっくり見ていこうかなと思っていましたが、その前にこれをやっておくと良いかなと思い、まず挟んでみますね。新しいトピックなので、この機会に新しく来てくれる人もいるかもしれないですし、ちょっとだけこの勉強会の特徴を軽く紹介しておこうかなと思います。
まず、せっかく皆さんと集まる会なので、意見交換や情報交換をしながらやっていけたら有意義かなと思っています。いつでも話しかけてくれてオッケーです。コメントでも大丈夫です。そういった感じで進めていこうと思います。ただ、話しかけるのには勇気がいることもあるかと思うので、そのあたりの心構えだけ丁寧に紹介しておきます。
話しかけるのはなかなか難しいことかもしれませんが、どんなにすごそうな人や詳しいと思う人でも、ちょっとしたところを知らなかったりすることはよくあることです。「これぐらい簡単だからわざわざ言わなくてもいいよね」と思って話しかけるのをやめるのはとてももったいないです。そこからいろんなことが見つかっていくこともあるので、ぜひ簡単なことでも言いたくなったら言っちゃってください。
また、話しかける上で自信や証拠などは全く必要ありません。そういったものは話しながら見つけていけるものであり、実際に「正しい・正しくない」が存在しないことはいくらでもあります。ですから、あまり気にせず、「なんとなくこう思うんだよね」と気軽に話してもらえたら嬉しいです。
それでは今日のテーマに進みます。今日のテーマは「APIデザインガイドライン」です。Swiftのコードを標準化するためのガイドラインというものですね。Appleが公式に出している資料で、これを見ていくとSwiftらしい書き方が見えてきます。とても貴重な資料です。
このガイドラインはSwift 3から提供されました。それまでは「Swiftらしさ」というものがみんなそれぞれに存在していて、分からないときには標準ライブラリの書き方を参考にして「きっとこれがSwiftらしいんだろう」と追求していました。しかし、これが登場してからは皆で共通認識を持てるようになり、よりSwiftらしいコードになってきて、誰もが書いたコードが読みやすくなりました。
確かにこの「APIデザインガイドライン」は強制ではないと以前見かけたような気がしましたが、今回この題材を準備するにあたってその記述を見つけることができませんでした。もしかすると馴染んできたのか、単に見つけられなかっただけかもしれません。しかし、このガイドラインに沿っておくと良い感じになると思います。
このガイドラインは優れた内容です。特にObjective-Cを知っていると役立つ部分もありますが、それだけではありません。Objective-Cは、もともとこのようなガイドラインが明確に記されていなかったように記憶しています。そのため、Objective-Cの頃も似た雰囲気でやっていましたが、Swiftでは明確に定められるようになった感じです。
このデザインガイドラインはとてもよくできていると思います。個人的には惚れ込んでいる文章です。Swiftを書かない場面でも役立つような内容が含まれているので、Swiftにあまり縁がない方でも何かの参考になると思います。
APIデザインガイドラインの目的は色々ありますが、まず大事なポイントとして公式のSwiftを書くときの指標になっています。このコードがSwiftらしくないのではないかと誰かに伝えたいときには、「公式ではこういうガイドラインになっているから、これに従うと良い感じにみんなと調和が取れるかもしれない」と言えるので、とても役立つ文章です。
このガイドラインがなかったときには「これは自分のSwiftらしさだ」と主観でしか言えませんでしたが、今では明確なガイドラインがあるので、非常に助かります。 このガイドラインの大部分は、名前の付け方や慣用表現といった部分に触れています。この辺りが体に馴染んでくると、APIを定義する際にとても楽になります。迷いが少なくなり、実装の方に意識を集中できるので、実装の品質が高まるという印象です。Swiftのエコシステムの一部として、そのような魅力があると感じるでしょう。
例えば、Objective-Cのガイドラインについても触れました。見つけてくれた方がコメントに書いてくれていましたが、名前の付け方はしっかりと存在していましたね。公式文書をあまり見なかった私は経験的に身に付けた内容ですが、ガイドラインには詳細が記されています。後でゆっくり見てみます。
Objective-Cのときには、イニシャライザーが init
であることは当たり前のことでした。他にも、パラメータを使うときには with
何とかといった書き方や、インスタンスを作成するメソッドの場合には make
を使うなどのルールがありました。例えば、String
型のメソッドの場合には String
から始めるといったルールです。
APIデザインガイドラインにもそのようなルールがしっかりと書かれていたおかげで、Objective-CとSwiftのインターオペラビリティ(相互運用性)においても、自動的にパラメータが変換されるなどの利便性がありました。ルールが定まっていたことで、こういったときにはこうするといった仕組みが伝わります。
具体的な例として、インスタンスタイプである String
で始まるメソッドは、オートリリースとしてインスタンスを返す必要がありました。このルールを守らないと、オートリリースし忘れてメモリリークを引き起こす可能性があります。このため、APIを設計する際のルールがとても重要なのです。
Objective-Cをやっていた人には、このようなルールの重要性が伝わると思います。APIデザインガイドラインの基本事項に関しても、非常に概念的なところからまとめられており、視野が広がる良い内容が記されています。特に、APIを使うときの明瞭さを一番重視しています。これは、一度定義して繰り返し使う現代のプログラミングスタイルにおいて非常に重要です。
APIを定義する際、そのAPIがどのようなものなのか、どう使うのかがユーザーに明確に伝わるように命名しなければなりません。これがルールづけられているのです。SwiftのAPIデザインガイドラインでは、コード量が少なくなる必然性がありますが、それが目的ではなく、あくまで意味が明確に伝わることを重視しています。
具体的な例として、C言語では文字列の長さを取得する際に strlen(str)
のように略記されますが、Swiftでは略さずに何を指しているのかを明確にする方針をとっています。これにより、APIを使用する際の直感的な理解が促進され、誤解を生むリスクが減少します。
このように、ガイドラインのルールをしっかりと抑えることが、良いAPI設計に繋がります。APIデザインガイドラインについてのご意見や思い入れがあれば、いつでもお聞かせください。 なので、std
ってのはちょっと出てこないですけど、出てこないのももしかすると std
というよりはスタンダード。でもスタンダードというよりはスタンダードライブラリだったら、SwiftのライブラリのString
みたいな感じですね。こういう書き方になってきます。
C++の場合はstd::string
ですよね。こんなふうに違ってきます。面白いコメントがありましたけど、stdio
ね。C言語のね。自分も初めはそう思ってたかも。スタジオみたいな、何の略なんだろうこれは、みたいなね。これはね、スタンダードIO(入力・出力)って意味ですけど、これを知ってる人ってなかなかいないと思いますね。最初は知らないとわからないです。
こういう専門用語はなるべく使うのをやめようっていう方針もあります。後で出てくるんですけど、SwiftのAPIデザインガイドラインで、専門用語は知っている人じゃないと通じない。知っている人にとっては明確にバシッと伝わるんですけど、でも知らない人にとっては謎。謎どころか誤解を生むっていう可能性があるので、使いどころはしっかり見極めていこうっていう方針があります。これがAPIデザインガイドラインの考え方です。
で、このSTR連もそうで、まずそもそもね、Swiftの場合STRっていう変数はあまり使わないんですけど、std::string
とか&&
って書かない。STRっていうのがC++の基本的な定義の仕方になるわけですけど、Swiftの場合はString
。まあ、String
とも書かないですけどね。これが何のString
なのかっていうのが大事になってきます。
例えばエラーメッセージ。まあ、そういう意味ではC++もちゃんと書くか。こういったところ、STRっていうよりはエラーメッセージですかね。C++は確かスネークケースだったと思うんですけど、これでねエラーメッセージ。で、確か実行できましたよね。暗黙的にc_str
に変換しましたよね、確かね。まあ、こういう風に書くのがC++のスタンダードです。
Swiftの場合はerrorMessage.count
みたいに書くのがスタンダードですね。APIデザインガイドラインの大事な要所っていうのは、これから自然と短くしていくことが出てきます。いい話も出てきました。そっかそっか、そうですね。
C++でそれっぽいのっていうのがERR_MSG
とか。ローワーキャメルケースが最近使われるかは自分はちょっと把握してないですけど、ERR_MSG
かERRMSG
、どっちか。とりあえずこちらにしましょうかね。こういう風にね、C++の場合。あーそっか、一応こっちにしてみましょうか。どっちかちょっと詳しくわからないので間違ってるかもしれないですけど、まあこんな感じでね。エラーといえばERR
だよねみたいなのがC++、要はC言語の文化にあって、エラーがない場合NO_ERR
って表現したりとか、いろいろあるんで、C言語の界隈ではERR
って書けばエラーってわかるので、これで問題なし。
こんな風にC++と比べれば長くなるけど、ERR_MSG.count
。ちょっとわかりにくいねこれね。何か文字数の場合、length
とかの方がわかりやすい気がするけど、まあここはAPIにcount
ってあるからこういう文化なんでしょうね、Swiftの場合はね。そうそうそう、コレクション。だからコレクションに定義されてるcount
を使っちゃうわけですよね。文字のコレクションって捉えるんですよね、Swiftの場合は。
この辺りはちょっとAPIデザインガイドラインから離れたルールっていうのかな、官用表現になってきますけど、とりあえずねERR_MSG
という文字セットのカウント。文字セットじゃないや、文字のコレクションのカウントみたいな風に慣れていくと、ERR_MSG.count
。ちょっとわかってくるかな。そうそうそう。
今コメントで教えてもらったNSString
ね、Foundation
入れてないや。import Foundation
。こっちはね、NSString
の文字列だった場合にはlength
だったんですよね。Objective-Cの文化ではlength
で文字数とってたんですけど、Swiftの文化になってからはね、count
で統一した感じですね。標準ライブラリでは。
そうなんですよね。文字のカウントと文字をバイトコードと見たときのカウントとかね、いろいろありますけど、これは話が長くなるからやめときましょう。いつかString
の話題になったときにやりましょう。
今のを見ても結構ね、APIデザインガイドラインの意義とか、あと雰囲気みたいなことがつかめた気がしますね。いろいろみんなと見ていけたおかげで。今みたいなのをちょっとイメージしつつ、APIデザインガイドライン、これからいろいろ話していくのを捉えていったらわかりやすいかなと思います。
あとね、もう一個大事なことが書いてあって、Swiftではね、コメントを書くっていうことも非常に大事なポイントとして挙げられています。これがね、言語によっては、というか、その言語を使っている有名な人たちによっては、「コメントは書かないほうがいい」「書かなくてもわかるコードを書くべきだ」という考え方もあります。それはそれでね、結構大事な考え方だと思うんですよ。
だからといってSwiftの場合は、APIを宣言するときにおいてはコメントを必ず書くっていう方針を掲げています。これがね、なかなか面白いところですし、とても有意義に働いてくるんですよ。 なのでね、コメントはいらないんじゃないか、いるんじゃないか、細かく書くべきだ、なくするべきかというところを日頃考えている人にとっても、このSwift APIデザインガイドラインは一つの指針になってくるかなと思います。あと、コメントで面白いお話をいただけました。コメントというよりも、ドキュメントコメントですね。
確かにそういう視点で見るのは面白いですね。自分はあんまりそのあたり意識してなかったけれど、Xcodeでも確かにドキュメントコメントと普通のコメントで色分けが違いますよね。あとキーワードも違いますが、ちょうど出てきたドキュメンテーションマークアップ、ドキュメントコメントの話をしましょう。自分は色を結構分けていますが、コメントの色とドキュメンテーションマークアップの色は少なくともXcodeでは違います。
Swift APIデザインガイドラインでは、このドキュメントコメントを大事にしろと言っています。例えば自分で関数(func
)を定義するとき、func doSomething(value: Int)
みたいなメソッドを作ったときに、これをdoSomething(value: 10)
とかで呼ぶときに、何にも説明のないコード保管が出てきますが、ここでドキュメントコメントを書いておくと良いのです。
例えば、オプションキー+コマンド+スラッシュ (Option
+ Command
+ /
)を打つとテンプレートが出てくる、とても便利な仕組みになっていますが、ディスクリプションとしてメソッドが何をするか書く必要がありますね。もちろん、英語が苦手な場合や適当な英語を書くこともあるかもしれませんが、説明を書くことは大事です。
こうやってドキュメンテーションマークアップとしてコメントを書いてあげると、///
や/**
のような書き方になります。これを行うことで、例えば doSomething
メソッドを呼ぼうかなと思っている時点で、先ほど書いたコメントが出てくるのです。こういったサポートはとても大事です。
ドキュメンテーションマークアップがSwiftで規定されているおかげで、これができるようになっています。このコメントのおかげで、APIを使うときに何をしようとしているのかが伝わりやすくなります。例えば、サムシングメソッドを呼ぼうとしたときに、「何かをする」としかコメントが出てこない場合、このメソッドは危険だなと分かるわけです。
もちろん、例によってコメントの内容が重要になるので、具体的でわかりやすいコメントが理想です。APIデザインガイドラインには、コメントを書くことが非常に大事だと書かれています。これが大きなポイントです。実際に適切なコメントを書くことでAPIの機能を簡潔に説明できない場合、そのAPIの定義自体が間違っている可能性があります。
理想論ですが、コメントは絶対に書いたほうが良いです。実際の業務では時間を食うので難しい部分もあるかもしれませんが、APIデザインガイドラインではコメントを書くことが推奨されています。言語化することが大事なキーワードであり、ドキュメントコメントを書くことで思考を整理できます。
ドキュメントコメントにはMarkdownのような記法が使えます。あまりデザインに凝る必要はありませんが、マークアップすることで意図を読んだ人や解析したプログラムに使えるようになります。ドキュメントコメントを書く際には、API宣言の概要から書き始めることが重要です。最初の行は概要の説明から始めます。
以上がドキュメントコメントについての基本です。丁寧に記述することが、結果としてより良いAPIの設計につながります。 ほとんどのAPIは、その一行を読めばAPIの意味が完全に理解できるといわれています。ここで「完全に理解できる概要説明を書く」というルールがあります。必要に応じて補足説明として文章を追加で添えたり、箇条書きで説明するのが基本的なコメントの流れになります。
例えば既存のAPIの例として、それほど長くないものを見てみましょう。ダブル型のpi
を例に取ります。これの定義を見ると、標準ライブラリはAPIデザインガイドラインに従って記載されています。このように説明が書いてあります。「数学的な定数のパイ(π)、円周率で、半径1の円の円周の長さ」という意味です。定数とは書かれていませんが、コンパウンドとして定義されています。これだけで説明が簡潔に終わりますね。さらに、英語で補足説明が記載されていて、詳細な情報を提供しています。
こういったコメントは、APIの動きと一致していることが理想です。コメントを読むだけでAPIの動作や設計思想を理解することができるからです。実装を考えるときにはまず「何を作ろうと思ったか」として、その思想に従った実装を行います。もしその実装に不備があれば、それはバグとなります。コメントはその設計思想を補完するものであり、実装が正しく書かれているかどうかの判断材料となります。
コメントは実際にAPIを使用しようとする開発者にとっても重要です。ドキュメントコメントが適切に記載されていれば、実装を確認しなくてもAPIを使用するかどうかの判断がつきやすくなります。従って、コメントを大事にすることは非常に価値があります。
変更を加える際には、ドキュメントコメントもチェックしておくことが重要です。コードの変更によってドキュメントコメントと動作が矛盾していないかを確認することが大切です。適切なドキュメントコメントがあるAPIは、それを使う際に、コメントを書かなくてもスムーズに理解できるようになります。結果として、コード自体がコメントとして機能するようになります。
このようにAPIデザインガイドラインを意識してコメントを書くことは、Swiftだけでなく多くのプログラミング言語においても有意義なことです。 概要説明の書き方についてお話します。ドキュメントコメントは、SwiftのAPIデザインガイドラインでは最重要項目として位置づけられています。それはなぜかというと、概要説明だけでもAPIのドキュメントコメントは成立するからです。ほとんどのAPIはこれだけで説明がつくとされています。もしこれで説明がつかない場合、そのAPIが欲張りすぎているか、そもそも設計が間違っているのではないかと疑いましょう。例えば、以前話した「DoSomethingメソッド」は、ドキュメントコメントを書くにも「DoSomething」としか書けなかったため、ここでAPIを再設計する必要があると気づくことができる非常にいい例です。
ドキュメントコメントの書き方については、ガイドラインがあり、「断片的な単一文章を使ってピリオド(日本語の場合は句点)で終える」というルールが決まっています。完全な英語らしさが求められるわけではなく、例えば「Return the view of self containing the same element」といった書き方をします。稀にセミコロンで文を連ねることもあります。
SwiftのAPIデザインガイドラインでは、APIをSwiftコードで定義する際には自然なアメリカ英語を使うよう規定されています。ただし、ドキュメントコメントについては英語か日本語かの言語指定はありません。日本語で書いていいプロジェクトであれば、日本人にとって誤解なく伝わる日本語で書くのも良い判断だと思います。最近、いろんな国の方がプロジェクトに参加するケースも多いですが、日本語で書けるのであれば日本語で記述するのも合理的な選択だと思います。
こうした概要説明の書き方が大切です。現在表示されている一行をしっかり書いておけば、APIの説明としては十分です。英語でドキュメントコメントを書くプロジェクトでも、最初は日本語で書いておくと他のメンバーが後で修正しやすいです。英語で書かなければならない場面でも、何も書かないよりは日本語でさっと書いておいた方が良いかもしれません。
概要説明の最初の一行には、APIが何をするのか、何を返すのかといった期待を記載します。ただし、効果がないことや戻り値がVoid
であることには触れません。実際、Swiftでは原則として戻り値は必ず返すようになっています。例えば、mutating func pretend
というメソッドが戻り値を書いていませんが、これはVoid
を返すことが省略されているだけです。したがって、コメントで改めて戻り値がVoid
であることを記載する必要はありません。
サブスクリプト(添字構文)についても簡単に触れます。例えば、配列の6番目を取得するような時に使うサブスクリプトの説明を書く際には、それが何にアクセスするかを記載します。以上が、概要説明を書く上での重要なポイントです。 なので、このAPIデザインガイドラインを活用する大事なポイントとしては、サブスクリプトのコメントに何を書くか迷ったときに、このドキュメントコメントの項を見て「何にアクセスするか」を書けばいいのだな、と確認して書くことです。こういった使い方をすると、コメントも書きやすくなると思います。
例えば「インデックス番目のエレメントにアクセスするんだよ」と書いてありますね。ここでは「0から始まるインデックス」とかは書かれていません。そのあたりは常識となっているのかな。その辺りが常識としてわかりづらいときには、この概要説明ではなく、もう一段落空けて詳細を追加で書いてあげる、といった感じです。
イニシャライザーについては、何を生成するかを書いてあげる、ということが書いてあります。このときに「しっかりどんなインスタンスを作るのか」といったところまで書いてあげて初めて、完全なドキュメントになるわけです。サブスクリプトやイニシャライザー以外の宣言の説明についても、そのエンティティ、つまり指定している項目がメソッドやプロパティであれば、それが何であるのかを明記することが大切です。
例えば、first
というプロパティであれば、それは「最初の要素です」あるいは「なければnilです」といった説明も書いてあげる。list
は「挿入や削除が自由に行えるコレクションです」といった説明を加えてあげると、そのAPIを完璧に説明できるドキュメントコメントの概要文になります。
また、他にも細かい説明ができるように追加説明を入れることができます。最初の一文で概要を書いた後に一行開けて、シンボルドキュメンテーションマークアップを使って詳細な情報を埋め込む、という形です。使えるキーワードも色々と規定されているので、興味のあるものをピックアップして使うとよいでしょう。
特によく使われるのは、throws
、returns
、parameters
といったキーワードです。実際にこれをどう使っていくのかという例としては、一番最初の行までが概要説明です。長すぎるとエディタとして読みづらくなるので、開業しているだけで、流れとしては完璧に英語の一文で書かれています。
例えば、func print
に対するコメントでは、まず概要を一文で捉え、その後に具体的にどういう風に動いていくのかを詳細に書きます。ここで一行空けてありますが、空けなくても良いです。とにかく、追加説明の中にシンボルコマンド構文を埋め込むようにします。-
で始めてシンボルコマンドを書き、その後に必要に応じてパラメータの説明文を書きます。
例えば、print
メソッドでは、パラメータとしてのseparator
やterminator
が何であるかを補足説明します。こういった詳細な説明が書けるようになっています。
実際にこれを書いてあげると、print
を使おうとするときにクイックヘルプが出てきて、詳細に「サマリーは何です」とか「ディスクリプションに詳細な説明があります」と表示されます。パラメータが何を取るのかといった情報も出てきます。定義を見ると、print
文に様々なドキュメントマークアップが書かれていて、先ほどのクイックヘルプに繋がっています。これがドキュメントコメントです。
今回は、ドキュメントコメントについて詳しく見ていきました。次回は、具体的な命名規則について見ていこうと思います。これで今回の勉強会を終わりにします。また質問などあれば、OJTチャンネルに書き込んでもらえると嬉しいです。では、お疲れ様でした。