Hatena::ブログ(Diary)

達人プログラマーを目指して このページをアンテナに追加 RSSフィード Twitter

2010-12-02

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フレームワークプログラミング言語が本来持っている柔軟性や良さを殺しているケースがほとんどであると思います。

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

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

f:id:ryoasai:20101202213849p:image

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

確かに天才プログラマーを集めて領域③で開発をするということはMicrosoftGoogleのような特殊な会社を除き、一般的な開発プロジェクトでは現実的でないでしょう。ただし、オブジェクト指向などの基礎教育を行い、また、プログラマーの技術力もきちんと評価するようになれば、少なくとも領域②の範囲で仕事をすることは不可能ではないと私は思います。*10そうすればもっと効率的に開発でき、プログラマーも待遇面でもっと評価されるようになり、皆が幸せになれると思いますがいかがでしょうか。

このエントリーをはてなブックマークに追加



*1COBOLには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のエキスパート的な知識があれば相当高い給料がもらえる一方で、スキルのないプログラマーはすぐに首になるという厳しい面もあるようです。だから、プログラマーも相当がんばって勉強することになります。ある程度そのような生産性が重視される方式に業界の構造が変化していけば、自然と領域①から領域②へ中心がシフトすることにならざるを得ないと思います。

tunemagetunemage 2010/12/03 11:41 初めまして。
私は去年まで典型的なSIerで働いていました。
現在は自社開発中心のベンチャーで仕事をしていますが、
御記事を読まなければSIerの悪しき慣習を持ち込むところでした。
素晴らしい記事をありがとうございます。

doloopwhiledoloopwhile 2010/12/23 20:58 はじめまして、趣味でプログラミングをしている学生です。
プログラマ志望なので、大変興味深く読ませていただいております。
質問させていただきたい事があります。

確かにJavaは冗長です。しかし、
『COBOLの得意分野については、下手なJavaプログラムよりよほど生産性が高い』
という事が信じられません。

固定長ファイル読み書きや10進小数も、
フレームワークというほど大げさな仕組みでなくても、
専用のライブラリがあれば十分短くなるはずです。

変数の型名は書かねばなりませんが変数の前に"BigDecimal"と書く事が
COBOLと圧倒的な差をつけられる原因とも思えません。

COPY文も、コード生成が本当に必要なら別ですが、
レコードを共有する為ならクラスなど適当な仕組みが用意されています。

『COBOLの得意分野については、下手なJavaプログラムよりよほど生産性が高い』とは、
正規表現やBigDecimalすら使わないJavaプログラムを念頭に置いているのでしょうか?

