アバンダンウェアで懐かしい過去の時代にタイムスリップしてみる

皆さんはアバンダンウェア(Abandonware)という用語をご存知でしょうか?
wikipedia:アバンダンウェアにあるように、

著作権者が既に販売をやめたりサポートしていないソフトウェア、あるいは様々な理由により、誰が著作権者であるか不明なソフトウェアを指すために用いられる語である。

ということで、既に商品としての価値が無くなっていたり、著作者が既に不明になっていたりしているような非常に古いソフトウェアを指す用語です。*1

  • コンピュータ技術の進歩はあまりも急速なため、通常多くの国で認められている著作権の消滅期限より遥かに前に、商業的な価値がなくなる可能性が高い
  • ソフトウェアはインターネットなどを通して簡単にコピーが出回ってしまう

ということから、コンピューターソフトウェア固有の現象と思われます。もちろん、

この用語は法的な意味を持たない。すなわち「アバンダンウェア」と呼ばれているソフトウェアの複製物を、著作権者の許諾なしに取得することが法的に許されているわけではない。著作権者がその著作権を放棄するなどの理由により著作権が消滅しない限り、全てのアバンダンウェアは著作権の保護期間が経過するまで、著作権の対象となる。

ということで、アバンダンウェアの配布やダウンロードを行うことは限りなく黒に近い違法行為であると考えられ、決して声を大にして他人に勧められる行為ではないことは確かなのですが、まあ、個人で楽しむだけなら許容されるのではないでしょうか。(その点、くれぐれも個人の判断で行っていただきますようお願いします。)ここでは、アバンダンウェアを使って、私が始めてプログラミングを勉強した頃の時代(年齢がばれますが)にタイムスリップしてみたいと思います。

MSXパソコンのシミュレータで遊ぶ

私が始めてパソコンと呼ばれるものでプログラミングをしたのは小学校の中学年の頃だったと思います。今は亡き私の祖父*2が趣味で電子音楽の制御に使っていたYAMAHAMSXパソコン(おそらくCX5という機種だったと思う)を譲ってもらったのがきっかけでした。当時は私は英単語もまったく読めませんでしたし、ブラインドタッチもできなかったのですが、雑誌*3などに載っていたBASICのプログラムリストを必死に打ち込んでゲームを作成したのを覚えています。以下の動画の中に私の打ち込んだ雑誌のゲームもあってすごく懐かしいです。

幸運なことに、現在では非常に優秀なMSXエミュレーターをフリーで簡単に入手することができます。
MSX エミュレータ|エミュポータル
こうしたエミュレータを使うと、BASICやマシン語などで実際にプログラムを作成してみることができます。
たとえば、

のように順番に円を描くプログラムはBASIC言語で以下のように記述すれば簡単にできます。(今では信じられないことですが、変数名は大文字小文字を区別なしの英数字2文字まで、GOTO先も行番号指定のみでラベル名が使えせんでした。当然ローカル変数というものはないです。)

なお、以下の雑誌には公式MSXエミュレーターだけでなく、MSX用のOSであるMSX-DOSMS-DOSではない!)やZ80のマクロアセンブラやCコンパイラが付属しているので、いろいろと楽しめます。MSXプログラミングの参考書などはヤフオクなどで今でも結構出回っています。

MSX MAGAZINE永久保存版3

MSX MAGAZINE永久保存版3


もし、私に天才的なプログラミングの才能があれば、すごい面白いゲームを作成して雑誌に投稿していたりしていたのでしょうが、MSXに関しては当時は結局そこまで使いこなすことはなく、結局ゲーム機*4として終わりましたね。
Z80マシン語などはJavaプログラマーでも教養として有用なので、時間のあるときに一度勉強しておくのも良いでしょうね。
はじめて読むマシン語―ほんとうのコンピュータと出逢うために

はじめて読むマシン語―ほんとうのコンピュータと出逢うために

Turbo Pascal*5OOPに初めて出会った時の感動を再度味わう

それからしばらく、プログラミングからは遠ざかっていたのですが、私が再びプログラミングの面白さに目覚めたのは大学の授業でPascal言語を習ったことがきっかけでした。*6学校では構造化型言語ということで学び、初めて関数、手続き、ポインターなどの基本概念を学んだのですが、より深く勉強しようと自分で購入したTurbo Pascal6というパッケージには、Turbo Visionと呼ばれるアプリケーションフレームワークが付属していました。それに付属していたユーザーズガイドのなかにあるオブジェクト指向プログラミング入門というのが非常に分かりやすいく書かれていたと記憶しています。残念ながら、そのマニュアルは紛失してしまったのですが、英語版であれば、以下からダウンロードできます。
E-Book | Turbo Pascal 5.5 Object Oriented Programming Guide
今でこそアメリカなど海外ではオブジェクト指向プログラミングは常識として浸透しているみたいですが、当時(20年前)は一般のPC環境でようやく利用されるようになった頃であり、多くのプログラムはオブジェクト指向言語を使って書かれていませんでした。このマニュアルを読むと、オブジェクト指向という考え方*7がいかに画期的ですばらしいものなのかという作者の意気込みが感じられます。オブジェクト指向プログラミングの威力を最もはっきりと感じるのは、やはり、マウスやウィンドウ、メニューバーを使うようなGUIのプログラミングを行う時です。当時はWindowsのようなグラフィカル環境はまだ一般的ではありませんでしたが、この製品に付属していたTurbo Visionというアプリケーションフレームワークを利用することで、MS-DOS上で簡単に「GUI」っぽいアプリケーションを開発することが可能でした。

ここで、非常に感激したことは、Turbo Pascalの提供するIDE環境そのものがTurbo Visionというフレームワーク上に構築されていたという事実ですね。実際、上記のサンプルアプリケーションの画面とIDEの画面は非常に似通っていました。

MSXのBASICでは「円を描く」「線を引く」という一個一個の基本的な処理を呼び出してプログラミングしていたものが、TWindowをNewしてデスクトップに貼り付けることで、自分からひとりでにリサイズやドラッグなどのイベントに反応するウィンドウが画面に表示されるようになるのです。「なんと効率的で再利用性の高いプログラミング技術があるのだろう!」私は心の底から感動したのを覚えています。実際、自分のような平凡な人間が少ないコードの記述で見栄えと操作性のよいアプリケーションを作成できてしまうのですから、当時としては実際すごいことでした。自分は当時完全に独学でOOPを勉強した*8ので、OOPのすごさを実感として分かったといえるレベルになるまでに2〜3年はかかったような気がしますが。なお、Turbo Pascalは完全に16ビットのDOSコンパイラなので、64ビットWindows環境では仮想環境上でないと動作しません。しかし、現在でもFree PascalというフリーのコンパイラーがOSSとして開発されています。Turbo VisionについてもFree Pascal上に移植されています。
Free Pascal - Advanced open source Pascal compiler for Pascal and Object Pascal - Home Page

ちょっと思ったこと

