Wolfram言語での大規模ソフトウェアシステムの構築

Wolfram言語で大規模ソフトウェアシステムを構築する場合も,他の大規模ソフトウェアシステムの構築に適用される一般原則に従わなければならない.細部はWolfram言語独自のものかもしれないが,原則の多くは非常に一般的なものである.また,特にWolfram言語が適しているような他の方法もある.それを理解し,利用するとよい.
この一般原則は,高速探査用のツールをすぐにプロトタイプ化する場合以外のすべての開発に適している.この原則が適用されるシステムには以下のようなものがある.
システムをコンポーネントに分割する
まずシステムをコンポーネントに分割する必要がある.多分これが最も重要な原則であろう.満足のいく自然な分割ができたら,その後は苦労しなくてもうまくいく.あるものを異なるコンポーネントに分割する場合,ほとんど常に自然な方法が存在する.これらのコンポーネントを見付け,それぞれのコンポーネントを独立した部分システムとして構築する.
次に,コンポーネントとして構築するのが便利な理由をいくつか挙げる.

コンポーネントの方が速く開発できる

それぞれのコンポーネントだと理解しやすいし,目標も少なく,実装もあまり要求されない.そのため,はじめに書くコードも少なくてすみ,後で操作するコードも少なくてすむ.これは特に,プロジェクトを開始する新しい開発者に便利である.効率よく行うために学ばなければならないことが少なくてすむ.

コンポーネントは別々に開発できる

開発をチームで行う場合,コンポーネントをチーム内で割り振って,それぞれのメンバーの専門性を生かすことができる.データベースコンポーネントはデータベースを知っている人に割り当てるようにすることができる.これで微分方程式を知らない人が,微分方程式についての知識を必要とするようなコードに触れずにすむ.

コンポーネントは別々にテストできる

開発プロセスの統合された要素としてのテストは,ソフトウェア開発を成功させるための重要な部分である.コンポーネントで作業することでテストのプロセスが非常に簡約される.ユーザインターフェース等のコンポーネントは非常にテストしにくいものであるが,他のコンポーネントはそれよりテストが簡単である.つまり,システムがコンポーネントに分割されていると,テストがずっと簡単に行えるのである.また,コンポーネント別にテストすることで,テストに失敗した場合エラーを引き起しているコンポーネントはどれかがすぐに分かり,すぐに問題が解決できる.

コンポーネントは置き換えることができる

開発は継続したプロセスであることが多い.新しい動作環境等の変更点が生じたり,新しいテクノロジーが使えるようになったりということはよくあることである.コンポーネントで作業していると,新しい方法に変更するのが簡単である.例えば,新しいタイプのデータベースが利用できるようになったとする.もしすべての接続機能がデータベースコンポーネントに入っているならば,そのコンポーネントを新しいもので置き換えるのはずっと簡単にできる.

コンポーネントは思いがけない方法で使える

