まえがき

2012-1-28追記


JavaWorld, JavaPressなどのJavaの雑誌が無くなったのが2007年頃でしょうか。Web+DB PressやDB Magazineでたまに出てくると大抵スクリプト言語の実行環境としてか、Javaライブラリの呼び出しの話となりました。

Javaという単語が出てくるのは、TwitterがRubyをやめてScalaにしたとか、JRubyとか、Grailsとかで、どうも開発言語としてのJavaは話題になりません。

ScalaがJavaの発展系に思えて胸がときめきますが、このまま業務ソフトに使うのはどうか(ただしLiftフレームワークでラップすると多少楽になりますが)と思いますし、Rails系は確かに作るのは早く楽にできますが、一旦エラーになったときはデバッグ地獄です。

Spring CommunityがRooというRails的にコマンドでMVC+ORマッパーを自動生成するというツールが気持ちをやわれげてくれました。

日本ではSeaser ProjectとJavassist(JBossでも採用)の活躍が勇気を与えてくれました。

それにしてもJavaエンジニアは少し疲れているようです。 サーブレット, RMI(CORBA), JTS-JTA, Jini, EJB, Taglib, XML-XSLT-DOM-SAX, Struts, JSF, Hibernate, Spring.. と苦労して習得した技術が努力にみあうものだったのか考えてしまうのは、私がなまけものなせいだけではないと思います。

C言語は表面上は目立たなくなっていますが、OS、JavaVM、RubyVMなどほとんどの実行環境がすべてC言語で書かれています。Java言語もScala、JPython, Groovy, JRubyなどのライブラリ開発言語として残っていくと思われます。

まあ今からjavaをはじめたい人は少ないとは思いますが、本「Java道場」はまだ消さないでおきます。


短いサンプルによる成功体験が言語習得の早道と思い、簡単なサンプルを列挙しています。また、初級者が一度は通る失敗コードもいくつか含んでいますので、「失敗する」という句を見かけたら注意して見ていただきたく思います。

JavaFAQの内容が理解できるレベルが第1目標です。マルチスレッド、コールバックメソッド、CORBA/RMI、トランザクション(分散を含む)などJavaへの道は遠いですが、まずはバッチ(他のプロセス、スレッドとデータを共有しないプログラム)が自由自在に作れるようになれば業務プログラマとしてはたいてい大丈夫です。

それにしても最近はJavaを使った大きなプロジェクトの失敗が良く聞かれます。

凍結されずに実装中に変わる仕様、整合性のない設計書、経験の少ないコンサルタントと場合によりいろいろ原因はありますが、 Javaにもあまりに選択肢(staticメソッド/インスタンスメソッド、デザインパターンを使う/使わない、クラス名や定数をXMLファイルやプロパティファイルに持つ/持たない、機能の拡張に継承を使う/委譲を使う、使うフレームワークやライブラリ、テストツールなど)が多すぎて、プロジェクトとしての統一感を持つのが難しくなっています。

もちろん、コーディング規約とフレームワークでがちがちに縛ることも可能ですが、どこまで縛るのかと、どうチェックするかが問題です。またXML設定ファイルに膨大な記述が必要なフレームワークが多くてjavaの生産性に疑問も出ています。

後で書きますが、私が実プロジェクトで提案・導入して一番感謝されたのがJtestによるコーディング規約チェックと、JavaExcelライブラリによる設計書(設計書間を含む)のチェックでした。コーディング自体でないところがオジさんの悲哀かもしれませんが、アンチパターンの共有とチェックこそJava/オブジェクト指向に関係なく必要です。javaはそれがしやすいというメリットがある分救われているのかもしれません。

作者:城風敏彦 

http://www5.plala.or.jp/shirokaze/

でご意見お待ちしています。コードの業務での利用は自由ですがメールを下さるとうれしいです。意外に和暦クラスのお問い合わせが多いです(^^)

言葉の洪水

Javaやオブジェクト指向を勉強するとまず言葉の洪水に驚かされます。 "JDK"が"Java Development Kit" の略であるように、"J"ではじまるとたいてい"Java XXX YYY"の略です。 JRE,JTA,JTS,JSP,JSTL,JDBC,JFCなどきりがありませんが、何の略かくらいは 覚えておかないと、それが必要な打ち合わせでくやしい思いをしがちです。

あらかじめ、 Java FAQ、特に、 Java API FAQ : かんたん Java API 一覧/Java 略語一覧 で言葉に慣れておいた方がよいです。ここでわからなければウィキペディアGoogleで 打合せの前に調べておきましょう。

開発環境

