BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ ニュース Scalaを新鮮に保つ

Scalaを新鮮に保つ

原文(投稿日:2011/12/09)へのリンク

先週、Scala界隈には、目まぐるしい出来事があったが、Yammerのメールリークが問題の発端である。その後に Typesafeが丁寧なフィードバックと、将来のScalaの改善について述べた 回答を公開した

一番の改善部分は、Eclipse向けのScala IDEが予定されており、これは長い期間、開発が続いている。最初は、 Miles Sabin氏により始められ、今ではこのプロジェクトは、TypeSafeの従業員も開発に加わっており、現在のバージョン 2.0.0-RC2が存在している(訳注:既に2.0.0-RC4になっています)。他のコンパイル済みScalaライブラリのように、特定のScalaバージョンに固有のいくつものダウンロードモジュールがある。2.9.1, 2.8.3-SNAPSHOT、2.8.1のいずれかを使うことができる。

他の有償IDEのベンダーは既にScalaをサポートしている。最近リリースされた JetBrains IntelliJ IDEA 11 には、有償版でもコミュニティ版でも直ぐに使える Scalaサポート が含まれている。

TypeSafeはまた、特定の批判にも答えている。その中には、長い学習時間、ビルド時間、パフォーマンスがあり、彼らの改善目標記事の一部に上がっている。彼らが言っているのは、Scalaの開発は現在も進行中であり、またパフォーマンスは重要であるが、言語が成熟中の間は、未成熟な最適化をやらない、ということである。ビルドに彼らが勧めているのは、 Scala Simple Build Tool、すなわちSBTで、デーモンモードで動くので、ビルドチェーンの立ち上がりにかかる時間を節約できる。Scalaに関わるコミュニティの増加の1つとして、今やScalaもGitHubへ移った。

しかし、バイナリ互換性に対するコメントには、多くの人が満足していない。TypeSafeはサブスクリプションプランを提供しており、これを購入すると Scala+TypeSafeスタックのリリースが有償でサポートされ、メンテナンスされる保証が付くが、 Java, Python, PERLなどのような他のプラットフォームの成長の原因となった、より大きなコミュニティとフレームワークの観点が考慮されていない。彼らが提供するクローズなソース Migration Manager(移行マネージャ)は、ビルド間に生じるいかなるコンパイル時の変化でも、静的に見つけ出すことができる。彼らが言うには、彼ら自身がこのツールを使って Scala 2.9.0が 2.9.1と後方互換性のあることを確認している。彼らはまた、テスティング、IO、Software Transactional Memoryなどの共通ライブラリのように、開発者に必要なものを全てのプラットフォームで提供することを目標にしている、と言っている。

Lift webフレームワークの作成者として広く知られているDavid Pollak氏は、これがピントの合っていることなのか、非常に疑っている。「 Scalaのバージョン間の非互換性は、エンタープライズでの採用をほぼ不可能にしている」の中で、彼は、バイナリレベルでの非互換性が TypeSafeスタック以外での、Scalaエコシステムの成長を直接阻害している、と指摘している。

Scalaの特性は、Scalaコンパイラーが互換性のないバイトコードを生成することです。すなわち、実行コード (JAR やWAR)中の全てのコードは、同じバージョンのライブラリやコンパイラーを使って、コンパイルしなければなりません。もしあなたが自分のプロジェクトで Scala 2.9.1を使っているなら、あなたは Scala 2.9.1でコンパイルされたバージョンのLiftを使ってコンパイルしなければなりません。Liftが依存しているものも全て、同じバージョンのScalaでコンパイルされてなければなりません。Liftが依存しているScalaライブラリを極めて少なくしているのは、これが原因です。

複雑なエンタープライズ型のシステムにとって、Scalaのバージョン非互換性がもたらす2つの大きなコストは、

  1. 全ての依存モジュールは、Scalaの正確に同じバージョンと参照するあらゆるScalaライブラリとでコンパイルされなければなりません。このために、チームが複数ある場合、社内でのビルドが驚くほど複雑、すなわち時間のかかるものになります。
  2. (Liftのような)外部ライブラリは、複数レイヤを持つ依存関係は持つことができません。全レイヤにわたって、あらゆるライブラリのバージョンが、Scalaのバージョンと正確に合っていなければならないからです。

 

他の人々(直接Scalaの経験はないが、意見を持っているかもしれない)とは違って、 Pollak氏は5年の長期にわたり、Scalaを開発言語として使い、そしてより幅広くコミュニティと関わってきたことを誇れる非常に数少ない一人である。 Liftフレームワークプロジェクトの活動とその指針は、Scalaの(いや、実際いかなる)世界において、コミュニティがいかに活動すべきかに関する、素晴らしいモデルである。

このことが影響する問題は、あなたの開発チームが小さかったり、組織でScalaを使っている唯一のチームの場合には、問題とならない。新プロジェクトからScalaにすっぱりと移行する なら、新リリースにかかるこの移行コストは、1日もかからない仕事量である。しかしこれを2チームでやると、突然以前にはなかった調整問題が持ち上がる。問題は指数関数的に悪化していく。

そこで、もしあなたの組織に開発チームが2つ3つあり、全チームがバラバラにScalaコードを書いていても、一般にあなた方が使っていくScalaと様々なライブラリのバージョンについて合意することができる。Scalaやライブラリの新しいバージョンがリリースされた時は、2,3人を部屋に集めてアップグレードすべきかどうか決めることができる。しかし、一旦チーム数が4つ以上になると、調整努力が重要になる。10ヶの様々なチームが Scala、Lift、ScalaZ、Rogue、Dispatchなどのバージョンを調整しようとするのは、多大な労力が必要になる。

