ネタ元
業務系のJavaプログラマーが知っておくべき10個のBad Partsとその対策
結論から先に言うと、3と10以外は結構直接的にscalaで解決できるというか、javaに比べてscalaの方が便利だとおもいます。*1
あと、元ネタのblogの人はgroovy詳しいみたいですが・・・
groovyとscala比べるとgroovyの方が手軽で便利だったり、scalaのほうが型安全だったり*2いろいろあるかもしれませんが、groovyあまり詳しくないので、その辺の言及というか、比較はやめておきます。*3
1.標準APIのチェック例外が扱いにくい
チェック例外ってなにそれおいしいの?(・ω・)
java
Field field; try { field = getClass().getField("testField"); Object value = field.get(this); } catch (SecurityException e) { // 例外処理 } catch (NoSuchFieldException e) { // 例外処理 } catch (IllegalAccessException e) { // 例外処理 }
scala
val field = getClass.getField("testField") val value = field.get(this) //例外処理書きたくないなら書かなくていいよ
2リソースの解放処理の適切な記述が面倒
scalaは、リソースの開放の処理分離して書けるんだぜ
// tryブロックの外で宣言 Reader in = null; try { in = new BufferedReader(new FileReader("ファイル名")); // 入力処理 } catch (IOException e) { // 例外処理 } finally { // finallyブロックで後処理 if (in != null) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } }
元ネタのblogでもコメントで言及されてますが、C#的なusingという制御構造*4を定義しておけば、
using(new BufferedReader(new FileReader("ファイル名"))){ in => //inがBufferedReader型になり、それを使用した処理をここに書く。 }//この時点で、自動で閉じられる
という感じで書けます。
3 日付関連APIの使い勝手が悪い
scalaの標準ライブラリに専用のものはないので、とりあえずはJavaのモノ使うしかなく、使い勝手は悪いです(・ω・`)jodaTimeとか使ってください。immutableでscalaと相性いいし。まえにjodaTimeラップするようなちょっとしたDSL作ったことがあります。
追記:
jodatimeをwrapしたscala-timeっていうのがあるらしいです*5
https://github.com/jorgeortiz85/scala-time
4 BigDecimalを使った固定小数演算が面倒
scala.math.BigDecimalっていう、javaのBigDecimalをラップしたものがあります。
java
BigDecimal num1 = new BigDecimal("123456.789"); BigDecimal num2 = new BigDecimal("111.111"); BigDecimal result = num1.multiply(num2);
scala
//new も不要 val num1 = BigDecimal("123456.789") val num2 = BigDecimal("111.111") // * で演算できる。* はscala.math.BigDecimalのメソッド val result = num1 * num2
かけ算するのにmultiplyって書くのはめんどくさいよね・・・
すべてがオブジェクトで、すべてメソッドで処理しよう!そしてメソッドには省略せずにわかりやすい名前付けよう的なJavaの文化はいいときもありますが、こういう場合くらいは短く書きたいよね。
scalaなら、methodの名前に記号が使えるので、上記のようなことができます。
5 標準の文字列演算APIが限られている
StringUtils.isEmpty(str);
なぜisEmptyを例に出した・・・
nullと空文字かをチェックするなら大してめんどくさくないっていうか。*6
isBlankならわかるけど・・・*7
まえそのisBlankについてscalaに書き直す方法的な感じで書いたことあったな・・・
複数文字列からの文字の生成については
javaの場合、apache commonsを使って、こうなるけど・・・
String[] strArray = {"data1", "data2", "data3"}; StringUtils.join(strArray);
scalaなら、
//標準ライブラリしか使ってないよ! Seq("data1", "data2", "data3").mkString(",")
あと、Stringのmethodに関しては、scalaでも、implicit使うことによってWrappedStringというものに変換され、自動でjava.lang.Stringにmethod追加されたような感じで便利に使うことができます。*8
6 正規表現APIを使うのが面倒
Rubyとか正規表現リテラルがある言語に比べればちょっと使いにくいかもしれませんが、Javaよりは確実に使いやすいものが、標準ライブラリにあります。
一番便利なのが、 r という名前のメソッドで、Stringから簡単に正規表現のオブジェクトをつくれることでしょうか?
あと、パターンマッチの構文と統合されていたり。
ちょっとそのほかいろいろ解説するのは大変なので、あとはググッてください(・ω・`)
7 長い文字列の記述方法が面倒
scalaも同じで、「”””」という3つのダブルクォーテーションの文法あるので、略。*9
Groovyには「'''」「"""」という3つのクオーテーションを使って長い文字列を定義する仕組みがあります。
8.基本型とラッパークラスの存在
scalaではIntやDoubleも全部オブジェクトですよ。基本的には意識する必要ないようにできてます。それでいて、primitiveのままでいいところは、実際のbytecode上ではprimitive型のまま扱ってくれて、パフォーマンスもそんなに問題になりません。
9 配列型とコレクションとの不統一
scalaでは、引数なしのメソッドはカッコ省略できるので、*10この問題発生しない*11
配列はlengthフィールドで長さを取り出すのに、Listはsize()メソッドで長さを取得するなど、まるで統一感がありません。
Genericsについては、もう一つ大きな違いとして配列と違いコレクションの型は反変性
scalaには、Listなどのimmutableなclassが共変(covariance)になっているので、List
http://d.hatena.ne.jp/j5ik2o/20101106/1289028031
http://d.hatena.ne.jp/NetPenguin/20091012/1255356344
そういえば、配列とその他のコレクションに関する統一的な扱いについては、まえに書きましたね。それでもすべてを語ってるわけじゃなくて一部だけど
あと、Tが総称型のとき以下のjavaコードがコンパイルエラーになるっていうことに関しては
T[] array = new T[3];
10 互換性の問題に制約されていること
程度の差はあれ、どんな言語でも年月が経てばしかたないっていうか・・・後発の言語がうまくまとまっていて、使いやすいのはあたりまえなので・・・ライブラリに関しても。
あまり詳しくないけど、政治的な問題もあってかたしかにJavaの進化のスピードは遅いかもしれないけど*12
*1:というか後にも書いてあるけど、10はまぁ個人的には別問題と思うんだが・・・
*3:誰か両方詳しい人がいたらやってほしい
*4:だけど、実は関数を引数に取る関数
*5:自分は使ったことないけど・・・そして最終更新が2009年とかだけど・・・。ちなみにこれ作ってる人はfoursquareで働いてる人らしい
*6:ちょっと話それるけど、nullと空文字か両方チェックしなければいけない状況がおかしい気がする。
*8:このWrappedStringが、2.8からで、それ以前は似たような違うclassだったので、古い本持ってる人は注意
*9:groovyとは色々細かい違いはあるかもしれないけど
*11: この辺は「統一アクセス原則の法則」っていう思想があるらしく、コップ本に詳しく書いてあるので、コップ本嫁。もともと、その思想がEiffelという言語からきてるとか書いてあったような・・・。個人的な思い出だが、C# でもこれがなくて、プロパティだったり、引数なしメソッドだったりで統一性がなくてイライラした覚えがある。