シンガポールでアジアのエンジニアと一緒にソフトウエア開発をして日々感じること、アジャイル開発、.NET、SaaS、 Cloud computing について書きます。

その後の新人Javaプログラマ

»

 前回の私のコラムが思いの外、うけたようなので、その続編を書いてみることにする。ドラマでも映画でも、続編が良かったケースはまれではあるが……。

 Javaを使い始めた直後は、新しい開発環境に入るときにつきもののイライラ感があった。何かをやろうとするが、その具体的な実装方法がすぐに思いつかず、Googleを使って調べると確かに実装例が見つかるが、そうやって見付けた方法が本当に最適なのか、今いち自信の持てない状態にあった。しかし、本を数冊を読み終えて、本の中の何処に何が書いてあるのかが把握した状態になり、読んだ本から具体的な方法を素早く見付けられるようになり、さらに、Googleの検索で見付けた方法でも、それを自分なりに評価できるようになってきて、ようやく新しい言語になれつつある自分を感じる。

 さらに、前回書いた私の『不平不満』に対して、いろいろとアドバイスしていただける方がいて、そのアドバイスを取り込んで、私のコーディングの能率も徐々に挙がってきている状況だ。ということで、素人Javaプログラマが約1.5月を経た後、自分なりに得た意見を書いてみる。まず、前回書いた、不平不満それぞれについて。

1.クラスのプロパティーのコードが、Javaでは長くなってしまう。

 Lombokを使えば、ほぼC#でのプロパティの実装と同じレベルの簡潔さなるようだ。Lombokについては、これを読んで一発で概要を理解できた。

2. Javaにはプリミティブ型を表すクラスが、プリミティブ型そのものと、そのプリミティブ型をラップするクラスの2種類あって、それを使い分けなくてはならない。

 auto boxingがJava5以降サポートされたようで、そういう歴史を知らない私はauto boxingは当たり前と思っていた。しかし、それにもかかわらず、両者を使い分けしなくてはならないのは苦痛だと思った。私が苦痛だと思ったのはGenerics collectionで、例えばintそのもの、つまりPrimitiveTypeを格納できないことを知ったときだ。

 なぜそんな制限があるのかよく分からない。C#では、primitiveタイプを堂々とGenericsに格納できる。boxingやunboxingなど不要。というか、genericsを使うメリットの1つがcollection内にprimitiveタイプを格納して、読みだすときもキャストする必要もなく使えることだと思っている。genericsでないcollectionはobjectタイプしか格納できず、そこにprimitive タイプを格納すると、書き込みや読み出しのときにcastが必要で、(auto)boxingやunboxingが発生してしまうからだ。primitiveタイプをgenericsに格納できないJavaでは、genericsのメリットを半分しか生かしていないことになるのではないだろうか。

3.  Javaでchecked exceptionを投げる可能性のあるメソッドを使う場合、そのExceptionをメソッドの定義の「throws」節で、宣言しなければならない。そして、throws節が宣言されているメソッドをコールする側は必ずそのExceptionをcatchしなければならない。

 いただいたコメントで、checked exceptionとunchecked exceptionの使い分け方がよく分かった。つまり、自分で投げるexceptionはよほどのことでない限りunchecked exceptionにする。それもruntime exceptionにするのが良い。checked exceptionを投げるメソッド、例えばもともとのJavaのクラス体系が持つメソッドを使うなどのときはexceptionをそのメソッドを呼び出したメソッド内でcatchし、それに説明を付けてunchecked exceptionでラップして再投入する。Exceptionが発生した原因を一番把握できるのはそのメソッドを使った直近なので、明確な説明を記述しやすい。結果的に、自分で定義するメソッドでは『throws』節はほとんど使わなくなる。コールスタックの一番上で、すべてのExceptionをまとめて処理するプログラム構造を容易に作れる。

