YAMAGUCHI::weblog

海水パンツとゴーグルで、巨万の富を築きました。カリブの怪物、フリーアルバイター瞳です。

「オブザーバビリティ・エンジニアリング」という本が出版されました #o11yeng

はじめに

こんにちは、Cloud Operations担当者です。このたび私が翻訳として関わった「オブザーバビリティ・エンジニアリング」という本がオライリー・ジャパン社より出版されました。本日より書店ならびに各社オンラインストアでご購入いただけます。

www.ohmsha.co.jp

電子書籍版についてはオライリー・ジャパンのサイトよりePub、PDFの各種フォーマットにてご購入いただけます。

www.oreilly.co.jp

また上記書籍情報ページに質問は報告を行うための連絡先も記載されておりますので、なにかありましたらそちらよりお問い合わせください。

TL;DR

「オブザーバビリティ・エンジニアリング」はオブザーバビリティの概念を理解し、それを実際にシステムに備えるために必要な技術要件を知り、実践につなげるための書籍です。オブザーバビリティを実践いる方やこれからオブザーバビリティを活用していく方には必携の書籍になると思います。ぜひご一読ください。

「オブザーバビリティ・エンジニアリング」のおすすめの読み方

本書は350ページ程度の中型本で、技術書としてはちょうどよいボリュームだと思います。したがって、オブザーバビリティに関して包括的に理解を深めたいという方であれば頭から通して読み進めていただければと思います。本書は「オブザーバビリティ」と呼ばれるシステムの性質に関して、その技術的な要件や具体的な実装方法、導入の際の文化的側面などを扱った書籍です。そのため、オブザーバビリティの大局観が得られずなにか参照したい方、これからオブザーバビリティを導入していくための考慮事項を把握したい方、オブザーバビリティの技術要件を理解することで既存のシステム監視との差異を理解したい方におすすめです。

本書を読むにあたって、関連書籍として同様にオライリー・ジャパンから出版されている「入門 監視」をご覧いただけると、オブザーバビリティと監視の関連についてより深い理解が得られると思います。また「SRE サイトリライアビリティエンジニアリング」「サイトリライアビリティワークブック」などのサービスレベル目標やアラートの設定に関する章も、本書のテーマと大きく関連しているので、SREの推進としてオブザーバビリティの実践や導入をされている方は、そちらも参照いただくのが良いと思います。

いわゆるSRE本はSREをテーマに横断的にプラクティスを紹介しているのに対し、本書はオブザーバビリティをテーマに概念的な話から具体的な実装の話までを一気通貫で紹介しているので、併読することでオブザーバビリティがSREの中でどこに位置しているのか、何を可能にするのかの理解が明確になると思います。

一点、私のあとがきにも書きましたが、本書はHoneycomb.ioというオブザーバビリティSaaS企業のエンジニア3名によって著されているので、その点に留意して読み進める必要があります。本書の具体例がどうしても彼らの製品の機能や実装による説明になっていので、その背景にある技術や思想を常に意識しながら読みすすめると、皆様が利用しているツールやシステムにおいてどのように適用できるか、何が達成されているかの理解が進むかと思います。

出版に至るまでの話

本書はCharity Majors、Liz Fong-jones、George Mirandaによって著された、 "Observability Engineering" の日本語訳です。

本書が出版されたのは2022年6月だったのですが、本書はEarly Releaseの対象になっていたのと、著者の一人であるLiz Fong-Jonesが元々Googleで同じチームでの同僚だったこともあり、出版以前に最初の数章が公開されてからすぐに読み始めていました。本書が解説しようとしている内容は、SREがだいぶ普及してきた現在において、サービスレベル目標をもとにした運用をする上で切っても切り離せないオブザーバビリティの獲得を行う方法であり、正式版の出版をかねてより期待していました。実際に正式版が出版され、改めてその内容は「オブザーバビリティ」の定義を解説し、本来の監視(モニタリング)と技術的にどのように異なる要件が必要なのかを解説した素晴らしい書籍であると感じました。「オブザーバビリティ」という用語が本来の意味合いから離れて、監視系ツールのマーケティング用語として濫用され、ただ「監視」という用語の置き換えとして用いられるケースが散見される中で、利用者側がその用語の意味を正しく理解するということは非常に重要であると考えています。当たり前ではありますが、そもそも別の言葉が導入されたということは概念として異なるからです。