ちょうど私の世代(団塊ジュニア世代)というのは、以上のような手続き指向の環境からオブジェクト指向の環境への移行をまさにリアルタイムに肌で体験することができた幸運な世代であったのかもしれないと思いました。それより古い世代だとCOBOLFORTRAN、BASICといった手続き型全盛の時代になってしまいますし、JavaWindows以降の世代では、オブジェクト指向は日常既に空気のようなあたりまえの存在になってしまっており、そのありがたみをまったく感じなくなってしまっていますから。オブジェクト指向の存在意義がよく分からないという人は、ここで紹介したようなアバンダンウェアを使って、オブジェクト指向が登場してきた時代にタイムスリップしてみることで、「あ、そういうことだったのか」という気になるかもしれませんね。よくオブジェクト指向の入門書で書かれているように「哺乳類を継承して犬や猫になる」という抽象的な説明を何度も聞くより、Turbo Visionでウィンドウを開くプログラムを作ってみるのがOOPの威力を感じるのに非常によい手段だと思います。まさに百聞は一見にしかずということで。*9

*1:一般にAbandonwareというと多くはROMデータとして違法に出回っている昔のゲームのことを指すことが多いようです。古いゲームは現在でも商業的な価値が高いものが多いため、特に問題が大きいと思われます。

*2:文字通りコンピュータおじいちゃんという感じの人でした。80歳を超えて亡くなるまでパソコンやデジタル家電に興味を持っていました。このgeekな趣味は隔世遺伝で私に受け継がれているようです。

*3:コードリストが入手したくてオークションなどしばらく探していたのですが、今ではなかなか出品されないですね。

*4:当時みんなが持っていたファミコンは勉強しなくなるからという理由で買ってもらえなかった。

*5:Turbo Pascalは以下のようなサイトでダウンロードできます。http://vetusware.com/

*6:私は情報専門の学科は卒業していませんが、プログラミングの授業としてPascal言語は必修科目でした。

*7:当時はGoFデザインパターンも知られていない時代だったので、継承を多用しすぎるなど現代のオブジェクト指向プログラミングのベストプラクティスから考えると不適切な設計もありましたが。

*8:当時はヒープとか動的変数割り当てといった基本的なことをよく理解していなかった。

*9:Turbo Pascalの少し後に登場したVBだとあまりにもブラックボックス化されてしまったため、オブジェクト指向がちょっと見えにくくなってしまっています。

もしSIerがまともなエンジニアリングの会社だったとしたらどんな仕事が考えられるか?

以前にも何度か書いたように私自身一応SIerと呼ばれる会社で(肩書き上SEとして)働いているのですが、このブログでSIerのことについて書くと、おそらく技術力のある優秀なPGの方からだと思うのですが、

なぜみんなSI業界から飛び出さないんでしょうね

真っ当なプログラマーを目指すのならSI屋には就職しちゃダメ

のようなコメントをいただくことが多いですね。本当にPGが技術力を発揮しようと考えたら、SIerやその下請け専門の会社ではなくて、最新のWebサービスをやっている会社とか、ネットゲームの会社とか優秀なPGにとってもっと働き甲斐のある魅力的な分野が他にたくさんあるということでしょうか。極端な話、外資系の銀行とか、海外で仕事をすべきという意見すら時々聞きます。
ただし、(私自身そういった分野で活躍しようと考えるほど最新の高度な技術力を持っているという自信がないというのもありますが)、私がもともとSI業界で働こうと思ったきっかけは、基幹業務を支える業務システムの開発というものに最大のやりがいを感じたというところにありますね。
実際、理論が整然と確立されており、仕様が明確に記述できるコンパイラーの開発とは違って、業務システムの要件はもともと無駄が多かったり、矛盾だらけだったり、重複が多かったりするわけです。しかも、要件はどんどん変更されたり、追加されたりします。そういう制約が多くぐちゃくちゃな世界から綺麗な構造を見つけ出して、機能拡張や変更に耐えられるアーキテクチャーを考え出していくというところに私は業務システム開発の本来の面白さがあるはずだと期待しました。業務システムは社会を支えるインフラを構築するという社会的な責任の面でも重要だし、プログラミング技術としても本来非常にチャレンジングで面白みのある分野であると信じていました。このブログでも紹介したファウラーなんかの本を読むとドメインモデリングリファクタリングなどの設計技法を駆使して複雑な業務要件を綺麗に解きほぐして無駄のない設計にしていくというようなことが書かれていますが、そういった手法によって、システム開発のやり方をもっとスマートに効率的に改善することができるに違いないと素直に信じてしまったということがあります。(私も若かった、笑。)
残念ながら、私のそうした期待とは違い、多くの場合企業の業務システム開発を担当する中心的な存在である大手SIerは大きなプロジェクトを請けて下請けに丸投げするITゼネコンと化してしまっています。*1だから、大手SIer側は技術の会社ではなくて、単なる人集めと営業のビジネスとなり、下請けの中小SIerソフトハウスの側は付加価値の低い単純労働作業となってしまっているという現実があります。Java EEや.NETのようなオブジェクト指向のプラットフォームやESBといった技術も既に何度も指摘してきたように現状あまり有効に活用されているとは言えないようです。
ところで、実は「SIerとは何か」という点を考えると、そもそも非常に分かりにくいところがあります。システムインテグレーター - Wikipediaだと、

システムインテグレーター(英語:System Integrator)は、個別のサブシステムを集めて1つにまとめ上げ、それぞれの機能が正しく働くように完成させる「システムインテグレーション」を行なう企業のことである。
日本の情報システムにおけるシステムインテグレーターとは、情報システムの開発において、コンサルティングから設計、開発、運用・保守・管理までを一括請負する情報通信企業である。SIerエスアイアー)とも呼ばれる。

と定義していますね。もともとの英単語の意味からすると前半の定義の通り、EAISOAなどの技術を使ってシステムを統合するのが仕事のように思われますが、実際はシステム統合案件ばかりやっているわけではなくて、業務システムを一括請負して開発したり、保守、運用、管理までやっている会社ということになるようです。歴史的な理由や雇用の問題からゼネコン化しているという実態はありますが、本来SIerという言葉自体にはエンジニアリングと対立するもの、PGと敵対するもの(?)という意味は含まれていないようです。
私は、SIerが初心に戻って本来のSIとな何かという点を考えなおすことで現状の請負中心のビジネス構造をある程度保ちながらも、本来あるべきエンジニアリングとしての仕事ができる道がないわけではないと思います。いくつかアイデアをあげると

  • SIerは業務フローやユースケース分析などシステムの純粋にwhatの部分のみ考え、画面定義や実装などhowの部分は実装者の自由に任せる。(howとwhatの分離)
  • SIerはシステム固有の業務知識が必要なドメイン層を実装まで含めて担当し、画面開発や帳票など業務知識があまり要らないところを専門の業者に外注する。(コアドメインと周辺機能との分離)
  • SIerはシステムの全体的なベースラインアーキテクチャ(もちろんモデル図だけでなくてソースコードも作成する前提。)やコンポーネントのインターフェース、SLA上の規約のみを決め、コンポーネントの実装を外注する場合中身の実装には口を出さない。実装の詳細や設計は下請けに自由に考えさせる。(インターフェースと実装の境界で役割を分担する)
  • SIerは名前のとおり、コンポーネントやサービスの統合案件を中心に仕事をする。(モノリシックな大規模アプリケーションの開発は避ける。)
  • SIerはユーザーの代理として最終的な機能試験、システム試験、性能試験を行う役割を担う。これらの試験のエキスパートを育成する。(試験タスクの体系化、知識集約化)
  • SIerは生産性の高い開発環境一式(ビルドシステムなどを含む)を構築、標準化する役割を担う*2(開発生産ライン構築)

