べつにバイナリ互換の話はScalazに限らないですが、Scalazが7.0.xにおいてmigration-managerを使ってバイナリ互換を保つことを実践している数少ないライブラリで、
「どうするとバイナリ互換が崩れるのか」「逆に、バイナリ互換が崩れない変更とは?」
というノウハウがちょっと溜まったので簡単にまとめ。
まず簡単にmigration-managerの概要 https://github.com/typesafehub/migration-manager
migration-managerとは、Scala自体を作ってるtypesafe社が公開してるライブラリです。略してmimaと呼ばれることが多いです。バイナリ互換をチェックするものです。実際「Scala2.10.1とScala2.10.2がバイナリ互換か?」などをこれ使ってチェックしてます。sbt pluginもあります。*1
Scalazでは、7.0.xからmimaでバイナリ互換のチェックをしてます。(それ以前はやったことない)
mima使ってバイナリ互換維持しようとしてるライブラリは、現状では数えるくらいしかない気がします。自分が知ってるのは、あとplayframeworkでしょうか。ほかになにかあったっけ?あとで判明したら追記するかも github上を検索すると、数十件でてきますね
で、7.0.0をリリースしたあと、実際バイナリ互換維持しようとして、ちょっとだけ問題がでてきました。
というわけで、現在Scalazは7.1.0 finalに向けて開発中ですが、
「7.1.0 final をだした後に、7.1.0 と 7.1.1の互換性を保ちつつ、メソッド追加をできるだけやりやすくするため」
に、
「いままでtraitだったものでも、classに変更できるものはclassにする」
という方針がとられています。*5
あと、「sealed traitへのメソッド追加」の問題に関しては、mimaのsbt pluginは例外としてfilterを設定できるので、現状こんな感じになってます。
https://github.com/scalaz/scalaz/blob/v7.0.2/project/build.scala#L161-L176
さらに、"series/7.0.x" というbranchでは、travisでmimaのチェックが走るようになっています
現状大まかにまとめると、この程度でしょうか。
ただ、「"バイナリ互換を維持するライブラリ"を作る人」以外は、この知識ほとんど必要ないです。が、「"バイナリ互換維持するライブラリ"を作る人」にとってはややこしい問題で、まだmima利用者が少なく知見が溜まっていないので、面倒です。
さらに分かったことがあればまた別の機会に書くかもしれません。
*1:なぜかswingのGUIとかもあるらしいです。使ってる人いるのか・・・?
*2:scalazでは(classにできるとしても)traitが大量に使われている
*3: ところで、Java8からinterfaceのデフォルト実装ができるようになるけど、同じ問題発生するのだろうか?
*4:つまり、そのsealed traitを継承してるのが、privateだったりfinalだったり、もしくはobjectだったり
*5:詳しい事情とか経緯はwiki https://github.com/scalaz/scalaz/wiki/Roadmap#classify-traits とかMLとかissue探せばいっぱいでてきます