コンポーネントに分割することで柔軟性がかなり向上する.例えば,補間について独自の特別な方法がある場合,別のアプリケーションでもそれが使いたいであろう.もしこれがそれ自身のコンポーネントに存在するのであれば,他のアプリケーションに簡単に提供できる.うまく分割されていないアプリケーションでは,ただその実装をコピーしようと思うかもしれない.しかし,そうすると同じものを2部持つことになり,バグの修正や新機能を2ヶ所に加える必要が出てくる.また,アプリケーションの一部の機能を使うためだけにアプリケーション全体を提供すると別の問題が生じる.知的財産,企業秘密,ライセンス問題等があるかもしれない.一番よいのは,必要なコンポーネントだけを提供することである.
また,コンポーネントを使っている場合,webMathematica を使って自分のシステムをWeb配信システムに変換することがかなり簡単にできる.
コードではなくアーキテクチャを考える
これはコンポーネントに分割するという原理に密接に関係しており,コードの詳細すべての代りに,システムの大きな粒度,特にコンポーネントについて考えるようにした方がよい,ということである.プロジェクトのアーキテクチャがよいものであれば,コードは簡単にそれに従ってくる.よいアーキテクチャを作成する方がコードを書くよりずっと難しい.たいしたトレーニングや経験がなくてもコードが書ける人はたくさんいるし,よくないコードにより生じる結果は,よくないアーキテクチャによる結果よりもずっと簡単に対処できる.
システムを構築する際に避けるべきなのはコードを書くことだとする原則がある.実際にコードを書くことを避けるためにできることをすべてしてみる必要がある.コードの代りにアーキテクチャ,テストの作成,ドキュメントの執筆に焦点を絞るのである.「コードに飛びつき,狂ったようにコードを書き始めるべきだ」という態度の開発者もかなり多いが,それをやめて自分が構築しているものについて考えた方がうまくいくことが多い.
Wolfram言語コードをパッケージにする
Wolfram言語にはコードをパッケージやアプリケーションに分割する機能が多く備わっている.これらを十分活用することが大切である.多くの場合,BeginPackageで始まりEndPackageで終るコードすべてをパッケージに入れる必要がある.パッケージはアプリケーションにバンドルされていなければならない.このようにしてアプリケーションが配信されるのである.これに対する例外は,Wolframシステムデモンストレーションのバンドルメカニズムである.
パッケージおよびアプリケーションとして設定するには少し時間がかかるが,Wolfram言語はまさにこの目的のために設計されたWolfram Workbench 等のツールを提供している.そのようなツールはWolfram言語をソフトウェア開発に簡単に使えるようにする多数の生産性機能を提供している.
簡潔さを維持する
この原則は主に実際の実装に関係している.これは,物事を表現するのに小さい関数を書いたり簡単なシンタックスを使った方がよいということである.非常にシンタックスが豊かなWolfram言語では特に重要なことである.またWolfram言語がサポートする非常に文芸的なプログラミングスタイルを利用するのもよい考えである.
BeginPackageEndPackageをオーバーロードする等のおかしい制御構造を作成することも避けなければならない.そうすることが可能であるというのはWolfram言語の面白いところであるが,ほとんど常に避けなければならない.そのような構造は,システムを見たいという人にとっては迷惑なことであり,書いたコードの有用性を制約することもある.
ソース制御を使う
2日以上に渡り使用し作業を続けようと思っているシステムはすべてソース制御しなければならない.これは複数の開発者がいる場合やプロジェクトが数ヶ月以上に渡り開発される場合に,重要な点である.
ソースコード制御システムには,CVS,SVN,Rational ClearCase等がある.これらは異なるバージョンのコンポーネントファイルを保存する,ファイルへの変更理由の説明を記録する,リリースされるバージョンに対するファイルグループにタグを付ける,異なるバージョンのファイルを比較する,変更点をマージする等の一般的な機能を提供する.ソースコード制御は開発者のチームにとっては不可欠であるが,単独の開発者で開発されるプロジェクトの場合にも非常に有用である.
Wolfram Workbench にはCVSのクライアントが含まれており,SVNのクライアントを含むようアップデートされているところである.他のほとんどのソースコード制御システムのクライアントサポートを含むためのアップデートも可能である.
ソースコード制御を使用するためには,ソースコードサーバかレポジトリにアクセスできなければならない.これは自分のマシンに比較的簡単に設定できる.これ以外にも多数のパブリックシステムがある.しかし公用システムはソースコードが公に見られてもよいアプリケーションにしか適していないので注意が必要である.また,多くの組織で,そのITインフラストラクチャの一部としてソース制御を提供している.
ソース制御に加え,ビルドシステムや設定管理ツールもある.これらはソース制御と一緒に使ってエンドユーザに配布するアプリケーションのリリースバージョンを構築することができる.
ドキュメントの執筆
アプリケーションのドキュメントには,対象となる読者によりさまざまな書き方がある.

