本家「@IT」にはない内容をエンジニアライフで技術紹介するコラム。広く議論する場になることを目指します。

第002回_テーマについて

»

さて、第1回のコラムで自己紹介を終えました。第2回はコラムのテーマについて述べます。

また、第1回の最後に述べたように今回も「なぜこのテーマにしたのか」という意図について長々と説明しますが、本来、紹介する「技術」と「意図」には関連はありませんので、読み飛ばして頂いても問題はありません。

テーマ・目的・意図

■テーマ
 本コラムの連載では、「XMLパーサを作る」ことを最初のテーマとします。

■なぜXML?
 なぜXMLをテーマにするのかについては4つの理由があります。

1.ファイル形式がメジャーで判りやすい
 プロのプログラマやシステムエンジニアの方、また、それらになろうとしている方にとってXMLは、お馴染みのファイル形式であると思いますので概念的な部分で躓くことがないと思います。

2.汎用的な設計にしやすい
 XMLパーサそのものより、字句解析器・構文解析器の説明が主題です。
その点で、XMLは76個の生成規則を持っていて実装量が増え、主題がブレるのでは?と考える方もいると思います。また、実装量が多いと挫折する読者の方もいると思います。でも、「生成規則が少ないミニ言語を作る」といった練習テーマを最初に行うと、設計面で(汎用的なものより)目先の楽な設計を採用してしまいがちです。結局、記事の量が増えて遠回りする羽目に陥ったり、主題から実装がブレると筆者は考えています。
 このコラムを読んでくださる読者の方においては、最初の勢いで50回分くらいを読んでくださるだろうと思っています。そのパワーを無駄な内容に費やすよりも、最初からXMLパーサを題材に汎用性の高い設計を考えるのに使っていただきたく思います。

3.より高度な機能について説明できる
 XMLは固定の構文として生成規則を持つ他に、ユーザが決定する--パーサから見た場合、実行時の--規則:DTD を持つので実行時構文を解釈する構文解析器についても解説できます。
※本コラムで動的構文解釈の技術まで公開するかはわかりません

4.経済的有用性
 現在、プログラマが構築するシステムに対して、入力ファイルがXMLであることが多いと思います。よって、XMLパーサを自作できるようになれば、細かい動作についても理解でき、世の中にあふれるXMLパーサと比較することもできると思います。
 また、XMLには空白が意味をもつ仕様がありますが、プログラムの入力形式-文字列や数値-にとっては不要なものなので自作のパーサがあればより使い易い入力ファイル形式を検討できるようになると考えています。

■なぜパーサ?
システム開発・ソフトウェア開発の核心部分はコーディングです。だから、「コーディングをもっと効率的に行えるようになるべきである」と筆者は考えています。そして、コーディングをもっと効率的に行うために必要なのが、パーサであると考えています。

端的に言うと、
 上流工程バグを減らすのは難しいし、エンジニアが病んでしまいます。
 一方、下流工程を効率化するためには"積極的コードジェネレータ"を作るのが一番の近道です。
 そこで、"積極的コードジェネレータ"として自作のパーサを準備するとなります。
上記のような結論は、これまでの業界の意見とは異なるように感じます。そこで、少し長くなりますが、私がそう考える理由を順を追って説明したいと思います。

上流工程のバグを減らす努力は必要か?

上流工程と下流工程のどちらのバグを減らすべきでしょうか?まずは工程の位置付けから説明して、上流工程のバグを減らすべきだという業界の意見に沿って考えていきます。

1.工程の位置付け
上流工程とは、 顧客と相談し、顧客の要望から要件を引き出す。(要件定義)
 機能仕様書として文章化する作業(機能設計)
の2つのフェーズと定義します。
一方、下流工程は、
 詳細設計・製造(コーディング)・各種テスト
の3フェーズ(テストフェーズを目的別に分類すればもっと多くなる)と定義します。

2.プロジェクトに対する影響力
構造的に、重大なバグ・仕様変更が起こるのは上流工程です。"重大な"とは、プロジェクトに大きな影響を及ぼすという意味です。ということは、プロジェクトの効率性を向上するためには、上流工程を改善したほうが効果が高いです。「構造的」の部分については開発モデルとして長く使用されているウォーターフォールモデルを前提にしています。ここでは詳しく説明しませんので、気になる方は別途、調べてください。 それでは上流工程のバグとその要因を考えてみましょう。