ライブラリを作る者として、バージョン非互換性問題は、我々のライブラリは、以前のもの程良いものではなく、我々は自分達が望む方法で、我々のコミュニティにサービスできない、ということである。

Pollak氏は以前にも彼の懸念を表明したことがある。それは10月に公開された Scala採用の障害 、というInfoQの記事の中であった。しかし、彼はこの問題は尚も充分に注目されておらず、ソースが非公開である、バイトコードチェッカーは、根本的な解決ではなく、対症療法でしかない、と感じていた。

私がこの問題についてしてきたことは、何かと言えば。何年にもわたり、この問題を個人的に指摘してきましたが、取り組んでくれませんでした。私はこの問題の一部を解決しょうとプロジェクトを組織しようとしましたが、プロジェクトにボランティアの理解を得ることができませんでした。

1年余り前、2.8の開発サイクル期間中に、我々の何人かが "Fresh Scala" プロジェクトのために集まりました。基本的に、考えはScalaの主なライブラリの継続的統合(CI)を毎週行なうことで、コミュニティとエコシステムがScalaの新バージョンに対して、より良いフィードバックを行うことでした。ボランティア時間の不足で、我々はCIシステムを作れませんでした。それから1年半経った今日でも、我々は同じScalaのバージョン非互換性問題を抱えています。

Fresh Scalaイニシアチブは1年半前には余り注目されなかったが、TypeSafeのJosh Suereth 氏が Scala Fresh 2.0の投稿でその責務について述べている。その中で、彼は Scala Fresh 2.0をGitHubを最終目標にしたプロジェクトの再立ち上げとしてアナウンスした。

Scala freshに何が起きたのでしょうか?

人々は認識していないかもしれませんが、「私」が Scala Freshを怠ったために Scala Freshは失敗しました。私はGoogleでフルタイムで働き、プログラミングし、子供の相手をすることで、その他のことに時間を割くことができませんでした。Typesafe がバイナリ互換性を真剣に考えているために、このようなことは、これから先問題になりません。

私は、"Scala Fresh 2.0"と呼ばれることだけに専念し始めました。すなわちコミュニティのライブラリは、最新バージョンのScalaでビルドされ、デプロイできるようになります。これにより2つの目的を果たすことができます。

  1. Scalaの将来バージョンは、コミュニティのライブラリを壊さないことを保証する
  2. Scalaのコアライブラリは、Scalaのあらゆる主要バージョンに提供されることを保証する。
  3.  

Suereth氏は、バイナリ互換性がプラットフォームではなく、ライブラリ開発者の責任である、と言っている。

バイナリ互換性は、コミュニティ活動です。TypeSafeがリソース面の面倒を見ます。私は個人的にできる限りの取り組みをしています( おそらく余りに多くのボールを操つろうとしすぎています)。しかし、もし私を助けたければ、ぜひ私にメールをください。

最後の指摘は注意に値する、すなわち後方非互換なやり方で成長するJavaコードを書くことは可能である(公開なメソッドを取り除いたり、メソッドのシグネチャを変えるなど)。ライブラリを成長させる際に、メソッドを削除したり、変更すればどんな言語でも、後方互換性問題が起きてしまうだろう。その一方で、ライブラリを後方互換であるように設計することは、多くのJava開発者が自動的にやっていることで、PDEのAPI Usage Scanのようなツールが同様な役割を実行する助けとなる。

しかし、Javaライブラリの成長は幾分予想可能である(クラスは1ファイルに実装されるお陰で)。氏は、Scalaでは、実質interface+実装であるtraitによって非互換な変更を導入する事が可能であることを強調している。

 trait Foo {    def foo = "foo" } trait Foo { // backwardly compatible with the above   def foo = "foo"   def bar = "bar" } --- trait Bar {   def foo = {     " foo"   } } trait Bar { // not backwardly compatible   def foo = {     bar + " foo"   }   def bar = "bar" } 

結果的に、ソースコードに互換性のある変更をすることが可能である( Bar を持つクラスは、両方の場合でコンパイルできる)が、Barの古いバージョンでコンパイルしたクライアントは、bar() メソッドを持ってないので、より新しいクライアントは、実装のないメソッドを呼ぼうとすることになる。

ある種の苦痛の原因は、Scalaの主要なライブラリがいつもこの問題に悩まされていることである。Scalaのcollectionライブラリは、Scalaのリリース毎に手が加えらており、またほとんどのAPIがScala collectionライブラリを使っているので、生成されたバイトコードのコンパイルに使われたScala(そして一緒にコンパイルするコアライブラリ)のバージョンへハードコードされた依存関係が存在する。中には次のような疑問を持ち始めている人達もいる。すなわち、Scalaをコンパイル言語とは見なさないで、2.10の開発パスにあるものとして扱った方が良く、また後方非互換性は解決される徴候がないので、もし2.10で開発していきたいと思ったら、動くことを保証するために、あらゆるものを再コンパイルする必要がある、と言ったほうが安全である、という疑問である。InfoQは先週TypeSafeに、仕事に戻ったらコメントするよう求めたが、この記事の公開前には何の回答も得られなかった。

この記事に星をつける

おすすめ度
スタイル

BT