メニューボタン
IBMi海外記事2009.07.22

RPGのリサイクル

ポール・コンテ 著

既存のコードを利用して新しいアプリケーションを作成するための戦略

最近話題の「グリーン・コンピューティング」では、紙資源やエネルギー消費量を削減することや社員の在宅勤務などに焦点が当てられることが多いですが、IBM i開発グループでは、RPGアプリケーションのコードを「リサイクル」することが「グリーン対応」のもう一つの重要な道筋になる可能性があると考えています。既存のコードをリサイクルするということには、コードを再利用することだけでなく、コードの構造を再構築することで新しいアプリケーションの機能やインタフェースを構築することも含まれます。本稿では、リサイクルする際に考慮すべき戦略について説明します。

「削減、再利用、リサイクル(Reduce、Reuse、Recycle)」は環境対応戦略として正しいことではありますが、IT分野における利点は何でしょうか。既に出来上がっているコードの中から不要なコードを削減する、なかでも実績のあるコード再利用技術を使って削減すると、アプリケーションの保守コストを削減することができます。しかし、従来の方法でコードを再利用することができない場合は、コードのリサイクルがその代替策となります。たとえば、Javaアプリケーション中にRPGのコードを「include」することはできませんが、だからといって、新しいあるいはモダンなアプリケーションを作成するには、RPGコードをゴミ箱に捨てて元のコードの機能を全く新しい言語で再実装するしか方法はないというわけではありません。

作成してあるコードの大半を捨てて一から書き直すのは高くつきますし、そのようにして書き直したコードを導入しても、ビジネスの運用に大きな不安定要素を持ち込むことになりかねません。しかし、古いアプリケーションに頼り切っていると、特にそれが融通の利かない5250インタフェース・プログラムだったりすると、運用効率が大幅に低下し、お客様やビジネス・パートナーとのビジネスチャンスを失うことにつながりかねません。

RPGアプリケーションをリサイクルすることで、何もせずに放置しておくことによる不利益も、すべてを一から書き直すことによる不利益も、両方避けることができます。既存のコードの大半を再利用して、その上に新しいアプリケーション機能やインタフェースを徐々に実装することができる場合がほとんどなのです。アプリケーションの新しいバージョンを全く新しい別の言語で開発するにしても、「リサイクル」することでコストとリスクを低減する方法はあります。

コードの変換とリフェーシング