エンドユーザ用のドキュメント

Wolfram言語はWolfram言語アプリケーションで使用でき,Wolfram言語ドキュメントセンターと統合され,HTMLドキュメントも生成できるドキュメントシステムを提供している.この他,お持ちのシステムにもそれ自身のドキュメントがあるかもしれない.
エンドユーザ用ドキュメントがよいと,システムがよりプロフェッショナルに見え,使用しやすくなる.その上開発プロセスの助けにもなる.文書化するのが難しい,あるいは文書化すると妙に聞こえる場合は,適切に設計されていないことがよくある.このように,エンドユーザ用のドキュメントは,開発の統合された部分の一つとして作成されなければならない.

開発者用のドキュメント

これは開発者用に書かれるドキュメントであり,いろいろな形式を取ることができる.コードにコメントを入れたり,関数を説明する名前を使ったりすることができる.また,ソース制御を使う場合,変更点をコミットするときにその変更の理由を説明することができる.この他にも,プロジェクトにドキュメントを保管することができる.これはWolfram言語ノートブックで間単に行うことができる.Wolfram Workbench ではソースコードからノートブックへのハイパーリンクを付けるためのシステムを提供している.
一旦コードを書いた後で別のアルゴリズムを使う等してその動作を変更する場合,使用した名前を変更する時間を取るべきである.名前には,実際の実装を表す名前を使うとよい.Wolfram Workbench には名前の変更を助けてくれるような便利なツールが含まれている.実装に使われるファイル名やシステム全体の名前を変えることですら恐れてはならない.
命名規則のひとつに,接頭辞として「new」を使わないようにするというものがある.新しい補間の方法を導入するときにその関数を「newInterpolation」としてはならない.その理由は,この関数が永遠に新しいはずはなく,最終的にシステムの最も古い部分になることがあるからである.さらに悪いことに,機能を再び変更したいときにもう「new」が使えないからである.
通常Wolfram Researchでは,内部コードの命名に力を入れており,必要に応じて関数名,変数,ファイル名等を変更している.
単体テストを書き,使用する
テストは現代の開発プロセスの重要な要素となるべきである.以前は,テストはそのシステムをテストすることを目的とした別のグループの人たちが行うものという見方が強かった.ソフトウェア品質管理部が重要な役割をになっているとはいえ,テストは開発において統合された役割を果たすべきであり,開発者がコードを作成すると同時に行われなければならないものである.
Wolfram言語コードは,データが簡単に保存・復元できる,異なるWolfram言語関数が簡単に呼び出せる等多くの理由で単体テストに役に立つ.また,通常Wolfram Workbench を介して実行される,MUnitという非常に便利な単体テストも提供している.
新しい機能がすべて対象となるよう,作業を進めるに従ってテストを開発しなければならない.コードにバグや弱点があったら,それを修正したときにすぐにテストを書かなければならない.テストは頻繁に実行する必要がある.例えば,ソース制御にコミットする前に必ず実行するのである.また,テストは100%成功するように維持しなければならない.テストを利用するためには,システムが異なるコンポーネントに分割されるようにしておく必要がある.こうするとそれぞれのコンポーネントに対していくつかのまとまった異なるテストができる.
テストを継続することには次のような多くの利点がある.

バグの修正がより簡単になる

頻繁にテストを実行することで,ずっと速くバグを見付けることができる.通常,バグが発生してすぐ見付けた方が格段に早く修正できる.発生してから6ヶ月後に見付けたバグは修正しにくい.テストを実行することで,開発の生産性が向上する.

リファクタリングがより簡単になる

リファクタリングとは,アプリケーションの動作は変更せずにアプリケーションの実装を変更することである.これには名前の変更,システムの分割方法の変更,異なるアルゴリズムの使用等が含まれる.これらすべてで,変更を加えた後でも使えるテストがあれば,変更を行ってよかったという自信が持てる.