この場合、最初の案はコンサルファームのように純粋に上流工程に特化した仕事となりますが、それ以外はPGまで含めて上流から下流まで担当する要素がある点に注意してください。少なくとも現状は建設業や製造業の発想で工程で上流、下流と分け商流の構造もその工程に対応したものとなっています。しかし、それ以外のオブジェクト指向、サービス指向、クラウドにより適合した方法で分離する方法もあってしかるべきと考えます。
ビジネスモデルとしては収益構造など難しい問題があるため簡単ではないはずですが、少なくとも現状のように工程で分離して下請けに丸投げする方法よりエンジニアリングの観点からもっと賢い方法があるのではと思います。そうすることでPG(この場合本来のSEを含めてもよい)がSIerでもっと活躍できる場所が増えるのではないでしょうか。しかも、顧客や下請けからもっと尊敬される会社になることができるのではないでしょうか。
※なお、SIerにはハードウェアなどシステム基盤や運用の仕事もありますが、ここではPGとして興味のある開発の部分に絞って考えました。

*1:こうなってしまった背景にはさまざまな合理的な理由が考えられるようですが。http://blog.goo.ne.jp/ikedanobuo/e/e4391dbc2cedccfac7d3b57061b2ab14

*2:最近は仮想技術を使って開発環境一式をオンデマンドで配置するといった技術もあるようです。

上流の壁?

達人プログラマーを目指すための素質 - 達人プログラマーを目指してで、PGの社会的地位の低さについて言及したのですが、ステレオタイプな上流コンサルと思われる方から、以下のようなコメントをいただきました。

現在の貨幣経済において、情報システムサービス業(SIer)におけるPGはそこまでの価値なんだと受け止めるべきかと。
実際の話、SIerにおいては優秀なPGが沢山いるより、大型案件を扱えるPMが沢山居る方が、より儲けやすいでしょう。

あと、別にPGだけが頑張って勉強してるわけではないです。
上流コンサルやITアーキテクトと呼ばれる人たちも勉強はしています、平均をとればPGたちよりも勉強はしてるでしょう。
営業だって馬鹿ではありません、刺しつ刺されつの世界でなんとかプロダクトを売っているんです。

貨幣経済において、付加価値の高くないことを勉強しても付加価値は低いままです。
「清掃作業において俺は誰にも負けないほど勉強しているが、なぜ給料は低いんだ!?」
と叫んでるのを聞いてあなたは何を思いますか?

要するにこの人はプログラミング作業を清掃作業に類する単純労働作業と捉えており、それゆえ付加価値の低い仕事だからそれなりの地位と収入なのは妥当であると考えておられるようです。(この方は年収1000万近くも稼ぐかなりの高給取りの方のようです。)もちろん、すべての上流コンサル、上流のITアーキテクトの方が全員この方と同様な考え方をされているわけではないと思いますが、割合的にはこのような考え方をされる方が多いのでしょうか?もし、そうだとすると上流のエンジニアの方と私のようなコードを書く下流のエンジニアとの間には容易には崩せない厚い壁が存在していることになりますね。
私の考えでは、マーチンファウラーのようにコード上の設計もできる人が、上流のアーキテクチャーやシステムの要件を考えるというのが理想的であると考えています。そうすることにより、オブジェクト指向的な発想で拡張性や再利用性の高いシステム設計、本当の意味で付加価値の高い分析や設計というのが可能になると思います。逆に、OOPとかデザインパターンなどプログラミング上の設計技法を理解していないような人が高給取りの上流エンジニアの立場になって、SOAなどの手法を活用して本当に有効な設計ができるのか疑問を感じてしまいます。
20年くらい前からシステム開発のアウトソース化が急激に進み、SIerという会社が生まれたと聞いていますが、不幸なことに、この時期はちょうどオブジェクト指向プログラミングやC/S環境などの普及が本格的に始まった時期と見事に一致しています。SIerのゼネコン化の問題もあり、そうした中でオブジェクト指向などの下流の技術革新をまったく理解しない上流専門の会社と立場の低い下流の会社に分断されてしまいました。立場の高い上流の人は新しい技術を知らず、逆に新しい技術を正しく使う能力のあるPGの立場が必要以上に低く、付加価値の高いポジションで仕事をする機会が極端に少ないというのが現状の日本のIT業界なのかと思いました。
やはり、上流と下流を隔てる壁を今後何とかして崩さないと先に進めない気がしました。自分がプログラミングを中心とした仕事をしているということはありますが、やはり、基本的にはPGの地位をもっと向上させ、プログラミングの分かる人がもっと上流の付加価値の高い仕事に参加できるような環境を作っていくことが大切なのではないかと思います。アジャイルのような開発モデルがもっと浸透し、ユーザー企業も直接システム開発や運用をコントロールするようになれば、たちどころに、この「壁」を崩すことは可能かとも思います。冷戦の終結によりベルリンの壁も一気に崩壊したのです。もっと多くの人がこの問題に気づいて、改革することを望めば、ちょっと馬鹿げた上流の壁を崩すことは決して不可能なことではありません。

Java EEや.NETはCOBOLやVB6よりも本当に生産性が高いか?

プログラミングと設計は本来切り離せないものなのではがすごい反響だったのですが、結局この記事で私が言いたかったことは、

  • Java EEなどの現代的な開発環境はCOBOLなどの古い言語を使った開発とは根本的に設計の手法が異なる
  • 多くの現場では未だに古い設計手法を使っているため、オブジェクト指向などの最近の開発環境のメリットが活用できず、低い生産性にとどまっている。

ということに要約できると思います。ただし、どうして、Javaではオブジェクト指向で開発しないといけないのか、どうして昔ながらの伝統的なやり方を改め、新しい設計手法を採り入れないといけないのかと疑問を持たれた方もいらっしゃるかもしれません。ここでは、開発手法と生産性の問題について、もう少し掘り下げて検討してみたいと思います。

レガシー言語の生産性

最近のCOBOLでは、オブジェクトやスタック変数すら使えますが、ここではCOBOL85のような伝統的な手続き指向の言語についてちょっと考えてみます。最近はCOBOLで書かれたプログラムを読んだことがまったくないプログラマーも珍しくないかもしれませんが、固定長ファイルの読み書きや帳票の出力など、もともとCOBOLの得意分野については、下手なJavaプログラムよりよほど生産性が高いのではないかとすら思えます。たとえば、固定長ファイルを処理するロジックなら大体以下のような感じで記述できます。

       IDENTIFICATION DIVISION.
       PROGRAM-ID. SAMPLE.
      * 環境部
       ENVIRONMENT DIVISION.
        INPUT-OUTPUT SECTION.
         FILE-CONTROL.
           SELECT DATA-FILE
               ASSIGN       TO  infile
               ORGANIZATION IS  LINE SEQUENTIAL.
      * データ部
       DATA DIVISION.
        FILE SECTION.
        FD  DATA-FILE.
        01  DATA-RECORD.
            02  USER-RECORD.
                03  USER-CODE    PIC X(4).
                03               PIC X.
                03  USER-NAME    PIC X(20).
                03               PIC X.
                03  USER-AGE     PIC 9(3).
      * 手続き部
       PROCEDURE DIVISION.
           OPEN INPUT  DATA-FILE.
       LOOP-POINT.
           READ DATA-FILE AT END GO TO TERM-PROC