こういった背景から、日々コミュニティで親しく、また「Java開発者のための関数プログラミング」「Go言語による並行処理」での編集としてお世話になった、オライリー・ジャパンの瀧澤さんに本書を日本語化する意義を紹介したところ、2022年7月半ばには早速企画にしていただき、そのまま翻訳の流れとなりました。また同様にいくつかのコミュニティでかねてよりオブザーバビリティやOpenTelemetryに関する情報を共有している大谷さん(以後、かっちゃん @katzchang)も翻訳に興味があるとのことだったので、半分ずつ担当して共訳することとなりました。

前述の通り、かっちゃんとは以前からオブザーバビリティに関して意識合わせがだいぶされていたこともあり、共訳の作業は大変スムーズでした。私自身が共訳をするのが初めてだったこともあって、訳語の統一などの点で難しさを感じた点もありましたが、自分の担当箇所の初校分に関しては9月中には終わらせることが出来ました。ただ、その後本業がだいぶ立て込んでしまい、見直しの時間があまり取れなかったので、レビュワーの方々にはだいぶ負担をおかけしてしまいました。

謝辞

訳者あとがきにおいても掲載いたしましたが、本業の合間を縫って、年末のお忙しい中、短い時間にもかかわらず有意義なレビューを数多くくださったレビュワーの皆様に感謝致します。

レビュワーの皆様(五十音順)