新バージョンへのアップデートがより簡単になる

Wolframシステムの新バージョンにアップデートするときは,その新バージョンを使ってテストを実行することができる.これにより新しいシステムにアップグレードできるという自信が持てる.

新しい開発者のためのトレーニング

プロジェクトに新たに加わった開発者は,単体テストの改良や強化に携わることでそのプロジェクトについて学ぶことができることが多い.
Wolfram Workbench を使う
Wolfram Workbench はWolfram言語のための統合開発環境である.これは,多くの商用環境で使用されているEclipseというIDEプラットフォームに基づいている.Workbench は直接使うこともできるし,EclipseにこのWolfram言語ツールをインストールすることもできる.
Workbench は大規模アプリケーションの構築のために便利なツールを数多く提供する.これにはデバッガ,プロファイラ,単体テスタがある.また,Workbench はコード,ドキュメント,Javaクラス,ノートブックドキュメント等異なるタイプのリソースを含むプロジェクトをサポートしている.作業に対するこのプロジェクトの考え方は,開発の生産性を高めることのできる重要な方法のひとつである,システムを異なるコンポーネントに分割するということに合致する.
Workbench にはWolfram言語コード用の特別エディタも含まれており,Wolfram言語パッケージおよびアプリケーションについての多くの情報が備わっている.Workbench で,このように開発・作業することが簡単になる.またCVSとうまく統合されており,別のソース制御システムで使用するよう拡張することも簡単にできる.
Java,Python,C,C++等の別の言語での開発に対するサポートもある.システムで,これらの言語とWolfram言語を統合する必要があっても,非常に簡単に統合できる.
Workbench の面白い機能のひとつに,Wolfram言語の並列計算の使用に役立つツールを与えるというものがある.並列プログラムをデバッグおよびプロファイルすることで,システムに並列プログラミングを加える助けとなる.
次は,大規模プロジェクトを助ける Workbench 独自の機能である.

プロジェクトの構成

Workbench で行った作業はすべてプロジェクトとして集められる.プロジェクトはWolfram言語コード,ドキュメント,Javaクラス,ノートブックドキュメント等の異なるタイプのリソースで構成される.他のプロジェクトベースのシステムとは異なり,Workbench のプロジェクトは特にシンプルで,管理しやすい.Workbench にはドキュメントを開くための特別なエディタ,特化された検索機能,異なるコンポーネントに対するレポート等,プロジェクトを操作するための特別なツールがたくさんある.また Workbench はWolframシステムのノートブックフロントエンドとも結合している.

コードの起動と実行

Workbench はプロジェクトからWolfram言語コードを起動・実行するための高度なインターフェースを提供する.これによりプロジェクトのためだけにWolfram言語を初期化することができ,コード,Javaクラス,ノートブックスタイルシート,開発中のパレット等の異なるリソースすべてが集められる.作業内容を関連するいくつかのプロジェクトに分けているばあいは,起動時にそのことが認識される.また,Wolfram言語をバージョン間で切り換えるための非常に便利な方法もある.

デバッガ/プロファイラ

Workbench はWolfram言語デバッガおよびプロファイラのインターフェースを提供する.並列およびユーザインターフェースのコードを含む多くのタイプのWolfram言語プログラムを検査することができる.プロジェクトにJavaのソースコードがある場合,Wolfram言語とJavaのコードを同時にデバッグすることができる.これは非常にユニークな機能である.

単体テスタ

Workbench はWolfram言語の単体テスタであるMUnitのインターフェースを提供する.個々のテストファイルを実行することもテストファイルのグループ全体を実行することもできる.

リファクタリング

Workbench は変数の名前変更等のためのリファクタリングツールを多数提供している.また,コードを見付け修正するためにWolfram言語パターン言語を使う,特化された検索/置換ツールも備わっている.これらのツールは,文字列検索/置換ツールを使ってソースコードのテキストに作用するのではなく,パターンを使って実際の式の木に作用する.

