Goとかの思想的な問題で、外部に公開した部分での仕様変更があった場合にパッケージの名前を変更して対応すべきか
2016·01·22
今宵の月はどうでしょう。こんばんは、@CreatorQsFです。
とか言いつつ寒いだけです。雪はもう勘弁。
今日は、パッケージの更新の話と名前空間的なお話です。
Goの思想を紹介します。
Goにはgo getというコマンドがあります。文字通り、これはgithub等からGoのパッケージを落としてくるかなり優秀なやつなのですが、一点ずっと前から言われていたよくない点を抱えています。それが、バージョンの指定ができないことです。
私たちdeveloperにとって、そのバージョンのみでしか動かないプログラム、などというのはよくある話で、そういうときにその切り分けをしたりsandboxしたりとか色々工夫するわけなのですが、そもそもバージョン指定がないというのはかなり斬新です。
もちろん自分でgitでcloneしてきてbranchで指定とかすればうまくいくわけなのですが、GOPATHは1台につき1つをオススメされていますのであまり賢い方法ではない。
じゃあどうしているのかというと、バージョンアップして動かなくなるというのは、(コード自体に問題がない、つまりmaster branchに傷が付いていない場合に限る)たいていはそのプロジェクトが公開している部分のapiに仕様変更があったりなくなったりしてしまったりする場合です。
どこかで読んだのですが、こんな時Goはどのようなやり方を提示しているかと言いますと…
パッケージ名を変える
です。見た時は何て明快でexcellentなんだ、と思いました。そもそもパッケージを別物にしてしまえばなんの問題もないわけです。これは目から鱗です。
つまり、あるパッケージhogeがpublicなstruct Fooを用意しているとしましょう。これがGetというmethodを持っている時にその引数が(string, int)だとしますよね。
しかしある時以来仕様変更でこの引数が(int)のみとなりました。こうすると今までそのライブラリを使っていたものは当然、このパッケージを更新した時点で動かなくなるわけです。継続的メンテが必須ですねw
しかし、このパッケージ公開者が新パッケージをpresentrabbitにしたとしましょう(特に意味はない)。そしてこれを公開し、今後はこっちのパッケージを継続的にメンテしていきますよと一言添えたら、それを使っているプロダクトはそれを知らないかそれに合わせて書き換えて最新を使うか知りながらにしてそのまま使い続けて自分でpull requestを送るか、の3パターンの余裕ができます。この余裕こそが実は大事なのかもしれません。
…まぁよくよく考えれば当たり前の方法ではあるんです。APIだってv1, v2として公開されているのが結構ありますし。たぶん実際、このようにしている人も大勢いらっしゃることでしょう。
しかし、私はびっくりでした。実にスマートで理にかなっています。
そしてここからが私の書きたかったことです。
名前とはパッケージの衝突を防ぐだけでなく、それは簡潔に分かりやすく示されねばならない。バージョンによる検索のしやすさ、扱いやすさ、導入のしやすさも考えねばならない
仮に、私が今github.com/Qs-F/ossan というパッケージを公開しているとします。package ossan。これが文字通り古くなり、公開部分に調整を加えたくなった時、githubに新しく、github.com/Qs-F/sewashikun を作ったとします。この場合、packageはossanのままで行くか、それともsewashikunにするか。私の迷いどころはそこです。
もちろん、普通の理論ならばsewashikunにするんだと思うんです。このままいけば。でも、ossanとsewashikunの両方を使われることはあまり好ましいことではありません。世に広まるのがossanとsewashikunの両方だと、作った側は困るのです。使われている側にしてみれば古いもので問題が生じた時にsupportしてあげることができないからです。だから、僕は今あえて、sewashikunでディレクトリを切り直してもパッケージ名はossanのままにしてみる作戦を取っています。
またこの利点はソースを後で書き換える時に多くの変更が必要ないという点です。大部分はimport部分を書き換えるだけで済むでしょう。もちろん名前を変更してimportという方法もありますが、それはあまり取りたくない方法なので、これがいいのかななんて思っています。
ただし、変えることにも利点はありそうで、Google検索されるくらい有名になった時に変に交錯しないという点があります。常に最新パッケージに目を通してもらえていれば、それでググってもらえれば過去のパッケージは出てきませんので初心者を突き落とす心配はなさそうです。あくまでも推論上のお話ですが。
あと、goにはgo fixというのがあってですね…これがどうも古いAPIを書き換えてくれるらしいんですが、私は未だに使い方がよくわかっておりません。それくらい過去に作ったものはほったらかしということなのですがw
この記事の重要な点は、小さな変更でもパッケージを変更することにあります。
私は未だにこれについては良い答えが出ていません。そこまで詳しいわけでもないのでもっと高等な人が見たらもっと高等な問題が出てくるお話だと思いますし、これが最善策とは決して言いきれません。
また、それをversionで名前をつけていくと面白みがかけますが、名前からパッケージを推論できないのも困り者ですから、その辺も考えていかねばなりません。
ようは、ちゃんと自分の作ったものには責任を持て。と。また、REST APIのお話を借りると、真に良いAPIは半永久的に仕様が変わることはない、と言われております。そういう先をきちんと見れるdeveloperになりたいものです。
おわり