ソフトウェア開発プロジェクトや開発チームの規模が大きくなるにつれ、内部用あるいは外部用のユーザー・ガイドなどのリファレンス・マニュアルを作成する必要に迫られる場合があります。そうしたドキュメントの作成は、遅い段階になればなるほど面倒になります。単一のソースからいくつかのタイプのドキュメントを作成できる仕組みを作成すると、小規模なプロジェクトにも大規模なプロジェクトにも同様にメリットがもたらされます。また、事前に検討を行うことで、そのドキュメントをプロジェクトの QA (品質保証) やテストにも活用することができます。この記事では、DITA と XSLT 2.0 変換を利用して開発用のドキュメントとユーザー用のドキュメントを単一のソースから容易に作成する方法について説明します。
この記事で行っている XSL 変換 (「ダウンロード」を参照) は、私がドキュメント作成の時間と QA に要する時間をともに短縮しようとして 5 年前に作成したオープンソース・プロジェクトの拡張機能を利用しています。私は当時、ユース・ケースを収集してそれを基に顧客による受け入れテストを作成し、さらにそれを新しい開発者のトレーニング資料として使っていましたが、その作業を減らしたいと考えていました。このプロジェクトには、いくつかの点でビジネス・インテリジェンスの各部分が反映されています。つまり私は、QA、テクニカル・ライター、開発リーダーという役割を果たしていたのです。私はこうした作業について、別の観点からアジャイル戦略の必要性を早い段階で示すものとして捉えています。そのアジャイル戦略とは、今後のプロジェクトには欠かせないと私が認識していたもので、多くの場合、顧客による手順の実行を容易にしたり、ユース・ケースと疎結合にしたり、先に進む上で必要最低限のことのみを行ったりするなどの形で表れるものです。
このプロジェクトの規模が拡大するにつれ、私は大きな XML ファイルを XML DBMS に永続化する羽目になりました。この XML ファイルには開発中のソフトウェア・アプリケーションのアーキテクチャーに関する概要の記述が含まれており、この XML を分解すると、モジュール、ページ、ページの状態、ページ上のコントロールに分けられました。このファイルと共に、私は一連の XQuery と XSL 変換も作成しました。これらの XQuery と XSL 変換は、ユーザー・ガイド、受け入れテスト用のドキュメント、そして過去 2 週間に行われたアプリケーションの変更に基づくナビゲーション・パスを含んだ RSS フィードを、抽出、公開できるようにしたものです。この RSS フィードは手動によるテストには欠かせないものでした。
この当時、私は DITA のことを聞いたことはありましたが、当時は比較的新しい仕様であった DITA を実際に使用したことはありませんでした。そのため私は、独自のスキーマを作成してデータの収集を開始し、さらには変換プログラムを作成しました。しかし DITA の仕様を読んだことで、間違いなく、私が採る手法に影響が及ぶことになり、私は以下の手法を採りました。
- モジュール性と再利用性を向上させる
- 基本的なトピック構造を作成する
- 概念の集合やタスク・リストを作成する
この記事で説明するサンプル・アプリケーションは驚くほど単純で、ホームページがあるほかは、人の名前と住所を入力するための 3 ページ構成のウィザードがあるだけです。ただし、このアプリケーションは実際には存在しておらず、記事の説明の中でのみ存在しています。そして、このアプリケーションには 1 つのパスしか含まれていません (ただし、このサンプル・ファイルを今後繰り返される作業の中で拡張し、このパスの代わりとなる複数のフローを含めることを考えています)。
ユーザー・ガイドを作成するためのデータはページとケースに分けられており、各ページは 1 つの HTML ページを表し、1 つのケースは 1 つの単純なユース・ケース (name フィールドに名前を入力し、適切に大文字で始められていることを検証する、など) を表します。これらのトピックは DITA トピック・マップに集められます。トピック・マップと DITA Open Toolkit を使用すると、ページ単位で構成されたユーザー・ガイドを含む PDF ファイルを作成することができます。
トピック・ベースで作成する DITA の手法では、以下の基本的な 3 つのトピック・タイプに注目します。
- 概念 (concept) タイプ (多くの場合は抽象的です)
- 参照 (reference) タイプ (多くの場合は概念タイプよりも具体的です)
- タスク (task) タイプ (何かを実現するために実行されるステップを記述します)
リスト 1 は概念の例を示し、リスト 2 はタスクの例を示しています。いくつかのトピックを作成したら、それらのトピックを収集し、トピック・マップを使ってドキュメントとして構成することができます (トピック・マップは目次のようなものです)。同じトピックから、複数のトピック・マップを使って複数のドキュメントを作成することができます。
このサンプル・アプリケーションの各ページは DITA 概念によって表現されています。DITA 概念により、そのページの目的の説明、そのページ上の一連のナビゲーション・コントロール、そのページに適した任意のユース・ケースへの参照などが結合されます。リスト 1 を見ると、ページの内容を記述する DITA 概念の中に、そのページ上の UI 要素の記述や、1 つのユース・ケースへの参照が含まれていることがわかります。
リスト 1. アプリケーションのページに対する DITA 概念
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE concept PUBLIC "-//OASIS//DTD DITA Concept//EN"
"../../dtd/concept.dtd">
<concept id="wiz2" xml:lang="en-us">
<title>Wizard Page 2</title>
<conbody>
<p>Name Details</p>
<section>
<title>User Interface: Controls</title>
<screen>
<uicontrol id="wiz3">Continue</uicontrol>
<uicontrol importance="optional"
id="cancel">Cancel</uicontrol>
</screen>
</section>
<section>
<title>Use Cases</title>
<xref href="../cases/case_004.dita" type="task"/>
</section>
</conbody>
</concept>
|
screen 要素と uicontrol 要素は通常、DITA ドキュメントの中で UI コンポーネントを記述するために使われます。この記事でも同じく UI コンポーネントの記述に使われていますが、これから説明するように、screen 要素と uicontrol 要素によってサンプル・アプリケーションのナビゲーション・パスを表すこともできます。
ユース・ケースは DITA タスクによって表現されます。タスクにより、ある結果を生成するために実行される独立した一連のステップが示されます。私はこの手法を使って実際のアプリケーションのドキュメントを作成した際、既知の問題に対するケースを追加して regression というキーワードでタグ付けし、ユーザー・ガイドからは除外しました。テスト用ドキュメントとして使用するためにトピック・マップを再作成する際には、これらのリグレッション・テストを含めること、そして手動でテストをするためのコンテキストを提供することができます。
リスト 2 は DITA タスクを示しています。このタスクには、あるページ上で実行可能なアクションを別のところで行えるようにする上で必要なステップが詳細に記述されています。これらのステップのうちの 1 つ、つまりミドルネームを追加するためのステップが、optional にされていることに注意してください。
リスト 2. アプリケーションのユース・ケースに対する DITA タスク
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE task PUBLIC "-//OASIS//DTD DITA Task//EN"
"../../dtd/task.dtd">
<task id="case_004" xml:lang="en-us">
<title>Case 004</title>
<prolog></prolog>
<taskbody>
<context><p>context: case 004</p></context>
<steps>
<step><cmd>Enter First Name</cmd></step>
<step><cmd>Enter Last Name</cmd></step>
<step importance="optional"><cmd>Enter Middle Name</cmd></step>
</steps>
</taskbody>
</task>
|
このサンプル DITA プロジェクトは、かなりフラットなフォルダー構造をしており、ケース用のディレクトリー (cases) とページ用のディレクトリー (pages) があります。後ほど、これらのディレクトリーとは別にテスト用のディレクトリー (tests) を追加します。またテスト・トピックの生成に使われる XML 変換用のディレクトリーがあります。DITA トピック・マップは、このプロジェクトのルートにあります。
この単純なアプリケーションの場合の DITA トピック・マップ (リスト 3) も、同じように単純です。DITA Open Toolkit を使ってユーザー・ガイドを生成すると、生成される結果は単純かつ有用であり、個々のページ・ファイルに容易に情報を追加して、複雑かつ詳細なページにすることができます。リスト 3 を見ると、このトピック・マップは 4 つのセクションを含む目次のようであることがわかります。
リスト 3. DITA トピック・マップ
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE map PUBLIC "-//OASIS//DTD DITA Map//EN"
"../dtd/map.dtd">
<map title="Sample Application User Guide">
<topicref href="pages/home.dita" type="concept" id="home"/>
<topicref href="pages/wiz1.dita" type="concept"/>
<topicref href="pages/wiz2.dita" type="concept"/>
<topicref href="pages/wiz3.dita" type="concept"/>
</map>
|
DITA の screen 要素と uicontrol 要素を使ってページ上のナビゲーション・コントロール (リンク、ボタン、メニュー) を記述したので、個々の DITA ページ・ファイルから情報を抽出し、その情報を使って新しい一連の DITA タスクを作成することは技術的に難しくありません。これらのタスクにより、あるページから別のページへのナビゲーション方法を記述します。リスト 4 の nav_home_wiz1.dita というナビゲーション・タスクはその一例です。この命名規則では、2 つのページの ID を連結し、あるページから別のページへのナビゲーションを表していることがわかります。元のページの概念の情報が、今度はナビゲーション・タスクを表しています。
リスト 4. ナビゲーション・タスク
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE task PUBLIC "-//OASIS//DTD DITA Task//EN" "../dtd/task.dtd">
<task id="nav_home_wiz1.dita" xml:lang="en-us">
<title>Navigate to Wizard Page 1</title>
<prolog/>
<taskbody>
<steps>
<step>
<cmd>On Home Page, click
<uicontrol>Launch Wizard</uicontrol>
</cmd>
</step>
<step>
<cmd>Verify that Wizard Page 1 loads</cmd>
</step>
</steps>
</taskbody>
</task>
|
ナビゲーション・タスクは、pages ディレクトリーや cases ディレクトリーと同じ場所にある、tests という新しいディレクトリーに保持されます。tests ディレクトリーには、ナビゲーション・タスクの他に、テストのための一連の新しい概念が含まれています。このテストの概念はページごとに 1 つあり、そのページがテストの対象であることを示しています。これらの概念は拡張が可能です。例えば、概念をテストするためのウィザード・ページ (リスト 5) のように、ページのテスト方法に関する追加情報 (どのページがどのユーザー・ロールに適用されるかを特定するための情報や、テストの優先順位および重要度など) を含めることができます。
リスト 5. テスト用の概念
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE concept PUBLIC "-//OASIS//DTD DITA Concept//EN" "../dtd/concept.dtd">
<concept id="test_wiz1.dita" xml:lang="en-us">
<title>Wizard Page 1</title>
<conbody>
<p>This is the first wizard page: Name Details</p>
</conbody>
</concept>
|
テスト用の各概念のドキュメントに含まれている情報は、pages ディレクトリーの DITA 概念から直接抽出することができます。実際、tests ディレクトリーに含まれているトピックはすべて、他の 2 つのディレクトリーの中にあるトピックと、ユーザー・ガイドのトピック・マップ (リスト 3) から XSLT を使って直接生成されます。リスト 6 は手順説明用の新しいトピック・マップを示していますが、このトピック・マップも同じファイルから生成されます。この手順説明用のトピック・マップを DITA Open Toolkit のビルド・スクリプトのパラメーターとして提供すると、DITA Open Toolkit は新しいタスクと概念を使用して、サンプル・アプリケーションのナビゲーション・グラフをトラバースする手順説明用ドキュメントを生成します。その結果示されるアプリケーションのパスは、内部監査用あるいは顧客用アプリケーションの構造化された手順を示してくれます。
この手順説明用ドキュメントの各ページ部分には、ユース・ケースから抽出された受け入れテストの基準も含まれています。これらの基準は顧客へのデモの際の論点として使用することや、手動テストを行う人がユーザーによる受け入れテストや工場での受け入れテストの際に使用することができます。また、tests ディレクトリー以外の 2 つのディレクトリーの内容が変更された場合には tests ディレクトリー全体を再生成することができるため、1 ページのドキュメントの場合であれ、100 ページのドキュメントの場合であれ、このドキュメントを開発サイクルの任意の段階で再生成して使用することができます。
リスト 6. 手順説明用の DITA トピック・マップ
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE map PUBLIC "-//OASIS//DTD DITA Map//EN" "../dtd/map.dtd">
<map title="Sample Application User Guide">
<topicref href="tests/test_home.dita" type="concept">
<topicref href="pages/../cases/case_001.dita" type="task"/>
<topicref href="pages/../cases/case_002.dita" type="task"/>
</topicref>
<topicref href="tests/test_wiz1.dita" type="concept">
<topicref href="tests/nav_home_wiz1.dita" type="task"/>
<topicref href="pages/../cases/case_003.dita" type="task"/>
</topicref>
<topicref href="tests/test_wiz2.dita" type="concept">
<topicref href="tests/nav_wiz1_wiz2.dita" type="task"/>
<topicref href="pages/../cases/case_004.dita" type="task"/>
</topicref>
<topicref href="tests/test_wiz3.dita" type="concept">
<topicref href="tests/nav_wiz2_wiz3.dita" type="task"/>
<topicref href="pages/../cases/case_005.dita" type="task"/>
<topicref href="pages/../cases/case_006.dita" type="task"/>
</topicref>
<topicref href="tests/test_home.dita" type="concept">
<topicref href="tests/nav_wiz3_home.dita" type="task"/>
</topicref>
</map>
|
これらのドキュメントの作成や再利用に使用する情報をモデリングするために初めてスキーマを作成したとき、私は、あるプロジェクトで遭遇した問題を避けようとしました。そのプロジェクトの前までは、私の作成したスキーマは詳細すぎたのですが、そのプロジェクトでは逆にファイルが一体化されすぎ、すべての XML は 1 つのファイルにまとめられていました。もちろん、この 1 つにまとめる方法にもメリットはいくつかあります。ファイル管理やバージョン管理の問題が減る一方、新しい情報の生成に必要な変換の複雑さも減少します。DITA の場合も、ditabase 要素を使用すれば一体型の手法は可能です (ditabase 要素は基本的に DITA トピック (concept、task、reference など) のコンテナーの役割をします)。しかしDITA コミュニティーでの一般的なベスト・プラクティスとしては、各ファイルに対して 1 つの DITA トピックを作成します。各ファイルに対して 1 つの DITA トピックを作成するという詳細な方法により、きめ細かなバージョン管理を行うことができ、再利用や転用もしやすくなります。まさにそれが、現在私が行っている方法のポイントです。
私が行ったように、できるだけ詳細にした方が効率的になります。しかし XSL 変換自体に関して言えば、より詳細にすることで 2 つの大きな問題が発生します。つまり複数のファイルから情報をプルし、複数のファイルに情報をプッシュすることになります。複数のファイルから情報を取得するために、私は xsl:document() 関数を使用しました。フラットなファイル構造を処理する場合であれば、xsl:document() 関数を使うのは簡単です。tests ディレクトリーの中にある多様な DITA ドキュメントから複数のドキュメントを生成するために、私は XSLT 2.0 で導入された xsl:result-document 要素を使用しました。リスト 7 とリスト 8 は、XSL 変換の中で xsl:result-document を使用して新しい概念と新しいタスクを作成する方法を示しています。
リスト 7. xsl:result-document を使って DITA 概念を生成する
<xsl:result-document href="..\{$doc-path-test}"
doctype-system="../dtd/concept.dtd"
doctype-public="-//OASIS//DTD DITA Concept//EN">
<concept id="{$doc-name-test}" xml:lang="en-us">
<title>
<xsl:value-of select="title"/>
</title>
<conbody>
<p>
<xsl:value-of select="conbody/p"/>
</p>
</conbody>
</concept>
</xsl:result-document>
|
注: リスト 7 とリスト 8 の両方で、xsl:output-encoding 要素に使用される doctype-system 属性と doctype-public 属性が xsl:result-document 要素にも使用できることに注意してください。これらの属性を使わないと、生成されるファイルに対し、適切な DITA DTD を追加することができず、それらの DTD を使わないと、生成されたファイルを DITA Open Toolkit に使用することができません。そのため、必ずこれらの属性を使用する必要があります。
また、DITA タスクを使用してユース・ケースを表現することは至って理にかなっていますが、DITA 概念ではなく DITA 参照を使ってページを表現することも理にかなっています。DITA 参照は、HTML ページなど、実際のものを参照するからです。私が DITA 概念を使ってページを表現することにした理由は、DITA 概念から、より抽象的なテストの概念を生成するつもりでおり、その方式を維持したかったからです。つまり、単なる私の好みにすぎません。
リスト 8 を見るとわかるように、ナビゲーション・タスク・ドキュメントを生成するための XSLT の方が、概念の生成に使用した XSLT よりも少し複雑です。
リスト 8. xsl:result-document を使って DITA タスクを生成する
<xsl:result-document href="..\{$doc-path-nav}"
doctype-system="../dtd/task.dtd"
doctype-public="-//OASIS//DTD DITA Task//EN">
<task id="{$doc-name-nav}" xml:lang="en-us">
<title>Navigate to <xsl:value-of select="title"/>
</title>
<prolog/>
<taskbody>
<steps>
<step>
<cmd>On <xsl:value-of select="$source_title"/>,
click <xsl:copy-of select="$uicontrol"/>
</cmd>
</step>
<step>
<cmd>Verify that
<xsl:value-of select="title"/> loads</cmd>
</step>
</steps>
</taskbody>
</task>
</xsl:result-document>
|
この場合にも、XSL 変換によって作成されたトピックに適切な OASIS DITA DTD を関連付けるために、doctype-system 属性と doctype-public 属性を使用していることに注意してください。作成されたタスクの例については、リスト 4 を参照してください。
新しいドキュメントが生成されると、それらのドキュメントを生成した同じ XSL 変換の中で、生成された新しいドキュメントが参照されます (リスト 9)。これらの参照を使用して、ユーザー・ガイドの既存のトピック・マップから手順説明用の新しいトピック・マップを作成します。そのためには、ソース・ページの概念の uicontrol 要素に含まれる id 属性に従って再帰処理を行います。XSLT 2.0 を使用することで、私はトピック・マップとすべてのサポート・ファイルを 1 つの変換で作成することができました。これは XSLT 1.0 を使った場合にはとても不可能であった (あるいは少なくとも、手軽には得られなかった) 成果です。
リスト 9. 生成されたテストの概念とタスクを参照する
<topicref href="{$doc-path-test}" type="concept">
<topicref href="{$doc-path-nav}" type="task"/>
<xsl:if test="@id != 'home' ">
<xsl:apply-templates select="conbody" mode="cases"/>
</xsl:if>
</topicref>
|
注: 完全な XSL 変換を見るためには、この記事に添付されたサンプル・ファイルをダウンロードしてください。
これらのトピックの生成に使用したコンテンツを変更する場合には、いつでも新しいトピックを再生成することができます。そのため、手順説明用のドキュメントや受け入れテスト用のドキュメントをタイムリーな最新のものにすることができます。例えば、ビルド・スクリプトにより、生成された既存のファイルを削除してユーザー・ガイドから手順説明用ドキュメントへの変換を実行し、続いて DITA Open Toolkit のビルド・スクリプトを使用して、受け入れテスト用ドキュメントまたは手順説明用ドキュメントとユーザー・ガイドの最新版を PDF ファイルとして生成することができます。
DITA の screen 要素と uicontrol 要素を使用すると、ナビゲーション・コントロールを描画することができるため (リスト 1)、単純な再帰処理によってアプリケーション全体のパスをトラバースできるようになります。私は至るところに (DITA 要素には一般的な) importance 属性を使用し、ナビゲーション用としては無視することが可能な、オプションのナビゲーション・コントロール (「Cancel (キャンセル)」ボタンなど) を表現しました。同様の方式を使うことで、恐ろしいスタック・オーバーフローを防止しています (スタック・オーバーフローが起こるのは、ページ外にナビゲートすることにより、既にトラバースされたページにフローが戻ってしまうためです)。また、otherprops 属性も一般的でどの DITA 要素でも手軽に使用できるため、ナビゲーション用には有用であることもわかりました。
ここでは単純なアプリケーションを使って単純な変換について説明しました。この記事では、ドキュメントを再利用するための戦略の立て方と、ドキュメント作成プロジェクトを早い段階から開始することによるメリットについて、例を用いて説明しました。早い段階から再利用計画を立てることで、ソフトウェア・プロジェクトの初期の段階でも、そのプロジェクトのライフサイクル全体を通じても、作成されたドキュメントを他の目的に転用できるようになります。開発サイクルの多様な段階で関わる複数のドキュメント作成プロジェクトを単一のソースから生成することにより、この共有情報を活用するさらなる機会が開けてきます。この手法が重要な理由は、ソフトウェア・プロジェクトの複数の利害関係者が単一のドキュメントを使用することになると、そのドキュメントは時間が経過しても保守が行われ、価値が高まる可能性が非常に高くなるからです。
柔軟な手法でドキュメント作成を行うと、多様な手法を横断的に使用できるというメリットもあります。例えば、顧客が形式や格式を非常に重視している一方で開発チームはアジャイル手法を実践している場合、顧客とアジャイル手法の両方の要求に対応するためには、ドキュメントを転用して再利用することが最も適切かもしれません。そうした場合、DITA と XSLT 2.0 は最適のツールです。
| 内容 | ファイル名 | サイズ | ダウンロード形式 |
|---|---|---|---|
| Source files for the DITA project | sample_code.zip | 44KB | HTTP |
学ぶために
- 「Darwin Information Typing Architectureの紹介」(Don Day、Michael Priestley、David Schell の共著、developerWorks、2001年3月 (原文は 2005年9月に一部更新)) を読み、DITA の用語と概念の基本を学んでください。
- OASIS の Cover Pages で Darwin Information Typing Architecture (DITA XML) のページを調べ、DITA について学んでください。
- 「Saxon: XSLTプロセッサーの解体新書」(Michael Kay 著、developerWorks、2001年2月) を読み、Saxon がいかにして XSLT 2.0 仕様の採用で先頭を切ったのかを調べてください。
- この記事を書くきっかけとなったオープンソース・プロジェクト、CaseBook (SourceForge、2007年2月) のサイトを訪れてください。
- DITA に関連した他の記事一覧 (developerWorks、2005年1月から現在まで) には、DITA に関する記事とチュートリアルが網羅されています。
- developerWorks の XML ゾーンには XML のスキルを磨くための資料が豊富に用意されています。
- XML および関連技術において IBM 認定技術者になる方法については、IBM XML certification を参照してください。
- developerWorks の XML ゾーンを XML の技術ライブラリーとして利用してください。広範な話題を網羅した技術記事やヒント、チュートリアル、技術標準、IBM Redbooks などが用意されています。
- developerWorks の Technical events and webcasts で最新情報を入手してください。
- developerWorks を Twitter でフォローしてください。
- developerWorks podcasts ではソフトウェア開発者のための興味深いインタビューや議論を聞くことができます。
製品や技術を入手するために
- DITA を処理するためのオープンソース・ツールキット、DITA Open Toolkit をダウンロードしてください。
- IBM 製品の評価版をダウンロードするか、あるいは IBM SOA Sandbox のオンライン試用版で、DB2®、Lotus®、Rational®、Tivoli®、WebSphere® などが提供するアプリケーション開発ツールやミドルウェア製品を試してみてください。
議論するために
- XML zone discussion forums に参加してください。これらのフォーラムでは XML を中心に議論が行われています。
- developerWorks blogs から developerWorks コミュニティーに加わってください。