4. Javaには.NETのdelegateやラムダ式など、関数を変数として扱える仕組みがない。

 条件によって使うメソッドを切り替えるためには、工数がかかるが、state patternを使うなどして、同等のことを実現できる。また、もちろんReflectionを使えば可能だが、これは多分性能的に問題があるのかと思う。非同期処理を容易に実装するために使うdelegateだが、これにはclosureのサポートが必要だが、そのサポートはかなり前から議論されているようだが、最新のJava7でもまだサポートされていない。

 JavaがSUNからOracleに移るようなごたごたがあったおかげで、言語の進化が止まってしまったかと勘繰りたくなる。AndoroidはJavaを使っているので、GoogleがJavaの進化を進めてくれればよいのにと思ったりもする。とにかく、この辺りの話の解決策は、同じJVM上で使えるScalaを使うしか今は解決策はないらしい。

 問題は、ScalaがかなりJavaと異なる言語になってしまっていること。これはかなり敷居が高い。今回、本を購入してScalaを読み始めたが、最初の1、2章を読んだだけで、他にもっと勉強しなければならないことが持ちあがり、止まってしまった。Scalaを使うプロジェクトにでも当たらない限り、これを勉強するモティベーションが挙がってこないかもしれない。

 ところが、ClosureとJavaをキーワードにして検索して分かってきたが、どうやら来年末ぐらいにGAになる予定のJava8Closureやramda expressionがサポートされるらしい。後一年も先かと思うと、遅すぎ感があるが、少なくともサポート予定があるということで、Javaを勉強する意味はあるようだ。

5. Javaに.NETのLINQに相当するものがない。

 これも多分、Scalaしか解決法がないのかと思う。

 いろいろ勉強した結果分かってきたことを、結論からいえば、Javaでも.NETと同程度の能率の実装を達成することはできそうだが、それには、優秀で経験豊富な上級Javaプログラマが、持っている知識、能力を駆使して、初心者プログラマでも、楽に高能率で実装できる環境を準備してあげる必要にあるのかと思う。具体的には、開発環境であり、各種Frame workであり、Reference実装だ。もちろん、.NETの環境でも、そのような準備は必要だがJavaで準備しなかればならない環境と比較すると.NETではずっと楽にそれを準備できる。

 ということで、大きな受託開発業者、つまり、多くのJavaを使ったプロジェクトが同時に走っていて、少数の高い給与の上級プログラマを複数のプロジェクトの作業にあたらせやすい会社では、Javaでの実装は有利に働くのかと思う。.優秀なプログラマの側も、その能力の違いを差別化しやすくて、高い給与を要求しやすくなる。

 .NETには、上級プログラマはいるが、必要とされるフレームワークなどは比較的小さくて済むので、能力の差別化をしにくい面がある。上級プログラマのの需要も小さい傾向があるのかもしれない。

 そんなところで、Javaがいろいろと欠点はあるが、今もシステム開発の主流である原因かと思った。僕のパーソナルなページに書いたが、シンガポールでのプログラマの報酬はそれほど高くない。インドやフィリピンなどから優秀なプログラマが簡単に参入できるため、報酬が低く抑えられがちなためだ。そんな中で、高い報酬を得るためには、自分の希少価値を高める必要がある。

 私の場合、もちろん日本語を使え、かつ日本の会社文化を知っているということは、日系企業内では大きな希少価値だが、最近はその価値は高くなくなってきている。最近の傾向として、海外に進出する日系企業も現地に出る限り徹底して現地化する傾向が広まっているからだろう。私に残された方法は技術だけだ。ところが、.NETでは、その高い技術を生かす場所は多くない。しかし、Javaなら、結構多くあるようだ。今回の機会ををうまく使って、高いレベルのJavaプログラマになれるように努力していこうと思う。

Comment(6)

コメント

他はともかく、LINQなんかはほとんど.NETが発祥と言っていいのですから、
Javaにないというのはないものねだりなのではないですかね。

自分の慣れた環境と同じものがないから、
新しい環境はだめだ、という発想は、
プログラム業界ではよく宗教戦争を巻き起こしていますね。

プログラム業界以外でもそうかもしれない。
関東に引っ越した関西人なんかがよくそんなことを言っているといううわさがありますが。

私もC#から入ってJavaにちょっと手を出し始めたくらいですが、
たぶん慣れればよい環境だと思いますよ。

C#やRubyなんかのようにプログラムしやすくなるためのいろいろな機能を取り入れるのではなく、
オブジェクト指向という一つの、そして一つあれば十分と言っていい便利な機能を用意し、
それ以外の要素はむしろ極力そぎ落とすことによって、
シンプルにオブジェクト指向という概念を利用することができるようになっています。

