連載

.NETで簡単XML

第15回 川俣流XMLプログラミングの定石(1)

株式会社ピーデー 川俣 晶
2004/03/06


Back Issue
1
XML超入門
2
プログラムでXML文書を作成する
3
XML文書を読み書きするプログラムの作成
4
DOM(Document Object Model)

5

DOMとXPath

6

.NETプログラムでXSLTスクリプトを使う

7

VS.NETでXML Schemaを活用する(作成編)
8
VS.NETでXML Schemaを活用する(動作編)
9
オブジェクトをXMLでシリアライズ(1)
10
オブジェクトをXMLでシリアライズ(2)
11
オブジェクトをXMLでシリアライズ(3)
12 オブジェクトをXMLでシリアライズ(4)
13 オブジェクトをXMLでシリアライズ(5)
14 オブジェクトをXMLでシリアライズ(6)

今回および次回のサンプル・プログラムについて

 今回および次回のサンプル・プログラムは、Visual Basic .NET(以下VB.NET)とC#を用いて記述してある。ほぼ同じ内容のものが、2つのプログラム言語で記述されている。開発環境としてはVisual Studio .NET 2003を使用することを前提にしている。

 サンプル・プログラムは、Windowsアプリケーションとしてプロジェクトを作成した後に、フォームのLoadイベントに実行するコードを書き込み、Trace.WriteLineメソッドで結果を出力し、統合開発環境の出力ウィンドウで結果を確認するように構成されている。ただしクラスとモジュールだけはフォームのクラス外に別途記述する必要がある。そのほか、今回および次回は、前回までと異なり、それを実行するために必要な手順をすべて説明していない。Importsステートメント(C#ではusingステートメント)の記述が必要であったり、アセンブリの参照を追加したりする必要があるものも含まれる。しかし、前回までをしっかりマスターした読者なら簡単に分かることと判断して今回および次回はそのあたりの説明を省いている部分がある。

 なお、Privateメンバの名前がVB.NET版とC#版では異なっているので、結果が完全に同じにならないケースがある。PublicメンバとPrivateメンバの名前が重複する場合、VB.NET版ではPrivateメンバの名前の先頭の1文字を小文字に変えた上で、先頭に“m_”を付けているが、C#版では先頭の1文字を小文字に変えるだけで対応している。VB.NETは大文字小文字が違うだけのキーワードは同じ名前と見なすが、C#は見なさないという相違によるものである。フィールド名がXML文書に出力されているケースでは、この理由により、結果が同じにならない場合がある。本稿はVB.NETを基準に解説を進めているので、C#プログラマは注意していただきたい。

なぜ定石なのか

 筆者はさまざまなプログラミングの入門記事を書いてきた。それらの入門記事は、伝えたいことが明確になるように最善の形でまとめているが、そのために抜け落ちてしまうものがあった。最善を目指すことによって抜け落ちるというのは、少々困った矛盾だが、致し方ない。例えば、C#入門であるとか、VB.NETプログラミングであるとか、この連載もそれに該当する。

 では、いったい何が抜け落ちたというのだろうか。

 これらの入門記事を通して伝えようとしたことは、プログラム言語やクラス・ライブラリが持っている機能と、その使い方である。それを分かりやすく伝えるためには、説明すべき対象以外を可能な限り削ぎ落とした短いサンプル・プログラムが必要だと考えている。実際、筆者自身の体験として、サンプル・プログラムを見てどこがポイントなのか分からずに迷うという経験がある。未知の技術を学ぶためにサンプル・プログラムを見ているので、本文の説明が抽象的だと、説明文が示す個所がソース・コードのどの行に対応するのか分からないケースがあるのだ。そのような苦労を読者にできるだけさせないために、関係のないコードをできるだけ排除しようと努めている。例えば、ファイルを読み込むサンプル・プログラムでは、ファイル名は文字列定数として直接書き込んでしまい、ファイルを選択するユーザー・インターフェイスなどの説明文に関係のないコードは入れないようにしている。また、この連載では行っていないが、よくコンソール・アプリケーションとしてサンプル・プログラムを作成するのも、その方が無関係なコードが少なくて済むからである。

 しかし、このような方法を取ると、ある機能の使い方は分かりやすくなるのだが、機能と機能をどう組み合わせて使うのかが伝わらなくなることがある。実際のプログラムは小さな機能を集めて作り上げるが、ただ集めればよいというものではなく、有機的に連携するように正しく機能を組み合わせる必要があるためだ。実は、それこそがプログラミングの難しいところであり、なかなか簡単な正解が得難い領域でもある。そんなに難しいことなのだろうか、と思う読者もいると思うが、破たんなく、しかも効率よく、機能を有機的に連携させるというのは、けっこう難しい。なぜ難しいかといえば、考慮すべき小さなポイントが多数あり、それらをすべて把握して、そのすべてのポイントを満たすコードを考えることは困難であるからだ。

 小さなポイントというのは、例えば、XML文書を読み込むXmlTextReaderクラスのコンストラクタに、TextReaderクラス(正確にはそれを継承したクラス)のインスタンスを渡す方がよい場合と、ほかの方法で渡した方がよい場合がある、というような話である。この場合、TextReaderクラスのインスタンスを渡すということは、XmlTextReaderクラスはXML文書を文字列として受け取ることになる。TextReaderクラスは読み取ってデータを文字列として提供する役割を持っているためだ。

 この特徴は、文字列として用意されたXML文書をXmlTextReaderクラスで解析する場合には便利である。TextReaderクラスを継承したStringReaderクラスのインスタンスをXmlTextReaderクラスのコンストラクタに渡せば、短いコードで実現ができる。だが、もしTextReaderクラスではなく、StreamクラスのインスタンスをXmlTextReaderクラスのコンストラクタに渡すような設計ならば、短いコードでは済まなくなる。まず文字列をバイト配列に変換してから、MemoryStreamクラスなどを通じてXmlTextReaderクラスに渡す必要が生じ、かなりの無駄が発生する。これは、StreamクラスよりもTextReaderクラスを使った方がよい例である。

 逆の例もある。例えば、ファイルや通信で受け取ったXML文書を解析する場合、XmlTextReaderクラスのコンストラクタに、TextReaderクラスのインスタンスを渡すと面倒なことになる。なぜなら、外部のXML文書はどのような文字エンコーディングで記述されているか予測が付かず、XML宣言などを通して自動判定を行う必要があるためだ。そして、その機能はXmlTextReaderクラスにあるのであって、TextReaderクラスにはない。つまり、文字列にする前にXmlTextReaderクラスへXML文書を渡さなければ、自動判定が機能しないのである。自動判定が機能しないということは、プログラマが自分で判定するコードを書かねばならない。これは低レベルのバイト列を正しく判定する必要があり、難度の高いコードとなる。難度が高いだけでなく、最初から用意されている機能なので、それを重複して作成することは無駄でもある。

 このように、ある機能が使用される条件によって、コンストラクタに渡すデータ型を適切に選ぶようなケースはあちこちにある。

 さて、このポイントだけなら、注意を払いつつ設計すれば問題なく対応できるだろう。しかし、このような小さなポイントが無数にある状況で、すべてのポイントを正しく満たすように設計するのは難しい。しかも、実際にコーディングしてみて初めて見つかるポイントもあり得るだろう。これらは完全な設計を行う上でかなりの大敵となる

 では、事前に完全な設計ができないのなら、行き当たりばったりの作業をするしかないのか、というとそうではない。実際によく出現するパターンというものがあるからだ。オブジェクト指向の世界で流行しているデザイン・パターンと呼ばれるものも、よく出現するパターンに名前を付けたものといえる。ここで扱おうとしているものは、デザイン・パターンとは趣旨がやや異なるので、ここでは定石(じょうせき)と呼ぶことにしよう。ちなみに、「定跡」は将棋用語、「定石」は囲碁用語である。囲碁将棋は素人なので正しくないかもしれないがどちらの言葉も指し示す意味は同じと考えてよいと思う。しかし、文字が異なるので、検索するときに間違えると困ったことになるので違いを覚えておくとよいだろう(筆者も最近まで混同していた……)。

 定石を活用すれば、ある処理を実行する上で重要になるいくつかのポイントをうまく組み合わせた安定した設計およびコーディングを行うことができる。今回および次回では、筆者なりの定石を紹介してみようと思う。これは、あくまで筆者の考えによる定石であって、ほかのやり方もあり得るだろう。筆者が立てた前提と異なる状況では、異なる定石もあり得るだろう。定石を必要に応じて修正していけるように、なぜそう書く必要があるのかという考え方もできるだけ説明していきたいと思う。ぜひ、この定石を今後のプログラミングに役立てていただきたい。


 INDEX
  .NETで簡単XML
  第15回 川俣流XMLプログラミングの定石(1)
  1.XMLプログラミングにおける定石の必要性
    2.XMLファイル書き込み時の問題点
    3.安全なXMLファイル書き込みのための定石
    4.XML文書の読み書きにどの方法を使うか
    5.シリアライズを使った読み書きの問題点
 
インデックス・ページヘ  「連載 :.NETで簡単XML」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間