オライリー・ジャパン

  • 瀧澤昭広さん(@turky

レビュワーの皆様にはエンジニアとしての観点から多くのコメントを頂き、また解釈が不明瞭な部分に関しては、より明瞭になるように対案をいただくなど、非常に有益なコメントを頂きました。中でも何名かには多大なレビューを頂きました。瀬尾さんには、レビューが少なくなりがちな後半からレビューをいただくなど、訳者としてありがたかったです。松浦さんは「入門 監視」を始め多くの翻訳をされていることもあり、訳に関して良い対案をいただきました。馬場さんには、文章として説明が甘くなって部分(原文に原因があるものも多かったのですが)の的確な指摘をいただきました。若山さんには細かな解釈に関して指摘を数多くいただきました。

瀧澤さんに、Sphinxを使った執筆環境を用意いただいたことで、私は大変執筆しやすかったです。「Go言語による並行処理」を翻訳したころから、更にパワーアップして、瀧澤さん側でSphinxが生成するXMLからInDesignへの流し込みを自動化するスクリプトを作成されていたことで、依頼してから1日程度で組版された原稿をいただけるというのは、レビューを行う際に非常に有益でした。実際に執筆をされたことがある方は実感されると思うのですが、原稿のレビューを行う際に、フォーマット(テキストファイル、PDF、紙など)が異なるだけで見え方がまったく異なります。様々なフォーマットでの確認を手早く数多く行えるということは、ソフトウェアのレビューと同様、非常に有用です。ラムダノートの鹿野さんもそうでしたが、編集担当者がポストプロダクションの領域も担当されていることの心強さを感じました。

またかっちゃんとは本書の翻訳に関して、そもそもの本の立ち位置やその価値の認識、背景技術の理解など、息があっていたので、チャットで大きな反対意見でぶつかって議論になることはなく、ツーカーで作業を進めてこれたのはとても気持ちのいい体験でした。翻訳作業はこれまで割と孤独に行っていたので、息のあった共訳者がいる頼もしさを感じました。また機会があったら一緒にやりたいです。

あらためて、みなさまありがとうございました。

おわりに

手前味噌にはなってしまいますが、私が今現在で「SREおよびオブザーバビリティに関して読むべきN冊」という書籍を挙げるとするならば、確実にそのリストの上位に入るべき一冊だと考えています。ぜひ多くの方のお手にとっていただき、日本においてもオブザーバビリティに関する議論がより活発になることを願っております。

参照

"Enterprise Roadmap to SRE"の日本語訳が出ました

はじめに

こんにちは、Google CloudでオブザーバビリティとSREの担当をしているものです。今日は去年仕事でやってたものがようやっと表にでたのでその紹介をします。

「SREエンタープライズロードマップ」がでました

「SREエンタープライズロードマップ」はかねてより "Enterprise Roadmap to SRE" としてGoogle SREのウェブサイトで公開されていたレポートの日本語訳です。無料で公開されています。

googlesre.page.link

(英語になってしまう人は画面右下の言語設定を「日本語」に設定してみてください)

このレポートは役員レベルを始めとする意思決定者の方々でSREに関心が少なからずあり、自組織でどのように適用していくかについて、手早く理解したいという方々を想定読者としています。

このようなトピックを見て気になった方はぜひご一読ください。60ページ程度の小冊子ですので、時間のない方でもさっと読める分量だと思います。

さらに理解を深めたい方に

本レポートはSREの概要を理解するのには向いていますが、ここからさらに詳細を理解したいという方々には以下の書籍をおすすめいたします。

まずは本レポートの中でも参照されているSRE本こと「SRE サイトリライアビリティエンジニアリング」と、その演習向け書籍となる「サイトリライアビリティワークブック」です。

特に1冊目は書籍内で触れられている各プラクティスが共通言語として参照されることが多いので、通読はしなくても手の届くところにご用意いただくことをおすすめします。

次は明日発売開始の「オブザーバビリティ・エンジニアリング」です。

こちらは特にサービスレベル目標を決めた後に、実際に計装を行ったり、テレメトリーを分析するための基盤を考えたい、という方向けの書籍です。

また既存の監視システムからよりSREを目指した方向に発展させていきたい、という方には「入門 監視」をおすすめします。

この本は直接的にSREという名前は出していませんが、目指す方向性は一致した内容になっていますので、非常に参考になると思います。

本レポートの最後にあるGoogle以外でのSRE導入の事例をもっと見たいという方には「SREの探求」をおすすめします。各社事情が異なる状況からSREの導入を行い、どのようにその運用に至ったかを知る、良い書籍だと思います。

YAMAGUCHI::weblogの2022年を振り返る

はじめに

こんにちは、Cloud Operations担当者です。2022年も最後日となりました。そして私の誕生日です。だんだんと歳を重ねることが億劫になる年齢となってきました。例のやつを貼りました。よろしくお願いします。

www.amazon.jp

2020年、2021年に引き続き、相変わらず新型コロナウイルスの猛威に左右される1年でした。しかしながら経済的な要請などから人出も増え、オフラインイベントも増えるなど、リモートワーク前提だった過去2年からはまた違った気遣いの多い1年となりました。

ymotongpooの2022年

去年立てた目標

毎年思うんですが、翌年に向けて立てた目標はだいたい3月頃には忘れてるんで、このリストを見てびっくりしました。

  • オブザーバビリティ関連の展開
    • OpenTelemetryは安定版がでるので、イベントを行っていきたい
    • Collector関連でOSSを出したい
  • Goコミュニティ関連
    • Go Conference 2022 Springの運営を無事終わらせる
    • Gophers Japanの運営体制を確立する
  • 執筆・翻訳・監訳をすすめる
    • 翻訳はコツコツ
    • いま行っている監訳を終わらせる
  • 自作キーボード
    • 自分でキーボードの基板を設計する
  • キャンプ
    • 引き続きキャンプ道具の洗練をさせていく
    • 悪天候キャンプに慣れる(雨キャンプは未経験)
    • ソロキャンプの充実
  • 語学
    • DELEかHSKを受ける

2022年は会社では1年を通してオフィス勤務となって生活リズムや職務内容もだいぶかわってなかなか思うように出来なかったこともありました。

仕事

今年は社内の仕事で技術的な仕事とプロジェクトリード的な仕事の割合がだいぶ後者が増えてきたので、なかなか思うように時間が取れなかったのですが、いろいろとチャレンジングな仕事が多く出来たかなと思います。

イベント登壇

今年はオンライン、オフライン含めてイベント登壇が多くなった一年でした。公なものだけでも次のようなイベントに登壇していたようです。

またゲストスピーカーとしてパートナー企業のイベントに招待いただいたのもありがたい1年でした。

これ以外にも顧客向けのクローズドなイベントやセミナーなどもあり、登壇が非常に多い1年となりました。

インタビュー記事

SRE関連のインタビューも多く受ける1年でした。

去年の振り返りの記事では「今年は社内仕事がだいぶ多かったので、来年はもう少しブログ等も含めて露出を行っていければと思っています。」と書いていたので、一応目標は達成できたと思う反面、ブログ記事など文章でのアウトプットがなかなか出来なかったので、来年は改善していきたいと思います。

OpenTelemetry関連

メトリクスとログのリリースがだいぶ遅れたので安定版が出るのが遅れた都合もあって、イベントのタイミングを伺っていたのですが、今年はイベントはできませんでした。しかしながら12月に初めて企画したOpenTelemetryアドベントカレンダーでは多くの投稿があり、また1年を通じてOpenTelemetry関連のブログ記事などをだいぶ見かけるようになってきたので、来年はイベントをしたいなと思います。

qiita.com

Collector関連では、自社のプラグイン方面で社内での検証仕事が多かったのですが、来年は率先してコードのコミットも増やしていこうと思います。

zenn.dev

Goコミュニティ関連

次の2つの目標が立てられていましたが、概ね達成されたように思います。

  • Go Conference 2022 Springの運営を無事終わらせる
  • Gophers Japanの運営体制を確立する

これらは一緒にイベントや組織の運営をしてくださっている方々が大部分を率先してくださったおかげで無事に出来たなあという感謝の気持ちでいっぱいです。

gocon.jp

Go Conferenceなんかはもはや自分はちょこちょこと意見を共有するくらいしか出来ていないですが、新しく運営に参加してくださった方々がどんどん新しいことを企画してくれるので、本当に嬉しい限りです。

さらなるGo Conferenceの運営と日本のGoコミュニティの支援のためにGophers Japanという一般社団法人を共同で設立したわけですが、まだまだ財務処理面での課題が残っていて、一般社団法人の設立は大変なのだなと感じています。来年には諸々整って、多くの活動ができるのではないかと期待しています。

執筆・翻訳・監訳

つぎのような目標と立てていました。

  • 執筆・翻訳・監訳をすすめる
    • 翻訳はコツコツ
    • いま行っている監訳を終わらせる

今年は一念発起したこともあり、抱えていた翻訳と監訳の企画3件はすべて初校提出まで終えることが出来ました。数年抱えていた企画もあったので、ようやく終えることができてホッとしています。諸事情で年内の出版は出来ませんでしたが、来年には3冊すべて出版できる見込みなのでとても楽しみな年になりそうです。そのうちの一冊である「オブザーバビリティ・エンジニアリング」は無事に発刊の案内もでてAmazonを始め全国書店で予約が開始されました。

www.oreilly.co.jp

また会社でも翻訳の仕事があり、来年成果として出せるようになったと思うので、来年は成果がたくさん出せるかなと期待が膨らみます。

趣味

自作キーボード

本業の仕事量がだいぶ増えたことや生活の変化がだいぶあったことで、去年にオープンした自作キーボードのECサイトを一旦閉店することとなりました。これに関しても、ただ新規購入を停止してサイトを閉じればいいというだけでなく、予約販売だった商品が納品されて無事に予約された方々に届くまでを見届ける必要があったり、家に残っていた梱包材などの在庫を処分したりと雑多な処理がたくさんあり、思ったよりも大変でした。

キーボードの設計が時間が取れず出来なかったことが心残りですが、引き続きほそぼそと楽しんでいこうと思います。

キャンプ

キャンプに関しては次のような目標を立てていました。

  • 引き続きキャンプ道具の洗練をさせていく
  • 悪天候キャンプに慣れる(雨キャンプは未経験)
  • ソロキャンプの充実

去年に引き続き、毎月最低1回キャンプに行っていたこともあって、キャンプそのものは公園に遊びに行くくらいの感覚でできるようになりました。また今年はあえて雨が降ることがわかっている週末にキャンプ場に行き、雨キャンプを楽しむというようなことをしたので、だいぶ楽しみ方に幅が出てきました。また先日も買ってよかったものの記事に書いたように、ハンモック泊を始めたのでソロキャンプがぐっと楽しくなりました。

ymotongpoo.hatenablog.com

ハンモック泊はテントの中で寝るのと違った開放感や非日常感が得られて、キャンプならではの感覚を得られました。これはとても大きな変化で、非常に充実したキャンプライフを送れたなと思います。

語学

去年に引き続きDuolingoをコツコツとやっていました。去年に引き続き上位0.1%に入ったようです。

去年の段階ではDELE(国際的なスペイン語の試験)かHSK(国際的な中国語の試験)を受けると言っていたのですが、中国語はDuolingoだけでは心もとないと思ったまま教材を探しているうちに1年が終わってしまい、スペイン語に関してはDELEの試験が高いことと受けるのであればB1(英語でいうと英検2級レベル)から受けるべきというコメントを見かけたので、今年1年はDuolingoを多めにやってきました。その結果、ここ最近はYouTubeTwitterに流れてくるスペイン語のコメントもある程度読めるようになってきたので、来年こそはDELEを受験したいなと思うようになりました。DELEは東京だと年4回実施しているのですが、11月の試験を目標にしようと思います。

その他

奨学金完済

この1年の振り返りを書き始めた頃から毎月コツコツ返済してきた日本学生支援機構奨学金を今年の9月に完済しました。詳細は次のエントリーに書きました。

ymotongpoo.hatenablog.com

すべて第一種奨学金だったため、繰り上げ返済のモチベーションも特になく、自分への戒めとして毎月返済を行っていましたが、それもついに終わったと思うと非常にスッキリした心持ちになります。来年は返済に充てていたお金をなにか有益なことに使っていきたいと思います。

来年に向けて

来年はこんな感じでやっていこうと思います。

  • オブザーバビリティ関連の展開
    • SRE関連含めたプラクティスの普及
    • OpenTelemetryイベントの実施
    • Collector関連でOSSを出したい
  • Goコミュニティ関連
    • Go Conference 2023 Springの運営を無事終わらせる
    • Gophers Japanの活動の拡大
  • 執筆・翻訳・監訳をすすめる
    • 新たな翻訳企画
  • キャンプ
    • 1年を通じたハンモック泊の充実
  • 語学
    • DELE受験

2022年に買ってよかったもの

はじめに

こんにちは、Google Cloudでオブザーバビリティを担当しているものです。今年も残すところあと3日となりました。いかがお過ごしでしょうか。

2022年(2021年含む)に買ってよかったもの

去年このエントリーを書かなかったので、ついでなので2年分載せてしまおうと思います。2021年〜2022年は、コロナ禍において、緊急事態宣言で外出もおぼつかなかった2020年から、徐々にその生活スタイルを変化させつつ、人との接触も増えてきた2年間だったと思います。今現在進行形でまだまだ油断が出来ない日々が続いていますが、対面でのイベントなども増えてきました。そんな中、私は相変わらずなるべく感染リスクが高いイベントは避けつつ、適度に気晴らしをするためにこの2年間はキャンプやアウトドアを主な趣味として続けてきていました。2021年に買ったキャンプ系の買い物は次のエントリーに多く書いています。

ymotongpoo.hatenablog.com

ここでは2022年に買い足したキャンプ道具や、それ以外の買い物について良かったものを取り上げていこうと思います。

ハンモック用ギア

2022年の自分のキャンプスタイルでの大きな変化として、ハンモック泊を始めました。これまでは用意周到に、冬は絶対に凍えることのないように灯油ストーブやコット、厚手のインフレーターマットなどを使って、快適さ優先のキャンプをしていたのですが、YouTubeでいろいろな方のキャンプ動画を見ていて、どうもハンモック泊が面白そうだと思うようになりました。そこでまずカジュアルにハンモックを楽しめないかと思い一番上のUnigearのハンモックを購入し、郊外のハンモックが可能な公園やキャンプ場で昼間に寝転がったりしてみたわけです。これが思いの外楽しく、かつ準備や撤収も楽だったので、次のチャレンジとしてハンモック泊をすることにしました。 宿泊となると、ちゃんとしたハンモックや冬に向けた防寒装備が欲しくなります。幸い、ハンモック泊を調べるとすぐに出てくるDDハンモックとDDアンダーブランケットがそこまで高くない価格で買えるとわかったので、早速購入しました。冬用寝袋はすでに持っていたので、これらと合わせて11月末と12月頭に立て続けに道志村にキャンプに行ったわけですが、睡眠中まったく凍えることはなく*1、非常に快適に過ごせて新たな楽しみを見つけることが出来ました。設営撤収も早く、荷物もコンパクトなので、思い立ったときに行きやすいのが最高です。

保冷缶ホルダー

夏に冷たい缶ビールがすぐに温まってしまうのが嫌で購入しました。これはキャンプだけでなく家でも大活躍で、クーラーボックスや冷蔵庫から缶を出してすぐにこれに入れて飲んでいると、手の温度や外気で温まってしまうのが防げて、かなり長時間冷たいビールを楽しめるようになりました。またサーモスからはこれよりも安い保冷缶ホルダーも出ているのですが、こちらのモデルはこれ自身がタンブラーにもなるので、キャンプで荷物を減らしたいときに重宝しました。冷たい飲み物だけでなく、冬には温かい飲み物を入れてもいいのが便利です。

焼肉用トング

これもキャンプでグリルで肉を焼いたり調理の際に細かくものを掴みたいときに便利そうだったので買ったんですが、これが思っていた以上に便利でした。行儀は良くないですが、キャンプではこのままつまんで食べたりも出来ます。ここでこだわりポイントとしては、テーブルに置いて先が地面につかないような形になっているものを選んだことです。やはりキャンプだと土や砂がどうしてもテーブルに乗ってきたりするので、これは大事なポイントでした。これもキャンプだけでなく、家でちょっと調理するときに便利に使えているので、買ってよかったです。

リストウォーマー

冬キャンプにも慣れてきて、防寒着の着方なども覚えてきて外で暖房を使わずに過ごす時間が長くなってきました。より快適に過ごそうと思ったときに、どうしても手首が冷えて指先が冷えることが多かったので、今年の秋からこのリストウォーマーを使い始めました。これが非常に快適で、指が出ているので携帯電話を操作することも困らないし、しかしながら手首は常に温まっているので、手が冷たくなるのもだいぶ軽減されました。本当に寒い場合はこの上から手袋をしているので手首はずっと温かいままです。これまでは上着の袖の部分を締めるなどで対応していましたが、これを買ってからはそのあたりを気にしなくて良くなって快適です。

ミニランタン&マイクロフラッシュ

これまでもLEDランタンは持っていたのですが、夜にトイレに行くときなどに懐中電灯として使いたいときに光が拡散してしまって使いづらさを感じていました。また形も懐中電灯のように前を照らす場合には持ちづらいものだったので、そのように使えるものを探していました。ゴールゼロのミニランタンは昨今のキャンプブームで需要が高まりすぎて常に在庫がない状態が続き、多くの転売がはびこっています。(現在進行系)そして、コピー品も多く出回っています。2個ほしかった自分は1つはゴールゼロの正規品を購入し、もう一つはNaturehike製のコピー品を購入しました。両方とも使ってますが、ともに便利で、ハンモック泊のときは特にこれ1つあれば十分もろもろまかなえ、気に入ったので常にかばんにつけて歩いています。

asics GELLYTE III

5年履いたスニーカーがついにだめになったタイミングで、どうせならちゃんと自分の足に合う靴がほしいと思って試着しまくっていたら、このasicsのGELLYTE IIIの履き心地がとても良かったので買いました。自分の足はいわゆる甲高幅広な上にサイズが25.5cmとかで、いつも探すのに苦労します。国外ブランドの靴を履くと結構きついんですが、さすがアシックス、自分のような足もちゃんとカバーしてくれるんだなと関心しました。

*1:12月頭の方は最低気温が-5℃程度まで下がりました

Goの単一メソッドインターフェースと関数型について

はじめに

こんにちは!!Google Cloudでオブザーバビリティを担当しているものです。年に一度のGoアドベントカレンダーの時期がやってきましたね!本記事は Goアドベントカレンダー 2022 の12日目の記事です。昨日は @Maki_Daisuke さんの担当でした。

Goアドベントカレンダーもついに今年で10年目です!これまでに書いた記事を見るとなかなか懐かしいトピックがあったりしますね。

今年は何を書こうかなあと思ったときに、久々に原点に戻って、Goの設計プラクティスに関して最近同僚と話していて面白かった「単一メソッドインターフェースと関数型」について書こうと思います。

宣伝

ところでGo Conference 2023のCfPがオープンしました。開催は来年の6月、CfPの締切は来月末です。皆様のセッションプロポーザルをお待ちしております!

gocon.jp

単一メソッドインターフェース

単一メソッドインターフェース(Single Method Interface)というのは正式な名称ではないのですが、次のようなインターフェースを指します。

type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}
type Reader interface {
    Read(p []byte) (n int, err error)
}