エラー/警告

Workbench はプロジェクト内のすべてのWolfram言語ソースファイルの中の多くのクラスのエラーおよび警告を見付け,それを報告する.これはソースファイルが開かれたかどうかにかかわらず行われる.ソースファイルの問題の概要が得られることで,特に多くのソースファイルがある場合,その生産性が著しく向上する.

TODOコードドキュメント

Workbench はプロジェクト内のすべてのWolfram言語ソースファイルの中のTODOコメントを見付け,それを報告する.これはソースファイルが開かれたかどうかにかかわらず行われる.これはソースで実行する必要のあるタスクの文書化および追跡のための,簡単かつパワフルな方法である.

ソース制御

Workbench はCVSのクライアントを提供しており,他のほとんどのソース制御にも拡張することができる.
Wolfram言語を利用する
Wolfram言語は,ソフトウェア開発にとって非常に便利であるが,見過ごされている機能もたくさんある.それにもかかわらずその機能はすべて強力な利点であるため,かなりの使い道がある.

データの簡単なシリアライズ

Wolfram言語の基本的な構成要素は式である.プログラムやデータを含むすべてが式なのである.式はファイルに書き込みWolfram言語にロードし直すことが簡単にできるので,システムの状態を保存しそれをロードし直すのが非常に容易にできる.
このためシステムをコンポーネントとしてテストおよび開発することが簡単になる.例えば,データベースからデータが必要だとすると,Databaseコンポーネントを開発し,これを使ってデータファイルを準備することができる.こうしておけばComputationコンポーネントを開発したときにそのデータをロードして計算を実行できる.あるいは,これらのデータファイルをロードする単体テストを書くこともできる.コンポーネントは1つだけテストすることが重要であるので,この方法が非常に適している.
データの保存は,Save[file,data]等文字通り1行の簡単なプロセスである.JavaやC++で作業をしている場合,多数の行のコードを書かなければならず,データが変更されたらコードも書き直さなければならなくなる.同じことをWolfram言語にロードし直すと,簡単なdata=Get[file]だけでデータが回復する.

コードポイントへの簡単なアクセス

パッケージの中のいくつかの関数が呼び出したいときは,Wolframシステムノートブックフロントエンドにその名前を入力するだけで直接簡単に呼び出すことができる.これはWolfram言語の解釈特性を利用しており,例えば,コードを開発する場合のデバッグセッション前の準備量が著しく減少する.

可視化ツールの使用

Wolfram言語にはデータや曲面をプロットするための可視化ツールが多数含まれている.ツールの中にはグラフィックスのプロット等,非常に特化されたものもある.これらはすべてアプリケーションを実行することへの洞察を与えてくれる便利なものである.実行時間のプロットを作成して,入力サイズに従ってスケールされるかどうかを見たり,調査の必要性を示唆する可能性のある予期しない特性を探すための変換データの分布を調べたりすることもできる.

インタラクティブな調査

自分の関数を探究するためにWolfram言語のインタラクティブツールを使うことができる.例えば,1行にManipulate関数を使い,関数を呼び出すツールを作成することができる.これは予期しない妙な動作を明らかにするのに役に立つ.

乱数モデルの構築