3.上流工程のバグとその要因
上流工程のバグとは、  完成品が機能仕様書の仕様を満たしていない。(重度)
 完成品が顧客の要件を満たしていない。(さらに重度)
 完成品が顧客の要望を満たしていない。(目を覆いたくなるほどの重度)
 etc...
となります。
そして、その要因は、
 顧客システムへの理解力の不足
 顧客システムの勉強不足
 etc...
となります。

4.要因から見る問題点を解消するには?
要因で書いたような理解不足や勉強不足は、プロジェクト開始時点では常にあることです。サラリーマンエンジニアにとって、自分ができることだけを仕事にすることはほとんどありません。よって、要因にみるような問題点をプロジェクト開始時点では解消できません。 そういう理由で、この業界の構造は、
 「理解を深化させるために、システムエンジニアは顧客とよくコミュニケーションをとれ」
 「コミュニケーション能力を磨け」
とエンジニアに要求しています。言い換えると、
 「エンジニアのコミュニケーション能力によって、システム本来の要件や機能仕様書を顧客から引き出すことが重要であり、上流工程バグを撲滅するためにはエンジニアのコミュニケーション能力向上が重要である」
と論じられてきたと思います。
このように論じられてきた正否については、私が仕事に就いた当初(2000年代初頭)の課長級が、
 ・ボードコンピュータを触るのが好きな気質の人
 ・Windows95発売前から普及台数のすくなかったパソコンに触れていた人
 ・数学科を専攻して数学の教師や研究者になれなかった人
が情報系の仕事についていたという情勢であったことも関係があると思っています。(根拠はありません)
そういう人達の中には(当然そうでない人もいましたが)
 ・人と話すのを苦手としていた
 ・気難しかった
 ・職人気質であった(技術重視だった)
と分類され、コミュニケーション能力に問題点を見出すことも多かったと筆者は思っています。

5.コミュニケーション能力の向上を図ろうとして起こったこと
しかし、そのような努力を10年・20年続けてきたこの業界がどうなったかというと、# 直接的な因果関係を証明はできませんが
 「IT企業はブラック企業だ」
 「IT企業はうつ病の疾患率が高く、1部署に1人は休職者がいる」
 「IT企業は自殺者が多い」
と世の中が認識する結果を残しました。そして、インターネットの情報網の発達により、業界情報はネットにしっかりと浸透し、プログラマやシステムエンジニアは多くの優秀な若者が目指したくない職業になってしまいました。

6.バグを完全にゼロにすることは可能か?
経験的に、上流工程であろうと下流工程であろうとバグは漸近的に推移します。特に上流工程は、コミュニケーション能力といった対人スキルに掛かっていますから、0に近づけることは可能かもしれませんが、全く0になることはありません。そしてその1個が致命的になることがあります。

7.おおざっぱな結論
ここまでの説明で、上流工程のバグを減らしたほうがプロジェクトへの影響は大きいので、減らす努力は必要と述べました。しかし、いくら減らそうとしてもエンジニア自身が辛くなるだけなので努力の方向性としては正しくないということは伝わったと思います。つまり、下流工程を効率的にすることが、効果が薄いとしても精神的にまともなアプローチになるでしょう。

コーディングを効率化する概念と装置

下流工程のうちの大半はコーディングです。コーディングを効率化することによって、コーディング時間を短縮することができます。既に、多くの研究者がコーディング時間を低減するための装置を作り出しています。またそれらを分類するための概念についてもよく纏まっているので、コーディング時間を短縮するための装置と概念について紹介します。

■コードの再利用
コーディング時間を短縮するために、最も良く知られている概念が、「コードの再利用」です。「コードの再利用」の定義は、"あるプログラムを別のプログラムを書くときに利用する"です。サブルーチンコール、オブジェクト化、クラス化などの装置は、「コードの再利用」の概念を具象化した典型的な例です。また、C++のテンプレートやJavaのジェネリクスのようなジェネリックプログラミングの装置も「コードの再利用」の例といえます。これらは既に広まっていますし、言語仕様の一部にまで昇華されていますからわざわざエンジニアが自作する必要はありません。