いずれも標準パッケージの net/httpio から持ってきたものですが、名前の通りメソッドを1つしか持たないインターフェースです。Goにはこういう単一メソッドインターフェースが非常に多くて、これを駆使することで非常に柔軟で強力な型システムが実現されています。

関数型

一方で関数型(Function Type)と呼んでいるのは、あるシグネチャを持った関数を個別の型として宣言しているものです。同様に標準パッケージから例を持ってくると次のようなものがあります。

type HandlerFunc func(ResponseWriter, *Request)
type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)

これらはそれぞれ net/httpbufio から引用しています。関数型は単純に特定の関数シグネチャエイリアスするというだけではなく、「特有の型を作ることで、値として渡すときに制限を設ける」ことができます。

単一メソッドインターフェースと関数型の比較

これらは「特定の関数シグネチャを型として明示的に区別する」という点では同じですが、その性質は異なります。

アサーション

interface{} 型から型アサーションするときに、単一メソッドインターフェースのほうが挙動がわかりやすいです。たとえば次のような例の場合、結果はどうなるでしょうか。

type T struct{}

func (T) ServeHTTP(http.ResponseWriter, *http.Request) {}

func ServeHTTP(http.ResponseWriter, *http.Request) {}

func isHandler(data interface{}) {
    _, ok := data.(http.Handler)
    if ok {
        fmt.Println("a http.Handler")
    } else {
        fmt.Println("NOT a http.Handler")
    }
}