ryoasairyoasai 2010/12/23 21:27 プログラマーといってもいろいろな仕事がありますが、ここではもともとCOBOLが対象としているような業務システムのプログラム開発というコンテキストで回答します。
>正規表現やBigDecimalすら使わないJavaプログラム
この業界で実際に働いたことがないと信じられないかもしれませんが、実際に私が目にしてきたJavaコードだと
-1クラス1メソッドという規約でメソッドの行数が1000以上にもわたる
-メソッドのパラメーター数が60個もある
などというおよそJavaのコードとは思えないひどいものが結構あるのです。どこまで本当が知りませんが、こういう記事もあります。(http://togetter.com/li/41782)私のブログでいろいろ指摘していますが、SIerの規約というのはOOPが分かっていないPGというのを対象にしているなどという名目で、適切にクラスやライブラリを設計するということをまったく想定していないケースが多々あります。
この文章でJavaの方が生産性が低いと指摘したのは、ファイル読み込みをStreamなどの低レベルのAPIを直接使って処理するようなひどい設計が行われることを前提においています。きちんとプログラムの勉強をしているdoloopwhileさんなら、当然上位レベルのクラスライブラリを設計して処理すればと思うかもしれませんが、設計は上流のSEが行うという厳密なウォーターフォール開発だと勝手にPGがそういった設計をすることは許されない環境もあります。
ただし、どう考えても馬鹿げていますよね。ここで指摘しているようにJavaではPGのスキルによって生産性に大きな差ができるということが事実で、もちろんきちんと勉強した人がコードを書けばJavaの方が生産性を高くできると思います。doloopwhileさんのような方が就職されるころには状況が変わっているかもという楽観的な期待もありますし、是非がんばって改革していってもらえたら私としては非常にうれしいです。

ryoasairyoasai 2010/12/23 21:36 つまり、この文書のグラフで言うところのOSSフレームワークの曲線が、doloopwhileさんの普通に想定されるJavaの生産性を表しています。この場合ある程度Javaが分かる人なら生産性でCOBOLよりずっと高いのですが、SIerなどの規約に従ってJavaでOOPするななどという制約が与えられると、逆にCOBOL以下になってしまうのではというのがこの文章の論点です。

nobusuenobusue 2011/05/29 20:34 今更コメントですが、COBOLが得意とする業務系アプリケーションをJavaで実装した場合、Javaの主に言語仕様面でのデメリットが強調されてしまうと感じています。
例えば、Javaではお金の計算のように計算精度による誤差が許容されない場合はBigDecimalを使いますが、BigDecimal型の演算には演算子が使えず、plus()などメソッドで対応しなければなりません。これは「何を計算しているのか?」の可読性を大幅に損なう要因になり、開発時だけでなく保守の際に生産性に大きく影響します。
業務系の処理の大半は四則演算と文字列の編集(加工)なので、フレームワークやライブラリを駆使してもJavaでは生産性の向上には限界があると思います。少なくともBigDecimal相当の型に対して演算子が普通に使える言語が必要で、具体的にはRuby(JRuby)やGroovy、Scalaなどが効果を発揮する領域でしょう。

ryoasairyoasai 2011/05/29 22:28 コメントをありがとうございます。実際のところJavaはC++に文法が似ているところもあって、もともと低レベルなシステムプログラミングがターゲットで業務アプリに適用されたのは後になってからというところはあるかもしれませんね。
おっしゃるように、今後業務ロジックの部分は新しい言語やDSLのようなものを用いる方向に発展していくのだと思います。個人的にはJavaはインターフェースの宣言やアノテーションのよるメタ情報の宣言などアーキテクチャレベルの構造を定義し(従来のxmlの代わり)、ロジックの実相部分は関数型やDSLなどより簡単な記述方法を使い分けるような方向もあるのではないかと思います。

nobusuenobusue 2011/05/30 00:34 >個人的にはJavaはインターフェースの宣言やアノテーションのよるメタ情報の宣言などアーキテクチャレベルの構造を定義し(従来のxmlの代わり)、ロジックの実相部分は関数型やDSLなどより簡単な記述方法を使い分けるような方向もあるのではないかと思います。

同感です。フレームワークなどのインフラストラクチャはJavaで、業務ロジックはDSLやJVM言語など、より抽象度が高く業務処理を見通しよく記述できる処理系を採用すべきと考えています。
同様の目的を果たすためにルールエンジンなどを導入する場合もありますが、ルールエンジンの記述力は限定的なので適用できない場合もありますので。

Javaに演算子オーバーロードとクロージャ(関数オブジェクト)が導入されれば解決する問題かもしれませんね。。。

大手SIer大手SIer 2011/11/14 19:01 SIer製のフレームワークの目的は、基本的にプログラミングに制約を設けて自由度を奪うことで、予期せぬ方向に実装を進めないようにするとこです。
かつてフレームがろくにない頃は、インターフェース部分がバラバラで結合テストで大炎上するPJが多発しました。
クラスの存在自体がグローバル変数の多用よりも酷い状況を産むことに、歯止めをかけることが重要で、
スーパープログラマーにより高い生産性を要求するものではありません。

ryoasairyoasai 2011/11/17 00:22 本文の趣旨は、一部の限られた天才プログラマーでなくても、きちんと訓練されたプロフェショナルなプログラマーであれば通常SIerが考えているよりもはるかに生産性や保守性を高めることができるというものです。スーパープログラマーの指しているものが人それぞれ違っているかもしれませんが、天才でなくてもきちんと訓練すれば、オブジェクト指向やフレームワークを使いこなすことはできると信じます。