クリアコードのフリーソフトウェア・OSSの法人向けサポートサービスでは、お客様向けの納品物としてExcel形式のワークシートや目視確認用の検証手順書を提供する場合が度々あります。この記事では、そういった納品ドキュメントの作成と更新の手間を軽減するために行っている工夫の一部をご紹介します。
ビジネス上必要となる「体裁の整ったドキュメント」
自由な気風を好むITエンジニアは、資料にはMarkdownやCSVのようにプレーンテキスト形式を好む場合が多いです。プレーンテキスト形式の資料には、
-
diff
コマンドで簡単に差分を見られる。 -
Gitリポジトリなどに格納した時でも、コミットログで変更点を追いやすくなる。
-
スクリプト等で自動処理しやすい。
といった具合に、何かと取り扱いが容易であるという大きなメリットがあります。
しかし、それらのプレーンテキストベースの資料は、一般寄りの方にとってはあまりいい印象を持たれない場合があります。弊社の法人向けサポート事業においても、直接やりとりする情報システム部門の担当者の方はまだしも、その向こう側で決済等の意志決定を下される方々は、ITの専門家というわけではない事がままあります。そのため納品物としては、文章であればきちんと整形されたドキュメントが、表形式であればセルの色付けや結合などのレイアウト調整が施された物が望まれる傾向にあります。
その一方で、前述したようなメリットを享受しにくい事から、OSS開発者は整形されたドキュメントをできるかぎり一時ソースにはしたがらない印象もあります。
普段の作業効率を高める事と、納品物としての体裁を整える事。この両者をどうやって両立するかが、法人向けサポートでの地味に重要な点となります。
整形された文書はプレーンテキスト形式から自動生成できる
作業効率と納品物の品質の両立のための方法としてまず考えつくのは、ソースをプレーンテキスト形式で管理し、納品物を自動生成するというやり方です。
実際に、Pandocというツールを使うと、Markdown形式のソースからPDFやODF(odt)、Word形式(doc, docx)を自動生成したり、その際に目次を自動的に埋め込んだりといった事が容易にできます。これについての詳しい話は、Markdownで書いたテキストをPDFに変換して納品用ドキュメントを作成するという過去の記事をご覧下さい。
表形式のマスターデータはどうすればいい?
その一方で、表形式のドキュメントについて同じような事をやるのは大変です。表形式のデータのプレーンテキスト形式といえばCSVですが、CSVには行・列・セルに内容以外の属性情報を持たせることができません。また、セル内で改行するような複雑なデータや、セルの結合を含むような複雑な構成のデータだと、CSVのまま管理するのは骨が折れます。HTMLのtable要素やXML形式を使うとすると、そのような情報も問題なく保持できるようにはなりますが、今度は編集・閲覧が大変になります。このように、表形式のデータとは基本的にプレーンテキストの表現力では手に余るものだと言えます。
正攻法としては、必要なすべてのデータをRDBに格納しておき、Railsアプリケーションのようなインターフェースを介して編集・閲覧する方法が考えられます。この場合、入力・編集用のビューで入力しておき、何らかの方法で納品用のスプレッドシート形式のファイル(ods、xls、xlsxなど)を自動生成するということになります。この方法は柔軟性が高いですが、そのようなシステムの開発と維持にはそれなりのコストがかかるため、案件の性質によっては赤字になってしまいそうです。
システム開発よりは低コストで、完全人力よりは効率が良いスプレッドシートの利用
実際に弊社で手がけているFirefoxの法人向け導入支援や技術支援の場合、ほとんどのお客様は1年間は大きな仕様変更がないESR版を使われています。そのため資料の更新のための作業量も人力での作業で収まる規模です。変更点の調査やカスタマイズ結果の目視での検証など、システム開発では軽減できない部分のコストの方がはるかに大きいため、資料の作成部分だけをシステム化する動機は薄いというのが実情です。
とはいえ、資料の作成・更新を手作業だけで行うのにも手間はかかりますし、ヒューマンエラーによるミスも起こり得ます。容易に自動化できる部分だけでも自動化できればそれに越した事はありません。
システムを改めて開発するほどのコストはかけたくないが、ミスをしやすい部分は自動化したい。このような欲張りなニーズに対する答えとしては、スプレッドシート形式のファイルをマスターデータとして使うという方法が有効かもしれません。ods、xls、xlsxなどのスプレッドシート形式のファイルは、書式設定やセル結合などの高い表現力と、数式や関数による自動処理の機能を併せ持っています。また、これらの形式であればCSV形式への変換スクリプトを使って容易にプレーンテキスト化できるため、変更時の差分も確認しやすいです。
スプレッドシートとmustacheによる納品用ドキュメントの半自動生成
さて、ここからがこの記事の本題です。
相互に依存関係にあるカスタマイズ項目一覧表と検証手順書
前述のような事情から、クリアコードではFirefoxの法人向けカスタマイズ案件用の資料の一般化したバージョンについて、マスターデータをOpenDocument Formatのスプレッドシート(ods)として保持しており、各顧客向けに微調整したりExcel形式で保存し直したりして実際の業務に使用しています。
この資料は「カスタマイズ項目一覧表(カスタマイズメニュー)」と「検証手順書」が対になっており、それぞれ以下のようになっています。
-
カスタマイズ項目一覧表(
configurations/customization-items.ods
)-
形式:OpenDocument Formatスプレッドシート(ods)。
-
目的:法人での利用で頻出のカスタマイズについて「やりたい事」「その実現方法(設定内容)」を整理し、一覧で示す。
-
選択された設定を検証するための検証手順書中の見出し番号を示す欄があり、その内容は検証手順書の最終的な内容に依存する。
-
-
検証手順書(
verification_manual/verification_manual.md
)-
形式:PDF(Markdown形式のプレーンテキストから自動生成)。
-
目的:カスタマイズ項目一覧表の上で選択されたカスタマイズのための指定が期待通りに反映されているかどうか、また、それらの指定が期待通りの効果を発揮しているかどうかを目視検証する際の手順を示す。
-
検証手順書で何を検証する必要があるかは、カスタマイズ項目一覧表で選択されたカスタマイズの内容に依存する。
-
この時、
-
カスタマイズ項目一覧表で選択された設定の一覧を、どうやって検証手順書に引き渡すのか?
-
検証手順書で最終的に決定された見出しの番号を、どうやってカスタマイズ項目一覧表の「検証手順書対応番号」欄に引き渡すのか?
という事が問題になります。このドキュメントではこれらをどうやって解決しているのかを、順を追って説明していきます。
「カスタマイズ項目一覧表で選択された設定のリスト」の出力の自動化
カスタマイズ項目一覧表は、
-
Privacy-30は、ディスクキャッシュを制御する設定項目である。
-
Privacy-30-1が選択された場合、ディスクキャッシュは制御しない。
-
Privacy-30-2が選択された場合、ディスクキャッシュの最大サイズを制限する。
-
Privacy-30-3が選択された場合、ディスクキャッシュを無効化する。
-
という要領で「変更可能な箇所」と「取り得る選択肢」(およびその実現方法)が列挙されています。
この資料ですが、当初の運用方法は「静的なデータだけが記入された表を用意しておき、お客様向けに選択・推奨した設定をセルの色を変える事で示す」というものでした。つまり、スプレッドシートとは言いつつも、実際の所は「セルの結合と色付けができる静的な表」としてしか使っていませんでした。
ここから「どの設定が選択されたのか」という情報をそのまま出力するのは難しいです。というのも、odsやxlsxで使える関数には「あるセルの色を参照する」というような物が存在しないからです。仮にそれをダイレクトにやろうと思うと、Basicなどでマクロを書く必要があり、この方向に進むのは面倒ごとが増えるばかりになってしまいます。
こういう場面では、「セルの色という書式情報を、項目の選択状態を示すマスターデータにする」という発想を捨てれば話が単純になります。
-
項目の選択状態を記入する専用の列を設ける。(これをマスターデータとする)
-
選択状態を示す列に何か記入されていれ行を対象に、セルの色を変える。
-
選択状態を示す列に何か記入されている行を対象に、選択された設定のIDを示す文字列を別のシートに出力する。
ExcelもLibreOfficeも「書式情報を参照する」ことは不得意ですが、「条件にマッチする行に自動的に書式設定を反映する」ことは得意です。それが「条件付き書式」という機能です。本題から外れるためここでは詳しくは述べませんが、実際のodsファイルをダウンロードしてLibreOfficeで開き、「書式」→「条件付き書式」→「管理」を選択すると、そのワークシートでどのような条件付き書式が設定されているかを見られますので、参考にしてみて下さい。
選択状態を表す情報と書式情報とを切り離せれば、「選択された設定のIDを示す文字列を別のシートに出力する」という事も容易にできます。1番目のcustomization-items
というシートを例に取ると、
-
A列は「選択状態記入用の列」として使い、ここは自由入力とする(何か記入されていれば真、そうでなければ偽)。
-
B列には数式を使って、A列に何か記入されている行だけに連番を振るようにする。
-
C列には数式を使って、項目のIDとなる文字列を自動的に組み立てるようにする。
という事をした上で、verify-targets
という名前のシートにVLOOKUP()
関数を使った計算式を記入しておくことで、「customization-items
のA列に何か記入されている選択項目について、そのIDを自動的に出力する」ということを実現しています(数式の詳細は、実際のファイルをご覧下さい)。
他のシートも同様の方法で選択項目のIDをverify-targets
に出力するようにしてあり、後はodsをCSVに変換する方法などを併用すれば、「どの設定が選択されたのか」という情報を簡単に取り出せます。また、この程度の数式であればODFでもExcelワークシートでも互換性があるため、odsをLibreOfficeで開いてxlsx形式で保存し直せば、そのままExcelワークシートとして管理し続ける事もできます。
「カスタマイズ項目一覧表で選択された設定」に基づく、検証手順書の内容の自動決定
検証手順書は、以下のような要領で検証手順が記載されたドキュメントです(実際にはPDFになります)。
4.4 攻撃サイトに対する警告
4.4.1 確認する項目
• Security-5-*
• Security-6-*
• Hide-1
4.4.2 準備
1. 前項に引き続き検証するか、または以下の状態を整えておく。
1. カスタマイズ済み Firefox のインストールが完了した状態にする。
4.4.3検証
1. Firefox のロケーションバーに「 https://itisatrap.org/firefox/its-an-attack.html 」
と入力し、 Enterを押下する。
• 確認項目
1. 攻撃サイトとしてブロックされない。 (Security-5-2)
2. Firefox のロケーションバーに「 http://itisatrap.org/firefox/unwanted.html 」と
入力し、 Enter を押下する。
• 確認項目
1. 望ましくないソフトウェアの提供サイトとしてブロックされない。 (Security-5-2)
3. Firefox のロケーションバーに「 http://itisatrap.org/firefox/its-a-trap.html 」と
入力し、 Enter を押下する。
• 確認項目
1. 詐欺サイトとしてブロックされない。 (Security-6-2)
4. 「ツール」→「オプション」を開く。
• 確認項目
1. 「セキュリティ」タブが表示されていない。 (Hide-1)
納品後にお客様側でも検証できるようするため、あるいは納品前の検証をこのように実施しましたというエビデンスにするためという目的の物なので、人が手作業で実施する前提の検証手順が記載されています。
上記の例は
-
Security-5-2 攻撃サイトに対する警告を行わない
-
Security-6-2 偽装サイトに対する警告を行わない
-
Hide-1 セキュリティタブを非表示にする
が選択された場合を想定した内容ですが、例えば「Security-5-1 攻撃サイトに対する警告を行う」が選択された場合には当然ながら期待される結果が変わりますし、「Hide-1」が選択されなかった場合には「4.」以下の手順は不要となります。
このように検証手順書の内容を細かく切り替えるための材料になるのが、前述のverify-targets
ワークシートをCSV出力した結果です。
この検証手順書のソースはMarkdown形式ですが、mustacheという軽量テンプレートエンジンを使って以下のような書き方をしています。
## 攻撃サイトに対する警告
### 確認する項目
{{#Security-5}} - Security-5-\* {{/Security-5}}
{{#Security-6}} - Security-6-\* {{/Security-6}}
{{#Hide-1}} - Hide-1 {{/Hide-1}}
...
### 検証
{{#Security-5}}
1. Firefoxのロケーションバーに「 https://itisatrap.org/firefox/its-an-attack.html 」と入力し、Enterを押下する。
- 確認項目
1. 攻撃サイトとしてブロック{{#Security-5-1}}される。(Security-5-1){{/Security-5-1}}{{#Security-5-2}}されない。(Security-5-2){{/Security-5-2}}
1. Firefoxのロケーションバーに「 http://itisatrap.org/firefox/unwanted.html 」と入力し、Enterを押下する。
- 確認項目
1. 望ましくないソフトウェアの提供サイトとしてブロック{{#Security-5-1}}される。(Security-5-1){{/Security-5-1}}{{#Security-5-2}}されない。(Security-5-2){{/Security-5-2}}
{{/Security-5}}
...
mustacheでは{{#Security-5-2}}〜{{/Security-5-2}}
のようなタグ風の書き方によって、その名前のパラメータ(ここではSecurity-5-2
)の値が何か設定されている時だけそのタグで囲われた内容を出力する、という形で出力を切り替えることができます。これをMarkdownからPDFへの変換処理の中で前処理として行い、その際にverify-targets
ワークシートをCSV出力した結果の内容をパラメータとして組み合わせることによって、「スプレッドシートの設定内容に基づいて検証手順書の内容を細かく切り替えた結果」をPDFに変換しています。
(ただ、実際にはmustacheの表現力はそれほど高くないです。そのため、mustacheによる処理を終えたコンテンツをさらに加工して、出力する必要がなくなった検証手順や節・章などを丸ごと削除してから、それをPDFに変換するようにしています。)
これらの事を実際にはどのようにやっているのか、という事についてはRakefile
をご覧下さい。
検証手順書の見出し番号をカスタマイズ項目一覧表にフィードバックする
ここまでの処理を終えた段階で、手元には「設定が選択されたカスタマイズ項目表」と「選択されたカスタマイズ内容に対応する検証手順書」の2つができています。
しかしながら、これらのドキュメントの参照関係はあくまで一方通行です。検証手順書を眺めていて「この検証手順を実施すれば、カスタマイズ項目一覧のこの項目についての検証ができる」という事は読み取れるのですが、逆に、カスタマイズ項目一覧表を見ていて「この設定を検証する手順は、検証手順書のどこを見れば記載されているか」という事は読み取れないままです。
検証手順書の見出し番号が静的であれば、あらかじめカスタマイズ項目一覧に記入しておけるのですが、前述の通り検証手順書の章や節の数は選択された設定によって変動します。また、通しでの検証のしやすさを考慮した位置に検証項目を追加した場合にも、以降の章や節の番号がずれてしまいます。このような理由から、検証手順書の見出し番号は、最初からは記入しておけません。
そこで、先の検証手順書の生成時の前処理の一環として、「カスタマイズ項目のID」と「それに対応する検証手順書中の見出し番号」を列挙したCSVを出力するようにしています。カスタマイズ項目一覧表にはあらかじめこのCSVを入力として受け付けるための場所としてverify-targets-to-chapters
シートが用意されており、CSVファイルの内容を当該ワークシートに貼り付けると、他の各シートの対応する行に検証手順書の章番号・節番号が自動で流し込まれるようになっています。(CSVを自動的に参照するようにスプレッドシート内に数式を書いておくこともできますが、そうするとスプレッドシート単体での取り回しが悪くなってしまうので、今のところはCSVの内容を静的に貼り付けるという仕様にとどめています)
以上の手順によって、納品用のスプレッドシートと検証手順書のPDFが手に入る事になります。スプレッドシートの体裁を多少変える程度の事はここまでで説明した自動化のプロセスには何ら影響を与えませんので、後は実際のお客様ごとの要件に合わせて、スプレッドシートをExcel形式に改めたり、表紙を足したりといった微調整を行うだけです。
まとめ
以上、スプレッドシートとMarkdown形式のファイルの2つをマスターデータとして、納品用のスプレッドシートと検証手順書のPDFを半自動生成する事例についてご紹介しました。
フリーソフトウェアやOSSの開発者にとっては、Excelなどのスプレッドシートは「非ITエンジニアの人達とやりとりするためだけの物」という感覚が強いかもしれません。しかし、数式や関数を活用すれば、大仰なシステム開発無しに十分な品質の納品物を少ない労力で作るための素材としても使えます。
皆さんもスプレッドシートの持つポテンシャルを引き出して、ぜひ業務を効率化しましょう!