func isHandlerFunc(data interface{}) {
    _, ok := data.(http.HandlerFunc)
    if ok {
        fmt.Println("a http.HandlerFunc")
    } else {
        fmt.Println("NOT a http.HandlerFunc")
    }
}

func main() {
    sh := (T{}).ServeHTTP
    sh2 := ServeHTTP

    isHandler(sh)
    isHandlerFunc(sh)

    isHandler(sh2)
    isHandlerFunc(sh2)
}

よく訓練されたGopherの皆様であれば、なんのつまづきもなくこれらの結果を予想できると思いますが、Goまだ馴染んでいない方だと特にHandlerFuncかどうかの判定で戸惑うのではないかと思います。 sh では、メソッドのレシーバーがあるので実際には func(T, http.ResponseWriter, *http.Request) となっているのでだめ、ということ、後者は実装のまま func(http.ResponseWriter, *http.Request) として見られているのでだめ、ということになります。

これを見るとまだHandlerかどうかのほうがわかりやすい結果になっているかと思います。

型変換

型変換をする場合には、関数型は関数シグネチャだけ合っていれば型変換できるのに対して、インターフェースはメソッド名まで合っていないといけません。次の例を見てみてください。

type T struct{}

func (T) ServeHTTP(http.ResponseWriter, *http.Request) {}