... 各レコードの処理を記述

           GO TO LOOP-POINT.

       TERM-PROC.
           CLOSE  DATA-FILE.
       END PROGRAM SAMPLE.

確かに、最近のスクリプト言語とは比べ物にならないくらい冗長な記述ではありますが、固定長ファイルを処理するという本質的な部分についてみると

  • ファイルの中身が特定の変数に自動的にバインドされている
  • 変数の型変換も自動的に処理される

などを考えると、最近Javaでようやく利用できるようになったアノテーションを使ったBeanバインディングと大差ないようにも思えます。見方によってはPIC句による文字種や桁数の宣言はソース内部に記述されたメタデータといえなくない気がしますし。また、決まりきった部分をテンプレートとして流用すれば*1、可変部分の記述はシンプルで、IoC*2のように見えなくもないです。そのほか、COBOLでは固定小数演算で誤差のない金額計算などが得意といった特徴もあります。とにかく、COBOLでは細かい部分の設計としてSEがデータの型桁と処理ロジックを決め、アーキテクチャー的な部分は大規模なプログラムのモジュール分割や呼び出し順序の設計をすれば、基本的にはひたすらコードを書き下すだけです。*3インターフェースとかデザインパターンなどは本当に考える余地がないのです。変数も基本的にグローバルな静的変数となります。同じ第三世代の手続き型言語といってもCやPascalのような柔軟性の高い汎用言語しか知らないとCOBOL独特のこうした特徴は理解しづらいでしょう。COBOLというのは事務処理フレームワークが内蔵された言語と言えます。キーワード(予約語)が500種類*4もあるという点もこの事実を物語っています。
同様に、VB6などのツールはGUIを作成するツールとしては生産性が非常に高く、データアクセス用の部品を使えばCRUD処理などは簡単に実現できてしまいます。このようなことを考えると最近では開発ツールの使い勝手が向上したり、PCの性能が向上したりしたことによる生産性の向上はあるのですが、言語自体の生産性は昔からそれほど代わっていないのではないかという意見も当然出てくると思います。だから、最近でも

などといった意見も時々出てくるのだと思います。

どうしてオブジェクト指向言語なのか?

それではどうしてJavaなどのオブジェクト指向言語が現在では一般的になっているのでしょうか?こうしたことは書籍やネットなど、さまざまなところで既に多くの人によって語られていると思いますが、結局

  • 部品化によって再利用性が向上する
  • インターフェースと実装の分離などにより、変更の容易な保守性の高いプログラムが作成できる
  • 複雑なロジックをオブジェクト内に隠蔽することにより、巨大なプログラムを作成できる

ということになるのだと思います。実際、Windowsや3Dを駆使したゲームなど、きわめて複雑なプログラムをオブジェクト指向抜きで実装することは現実的でないと言ってよいと思います。業務システムでもオブジェクト指向言語を使って適切な設計をすることで生産性や保守性の高いシステムを構築することができるのです。ただし、ここで大切なことはオブジェクト指向言語を使ったからといって自動的にオブジェクト指向のメリットが得られるのでは決してないことです。Java言語を使っても、デザインパターンドメインモデリングなどを適切に利用して、正しい設計ができて初めて上記のメリットが得られるのであって、従来と同じ発想でデータ構造とロジックだけ考えていたのでは、高い生産性を享受することは絶対にできません。それどころか、固定長ファイルを単にバッチ処理するロジックを(クラスライブラリーやフレームワークを一切使わず)Java言語で手続き的に実装したらCOBOLよりもかえって生産性が下がるという危険性すらあるのです。

SIerJavaフレームワークの問題点

つまり、Javaなどのオブジェクト指向言語では適切にオブジェクト指向設計できる高スキルのプログラマーなら高い生産性を享受できるのに、初心者だと多くの場合COBOL以下の生産性しか得られない。ここに問題の本質があります。
SIerの多くはCOBOL時代からの伝統的な慣習からか、

プログラマー = PG = 初級レベルのエンジニア = 下流 = 単価が低い

という構図で考える傾向があります。だから、一般的に日本のSIerの作ったJavaフレームワークというのは、「いかにプログラマーに頭を使わせないか」という点に最大限の注意を払っているように思います。実際、今まで私が見てきたSIerフレームワークは以下の2通りのパターンのいずれかです。

  • なんちゃってパターンの使用を強制する。XXDto、XXAction、XXLogicなどのように同じ接尾辞が付く多数のクラスを作らせるのは典型的なケースです。(侵略的なフレームワーク - 達人プログラマーを目指して)ここではどうしてパターンを使うのかということは*5どうでもよくて、とにかく規約として一連のクラスの作成を強制させます。そうすることでオブジェクト指向している気分になっているのかもしれませんが。
  • 何でもかんでもとにかく自動生成させたがる。特にExcelなどの表から大量のクラスを自動生成させるなど。たいていそのようにして生成されたクラスはゴミで保守も大変なものになりがちです。

結局、たいていの場合SIer製のフレームワークというのは、プログラマーオブジェクト指向設計する自由を奪っているのであって、できるプログラマーの能力を殺してしまうのですが、もっとも重要な事として先に述べたとおり、Java開発の生産性をCOBOLVB以下に制約しているということすらいえる可能性があるのではないでしょうか?もともとの思惑としては、オブジェクト指向を使わずにCOBOLと同じ発想で設計していても、新しい言語なのだからJavaの方が多少なりとも生産性が高いだろうという期待があるのかもしれませんが、そんなことは決してないと思います。むしろ、本来の使い方とはかけ離れた不自然な設計を強制することで、多くの場合COBOL以下の生産性しか得られていないというのが実態な気がします。*6

最近のOSSフレームワークは何が違うか?

SIerフレームワークと比較して、Seasar2Spring Frameworkなど最近のOSSフレームワークは、プログラマーの自由を奪わない*7(侵略的でない)ことが特徴とされています。つまり、基本的に「優秀なプログラマーの優秀なプログラマーによる優秀なプログラマーのための」フレームワークとなっているのです。だから、必ずしもオブジェクト指向デザインパターンがわからないような初心者にやさしいかというと必ずしもそんなことはありません。しかし、天才プログラマーでなくてもある程度これらの基礎をきちんと勉強しているプログラマーが使うと、高い生産性を享受できるのが特徴です。きちんと勉強しさえすれば、平均的なプログラマーであっても天才プログラマーの考えた仕組みを取り込むことができるのです。
ところで、SIerフレームワークであっても最近はこれらのOSSフレームワークを取り込んでいることが多くあります。しかしながら、私の知る限りにおいて現状では、従来のSIerフレームワークと大きく変わるものではないと思います。基本的にプログラマーは初心者という前提で作られていることは以前とかわらず、OSSフレームワークプログラミング言語が本来持っている柔軟性や良さを殺しているケースがほとんどであると思います。

生産性とプログラマーのスキル

以上の説明をもとに、生産性とプログラマーのスキルとの関係をグラフに表すとだいたい以下のような感じになるのではないでしょうか。(あくまでも定性的な傾向を私の個人的な主観で表現したものです。)

