CLOSE

第 4 回では、PowerScript の文法的な「癖」を学びました。変数のスコープや NULL の挙動に戸惑いつつも、「意外と素直な言語だな」と感じ始めている頃ではないでしょうか。

連載第 5 回となる今回は、PowerBuilder (PB) の設計の骨格となる「オブジェクト指向」と「イベント駆動」について解説します。Web エンジニアが使い慣れた「コンポーネント」や「イベントリスナー」という概念が、PowerBuilder では「継承」という強力な武器を通じてどう表現されるのか。その実態に迫ります。

1. 「Window」は単なる画面ではなく「クラス」である

Web 開発において、画面 (Page) は URL に対応するルートコンポーネントであることが一般的です。しかし、PowerBuilder における Window は、それ自体が一つの独立した「クラス (Class)」として定義されます。

Window の中には、これまでに学んだデータウィンドウやボタン、入力フィールドなどの「コントロール」が配置されます。これらは Web フロントエンドでいうところの「子コンポーネント」に相当しますが、決定的な違いは、Window そのものがプロパティ (状態)、関数 (メソッド)、およびイベントを保持する完全なオブジェクト指向のクラスである点です。

  • 明示的なインスタンス化

  • Web ではルーターが URL を検知してコンポーネントを切り替えますが、PB ではコード上で Open(w_detail) のように関数を呼び出し、Window クラスを明示的にインスタンス化して画面に表示します。

  • マルチインスタンス (複数画面起動)

    ひとつの Window クラスから、複数のインスタンスを同時に生成して画面上に並べることも容易です。例えば「商品詳細画面」を、異なる商品 ID で 3 つ同時に開く、といった制御が標準機能としてサポートされています。

  • 状態管理 (State) のアプローチ

    Web フロントエンドのように Hooks や状態管理ライブラリ (Redux や Pinia など) を介す必要はありません。Window クラス内に「インスタンス変数」を定義するだけで、その画面が閉じられるまでのローカルな状態 (State) をカプセル化して保持できます。

2. イベント駆動 : Web と PowerBuilder のイベントモデルの差

Web 開発 (JavaScript) では、addEventListener や onClick={…} のように、イベントに対して関数を「アタッチ」します。
一方、PowerBuilder では、オブジェクトごとにあらかじめ定義された「イベント」という名のスロットに直接コード (スクリプト) を記述します。

イベント名 (PB)Web での相当概念実行タイミング
OpenuseEffect(() => …, []) / onLoadWindow がメモリにロードされ、表示される直前
CloseonUnmountWindow が閉じられる直前
ClickedonClickコントロールがクリックされたとき
ItemChangedonChange + Validationデータウィンドウの入力値が変更され、確定したとき

イベントの「戻り値」による制御

PowerBuilder のイベント駆動における面白い特徴が、「イベントの戻り値によって、その後に続くフレームワーク側の挙動をコントロールする」という仕組みです。

例えば、DataWindow (グリッドやフォームに相当するコンポーネント) の ItemChanged イベント (Web でいう onChange) を例に挙げてみましょう。

ItemChanged イベント (データウィンドウへの入力時)

// 未入力の場合
IF String(data) = "" THEN

    Return 1 // 入力を拒否し、フォーカスを移動させない

END IF

Web の event.preventDefault() との違い

Web 開発では、イベントの既定動作を止めたいときに event.preventDefault() というメソッドを呼び出します。PowerBuilder ではこれを戻り値に特定の数値を返すことで実現します。

  • Web (JavaScript) の場合

  • メソッドを呼ぶ (e.preventDefault() = 挙動のキャンセル)

  • PowerBuilder の場合

    数値を返す (Return 1 = 拒否、Return 2 = 無効化して次へ、など)

戻り値で「次のモード」を指定する

Web のキャンセルが「やるか・やらないか」の 2 択 (Boolean) に近いのに対し、PowerBuilder のイベントの戻り値は「フレームワーク (システム) に対する命令の分岐」になっています。

  • Return 0 (デフォルト)

    • 入力を受け入れ、次の項目への移動を許可する。

  • Return 1

    • 入力を拒否し、フォーカスをその場に留まらせる (エラーメッセージを出すなど)。

  • Return 2

    • 入力を拒否するが、フォーカスは次の項目へ移動可能にする。

3. PowerBuilder の真骨頂「継承」: Composition より Inheritance?