その分コードの一行一行を見ると冗長だったりしますけど、
コード一行一行の可読性にこだわらない分、概念的なオブジェクト指向設計がシンプルに見えてきて素晴らしい、
という使い方をするべく設計された言語なのではないですかね。

まあ私はC#のほうが好きですし、開発生産性も高いと思いますが。
Javaが好きな人の気持ちもわからないことはないと思いますね。

LINQはC#に今はありますが、たぶんC#を使う現場で実際に使っているところはたぶん少ないのではないのかと思います。理解するにはかなり、難易度が高いですし、使わなければそれで、使う必要はありませんので。さらに、LINQがC#でサポートされたのは、かなり最近です。ということで、JAVAでも後ずけでサポートすれば良いのにと思うわけです。サポートされていいても、使う必要はありません。たぶん大きなプロジェクトでは、LINQは使えないでしょう。使えるプロジェクトは、少数先鋭のプロジェクトのみになるのかと思います。

はい、そしてオブジェクト指向をよりピュアーに実装できるのはJavaだと思います。Javaではinterface ベースを理論道理にできますが、C#だとできないことが多い。しかし、これからは原点戻りで、C++かもしれませんね。

LINQを理解する難易度が高いってのはデマじゃないですかね。

SQLがわかれば大体同じように書けばいいですし、
またPerl,Ruby,PythonやScalaなど、クロージャがある言語のコレクションを使ったことがあるなら、同じように書けばよい。
これが難しいってことはないと思いますが。

内部までわかって使いこなすのは難しいですけどね。
遅延処理とか。

あと、LINQ to SQLやEntity Framework、WCF Data Services、WCF RIA ServicesからReactive Extensionsまで、最近はLINQを知らないと使えないライブラリが多いです。
今後C#でプログラマーをやっていく予定があるなら、
覚えておかないとまずいでしょう。

まあ今のところ少数精鋭のプロジェクトでしか使ってないというのは、
そうかもしれませんが。
みんなまだTableAdapterでやっているんですかね。

C#を使う現場が少ない云々の話は、私の少ない体験に基づきます。約10人程度のプロジェクトで、LINQを使える人、というか知っている人はゼロでした。たぶん、C#が出た始めの頃にそれを勉強して、プログラマになったのでしょうが、その後のC#の進化を勉強していないのです。シンガポール特有なのかもしれません。少数先鋭なら、長期のプロジェクトですから、リーダがリードして、スタッフに勉強させるようなこともできますが、短期ではそれも無理ですから、彼らは今まで覚える機会がなかったのでしょう。、こちらのプログラマは、あまり勉強しないように思います。難易度が高いと思うのは、遅延処理もありますが、ループ処理ゼロを目標に、Listだけでなく、Dictionary、さらにDictionaryの中のDictionaryなどどいうような、かなり複雑な構造を、LINQで作るようなことをやり出すと、自分でもわけが分からなくなります。

なるほど。そういうことでしたか。

使っている人が少ないのは日本でも同じじゃないですかね。
ただ、難易度が高いとこういうところに書いてあると、
ますます勉強する人が少なくなるんじゃないかと思ったので、
コメントしてしまいました。

職場で使ってみたところ、
その後そんなにプログラムが得意ではない同僚も使ってみてはいたようなので、
難易度が高いということはないと思います。

>ループ処理ゼロを目標に、Listだけでなく、Dictionary、さらにDictionaryの中のDictionaryなどどいうような、かなり複雑な構造を、LINQで作るようなことをやり出すと、自分でもわけが分からなくなります。

それは使いどころを間違えているように思えます。
LINQを使うと、複雑な処理が一文でかけるため、全部一文で書きたくなりますが、
複雑な処理は適宜分割すべきなのはLINQでも変わりません。

ただ、あまり分割したくないという心理になりがちなのは、LINQの欠点かもしれません。
その辺はSQLと同じですかね。
巨大なSQLはたまに見かけますが、たいへん保守性が悪いです。

アラファイブ

先日人生で初めて、VB2010の仕事をしましたが、ひな形のソースを見るとなんの断わりもなく、
For文にFrom Where Select(Selectは省略も有り)と書いてありました。

何らのImportsも書かなくて良いですし、もうVB2010では取り立てて『『LINQ』』と
技術の名前を言うまでも無い位置づけになっているのでは無いでしょうか?

コメントを投稿する