2001年にJavaの開発環境の50%はエディタとJDK(Ant)でした。2006年には60%がEclipseとなり、その他はNetBeans,JBuilder,エディタ+Antが分け合っていました。近年は JBuilderも2008からEclipseベースになり、Javaの開発環境はEclipseの独占的状態は不変ですが、NetBeansの奮闘も見逃せないといった状態が当分続くでしょう。JDK/Ant/Mavenはアプリケーションサーバーへのリリース担当者だけは知っているべきでしょうが。

Java道場(開発環境編) に開発環境のメモを書いたので、時間のある方は見てやって下さい。

オブジェクト指向

オブジェクト指向とは?

Googleで「オブジェクト指向とは」で検索すると、いろいろな観点で使われていることだけはわかります。

みんな自信を持って書いているようですが、Javaの実際のプロジェクトでは主流と思われたフレームワークが5年もたつと見向きもされなくなっています。EJBなどJava標準の技術、Strutsなどの有名なフレームワークは2000年から2005年くらいまで一世を風靡しましたが、2011時点ではレガシーとか存在自体が誤りだったといわれるし始末です。「J2EEパターンはEJBの使いにくさを解消するためのアンチパターン集」という文章が特に耳に残っています。

オブジェクト指向コンサルタントいわく

  • ifやSwitchは境界クラスのファクトリメソッドに集約すれば、機能内部の条件分岐が無くなって見通しがよくなる。1画面のクラスが何百個にもなるがそういうもの。
  • 1機能で使うデータはXXXContextという名前で集約して、関連する全クラスから参照、更新できるようにすれば、全メソッドの引数はXXXContext 1つになるので、実装が簡単になる。
  • 入力データを処理するメソッドの引数は抽象クラスにしておいて、機能の中で個別にダウンキャストしてして用いればよい。
  • 似たような画面の入力データは、既存の入力データクラスを継承して作っていけばよい。
  • 既存のクラスの表示形式を変更したい場合は、継承してtoString()をオーバーライドすればよい。
  • 巨大なSQLを出力するクラス群は、共通部分を抽象クラスを階層的に構築していく。
  • 画面に表示するオブジェクトを個別に取得していてはパフォーマンスが悪くなるので、1つのオブジェクトに集約して取得しよう。
  • データはいつ変更がはいるかわからないので抽象クラスにしておいて、機能は継承したクラスで実装する。

よくよく聞いてみるとCOBOLやCの発想と大差ないことが多いです。

結局のところ以下の2つの観点がからみあって、いったいどちらについて語っているのか誰にもわからないということでしょうか。

  1. プロジェクトを効率良く進行させるため機能を疎結合にしてスタブを作成し、平行開発を行う。
  2. プログラムの保守性を向上させるため、主にフレームワークを導入して異なる機能が同じ構造(入力チェック、DBアクセス、外部通信、ファイル出力、等)にしてソースを理解しやすくし、機能追加箇所をわかりやすくする。

継承と委譲と集約

JavaのクラスはObjectというクラスを頂点にした巨大な階層ツリーとなります。プログラマはその巨大なツリーのどこかに自分が必要なクラスに似たクラスがあるかを探し、ある時は継承し、あるときはラップして自作クラスを作ることになります。

以下にエラー処理に使う例外(Exception)関連のクラスの階層を書きます。ThrowableはObjectを継承し、ExceptionはThrowableを継承しています。プログラマが新規に作成するのは下で普通の例外(チェック例外ともいわれます)と書いたところで、Exceptionを継承するか、SQLExceptionなどのExceptionのサブクラスを更に継承するかします。

Object

  • Throwable←すべてのエラーと例外のスーパークラス
    • Exception←例外。制御しうる。
      • RuntimeException ←例外ハンドル処理がコンパイル時に要求されない
      • (普通の例外:SQLException等) ←例外ハンドル処理がコンパイル時に要求される
    • Error ←エラー。制御しようがない

雑誌などでは以下のような生物階層が良く出てきますが、プログラムとしてどうしたらよいかは不明です。メソッドとしては生まれる、成長する、繁殖する、戦う、共生する、死ぬなどでしょうが。

コンピュータシステムでは以下のような会計の勘定科目の方が集計という操作に使うので わかりやすいと思われます。ただしこのまま現金クラスのような細かいクラスを実装することはまずしないでしょうし、流動資産もクラスというより分類のためのインターフェース(実装のないクラス)でしょう。勘定科目クラスのインスタンスとして現金と名前のついた勘定科目インスタンスとするのが普通でしょう。

勘定科目

  • 資産
    • 流動資産
      • 現金
    • 固定資産
      • 機械及び装置
  • 負債
    • 流動負債
      • 支払手形
  • 資本
    • 資本金

