functional option patternについて

error packageを作るにあたり、調べてみた。Dave Cheneyが出している記事を要約してみる。

Functional options for friendly APIs

golangで分散型のSNSを作ったとしよう。
あなたはserver componentを作った。

いくつかのunexport methodを実行する必要がある。 また、requestを受け付けるためにはgoroutineを動かさないと行けない。 めでたくリリースすると、すぐにいくつかのリクエストがきた。

モバイルクライアントは接続が切れるので、再接続できるようにしたいとか、小さいVPSで動かしているから接続数を制限したいとか、botからの接続を制限したとか、そういったものだ。

スライドに収まらないほど長くなってきたのは、悪いサインだ。これらは明らかに複雑だし脆い。 新規ユーザには、どれが新規機能で、どれがoptionで、どれが必須か、わかりづらい。

問題はわかった。解決策を提案したい。

たくさんの関数を準備した。残念なことに、この数はどんどん増えてしまう。 この方法はどうだろう。

一般的な方法であり、アドバンテージもある。

  • 機能を増やしても、API自体はいじらなくていい
  • ドキュメントも出きる
  • default値でいいものは、設定しなけれいい

だけど、この方法も完全ではない。 ほとんどの場合、ユーザはdefault値でこのAPIを使いたいはずなのに、いちいちからのstructを渡さなくてはならない。 感覚的に、変だとも思う。

可変長引数を使えば、解決できる。 当然呼び出し側にはconfigを一つ設定してほしいわけだけど、複数設定できてしまう。これを改善する方法はないだろうか。

Self referential functions and designというブログポストからのアイディアだ。

最大の違いは、引数ではなくて、関数でserverの設定を変えていることだ。 NewServerでこれらのoptionを適用してしまうほうがわかりやすい。

所感

確かにわかりやすくていい。 ここでは構造体の初期化で利用されているけれど、この方法は構造体の初期化を伴わない関数でも使えそうだ。