SIerは一般的に領域①で大量のプログラマーを低い単価で雇って仕事をさせようと考える傾向があります。思惑としてはJavaフレームワークを導入することでCOBOLよりも高い生産性を確保したいということがありますが、多くの場合は、COBOL以下の生産性でプロジェクトが失敗したり遅延したりします。成功したといわれるプロジェクトでも性能面などの品質が悪かったり、機能拡張が極めて困難だったりと、オブジェクト指向の本来のメリットを享受できません。どうしてこんな非効率なことになっているのかということを、会社の上司などに言うとたいていは、「ハイスキルのスーパープログラマーを確保することは不可能だから」といいます。また、ビジネス的にも少人数のできるプログラマーをわざわざ集めてよいシステムを短期間に作るより、大量の頭数をそろえて非効率に開発した方が(少なくとも短期的な視野からは)儲かります。*8ただし、そのような領域で開発を続ける限りCOBOLVB*9の時代の生産性を大きく超えることはありませんし、長期的には競争力を失って仕事が取れなくなるという危険性すらあるのです。
確かに天才プログラマーを集めて領域③で開発をするということはMicrosoftGoogleのような特殊な会社を除き、一般的な開発プロジェクトでは現実的でないでしょう。ただし、オブジェクト指向などの基礎教育を行い、また、プログラマーの技術力もきちんと評価するようになれば、少なくとも領域②の範囲で仕事をすることは不可能ではないと私は思います。*10そうすればもっと効率的に開発でき、プログラマーも待遇面でもっと評価されるようになり、皆が幸せになれると思いますがいかがでしょうか。
このエントリーをはてなブックマークに追加



*1:COBOLにはCOPY文などテンプレートから一部置換しながら自動的にコピペする仕組みすらある。

*2:Inversion of Control=制御の反転

*3:そうは言ってもPERFORMのくくり出しや段落分割などでいかにきれいに構造化するかといったような工夫の余地は多少なりともありますが。

*4:日本人プログラマーの記憶している英単語の大半が予約語だったりするということです。

*5:本来パターンを導入するにはそれなりの理由=フォースが重要。

*6:ここではIDEなどの開発ツールの差は考慮していません。しかし、重たいアプリケーションサーバーやIDEが本当にCOBOLの開発環境より生産性の向上に寄与しているという証拠もありません。

*7:ここでは多くのSI開発で利用されているJavaフレームワークを例として取り上げましたが、RubyScalaなどの軽量言語やルール記述言語、関数型言語などを考えてみても、プログラミングの柔軟性を奪うという方向の言語はほとんどないと思います。以前よりもプログラマーのセンスやスキルが重要になっているということは一般的な傾向だと言えると思います。

*8:ただし、昨今ではユーザー企業も財布の紐が硬くなっており、生産性や費用対効果を重視することが多く、この従来モデルで売上や利益を上げることが徐々に難しくなってきている傾向があるようです。たまたま会社の合宿で技術系の役員の方と話をする機会があったのですが、多くのSIerで従来の生産性の低いモデルを何とか改善しないといけないという危機感を持っているところが多いと聞きました。ただし、SOAとかクラウドとか新しい言語やツールなどの手段の話は出てきてもプログラマーのスキルの重要性という面には会社のお偉いさん方の考えが及びにくいという傾向はあります。ただし、今後はそういう面に気づいて新しいビジネスモデルで仕事をするSIerが出てきてもおかしくないと思いますし、実際に改革に取り組んでいる会社も多いと信じます。

*9:ここではCOBOLVBを取り上げましたが、PL/SQLTransact-SQLPerlなど一般的にはオブジェクト指向言語より劣るあるいは時代遅れと「信じられている」ような言語に当てはめて考えることもできます。

*10:実際、プログラマーの能力を過小評価する傾向はゼネコン構造も関連した日本のIT業界独自の傾向という話もあります。たとえば、アメリカではSIerに丸投げということは稀であり、ユーザー企業が直接必要なプログラマーを雇うモデルのようなので、生産性やスキルは非常に重視される傾向があります。たとえばSpringのエキスパート的な知識があれば相当高い給料がもらえる一方で、スキルのないプログラマーはすぐに首になるという厳しい面もあるようです。だから、プログラマーも相当がんばって勉強することになります。ある程度そのような生産性が重視される方式に業界の構造が変化していけば、自然と領域①から領域②へ中心がシフトすることにならざるを得ないと思います。

多くの日本人がオブジェクト指向プログラミングを苦手とするのは英語アレルギーだからか?

やはり、多くの人からいろいろなコメントをいただくと、意外な発見がありおもしろいです。
プログラミングと設計は本来切り離せないものなのでは - 達人プログラマーを目指して
のブクマのコメントに

何か、主語がないから理解が難しい読み物

というのがありました。私の文章の拙さをまずは反省しなくてはなりません。ただ、普段から日本語を話したり、文章を書いたりする際にはあまり意識していなかったのですが、よくよく考えてみると日本語の文章で「主語」と呼ばれるものがなんとなく省略されることも多いように思えてきました。中学校の国語の授業では「は」や「が」という助詞がついた言葉が主語であると習ったと記憶しているのですが、実際に、文中で明示的にそのような文節が表れない現れないことが多いように思います。
そこで「日本語 主語」で検索してみたら、非常に興味深い記事がいくつか見つかりました。
http://www.geocities.co.jp/CollegeLife-Labo/6084/shugo.htm
リベラル21 日本語に主語はあるのか
主語 - Wikipedia

「花は美しい。」や「花が咲く。」は文である。
学校文法では、「花は」や「花が」を主語だと教える。(日本語に主語はある)
三上文法では、「花は」を題、「花が」を主格とする。(日本語に主語はない)

上司が部下に「この仕事、やってくれないか?」と声をかけたとする。これに答えるときには、「やります」というのが普通であろう。しかし、これには「主語」らしきものがない。かといって、「私はやります」と言っても、「私がやります」と言っても、意味は微妙に違ってきてしまう。「私はやります」だと、「他の人は知らないが私はやる」という意味になり、他に誰かに手伝ってもらいたいようである。「私がやります」だと「自分がやって手柄を立てたいから他の者にはやらせないでくれ」といっている感じとなる。このことは、「やります」が「私はやります」の省略形でも「私がやります」の省略形でもないことを意味している。つまり、日本語では、「主語」などなくとも、「やります」だけで十分に一つの文だということになる。

つまり、日本語にそもそも主語という概念が存在するかどうかという点については、専門の学者の間でもまだ統一的見解がないというのが事実のようです。そもそも主語がないという説によれば、主語は省略されているのではなくて、そもそも存在しないということになるのだそうです。だから、主語が必須である英語を機械的に翻訳した文章では、「それは」「我々は」「彼女は」などといういかにも不自然な言い回しが多用されることになってしまうのでしょう。主格をはっきりとさせたい契約文書などでは「甲は」、「乙は」などという様に「主語」を明示しますし、技術文書などでも曖昧さをなくすために多少日本語としては不自然でも主語を明示するということはあるかもしれません。ただし、本来日本語の文法は英語やフランス語などもともと主語(subject)という概念が存在する言語とは構造が違うのであるということを今になって知り、目からうろこの落ちるような思いです。(そんなこと学校の授業では教わらなかったので)
ところで、主語の問題だけでなく、語順、複数形、時制の考え方なども日本語と英語ではまったく異なるのですが、そもそも、英語を母国語として日常から使っている人が作った多くのプログラミング言語*1で書かれたプログラムを理解するためには、好むか好まざるかにかかわらず、やはり、英語脳を相当鍛えておく事が大切なのかと考えざるを得ない気がします。日本人プログラマーにとって英語の壁が大きなハンディということは事実として受けとめ、それを乗り越えるだけの努力が必要なのだと思います。*2