まず初めに、考えられる2つの状況について簡単に説明します。会社の吸収、合併などといったさまざまな理由から、RPGアプリケーションを直接コンパイルあるいは実行できないプラットフォームで、すべてのRPGアプリケーションを実行しなければならなくなるかもしれません。こうした状況では、そのプラットフォームでサポートされている言語(たとえばC#やC++など)でアプリケーションを新たに実装し直さなければなりません。これを実現するための方法のひとつが、RPGの文をサポートされている言語に変換するツールを使用する方法です。

RPGコード・コンバータは、ウェブでconvert、RPG、"C#"などといった文字列を使って検索すれば見つかります。ただし、このようなツールを使用して生成されたコードに対して大幅な修正を加えると、変換先ターゲット言語の経験が豊富でないRPGプログラマはその新しい文法にてこずり、ターゲット言語を良く知っているプログラマは生成されたコードにおけるRPGの「opcode」の意味を理解するのが難しいかもしれない、ということを覚えておいてください。

RPGプログラム全体を他の言語に自動的に変換するのが最も適しているのは、元のRPGのコードが修正されるたびにプログラムが効率的に再生成できる場合です。(非ILE版のRPGで書かれたプログラムをILE版のRPGに変換するツールとしてIBMやサード・パーティー製のものもありますが、こうしたツールは、元のコードと似たプログラムでしかもRPGのプログラマでも理解ができて保守が可能なプログラムを生成するために、一度だけ変換するのに使用するのが通例です。)

多くの企業で耳にするのは、緑色の画面の代わりとしてブラウザのユーザー・インタフェースにしたいという要望です。さまざまなテクニックを使用したリフェーシング・ツールが有り余るほどあり、その中には、5250のデータ・ストリームを途中で捕まえて、ブラウザとRPGプログラムの5250入出力との間でデータや画面属性およびキーボードとマウスの動きをマッピングさせるものもあります。リフェーシングについては、他の記事でも多く取り上げられているので、本稿ではあまり深く掘り下げることはしません。

簡単なリフェーシング(たとえば画面のお化粧直し)をするだけでも、手早く、そして多くの場合それほど手間をかけずに、既存のアプリケーションにブラウザでアクセスできるようにすることが可能です。またリフェーシング用製品の多くは、たとえば選択操作にドロップ・ダウン・リストを使用するなどして、ウェブ・ページのレイアウトや入力操作をカスタマイズすることもできます。リフェーシングにより、アプリケーションへのアクセス方法の幅が広がり、より魅力的で使いやすい画面を提供することができます。ただし、リフェーシングだけでは、より広範なそして長期的な意味での目標を達成することはできません。

リサイクルで得られる本当の利益

RPGをリサイクルして達成できることとしては、既存のアプリケーション固有の価値を最大限に生かしてアプリケーションを改善する、あるいは新しいアプリケーションを構築するのに最も無駄の少ない方法を見つけるのが理想的です。既存のアプリケーションから活用できる可能性のある価値には、以下のようにいくつかの種類があります。

  • 完全で実行可能なアプリケーション
  • アプリケーションの外部インタフェースを介してすでに利用可能となっている、実行可能なアプリケーション機能とプロセス
  • サブ関数やプロセス中の特定のステップなどを実行する、実行可能なコードの断片
  • アプリケーションが対象とする問題領域のモデル、構造、メイン関数、サブ関数あるいはステップなどといった明示的には示されていないアプリケーションの設計

コードの自動変換とリフェーシングは、上記のリストの最初のカテゴリに対応しようというもので、リフェーシングは2番目のカテゴリについてもアクセス性を改善します。しかし一般的には、2番目から4番目のカテゴリにおいてリサイクルの価値を最大限に引き出すには、コードの自動変換とリフェーシングのほかにも方策やツールが必要となります。それらについて一つずつ見ていきましょう。

アプリケーションの機能とプロセスのリサイクリング

ILE RPGで実装され5250のユーザー・インタフェースをサポートしている、典型的な受注アプリケーションを例に考えてみましょう。このアプリケーションは一般的に項目の検索機能とプロセスを備えており、複数の画面を使って新しい顧客やその顧客からの最初の注文を入力できるようになっています。

このアプリケーションの既に実行可能な機能とプロセスを新しいアプリケーションでも使用したいときは、まずそのソースコードを表示させてみましょう。たとえ「既存」のアプリケーションであったとしても、そのソースコードが、GetItemProperties、InsertOrder、InsertCustomerなどのプロシージャの集合にしっかり構造化されていれば、リサイクルの作業は比較的容易にできるかもしれません。たとえば、RDiツールを使用してラッパー・コードを生成すれば、こうしたプロシージャがウェブ・サービスとして使用でき、どんな言語やツールで開発された新しいアプリケーションであっても、そこから呼び出すことができます。

しかしながら、既存のアプリケーションはパラメータ化されていないたくさんのRPGのサブルーチンからなる少数の大きなプログラムで実装されていて、ビジネス・ロジック、ワークステーション入出力、データベース入出力などがすべて絡み合っているという場合がほとんどでしょう。こうしたコードをリサイクルする方法はいくつかあり、いずれの方法も5250入出力命令が既存のアプリケーション内で重要な位置を占めており、これに左右されます。

まず、手動でコードを修正して、表示ファイルの「read」文をプロシージャの入口ポイントで置き換え、「write」文をプロシージャの出口ポイントで置き換えます。(EXFMT文はwriteのあとにread文を続けたものとして扱うことができます。) 新しいプロシージャに渡すパラメータはレコード構造となっており、その中にワークステーション入出力文が読み書きする入力フィールドと出力フィールドが保持されています。(新しいプロシージャにこれらすべてのフィールドを含める必要がない場合もあります。)

もちろん、一般的にはサービス・プログラムを作成する必要があり、プロシージャをウェブ・サービスとしてラップする必要もあるかもしれません。元のプログラムを分岐させればソースコードが重複することになり、以後両方とも保守しなければならないので、あまり良いアイデアではありません。ILE RPGはソースコードを「include」する機能と条件付コンパイルする機能の両方でこの問題に対処しています。(これら2つの機能を既存のアプリケーションでも使用していないのであれば、ILE RPGのシンプルで強力な2つの機能を活用していないことになります。)

IBM i開発ツールのベンダーの中には、プログラムの5250データ・ストリームを途中で捕まえて、このストリームを介して既存のプログラムとやり取りするウェブ・サービスを生成するツールを提供することで、上記の戦略をより簡単に実現しているものもあります。この方法は、5250画面の機能をパラメータ化されたウェブ・サービスとして公表するものです。

利用可能なアプリケーション・プロセスをリサイクルするということは、上記のテクニックの拡張に過ぎず、公表された関数を5250画面のシーケンスに沿って呼び出すシーケンス(条件付の場合もあり)を作成することで、より上位のプロシージャやウェブ・サービス(あるいは開発ツールのランタイム機能)がプロセスを構成します。ベンダーのツールの中には、こうしたテクニックとツールのリフェーシング機能を組み合わせて、5250のやり取りのシーケンスを、再構成されたブラウザ・インタフェースの1つ以上のページにマップさせることができるものもあります。このレベルの構成やインタフェースの再構成により、ブラウザ・インタフェースの機能の利点を生かして、既存の5250アプリケーションがサポートしているプロセスを簡素化することができます。

小粒の宝石を採掘する

既存のアプリケーション中の有用な機能がすべて、必ずしも5250画面とのやり取りで明らかになるわけではなく、前節で説明した通り、カプセル化されていることがあります。ビジネス・ルールを有効にしたり、中間計算を実行したり、5250関連でないタスク(たとえばメールを送信するなど)を実行したりしている、コードの小さい断片があることがしばしばです。

ここでも、コードが既に綺麗に構造化されているプロシージャでできている場合、そうした多くのルーチンは、ウェブ・サービスやその他のインタフェースでラップすることですでにアクセス可能となっているものがほとんどです。既存のコードがそれほど綺麗に構造化されていない場合は、まずコードの断片をプロシージャに変換します。RPGコードの塊に、必要なプロシージャ・インタフェースのコードを追加するのは少し退屈な作業ですが、コードの断片をリサイクルする際にもっと大きな障害となるのは、活用したい機能に関連するコードと、特定のアプリケーションの他の部分(例えば印刷)のコードが絡み合っているコードを扱うときです。コードを部分的にコピーして不要な文を削除することもできますが、これでは前述した「分岐」の問題が発生します。

ここでもまた、ILE RPGのinclude機能や条件付コンパイルを使用することが、強力な味方となります。プログラムのコードの大部分を切り取って、その部分を/Includeディレクティブで置き換え、プログラムをコンパイルする際に抽出したコードを再び合体させるのは、実用的な方法です。切り出したコードの塊の一部だけを使用した、独立したプロシージャを生成するには、切り出したい部分を/If Defined(_Exclude)ディレクティブで囲い、プログラムをコンパイルする際に使用するコマンドに_Exclude条件を定義するだけです。多くの場合、切り出したコードの物理的な並びを再配列する量が少なければ、必要となる/Ifディレクティブの数を減らすことができ、コードがより分かりやすくなります。ただし、条件付コンパイルの利点は、切り出したコードの実行構造を完全に再構成する必要がないということです。しかも、/Includeを使用すれば、元のコードを使用している既存のアプリケーションのコードをすぐに改訂する必要もありません。

上記で説明したテクニックを使用するには、SEUではなく、モダンなエディタを使用するほうが良いでしょう。なぜなら、前述のテクニックを使用すると、ソース・レベルの構成ブロックとして複数のソース・ファイル(あるいはメンバー)が生成され、これをSEUで管理するのは効率的でないからです。また、切り出しの候補となるコードの断片を探すには、それなりのエディタを使用したほうがはるかに容易でもあります。

切り出してincludeするテクニックは、値の検証や財務計算などといった、マルチステッププロセスの状態の影響を受けない関数を作成するのに適しています。別の言い方をすると、同じ入力値を使って繰り返し呼び出すといつも同じ値を返すようなものに適しているということです。しかし、ビジネス・アプリケーションのコードのほとんどは、一連の条件ステップに依存しながらトランザクションを完了させます。たとえば、新しい注文を入力するには、場合によっては、新しい顧客を入力しなければならない場合があります。

実装しようとしているコードが複数のステップに渡って多数のグローバル変数を使用している場合や、制御の流れが綺麗に構造化されていない場合(たとえばGOTO文を使用している場合)には、プロセス中のステップを切り出すのは単純な関数を切り出すより困難です。こうした場合に役立つその場しのぎ的な方法の一つが、状態変数を含むレコード構造を定義し、この構造を入出力パラメータとして使用するプロシージャとしてプロセス・ステップを切り出すという方法です。ただし正直なところ、本当にどうしようもないコードについては、リサイクルの前述の2つのカテゴリに集中し、別のアプリケーションを作って古いコードは堆肥の山に捨てる、というのが最良の方法である場合もあります。

聖杯 - 設計の抽出

ビジネス・アプリケーション(コードとデータベースの両方を含みます)は、その基礎をなすデータ、ビジネス・ルールと操作を単純に構成したものではありません。ビジネス・アプリケーションとは、現実世界の対象領域のモデルを明示的にあるいは暗示的に具現化した、特定の構成なのです。理想的には、元のアプリケーションの開発者が、対象領域を良く知っている人(たとえば企業の営業業務)と一緒に作業して、その領域についてしっかりしたモデルを持ち、アプリケーションを設計、実装、修正するのが一番です。アプリケーションの基礎をなしているモデルには、対象となる実体(たとえば、顧客、販売商品、社員)やそれら実体間の相互関係、ビジネス業務がどのように構成されているか(たとえば、営業チャネル、サプライ・チェーン)など、たくさんのものが含まれます。

私の経験から言えば、多くの開発者グループはかなり変則的なアプローチでアプリケーションをモデル化しており、その結果もきちんと文書化されていません。しかし、この不足分こそが、既存のコードから設計要素を抽出することで得られる利益がある理由の一つなのです。ビジネス・モデルのある有用な部分が既存のアプリケーション・コードから抽出できれば、新しい版のアプリケーションを異なるフォームや言語で作成することで、そのコードの設計を「リサイクル」できる可能性があるのです。

唯一の問題は、コードから設計を抽出するのはとても困難であるということです。

プログラム(またはアプリケーション)を理解するということは、設計を抽出することと、粛々と保守することの、両方の根底をなすものです。そして、プログラムの理解を助けてくれるツールやテクニックは、数十年来広く用いられているものです。初期のツールの中には、さまざまなクロス参照解析機能を備えて、プログラムが使用しているデータベース・ファイルやフィールドの関係や、どのプログラムがどのファイルやフィールドを使用しているのかを表示するものもあります。プログラム、サブルーチン、プロシージャ、その他のコード単位間の静的および動的関係を一覧する、同様のツールもあります。こうしたツールは進化を続け、WDSCやRDiなどといったモダンなコード・エディタやIDEでは、対話型の検索機能や探索機能(たとえばドリル・ダウン機能)が追加されたりしています。

より使いやすいツールにするために、コード探索機能や理解用のツールはより高度な分析テクニックを取り入れています。たとえば、プログラム変数の依存関係やライフサイクルをトレースできることで、影響度分析が改善できるだけでなく、プログラムの要素をより多く結びつけて、アプリケーションの基礎をなすモデルの完全な全体像を作り上げることが容易になります。

プログラムは、何年にも渡ってコードが追加されたり修正されたりして、わかりづらくなり、その根底にあるモデルも理解しづらくなっていくのが一般的です。したがって、便利なツールセットを使いこなせる開発者の力量が、設計の抽出を生産的に行うためには不可欠な要素となっています。聖杯を追い求める開発者は、モデリングと設計がアプリケーション開発の根底をどのように築いているかについて、基本的な理解を持っておらねばならず、それを理解することで何を探したらよいのか、見つけたものをどのように使ったらよいのかが、分かるようになります。(表示ファイル・レコード形式を使用してプログラムのモデルを理解する方法については、本稿の最後にある「プログラムの設計を見る秘密の『窓』」を参照してください。)

大規模な設計抽出は、気が小さい人にはお勧めしません。しかし、あなたの所属する組織が、既存のRPGアプリケーションをリサイクルする戦略の一部として、大規模な再実装プロジェクトを目指しているのであれば、利用可能な設計抽出用のツールを徹底的に調査し、設計抽出に関してスタッフに求められるスキルの強化を図らなければなりません。(設計抽出の作業に関する開発者候補としてもっとも適していると思われるのは、生産性が最も高い保守プログラマです。こうした保守プログラマのスキルは、必要とされるスキルと似ているだけでなく、保守プログラマは、アプリケーションのモデルについて、既にある程度の理解を持っている可能性があるからです。)

(少なくとも昔の言語で書かれているアプリケーションからの)設計抽出は、ツールによる支援が大いに役立つものの、人間による分析作業に取って代わるものではありませんし、今後もおそらくそれは変わらないでしょう。一方、実稼動しているプログラムの設計の一部または全体を一度抽出してしまえば、そのアプリケーション(あるいはその一部)の別の実体を自動的に生成できる可能性が期待できます。UMLなどといった実行可能でないモデル化言語から始めるのと違って、実稼動しているプログラムのソースコードから設計を抽出することは、実行可能なコードの別の形態を生成するのに必要な、正確な情報が得られるということです。

抽出された設計要素を使ってそこからコードを生成するのは、前述した、再構成をしない一対一の翻訳をする機械的な翻訳とは異なります。設計を抽出してそこからコードを生成するのは、プログラム理解ツールとアプリケーション生成ツールの両方のベンダーが前向きに取り組んでいる、有望な分野なのです。

次の「サイクル」に備えて

自然界では、持続可能なプロセスには常にリサイクルが関わっています。二酸化炭素であれば、大気中や海洋中のもの、あるいは、菜園から採れた野菜やコンポスト容器に入れた野菜くずから発生するものとして、循環しています。持続可能なソフトウェア開発にも効率的なリサイクルが必要で、ある世代のアプリケーションに注がれたエネルギーは、古い世代のアプリケーションを次の世代のアプリケーションで置き換えた際に、そのすべてが失われるわけではありません。

本稿では、既存のRPGコードに埋め込まれている「エネルギー」をできるだけ取り出す方法について述べてきました。長期的にみると、より効率的にリサイクルできるような開発手法をとることが重要です。そのためには、優れた設計手法と、アプリケーションの定義にモデルを明示的に含めることができるような開発ツールおよび言語を使用することが必要です。理解しやすく、しかも最新の状態に更新されているという意味で優れたドキュメントがあることも重要ですし、この分野に関するモダンな開発ツールや言語のヘルプも重要です。要件の収集やその管理、テストの自動化、などといったアプリケーション開発ライフサイクル全体を構成するその他の手法やツールも、ソフトウェアのリサイクルを効率化することができます。

将来のアプリケーション開発プロジェクトの際には、コードをリサイクルすることが「有機的な」プログラマへの第一歩であることを頭に入れておいてください。

プログラムの設計を見る秘密の「窓」

プログラム中にある現実世界のモデルを理解するには(いつもそうですが、最新の外部ドキュメントがないことを確かめた後に)、言うまでもなく、まずプログラムのプロシージャとサブルーチンの名前およびそれらの階層構造を見ることです。こうするだけでもかなりのことが分かりますが、RPGのような非オブジェクト指向言語、特に典型的な旧来のプログラミング・スタイルの場合、プログラマがコードの塊をどのように切り分けてプログラムの流れのさまざまな分岐にしたのかが、ルーチンに反映されています。こうした方法は、対象領域のアクター(たとえば社員)が現実世界をどのように描いているのかとは異なるアプローチです。

他人が記述したプログラムを保守することに多くの時間を費やしてきたプログラマのほとんどは、データベース・スキーマ、特にレコードのレイアウトや外部キー制約などを見て、実体やそれらの間の関係がどのようにモデル化されているのかを把握します。繰り返しますが、物理的なデータベースの実装は、論理データモデルをいつも反映しているわけではありません(必ずしも反映すべきものでもありません)。とはいえ、プログラムのルーチン構成とビジネス・プロセス間やユースケースよりも近い対応関係にあります。

私は何年にも渡って、さまざまなツールやその場しのぎ的なやり方をいろいろ使って、対象としている現実世界のアクティビティをどのようにプログラムにモデル化するかをなんとか引き出してきました。最近、プログラム理解テクニックの分野で豊富な経験をもつ仕事仲間の一人が、私が今まですっかり見落としていたIBM iプログラムへの「窓」を教えてくれました。プログラムが使用している表示ファイル・レコード形式が、その「窓」です。

表示ファイル・レコード形式は、データとそのデータに密接に関連したユースケースの集合に対して実行可能なアクションが一箇所にうまくまとまっている場所です。表示形式のインベントリと記述から読み始め、各フィールド間の依存関係をたどり、フィールドからデータベースへと紐解いていけば、一つ以上のユースケースを実装しているコードを詳しく見ることになります。こうすることで、プログラムの礎となっているモデルを理解するのに大いに役立ちます。

あわせて読みたい記事

PAGE TOP