Javaプログラマが初心者を卒業したと言えるのは?

あけましておめでとうございます。今年もよろしくです。今年の4月で入社8年目に突入するなんちゃってSEです。
僕は入社して7年間それほど多くないにせよJavaのコードを読んだり、書いたりしてきました。それで今まで見てきた(聴いてきた、書いてきたw)イケてないコードを思い出しつつ、どこまで理解していれば初心者レベルを卒業して中級者の仲間入りといえるのかを独断で書いてみたいと思います。

1. 文字列を==で比較したり、equals(null)と書かない

僕はこれをやった記憶は無いのですが、少なからずこういうコードを見たり、聴いたりします。要するにJavaの基本型と参照型を理解していないということですね。
書籍やネットに落ちているコードをコピペしているうちはこうはならなそうなんですけどね。やっかいなことにコンパイルは通るし、単体テストでも漏れがちなのでそのまま出荷というパターンが結構ありそう。静的解析ツールでチェックするのが効果的かな。

2. staticフィールドをグローバル変数として使わない

やった記憶あるわ(汗)。基本的に定数以外のstaticフィールドは(Singletonパターンとかをのぞけば)たいてい間違いでしょう。これもまず単体テストは通るし、さらに上記よりたちが悪いのはバグが見つかったときの原因究明が難しくなること。

3. クラスパスを理解している

NoClassDefFoundErrorが出ても対処できるよねってことです。要は自力で環境構築できるってことですね

4. 例外処理を理解している

これはちょっと難しい。ただそう遠くない昔の僕がそうだったように、「例外処理? ああ、なんかcatch節を書かないとコンパイラに怒られるから、catchしてprintStackTraceしてるよ。何か問題ある?」ええ問題ありですねw その例外は回復可能なんでしょうか不可能なんでしょうかという設計上のこともあるのですが、現実的にはすべて回復不可能と見なして実行時例外でラップしてthrowしてエラーページに飛ばすのが簡単でしょう。てか開発担当者にcatch節を書かせないようにすべきでしょう。
例えばBeanUtilsのcopyPropertiesは以下のようにthrowsを持ちます。

    public static void copyProperties(Object dest, Object orig)
        throws IllegalAccessException, InvocationTargetException 

これをそのまま使うとcatch(throwでもいいけど)を書かないといけなくなります。
StrutsのActionのexecuteメソッドだとthrows Exceptionなのでcatchを書かなくていいわけですが、それ以外だと書く必要があります。

その場合、以下のようなラップクラスを提供すればcatchを書かなくていいよね。

package aaa;

import java.lang.reflect.InvocationTargetException;

public class BeanUtilsWrapper {
	public static void copyProperties(Object dest, Object orig) {
		try {
			org.apache.commons.beanutils.BeanUtils.copyProperties(dest, orig);
		} catch (IllegalAccessException e) {
			throw new RuntimeException(e);
		} catch (InvocationTargetException e) {
			throw new RuntimeException(e);
		}
	}
}

また例外処理をコンパイラに強制されてないけど例外をthrowしたほうがいい場合もあります。

例えばWebアプリで入力JSP上のラジオボタンでmanとwomanのどちらかを選択してサブミットし、その結果をDBに格納という処理があるとします。
サーバ側のコードが以下のようになっているとまずい場合があります。静的解析ツールを使うとelseを書いてないと怒られるが、初心者だとまず「で、どないせえっていうねん」てなると思います。

String gender = ...
if ( gender.equals("man") ) {
...
} else if ( genger.equals("woman") ) {
...
}

DBに格納

このコードの危険性はmanとwoman以外のもの(例えばikkoとか)が来たらその値がDBに格納されてしまうことにあります。そんなんあるわけないじゃんって思いがちですが、ユーザが入力JSPをローカルにHTMLとして保存して編集したらってことです。なのでelseを書いてそこでIllegalArgumentExceptionとかをthrowすべきでしょう。

あとthrowする実行時例外も以下の3種類に分けてそれぞれエラーページを用意したほうがいいでしょう。

  • ユーザエラー
    • ユーザの不正操作など
  • アプリケーションエラー
    • アプリのバグなど
  • システムエラー
    • DB、ネットワーク障害など

5. リソースのクローズをfinallyでしている

6. System.(out||err).printlnじゃなくてロガーを使っている

7. デザインパターンを(ある程度)理解している

ま、SingletonだけじゃなくてTemplete MethodとかAbstract Factoryなんかも知っているとコードが読みやすくなるよね。

8. スレッドを(ある程度)理解している

スレッドはまあGUIとかスケジューラとかを作るのでない限り、使う必要は無いと思います。難しいし。ただWebアプリでは裏で出てくるので、StrutsのActionとかサーブレットインスタンスフィールド書いちゃだめっていうことは理解していたほうがいいでしょう。

9. セッションを(ある程度)理解している

Webアプリ限定ですが、知っておいたほうがいいかと

10. シリアライズを(ある程度)理解している

僕は最初シリアライズの意味がわからなかったです。サンプルコードとかを見て意味はわかったけど、いつ使うの?って感じでした。GUIだと使うのかな。
まずつかわないでしょうけどWebアプリではHTTPセッションのように裏で出てくるので知っておいたほうがいいかと

11. リフレクションを(ある程度)理解している

これもフレームワークを作るのでない限りまず使わないでしょう。ただ逆にいうとこれを知っているとフレームワークのコードが読めるので知っておいたほうがいいかと