いつになったら自信がもてるか?

Javaプログラミングは作成するのは比較的容易ですが、自信をもつことがむずかしいです。

テストコードを書いて1メソッドあたり正常系2、異常系3のテストをしたとしても、すでにある機能を実装してしまったのではないか、性能は悪くないか、nullに対してメソッドを呼び出してNullPointerExceptionが発生して業務が止まるケースがおきるのではないか、マルチスレッド環境で値が思わぬものになってしまわないか、とか不安はつきません。

2000年頃デザインパターンという変更に強くて成功しやすいパターンがあるというので読んだ私は、少しでも修正の余地があればインターフェース、抽象クラス、実装クラスの3つ組みでコーディングし、実装クラス名は外部ファイルに書いてClass.forName(String).getInstance()でインスタンス化しなければかっこ悪いと思いこんでしまいました。

その後、デザインパターンの使いすぎが最大のアンチパターン(失敗につながる爆弾)ということを知り、羹に懲りてインターフェースを自分では宣言しなくなりました。32行中に16種類のパターンという笑い話も聞きましたし。

Struts,Seaser2などのフレームワークを使えば自動的にコマンド、テンプレートなどのデザインパターンとインターフェースを使うことになるので、まずは理解して使うのが先決です。

教科書やWebのサンプルコードは極端に単純化されていてそのまま業務で使うとコンパイルできない、例外処理がない、ログ出力がない、コメントがない、マルチスレッドでこけるなどのえらい目にあうこともあります。JavaVMのバージョンが違うだけで結果が変わることもあるので、全て自分でテストしなおすことが自信への第一歩です。

私もたいして自信はありませんが、以前に比較してすこしは自信は持てるようになったのはJtestなどのアンチパターンを理解できるようになった時です。また面倒でも単体テストにSystem.nanoSec()で処理時間を含めておくのも自信になります。

単体で異常系テストや性能にこだわっていると、結合テスト、回帰テストでの障害点も見当がつくようになり、みんなに感謝されて生きがいを感じられます:-)

Java道場のサンプルコードも性能を含めた単体テストと業務で使える異常系処理をめざして加筆、修正つもりでおりますのでご期待ください。

基本文法

フレームワーク

実践