type N struct{}

func (N) ServeDebugHandler(http.ResponseWriter, *http.Request) {}

func main() {
    var (
        t T
        n N
    )

    var _ http.Handler = t
    var _ http.Handler = n // 動作しない

    var _ http.HandlerFunc = t.ServeHTTP
    var _ http.HandlerFunc = n.ServeDebugHandler
}

拡張性

構造体はインターフェースで定義されたメソッドを実装しているかぎり、インターフェースを満たしているとみなされるため、状態を保持するためのフィールドを定義したり、他の補助的なメソッドを追加したりなど自由に拡張できます。一方で、関数型の場合はそもそも関数シグネチャに縛られているので、拡張性はインターフェースと比較すると著しく乏しくなります。

宣言

インターフェースの実装はトップレベルでしか宣言できないのに対して、関数型は関数内でも定義可能です。

type T struct{}

func (T) ServeHTTP(http.ResponseWriter, *http.Request) {}

func ServeHTTP(http.ResponseWriter, *http.Request) {}

func main() {
    var (
        _ http.Handler     = new(T)
        _ http.HandlerFunc = ServeHTTP
    )

    type innerT struct{}

    // 関数内で構造体のメソッドは実装できない
    // func (innerT) ServeHTTP(http.ResponseWriter, *http.Request) {}
    // var _ http.Handler = new(innerT)

    f := func(http.ResponseWriter, *http.Request) {}
    var _ http.HandlerFunc = f
}