作成したアプリケーションで実行する特別なデータが必要な場合は,もちろんデータベースからそれを読み込むことができる.コンポーネントのいくつかを開発およびテストするためのデータを保管し復元するためには,シリアライズ法を使うことができる.別の方法として,特に構造化されたデータに有効であるが,Wolfram言語の乱数生成機能を使って乱数データを構築するというものがある.これには,生成されたデータには実際の内容がないという更なる利点があるので,実際のデータがより制約されるような方法で配布することができる.
他の開発者を考慮する
開発者は常に他の開発者のことを考慮しなければならない.コードを文書化するとかコードは簡潔にしておく等という原則に従う必要がある.たとえそのシステム上で作業しているのが自分一人だけだとしてもである.そのときは一人であっても,ずっとそのままであるとは限らない.最終的に別の開発者が関わる可能性もある.管理者は開発者がコードの一部を私物のように扱うことを許してはならない.許してしまうと正しい開発の規則を守らなくなるからである.
システムをアップグレードする
作成するプロジェクトが上記の原則のどれにも従っていないということもあり得る.このようなことは作業内容が小さい部分から付加的に大きくなり,どのように開発したかを一度も振り返らなかった場合に起る.行っていることを変更したいけれどしていない(変更でかかる費用が気になっている)場合もあろう.あるいは変更することに意味を見出さず,「抽象的すぎて自分には当てはまらない」と思っているのかもしれない.
ハードウェアやソフトウェアの技術が常に急速に進化し変更されていくように,ソフトウェア開発の方法も進化し変更される.ソフトウェアの開発に多くの時間をかけるのなら,どのように開発するか,またどのような新技術やアイディアを選び学ぶかを規則的に考えてみるのに,その時間の一部を使う価値はある.このドキュメントはWolfram言語での開発の場合にはどのようにすることができるかというアイディアを提供するものである.作業方法を改善したり利点を得たりするのに遅すぎることは決してない.
このドキュメントで紹介したアイディアをいくつか試したり使ったりしてみたいと思ったら,まず自分のシステムのアーキテクチャとコンポーネントの性質を考えてみるとよいだろう.システムがすでにコンポーネントに分けられているかどうかを知るためにはある程度の判断が必要である.極端な場合,アプリケーション全体がWolfram言語ノートブックドキュメント内の1つのセルに書かれていることがある.この場合のアプリケーションは完全にモノリシックで,コンポーネントには分割されていない.
実際の実装が何であろうと,まずシステムを見てそのコンポーネントを見付けなければならない.これは比較的明らかなことがある.例えば,アプリケーションがユーザインターフェースを提供する部分を含むとか,データベースを使うとか,計算を実行する等の場合がある.また計算には,補間をする特別な方法が必要等,特殊な機能があるかもしれない.これらはすべてコンポーネントの可能性があるものである.
コンポーネントを見付けたら,システムをリファクタしてそのコンポーネントに分割することができる.まず,テストのグループを開発して,リファクタリングの前と後でのシステムを比較するとよい.しかし,コンポーネントの性質の欠如は大きな欠陥となる.例えば,アプリケーションがユーザインターフェースからのみ実行できるものであり,常にデータベースに接続していなければならない場合,テストを書いて実行するのはかなり難しくなる.何をするにしても,アプリケーションを分割するので,コードが適切なパッケージ形式を使っているかどうかを確認することができる.また,ソースコードのレポジトリを見付け,使うこともできる.
このようにしようとすることで,このドキュメントの考えと実践方法が役に立つ形式へとシステムを導き,生産性を高めることができる.
まとめ
このドキュメントで説明した原則はすべてのソフトウェア工学に共通のものである.しかし,目標はWolfram言語でどのようにそれを実践するかということなので,説明および例題はWolfram言語に関するものを示している.このようにしたことで,Wolfram言語がWolfram Workbench のような最新ツール,および単体テストのような実践方法を使ってロバストなソフトウェア工学に非常にうまくフィットすることがよく分かったのではなかろうか.さらに式のシリアライズやグラフの可視化等,Wolframシステムの特定の機能がソフトウェア開発を実行する革新的でユニークな方法もある.Wolfram言語は大規模ソフトウェア開発にとって素晴らしいシステムである.規則,実践方法を守り,適切なツールを使うことでより素晴らしいものになる.

Wolfram言語リソース

Wolfram言語リソースをぜひご活用いただきたい.この多くはWolfram ResearchのWebサイトから利用できる.