■コードジェネレータ
そこでエンジニアが作ることになるのが「コードジェネレータ」です。「コードジェネレータ」とは"コードを生成するコード(コードを生成するためのプログラム)"です。 例えば、プログラムが示す入力欄に任意の入力をしたり、選択肢の中から選んだりすることで対話的にコードを生成するコードジェネレータの概念を具象化した装置がウィザードです。
また、これまでに作成したことのあるコード断片を登録しておき、必要に応じて、簡単な操作(GUIのボタンをクリックして選択etc...)を行うことで、ソースコード内にコード断片を追加するコードジェネレータがスニペットです。
 本「達人プログラマー」では、ウィザードやスニペットのようなコードジェネレータを"消極的なコードジェネレータ"に分類しています。"消極的なコードジェネレータ"とは、コードジェネレータで作成したコードのメンテナンスは通常の(手作業で作成した)ソースコードと同じように管理するものを言います。
 これと対をなすのが、本「達人プログラマー」で"積極的コードジェネレータ"と呼称する分類です。"積極的コードジェネレータ"は、生成したコードのメンテナンスはせずに使い捨てのコードを生成します。もし変更が必要になったときは、"積極的コードジェネレータ"に与える入力パラメータを変更する と定義しています。(もしくはコードジェネレータ自体を修正します)

どんなコードジェネレータについての解説をするべきか?

世の中には星の数ほどのプロジェクトがあってその内容もさまざまです。そのため、筆者がたった一つのコラムで特定のプロジェクトに合わせて固定的なコードジェネレータを紹介したとして、読者の納得性は高くならないでしょう。よって、汎用性の高い可変パラメータの入力ができるコードジェネレータの解説をします。

■各工程を効率化するコードジェネレータの入力パラメータと目標の設定
積極的コードジェネレータにおける可変のパラメータの実体は、機能仕様や詳細仕様です。また、テストコードを生成するコードジェネレータの場合は、入力パラメータは開発したソースコードです。ここで機能仕様や詳細仕様を形式言語化することはハードルが高いので、結局、ソースコードを入力にしてテストコードを生成するコードジェネレータを作ることを当面の目標にするのが妥当だと考えます。

■パーサ・コードジェネレータ・そしてコーディング時間の低減
話を「なぜパーサを作ることでコーディングが効率化するのか?」にそろそろ戻します。 テストコード用のコードジェネレータの機能は大きく2つあり、
 1.入力として自分が作成したJavaやC++のソースコードを読み取り
 2.必要なテストコードを出力する
となります。
そして、入力としてソースコードを読み取るためには、ソースコードの字句と構文を解析するパーサが必要となります。つまり、パーサを作ることがテストコードジェネレータを作る基礎となり、コードジェネレータがコーディング時間の低減を実現します。

■JavaやC++のパーサについて記事にしたら良いのでは?
先に述べたとおり、"目指すコードジェネレータは汎用性の高い可変パラメータの入力ができるコードジェネレータ"ですから、JavaやC++といった言語内容は、可変パラメータとして入力すべきです。判りやすい具体例を出すとすれば、yacc/lexのようなパーサジェネレータを作るべきです。そして、コードジェネレータに入力する可変パラメータは構造化したファイルとしてXMLライクなファイルを採用するのが一番わかりやすいだろうと思います。
 そこで、まずXMLパーサを作成し、それを汎用化してパーサコードジェネレータを作ります。その経験を活かしてテストコード生成用のコードジェネレータを作る段取りとします。

まとめ

1.効率化を推進するために、テストコードジェネレータを作ります。
2.テストコードジェネレータは
 2-1.ソースプログラム自体を読み込み字句解析・構文解析するパーサ
 2-2.JavaやC++などの構文や意味定義をするためのXMLファイルを解析するパーサ
 の2つのパーサが必要です。
3.ソースプログラムのパーサは具体性があるモノの汎用的には作り難いので具体性が
 あって汎用的になるXMLのパーサの作成を最初にします。
Comment(1)

コメント

宮川 健

(約1年前の記事を今頃読んでいます...)
コードジェネレータということでは、Lisp族のマクロがあり、これに触発されたものがGroovyやScalaで提供されていますね。C++でも、最近では、コンパイル時演算なるものが流行っているようです(C++は勉強していないので、よくわかっていません)。

コメントを投稿する