メソッド値と関数型

型キャストのところでも少し触れましたが、メソッド値は関数値として渡すことが可能なので便利です。

type Feature struct {
    DryRunMode bool
}

func (f *Feature) RenderDebug(w http.ResponseWriter, req *http.Request) {}

func New(mux *http.ServeMux) *Feature {
    f := &Feature{}
    mux.HandleFunc("/featurez", f.RenderDebug)
    return f
}

使い分け

以上は言語仕様から各々の特徴を確認しただけで、どちらが優れているということはありません。しかしながら、拡張しやすいという点や、総合的な挙動の理解のしやすさを考えると、一旦単一メソッドインターフェースを用意してあげるのがまずは安全なのかなあと思いました。

一方で、逆に拡張性を絞って渡す関数に制限を加えたい場合には、関数型を定義してあげるのも良いかなと思いました。

これらを考えた上で、さらに net/http パッケージの実装を見てみると、関数型自体が単一メソッドインターフェースを実装している(そして、これは単一メソッドインターフェースでないと実装は無理だと思う)関係性が http.HandlerFunchttp.Handler に見られて、本当に美しいな、などと思うのでした。(おそらくこういった実装をしている例は、標準パッケージ内で公開インターフェースで行っているのはおそらく net/http しかないと思います)

// In net/http:
// type HandlerFunc func(http.ResponseWriter, *http.Request)
//
// type (f *HandlerFunc) ServeHTTP(w ResponseWriter, r *Request)
//
// type Handler interface {
//     ServeHTTP(ResponseWriter, *Request)
// }
f := func(http.ResponseWriter, *http.Request) {}
var _ http.Handler = http.HandlerFunc(f)

おわりに

今年の記事は久々にGoの設計についての考察を書きました。Goは言語仕様が軽量なこともあり、こうした考察がしやすい言語になっていると思います。来年も仕事でGoをたくさん活用したいと思います。

明日は @otiai10 さんの記事です。