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を適用してしまうほうがわかりやすい。
所感
確かにわかりやすくていい。 ここでは構造体の初期化で利用されているけれど、この方法は構造体の初期化を伴わない関数でも使えそうだ。