コードが読めない顧客は設計で読むしかない。

というコメントで、確かに顧客がエンドユーザーということなら無理はないですが、元請SEということだったら、プログラムが読めない以前に、単に英語アレルギーなのでプログラムを読もうとしないのではないかとも思ってしまいますね。カプセル化などをきちんと行った設計をした場合、特にサービスレイヤーなど比較的上位のレイヤーに属するクラスのプログラムは、ほとんど英語と変わらないようなレベルの記述になると思いますので。SEと名乗っている以上、ある程度英語が読めるくらいの英語力は持っていてほしいのですが。*3
ちなみに、Javaだと普段は意識していないかもしれませんが、細かいところを見ていくと言語を作った人ができる限り自然な英語に近づけたいという思いを汲み取ることができて面白いです。たとえば、クラス宣言では

public class Customer extends Party {
}

という書き方をしますが、「extends」の部分に3人称の「s」がついていることから、この宣言文は「現在形」の英語を意識したものであると推測されます。実際、

The public class Customer extends Party.

という英文とほとんど変わりません。(冠詞のTheとピリオドがついたくらいの違い)現在形なのはこの文書が「publicなクラスであるCustomerがPartyを拡張する」という事実を宣言していると考えると非常に自然な表現です。同様にメソッドの宣言も現在形であることは例外宣言をするケースを考えれば明らかとなります。

public String doSomething() throws Exception  {}

この場合もthorwsに「s」がついており、この場合の主語はdoSomething()メソッドと考えることができます。
一方で、ロジックの実行中に出現するメソッド呼び出しには動詞に決して多くの場合「s」が付きません。つまり現在形ではなくて原形なのであって、これは英語の命令文を意識したものであると考えることができます。*4

Paul, pass me the salt!(ポール、そこの塩をとって)

中学校の英語の教科書に載ってそうな例文ですが、このような直接話法の命令文の場合、passという動詞は原形で「s」をつけません。実際、Javaの場合を考えると、たとえば、以下のようなDAO(データアクセス)クラスの実装に対して

public class CustomerDao {
  @PersistenceContext
  EntityManager entityManager;

  public void persist(Cusutomer customer) {
    entityManager.persist(customer);
  }
}

entityManager.persist(customer)の部分は

EntityManager, persist the customer!

と英語で叫んでいると思えば「エンティティ管理人よ、その顧客を永続化せよ」とごく自然に読めるのです。この場合entityManager*5というオブジェクトを擬人化して、それに対して命令をしているという形になっているため、英語として読むと、ごく自然にオブジェクト指向で考えているということになるのです。オブ脳以前に英語脳になっていないと、単なる関数の呼び出しに見えてしまい、オブジェクトに命令するという発想で考えにくいと思います。
その他、Ruby on Railsでは規約でDBのテーブル名を複数形の名詞にします。(Customerに対してはCustomersなのですが、ChildならChildsでなく当然Childrenとなります。)どうしてこうなっているかというと、もちろん、SQLでSELECT文を書いた時に英語に近くなるからです。単数、複数の使い分けも日本語には概念のため、日本人の非常に苦手とするところです。

SELECT child FROM children

さらに、最近はDSLという考え方があり、より英語に近い構文でプログラムを書くという発想もあるようです。*6こうなってくると、顧客がプログラムを書かないまでも、少なくとも読んで理解し、プログラマーと会話するということもまったく非現実的なこととは思えなくなります。
既に、どこかで誰かが指摘されていることかもしれませんが、やはり、多くの日本人がオブジェクト指向プログラミングを苦手とするのは英語アレルギーの人が多いからなのかと思ってしまいますね。もちろん英語がペラペラならJavaのプログラムが得意かというとそんなことはないですが、少なくとも達人プログラマーであれば英語がある程度理解できるのは当然ということは言えると思います。特に、業務アプリケーションのような場合だと、複雑なアルゴリズムは既にフレームワークなどでカプセル化されたものが再利用できるため、多くの場合は英作文の力の方が論理的思考やアルゴリズムの理解よりも重要とさえいえるかもしれません。(英語力とプログラミング力との相関関係について何らかの客観的、科学的な調査が存在するかどうかは今のところ不明。)
英語力は情報を調べたり、エラーを解析したり、英文の技術書を読んだり、適切な変数名を考えたり、プログラマーやSEとしては必須の事項なのではないでしょうか。時々上級職のSEでさえ「私は英語はまったく苦手で」と堂々と言っている人がいますが、それはエンジニアとしては本来すごく恥ずかしいことだと思います。

*1:Rubyなどは日本人が作った言語ですが、発想は英語を元にした他の言語を参考に作られているから、結局日本人向けではないのが悲しいところでしょうか?有名な日本人向けの言語としては、「なでしこ」などもあったとおもいますが、残念ながら仕事で使ったことはありません。