クラス、staticメソッド、コメント,標準出力

  • 最初はstaticメソッド。staticメソッドはクラス名.メソッド名()で呼び出せば、C言語の関数とほとんど変わりません。最初はJavaへの馴れのためstaticメソッドで色々な型や演算子になれると良いです。
  • Shortest.java public class, public static void main, string[] argsは暗記するしかない。ファイル名Shortest.javaのクラス名(public class の次の単語はShortestで無ければならない。固定(定数)文字列を画面に表示しています。
  • HelloWorld.java Shortest.javaのクラス名を変えてJavaDocコメントをつけただけのプログラム。
    • 例題:java HelloWorld実行後にecho $?を実行してみる。0と返ってくるはず。

コマンド引数、int、String, 配列、ループ

  • コマンド引数
  • System.exit()
  • 数値計算
    • Fatness.java 身長、体重をコマンド引数で与えて肥満注意メッセージを出力する。コマンド引数のStringからint数値への変換あり。
    • BMIIndex.java 身長、体重をコマンド引数で与えてBMI指数とメッセージを出力する。コマンド引数からStringからint数値への変換あり。

メソッド呼び出し

  • メソッドは関数にコピーが渡されるので、関数内で引数に代入しても呼び出し側では何も変わって見えません。ただし引数の配列、コレクション、JavaBeanなどの要素に代入またはセットすると呼び出し側で変わった値を見ることになります。
  • staticメソッドの継承。staticフィールドだけのクラスをユーティリティクラスと言うそうです。

インスタンス生成、インスタンスメソッド

文字列結合

コレクション

  • SystemProperty.java JavaVMのプロティ一覧を表示する。Properties,Enumeration,ArrayList等を用いる。
  • ListAccessTest1.java ArrayList/LinkedListのget/Iterater.nextアクセス速度テスト
  • ListSizeTest1.java ArrayList/配列のサイズを予め取得してループを回した場合とループ内でサイズを取得した場合の比較
  • ListSizeTest2.java ループのインデックスを最大から0までデクリメントした場合のテスト
  • HashAccessTest1.java HashMap/Hashtableのアクセス速度テスト
  • ListAddTest1.java Listに追加するオブジェクト変数が同じで失敗する場合の理解。
  • ListAddTest2.java ListのListの失敗パターン。

数値フォーマット

  • JDK1.5からは以下が使える。
  • java.util.Formatterが使える。
  • 標準出力の場合はSystem.out.printf()が使える。
  • C言語のsprintfのように使うには String.format()が使える。

ログ

  • ログはLog4jを使うのが標準となっています。ここでは開発時にファイルとコンソールに同時に出すサンプルの解説をします。アプリケーションサーバーで出力するときにはまた別の設定ファイルが必要になります。log4j.xmlはクラスパスのどこかに置きますが、たいていclassesフォルダに置きます(eclipseでsrcフォルダに置くとclassesにコピーされます)。
  • log4j.xml
  • Log4jTest.java
  • Debug.java 開発時に簡単なデバッグログを出す。System.outやSystem.errに出す/出さないを集中管理するのに便利。

和暦クラス

勤怠管理システム

JavaでExcel

ファイルアクセス

JDBC

  • ContainerUtil.java Java VMのシステム環境変数"catalina.base"からサーブレットコンテナがJBOSSかTomcatか無しかを判定

JSP、サーブレット

JSP(Java Server Pages)には見かけ上Classもmainも無い! 長大なmain()の中を書くようなもので、むしろ分かりやすいかも。マルチスレッドなので初心者はstatic変数もインスタンス変数も使わないでローカル変数だけで作成します。排他とかが必要ならStrutsのActionなどの通常のJavaクラスの中でやった方が良いです。

実行環境を作ったことのない方はTomcatインストールで環境設定してください。

  • MVC1.5
    • 2008年現在のJSFやStrutsのMVC(Model-View-Controller)フレームワークは2.0ですが、JSPが出た頃は1.0や1.5と言われていて意外なことにサーブレットは使われずに、ModelがJavaBeansで、ViewとControllerがJSPでした。
    • 画面が何十もあるような大きいシステムならコントロールサーブレットを使ったMVC2.0が必要ですが、画面が10程度でロジック(入力チェック、DBアクセスなど)も少ないならMVC1.5で十分と思います。JSPならサーブレットより初心者でも修正しやすい利点がありました。コードは美しくはありませんが。
    • StrutsやJSFがさっぱりわからない初心者の方にはこれくらいから読むと良いでしょう。
    • index.jsp コントローラJSP。セッションにログイン情報が無いとログインページにforwardし、有るとメニューページにforwardします。
    • login.jsp ログイン画面。
    • menu.jsp メニュー画面。
    • UserBean.java ユーザー情報保持JavaBean。
    • ICommand.java index.jspから呼ばれるコマンド(インスタンス変数を持たない、execute(request,response)メソッドだけのクラス)のインターフェース
    • HelloCommand.java ICommand実装クラス。requestにmessageを一つ登録する。
    • hello.jsp HelloCommandの結果を表示するJSP。
    • error.jsp Exceptionが発生したらエラーメッセージを表示する共通エラーページ。

帳票データ(HTML Table、CSV Tableとの変換)

  • 業務プログラムは帳票データが画面とDBを往復しているだけという場面も良くみかけます。帳票ごとにJavaBean(のList)を作ってDBのテーブルのカラムとJSPのformのnameと対応させてを繰り返すより、HashMapのキーとDBやformとリンクさせれば実装クラスが少なくなります。一般にHashMapではコンパイル時にチェックができないので推奨はされませんが、クラス数が把握の範囲を超える場合はこれも選択肢の一つと思います。VB.NETのDataGridが一つの目標です。
    • ReportData.java 帳票データ(JavaBean)。繰り返し明細をHashMapのList、それ以外のヘッダーをHashMapに持つ。ウイングアークテクノロジーのSVFはPDFのキーと値のペアをVrsOut()関数でセットすれば良い(明細は同じキーで複数回設定)ので、このクラスで十分であった。
    • FormHandler.java HTMLのformのパラメーターを帳票データに格納する
    • CSVHandler.java HTMLのformのパラメーターを帳票データに格納する。CSV Tokenizer & CSV Lineを利用させていただきました。CSVファイル中にカラム名(1行目がヘッダー用、3行目が明細用)を持つ拡張が考えられます。
    • a.csv CSVHandlerテスト用CSVファイル
    • report.jsp テスト画面
    • ちなみにCSVファイルをJavaでExcelのようにJavaExcelAPIでアクセスしようとしたら、「Unable to recognize OLE stream」とエラーメッセージが出ました。

struts

Struts1.3,Spring2.5,iBatis2.3環境設定

Swing(JFC)

Jtestのススメ

Hibernate

Weblogic11

ご意見ください

リンク集

Counter: 24455, today: 65, yesterday: 85

since 2007/05/18.

著者: 城風敏彦

shiro's webへもどる


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2012-04-24 (火) 19:17:08 (22d)