https://2019.scalamatsuri.org/#conference-day
2019-06-28 10:10 から @ C会場
「コードの再利用」がいかに強力であるかについては議論の余地はないでしょう。我々は何度も誰かがどこかで解いたことのある問題を繰り返し別の手段で解く必要などないのです。そのための仕組みが「ライブラリ」になるわけですが、当然作っておしまいではダメで、利用者が今後も困ることなく使っていけるようにメンテナンスされる必要があります。この発表では
- 複数Scala/JDKバージョンへの対応
- バージョニング
- バイナリ互換性
- Javaとの相互運用性
といったScalaライブラリを長く適切にメンテナンスしていく上で知っておきたいトピックについて解説します。
発表者: 渋谷 充宏 氏
(株式会社オプト データテクノロジー開発部 チームマネージャー)
自己紹介
Scalaガチ勢ではない
「Scala は 型のあるRubyだよ」派
前提
問題意識
再利用可能なコードを書くにはコストがかかる
多くの人に使ってもらえないと、作った甲斐がない
使われない理由
- 知名度、期待との乖離、使いにくい
- 特定環境でしか動かない、簡単に壊れる
後者2つの対策が今日のScope
多くの話が
https://github.com/opt-tech/bigquery-fake-client
の経験がベース
複数 Scala / JVM / JDK バージョンへの対応
作る分には特定バージョンだけに対応するのが楽だけど、そのぶん使ってもらえなくなる。
JVMバージョン
Version間で後方互換性があるので、
一番小さいJDKでCompileすればOK
Scalaバージョン
2つめの数字が変わると互換性がない
その分だけビルドが必要
SBTの機能で crossScalaVersions を使う
sbt> +complile // この プラス が肝。
意図せず壊れないようCI
クロスビルドの機能は有名所のCIならあるはず
Javaとの相互運用性
Javaから呼んでもらえるようにするには
ScalaのがJavaよりも言語機能が多いため、呼び方がトリッキーになることもある。
Some of Scala features are specially encoded to JVM bytecode.
Singleton object は Javaから呼ぶには謎の$を書く必要がある
Companion object なら自然に呼べる。
Javaから呼びやすくするには
以下のアプローチがある。
- Scala特有の機能を使わない
- https://github.com/scala/scala-java8-compat みたいなツールもある
- JavaでWrapperを書く
テスト
JUnitで書いてScalaプロジェクト内から呼べる
互換性
ソース互換性
「ライブラリのバージョンを上げたらビルドが通らなくなる」のがソース非互換。
ちなみに「バイナリ互換だけどソース非互換」というケースも有る
例: メソッドをPackagePrivateにした
バイナリ互換性
「ライブラリを新しくコンパイルして差し替えたら動かなくなる」のがバイナリ非互換。
JVMの仕様としてLazyにロードされる
見過ごしやすい
dependency hell になる原因。
どういうときにバイナリ非互換になるか
例1: adding method parameters with default values
配慮できてるように見えるがメソッドシグネチャ変わってるのでアウト!
他にもいろいろ
ツールで解決しよう
MiMa is the standard and easiest way for checking binary compatibility.
http://kmizu.hatenablog.com/entry/2016/03/16/203416
https://github.com/lightbend/mima
バージョニング
バージョニングは、ユーザーとのコミュニケーションの手段
非互換だよ、というのを伝えながら出す手段
Scalaの世界では2つある
Semantic Versioning
これは他の言語でも広く使われている
https://semver.org/lang/ja/
Java/Scala Style Versioning
正式な名前はないと思うけど、みんなこんな感じで呼んでる。
epoch.major.minor
epoch
謎です。でっかい根本的な変更で上げる、みたいな。
major
非互換なときに上げる
minor
互換なときに
どっちを使う?
今から作るならSemVerだと思う。
どっちにしても、明示することが大事。
ユーザーが混乱しないように。
メジャーどころだと
Play: epoch
Cats: Sem
それぞれちゃんと宣言している
めちゃ使われてる場合
Persistent Versioning
もう名前も変えちゃう。
アパッチとかで使われている
Changelog大事
https://keepachangelog.com/en/1.0.0/
がシンプルでわかりやすい
QA
Q1. 依存性地獄にハマった時の解決エピソードを聞きたい
A. まぁ上げれないよね。根気との勝負になる(笑)
Q2. 質問というか補足です
Java/Scala Style Versioning
正式な名前はないと思うけど、みんなこんな感じで呼んでる。
epoch.major.minorepoch
謎です。でっかい根本的な変更で上げる、みたいな。
Epoch は、もともと Linux の Debian系にて、
バージョニングルール/体系 が変わったときに上げる、という位置づけで使われていたもの。
「これまで末尾を英数字でやってたのが、次から数字でやっていきます」みたいなときに。
Q3. Q2について
Scalaの 2 から 3(Dotty) はそうではない(バージョニングルールを変えたいわけではない)ですよね。
Java界が曲解した?
Q2の方
たしかにその意味では「謎」と言える