« NUnit の "Hello, world!" ~ C# 2008 Express + NUnit 2.5 で、 テストファーストの Step by Step | トップページ | Lab Managment ~ VSTS 2010 の "1 Click Deploy" »

2009年5月28日 (木)

[プログラム設計事始] メソッドの外部設計(3)

今回は、 トランザクションを含むメソッドと、 フレームワークやライブラリ呼び出しの扱いかたを、 取り上げてみます。

 

◆ トランザクションの扱い

データベースへの更新処理を複数含むメソッドでは、 トランザクション処理をする場合が多いです。 次のようなメソッド DbUpdate() を考えてみましょう。 一文で書くと長くなりすぎるので、 箇条書きにします。
・ 引数: id, 文字列 a, 文字列 b
・ テーブル A に、 キーが id のレコードがあったら、 特定のフィールドを a に更新する。
・ テーブル A に、 キーが id のレコードがあったら、 特定のフィールドを a にしたレコードを追加する。
・ テーブル B に、 キーが id のレコードがあったら、 特定のフィールドを b に更新する。
・ テーブル B に、 キーが id のレコードがあったら、 特定のフィールドを b にしたレコードを追加する。
・ テーブル A または B に対する更新/挿入処理に失敗したら、 ロールバックする。
・ 処理に成功したら true を返す

これをそのまま表に書いていくと、 かなり複雑になってしまいます。
そこで、 最初からメソッド分割をしてしまいましょう。

まず、 テーブル A に対して更新/挿入する UpdateA() メソッド。

引数 外部条件 外部変化 返値
int id string a A への挿入操作 A の更新操作 テーブルA bool
テーブルA に有る値 (any) --- 成功 a に更新 true
テーブルA に有る値 (any) --- 失敗 (不明) false
テーブルA に無い値 (any) 成功 --- id 列が追加 true
テーブルA に無い値 (any) 失敗 --- (不明) false

※ 「---」 は、 その事象が起きないことを示します。
※ テーブル上では挿入や更新がされているのに SQL としては失敗することがあるので、 失敗したときのメソッド終了時のテーブルの状態は 「不明」 です。


テーブル B に対して更新/挿入する UpdateB() メソッドも同様です。 ( 表は省略 )

すると、 メソッド DbUpdate() は、 次のように定義できます。

引数 外部条件 外部変化 返値
int id string a string b UpdateA (id, a) UpdateB (id, b) テーブルA テーブルB bool
(any) (any) (any) true true 更新or挿入 更新or挿入 true
(any) (any) (any) true false 変化無し 変化無し false
(any) (any) (any) false --- 変化無し 変化無し false

※ UpdateA(), UpdateB() が失敗したらロールバックしなければなりません。 メソッド終了時にテーブルの 「変化無し」 というのは、 ロールバック処理が行われることを意味しています。
※ UpdateB() の最下段が 「---」 になっているのは、 UpdateA() が失敗したら UpdateB() の呼び出しはしない、 という意味です。


このように、 トランザクションのことを考えずにそれぞれのテーブルを更新するメソッド
( UpdateA(), UpdateB() ) と、 全体のトランザクションを管理するメソッド ( DbUpdate() ) に分解してやると、 うまく設計できるようです。
※ 実際には、 トランザクションを掛けたコネクションオプジェクトを UpdateA(), UpdateB() に渡してやったり、 あるいは、 トランザクションのためのフレームワーク ( MSDTC など ) を利用したりします。

 

◆ フレームワークやクラスライブラリなどの呼び出しの扱い

メソッドの外部設計書には、 メソッドとその外部とのやりとりを記載すると言ってきました。
では、 メソッド内で呼び出しているフレームワークやクラスライブラリなどのメソッドを、 全て書き出さないといけないでしょうか?
もしもそれをやると、 表がとんでもなく大きくなってしまうでしょう。 また、 それをするためには、 メソッドの内部が全て決まっていないと ( つまり、 コーディングが終わっていないと ) いけないということになるでしょう。

メソッドの振る舞いを定義する表には、 次のものだけを記載します。
フレームワークやクラスライブラリなどの呼び出しにより…
・ メソッドの振る舞いが変わるもの。
・ 外部に変化を及ぼすもの。

たとえば、 DateTime.Now の値によってメソッドの振る舞いが変わる ( 昼と夜で違う結果になるなど ) ならば、 表に含める必要があります。 そうでなければ、 省略します。

たとえば、 ConfigurationManager.AppSettings.Save() メソッドを呼び出したら、 app.config ファイルに変化が起きるはずですから、 表に含める必要があります。

※ ただし。 呼び出すことになるであろうクラスやメソッドやプロパティを、 全て洗い出しておくべきだ、 という見方も有ります。
これは、 プロジェクト間の参照関係を検討する必要もあるからです。
参照していないプロジェクトに存在するメソッドは呼び出せませんよね。 メソッドの実装に取り掛かってからそういう事態が発覚すると、 メソッドの置き場所を変えたり、 場合によってはプロジェクトの構成を考え直したりしなければならなくなることもあります。

|

« NUnit の "Hello, world!" ~ C# 2008 Express + NUnit 2.5 で、 テストファーストの Step by Step | トップページ | Lab Managment ~ VSTS 2010 の "1 Click Deploy" »

プログラミング」カテゴリの記事

コメント

この記事へのコメントは終了しました。

トラックバック


この記事へのトラックバック一覧です: [プログラム設計事始] メソッドの外部設計(3):

« NUnit の "Hello, world!" ~ C# 2008 Express + NUnit 2.5 で、 テストファーストの Step by Step | トップページ | Lab Managment ~ VSTS 2010 の "1 Click Deploy" »