*2:英語の学習方法は人によってさまざまだと思いますが、私の場合はCDの英語教材を聞きまくるというのが有効でした。もちろん学校で習う程度の基本文法や単語の理解はある程度前提ですが。特に最近は速聴を行うソフトもありますから(http://www.wweden.com/)、3倍速などで聞き取る訓練をすることで、相当英語脳が鍛えられますのでお勧めです。

*3:ライブラリーの英文マニュアルやエラーメッセージなど日々英語と触れ合わなくてはならない下流プログラマーと比較して、多くの場合上流SE(hands-offアーキテクト含む)は業務上英語にまったく触れることがないということも英語力低下の原因かもしれません。

*4:booleanを返す述語関数は通常現在形でis〜()、has〜()となる。また、getter、setterは対象オブジェクトに対する命令というよりIを主語とした現在形と考えるのが自然。ただし、Javaでは構文上メソッドと区別がつかないが、C#などの言語ではこれらのメソッドは本来プロパティとして定義できる。英語脳には、customer.getName()よりcustomer.nameの方が自然に読める。

*5:クラス名やインスタンス名に-er、-orなどの接尾辞のついた単語を使うことが多いのは、英語nativeの人がオブジェクトを擬人化している証拠ではないでしょうか。Manager、Translatorなどは人に対して使ってもおかしくない単語です。

*6:プログラムを英語に近づけようという試みは実はCOBOLの時代からあったものと考えることもできます。COBOLには何百という英語の予約語があり、文、節、段落などはまさに英文をモデルにしています。英語脳でないと、アルゴリズムやデータ構造ばかり考えてしまい、プログラムの文章としての可読性というところまで頭がまわらないのが問題です。

Spring MVCのススメ

先日、Struts1に代わるWebフレームワークの選択 - 達人プログラマーを目指してにて、現状アクションベースのMVCフレームワークとしてはSpring MVCが有望ということを書いたのですが、今までStrutsの影に隠れてあまり人気がないようですね。*1これから何が流行りそうかというマーケティング上の問題はおいておくとして、純粋に技術的な観点から、私がSpring MVCで気に入っているいくつかの点について説明します。

インターフェースに対するコーディングの徹底による拡張性の高さ

Spring MVCはDIコンテナーとしてのSpringのコア機能に隠れてあまり有名でないかもしれませんが、実は、Springが開発された当時から存在するコンポーネントです。ですから歴史的には意外に古く2003年くらいから存在しているということになります。(その原型は実践J2EEシステムデザインのサンプルコードにすでに存在している。)
そういう背景からか、Rod Johnsonの「インターフェースに対するプログラミング」というオブジェクト指向の基本原則が最初から徹底された(場合によってはちょっと過剰なくらいに?)設計となっています。したがって、フレームワークの基本的な機能の大部分がインターフェースとして提供されており、必要に応じて任意の実装を与えて拡張することが容易な設計となっています。つまり、Strategyデザインパターンがいたるところで応用されているということです。実際、以下のようなStrategyインターフェースが拡張ポイントとして定義されています。

Strategyインターフェース 拡張ポイントの意味
View 画面表示を行うビューのロジックを実装
ViewResolver ビューの論理名からビューのインスタンスを探すロジックを定義
HandlerMapping URLリクエストとリクエストハンドラーとのマッピングロジックを定義
HandlerInterceptor リクエストハンドラーに対する前後処理の定義
HandlerAdapter リクエストハンドラーを特定のインターフェースに適合させる
LocaleResolver ロケールを解決するロジックを定義
HandlerExceptionResolver 例外処理を行う方法を定義

たとえば、ViewResolverインターフェースは以下のように定義されています。

public interface ViewResolver {
	View resolveViewName(String viewName, Locale locale) throws Exception;
}

定義を見ればこのインターフェースの実装すべき責務がなんとなく推測できますが、ビューの名前(とロケール)を受け取ってViewのインスタンスを返すロジックを実装すればよいということです。Spring MVCではあらかじめCoC的にビューの名前からjspファイル名にマッピングする実装(InternalResourceViewResolver)やxmlで明示的に定義されたJavaBeanをViewとして返す実装(XmlViewResolver)などが提供されています。しかし、プロジェクトの用途に応じて上記のインターフェースを実装すれば想像力の許す限りどのような実装も可能なわけです。しかも、多くの場合複数のStrategyインターフェースを複数組み合わせて利用することが可能になっています。つまり、各実装に優先度をつけることができ、優先順位の高いものから順に処理を委譲し、最初に結果を返すことのできるビューレゾルバーが実際の処理を行うというような動作をさせることができます。(これはChain of Responsibilityパターンの応用例と考えることもできるでしょう。)以下の例のように宣言すると、views.xmlにて論理名に対応するIDのBeanが宣言されている場合については、そのBeanが返されます。それ以外の場合はデフォルトで/WEB-INF/jsp/論理名.jspでマップされるjspファイルがビューとして利用されます。

	<!--
		- XmlViewResolverを使ってビュー名をviews.xml中で宣言されているBean名として解決します。
                - 対応するBeanが定義されていない場合、後続のInternalResourceViewResolverで処理されます。
	 -->
	<bean class="org.springframework.web.servlet.view.XmlViewResolver" p:order="1"/>

	<!--
		- ビュー名に対してprefixとsuffixをつけることでjspファイルにマッピングします。
                - デフォルトで、このリゾルバー経由でJSP画面が表示されます。
	-->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/jsp/"
			p:suffix=".jsp" p:order="2"/>

order属性が小さなもの程、優先順位が高いので先に問い合わせられますが、最終的にいずれかひとつの実装がビューを返します。なお、PetClinicというサンプルアプリケーションではコンテンツタイプによってビューを選択するような、より複雑なビュー解決ロジックを使った例が使われています。

M、V、Cの真の分離

Spring MVCでは名前のとおり、モデル、ビュー、コントローラを明確に分離することができます。フレームワークによってはMVCと言ってもモデルとコントローラの境界があいまいなケースも少なくありません。たとえば、Struts2はCommandパターンに基づいており、アクションクラスがコントローラとモデルの役割を兼任します。つまり、アクションが画面に対する入出力データの保持とロジックの両方の責務を持つためコントローラーとモデルの境界があいまいになっています。*2
また、Struts1ではViewに対する抽象化が不十分なため、JSP以外のコンテンツを返すような場合は、通常アクションクラス内にダウンロードのロジックを直接記述することになります。一方、Spring MVCの場合、Viewインターフェースは以下のように定義されています。

public interface View {
	String RESPONSE_STATUS_ATTRIBUTE = View.class.getName() + ".responseStatus";

	String getContentType();

	void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;
}

つまりビューとはMapに格納されたモデルデータを使って、HttpServletResponseに書き出すことをする抽象的な「もの」であるとして、責務が明確に定義されています。*3ただし、逆にこのインターフェースさえ実装すればJSPでもCSVダウンロードでも、さらに、PDF帳票生成でも何でもよいということです。Springの最新バージョンではこの拡張性の高さを活かして、Atomフィードを行ったりDTOJSONに変換するなどのビュー実装が追加されています。コントローラーの責務は業務ロジックを呼び出してから、結果をビューに渡すまでとなり、あとはビューの実装が画面描画やデータダウンロードの処理を多態的に実行します。
このような分割で、結局何がうれしいかですが、コントローラの処理と画面生成の処理が分離されることで、特殊な画面生成ロジックがカプセル化されて再利用性が高くなる一方で、個々のコントローラの処理は簡単になるということが大きいです。スキルの高いプログラマーが帳票ダウンロードなど特殊なビューの生成ロジックを共通部品として一箇所で実装しておけば、個々のリクエストごとのハンドリングは平均的なプログラマーに任せられるため、チームの編成も容易になります。

@MVCと呼ばれる新しいプログラミングモデルの採用

今のところSpring MVCについて記述された日本語の本では、既に時代遅れのバージョンのことしか書かれていないこともあり、Spring MVCというとSimpleFormControllerなどの特定の親クラスを継承してコントローラーを作成する(やや侵略的な)方法を思い浮かべる方も多いと思います。しかし、Spring3ではこの古い手法は既にDeprecated化されており、@MVCと呼ばれるまったく新しいプログラミングモデルで置きかわっています。この新しいモデルではアノテーションを活用することで設定ファイルの量が激減しますし、コントローラークラスもPOJOとなり、設計自由度が高くなっています。*4
先に紹介したSpringの拡張性を活用することで、内部的なアーキテクチャーには大きな変更がされていないのに、表面上ここまで別の方式を定義できてしまうというところはオブジェクト指向言語を活用したアーキテクチャー設計がうまく行われているのだと思います。*5
@MVCについては、ちょっと古い記事ですが以下が参考になると思います。
Spring 2.5:Spring MVCの新機能

マルチアクションコントローラー作成が容易

意外に盲点となりそうなところですが、Spring MVCの特徴として、1クラスで複数の異なるタイプのリクエスト処理メソッドを複数定義できるマルチアクションコントローラーの作成が容易であるということが挙げられます。Struts1ではDispatcherActionなどの特殊形を除くと基本的に1アクション1クラスなのですが、Struts2SAStrutsなどの新しいフレームワークについても実質的には1アクション1クラスが原則となる傾向があります。それはこれらのフレームワークにおけるアクションクラスがCommandパターンに基づいており、1リクエストごとにActionのインスタンスを生成するしくみとなっているからです。したがって、リクエストパラメーターはアクションメソッドのパラメーターとしてではなくフィールドにバインドされます。これらのフレームワークでは、形式的にはアクションクラスに複数のアクションメソッドを定義することは一応可能なのですが、よほど関連性の高いメソッドでもない限り、複数のメソッドを定義するとリクエストごとに使われるフィールドとそうでないフィールドが同一クラス内に混在することになり、わかりにくいプログラムになってしまいます。
一方、Spring MVC(@MVC形式)の場合、コントローラークラスのアクションメソッドのパラメーターとしてリクエスト情報が渡されます。したがって、個々のメソッドの独立性を確保しながら容易に複数のメソッドを追加していくことが可能です。アクションメソッドのシグネチャーとしては、以下のようなさまざまなものを定義できます。
入力パラメーター

  • サーブレットリクエスト、レスポンス
  • HTTPSessionオブジェクト
  • @RequestParamのついたパラメータ
  • クッキーの値
  • 入出力ストリーム
  • Map、ModelMap
  • フォームオブジェクト
  • Errors、BindingResilt(バインド・バリデーションエラーが格納される)

戻り値

  • ビュー名の文字列
  • ModelAndView
  • ビューオブジェクト
  • Map(モデルとして解釈)
  • その他のオブジェクトはモデルの属性として解釈される

完全に自由というわけにはいきませんが、動的言語を使ったRuby on Railsのような感覚で、1つのコントローラクラスに対して気軽に複数のメソッドを定義できるのは慣れるとやはり便利です。特にAjaxを併用してあるメソッドからJSONの結果を返却させるとか、Excelをダウンロードするなどという場合に、別々のクラスを定義せずに同じコントローラで処理できるのは凝集性の高さという観点からもわかりやすいプログラムが書きやすいです。

まだまだ発展途上のフレームワーク

Spring MVCの魅力のひとつとして、現在でもまだまだ進化の可能性が残されていると思われることがあります。実際、従来は弱点として認識されていた以下のような機能がSpring3では追加されています。

  • JSR303(BeanValidation)を使った簡単な入力チェック
  • REST的なURLに対する対応
  • JSONなどへの変換
  • コントローラークラスごとのローカルな例外ハンドリング
  • HTTPのレスポンスボディーを直接返却

個人的には今のところSpring WebFlowとの統合が不十分で、会話管理の機能が弱いと思っているのですが、Spring 3.1になってCDIの機能が取り込まれれば、さらに、強化される可能性があるのではないかと期待しています。

Spring MVCのサンプルプログラム

Spring MVCを勉強するには、まず以下のSVNからサンプルを取得して動作させてみるのがよいと思います。
https://src.springframework.org/svn/spring-samples/
以下にSpring MVCの一通りの機能を示すデモの説明があります。
Spring MVC 3 Showcase

*1:日本でStrutsが使われるのが純粋に政治的理由が大きいと思いますが。Springなどという得体の知れないものを導入するための手段として「実績のある」Strutsと組み合わせることも多いと思うので。

*2:ModelDrivenを実装することで両者を分離することは一応可能ですが。

*3:Struts2にはResultというビューに対する抽象が存在しており、この点はSpring MVCと似ています。

*4:逆に柔軟性が高すぎてパターン化されていないため、初心者はどうやってコードを書いたらよいか戸惑うところもありますが。

*5:ちなみに、MVCに限らず、私がSpringでもっとも気に入っているところはアーキテクチャーの安定性がずっと長いこと保たれているところですね。設定ファイルの書き方やAPIなどの表面的な部分はバージョンアップするごとに大幅に進歩していますが、内部のアーキテクチャーは比較的安定しており、連続的に進化しています。ここがSeasarStrutsSeamTapestry、(JavaEE仕様そのものも?)と比較した場合のSpringの大きなメリットだと思います。他のフレームワークはメジャーバージョンが上がると以前とまったく別といってよい程、しくみやアーキテクチャーが変わっていることが多いです。やはり、エンタープライズ開発だと、段階的に進化させることができるのは使う側としては非常にありがたいことだと思います。

JavaEE、.NETの開発をするプログラマーが理解しておくべき設計のパターン

エンタープライズ アプリケーションアーキテクチャパターン (Object Oriented SELECTION)

エンタープライズ アプリケーションアーキテクチャパターン (Object Oriented SELECTION)

Patterns of Enterprise Application Architecture (Addison-Wesley Signature Series (Fowler))

Patterns of Enterprise Application Architecture (Addison-Wesley Signature Series (Fowler))

Java EEプログラマーとしてこの十年間に出版された本のベストを選べと言われたら、この本は間違いなく最有力候補になると思います。この本ではPOJOという考え方を広め、従来J2EEでベストプラクティスとされていたEJBWebサービスを使った過剰な分散オブジェクト化を非難し、O/Rマッピングドメインモデルなど本来のオブジェクト指向設計を活かす方法を紹介しています。エンタープライズ開発の世界でオブジェクト指向プログラミングの技法を復権させてくれた名著で(日本と欧米ではPOJOの意義に対して微妙な解釈の違いがあるような気がする - 達人プログラマーを目指して)、HibernateSpring Frameworkなどの現代的なフレームワークに与えた影響も計り知れないと思います。
従来から、エンタープライズアプリケーション開発というのはきれいな設計などは後回しで、とりあえず人海戦術で作ればよいという考え方があったかと思います。(プログラマの値崩れ - プログラマーの脳みそ
これは、業界の悪しき慣習ということももちろんありますが、上の立場の人だけでなく、プログラマーの側でも

  • エンタープライズ開発はたいした技術力を求められない。
  • 毎回カスタムメイドであり技術でがんばっても付加価値が少なく徒労に終わる。
  • 言語やツールの背後にある設計思想と比べて、業務システムの設計は美しくなく魅力を感じない。
  • 技術力のあるプログラマーがかかわる仕事ではない。

と考えている人が多いのではないのでしょうか。言語やツールなどにこだわるプログラマーは多いのですが、システムの設計そのものに関心のあるプログラマーが少ないのは残念なことです。しかし、この本を読むと、そうした一般のどろくさいイメージとは逆に、本来エンタープライズ開発はオブジェクト指向などを活用した頭を使った設計技法の格好の対象とするべきということが理解できます。

  • 業務システムは大量のデータを効率的に扱う必要がある
  • 業務システムは大量のユーザーのリクエストを処理する必要がある
  • 業務システムの要件はきわめて複雑で把握しにくい
  • 業務システムの要件は変化する
  • 業務システムのサポートする機能は大規模なことが多い
  • 業務システムは長期にわたって利用される
  • 業務システムは大量の別システムと統合する必要がある

したがって、本来は、よほど小規模な単純なシステムでもない限り、1機能1クラス(侵略的なフレームワーク - 達人プログラマーを目指して)や全部staticメソッド(業務システムでオブジェクト指向は必要か? - 達人プログラマーを目指して)などというばかげた規約で作ってよいはずがないのです。1〜2年目の初心者プログラマーには難しい内容であると思いますが、上級プログラマー、アーキテクトと呼ばれる立場の人であれば、必読書だと思います。会社で時間を作って勉強会をするのもよいと思います。
日本語訳が出ていますが、周りの評判を聞いても読みづらいという感想を持たれる人が多いのは残念なことです。そうかといって原書はファウラー独特の砕けた表現がところどころにあり、英語力が高くないとこれまた理解が難しいです。とりあえず、パターンカタログは以下で読めます。
http://capsctrl.que.jp/kdmsnr/wiki/PofEAA/?CatalogOfPofEAAInJapanese
ちなみに、タイトルから勘違いされやすいのですが、この本は一つの業務アプリケーションのアーキテクチャーに関するものでいわゆるエンタープライズアーキテクチャー(EA)とは扱っている内容が違います。