現代のフロントエンド開発 (React や Vue など) では、「継承より合成 (Composition over Inheritance)」がベストプラクティスとされています。コンポーネントを細かく分割し、Props や Slot で組み合わせる手法です。しかし、PowerBuilder の世界では「継承 (Inheritance)」こそが最強のアーキテクチャです。

Web 開発で「Props のバケツリレー」や「同じコンポーネントを何重にもラップする構造」にウンザリした経験はありませんか?PowerBuilder では、既存の Window (画面) や UserObject (コンポーネント) を「先祖」として、その資産をダイレクトに引き継いだ「子孫」を無制限に作ることができます。

継承による共通化のメリット

たとえば、すべての画面に共通の「閉じるボタン」や「ログ出力機能」を持たせ、これを先祖として入力系画面には「登録」「削除」、一覧系画面には「検索」「参照」など共通の処理と、それに対応するボタンやデータウィンドウなどのコントロールを追加します。さらにそれらを先祖としてカスタマイズして各画面を作成することで、システム全体の UI 統一に加え、開発工数を大幅に削減し保守性を高めることができます。

継承のイメージ

PowerBuilder の「継承」の 2 大アドバンテージ

見た目 (UI) とロジック (イベント・関数) をセットで一発継承
Web では、ロジックを Hooks や Composable に切り出せても、UI (ボタンの配置やレイアウト) まで綺麗に密結合させて継承するのは困難です。PowerBuilder は、先祖の「見た目」も「ボタンを押した時の裏の処理」も、すべて丸ごと子孫が引き継ぎます。

「先祖の処理」を 1 行で呼び出せる (拡張の容易さ)
子孫側で「先祖の動きをちょっとだけ変えたい」という場合、子孫のイベント内で SUPER:: ユーザーイベント名() または Super:: 関数名 () と書くだけで、先祖の共通処理を実行しつつ、子孫独自のロジックを前後にサンドイッチできます。ラッパー関数を何重も定義する必要はありません。

共通処理の修正が必要になったら、先祖を 1 か所直すだけで、数百画面ある子孫すべてに即座に反映されます。この圧倒的な開発スピードと統制力こそが、大規模エンタープライズ開発で PowerBuilder が長年愛され続ける理由です。

4. UserObject (ユーザーオブジェクト): PoweBuilder 版コンポーネント

「再利用可能な UI パーツやロジック」を作りたい場合、PowerBuilder では UserObject (UO) を使用します。これこそが、Web 開発における Component (コンポーネント) そのものです。

Visual UserObject (UI 用のユーザーオブジェクト) :
ボタンや入力欄、あるいはデータウィンドウを組み合わせたカスタムコントロールです。Web でいう「検索条件フォーム」「共通ナビゲーション」のようなパーツに相当します。作成した UO は、コンポーネントのインポート文を書く必要すらなく、開発画面 (IDE) 上で Window にドラッグ & ドロップするだけで配置できます。

Non-Visual Object (UI を持たないユーザーオブジェクト):
UI (見た目) を一切持たない純粋なクラスです。Web 開発における「Service 層」「カスタム Hooks」「Logic クラス」に相当します。PowerBuilder でも、画面 (Window) に直接ビジネスロジックを書き殴るとすぐにコードがスパゲッティ化します。そのため、ロジックを NVO に切り出し、Window からはインスタンスを生成して呼び出すのが、PowerBuilder 開発におけるベストプラクティスです。

第 5 回のまとめ

PowerBuilder のオブジェクト指向は、「継承」の仕組みを徹底的に活かすことで、大規模開発における高い生産性と強固な統制力を両立させる設計モデルです。

  • Window (画面) はクラスである :

    単なる表示領域ではなく、イベントというフックを持つライフサイクルを持ったオブジェクト。

  • 「継承」によるボイラープレートの削減 :

    先祖と子孫の関係を使い、UI と共通処理をコード 1 行書かずに引き継ぐ。

  • UserObject によるモジュール化 :

    Visual UserObject (UI パーツ) と Non-Visual (ロジッククラス) を使い分け、コンポーネントとしての関心を分離する。

Web の「自由で柔軟なコンポジション」に慣れた身には、最初は窮屈に感じるかもしれません。しかし、何百画面もの巨大な業務アプリを破綻させずに作り切る際、この厳格なオブジェクト指向のルールがいかに鉄壁のメンテナンス性を生み出すかを実感できるはずです。

関連記事

x instagram facebook youtube