伝票指向アプリケーション・アーキテクチャというのがあるそうですね。
日経システム構築2005年12月号P129によると。。
そこでは、各コンポーネント間でのデータ流通を、伝票という概念に統一させているそうです。
この考えが、はやるかどうかはさておき、たしかに、(JAVAなどでは)メソッド間(Cだと関数間)で、受け渡す変数と、返り値を統一すると、仕様決めがしやすく、すぐにテストでき(スタブも、テストドライバもすぐに作れる)、構成管理における、リンクできない問題(引数が違ってリンクできない問題)も解決されます。
具体的にいうと、
Javaの場合、メソッドの引数をハッシュマップ、返り値もハッシュマップにします。
perlやPHPの場合、連想配列にします
C++やCでは、
typedef struct
{
char **key;
void **val;
} VO;
というかんじの構造体(C++の場合は、クラス)をつくり、そのVOとします。
そうすると、結局、メソッドはすべて
HashMap VOret = methodXX(HashMap VO);
(methodXXは、どんなもんでもOK(任意のメソッド))
のカタチになってしまいます。
で、実際に受け渡したい引数の内容は、そのハッシュマップVOにセットします。
そして、処理内容は、受け取ったVOにセットし、返します。
(受け取ったVOに、そのままセットし、返します。そのため、このメソッドに関係ない値がVOに入っていて、受け取った場合、その値を削除することが、仕様になければ、そのまま返します)。
例を示します。
今、本来だと、月日をセットし、今年の曜日を数値で返すメソッド、dateToYobiというメソッドがあったとします。そうすると、こんな感じになります。
int yobi = dateToYobi(int tuki,int hi);
でも、この形式だと、こんな感じになります
HashMap VO;
// 月(tuki)日(hi)の設定
VO.put("tuki",new Integer(tuki));
VO.put("hi",new Integer("hi"));
// メソッドは、こんなかんじ
VO = dateToYobi(VO);
// 結果はVOに入ってる
Integer result = (Integer)VO.get("result");
Integer yobi = (Integger)VO.get("yobi");
これだけなら、呼び出しが、めんどくさくなっただけです。
ところが、dateToYobiの仕様が変更になり、年の指定も必要になった場合(そして求める結果は、その指定した年月日の曜日を求める)
上記の方法だと、
int yobi = dateToYobi(int nen,int tuki,int yobi);
に変えないといけません。これを変えるには、引数が変わっているため、すべて、このメソッドを使っているところを変えなければいけません。
さらに、構成管理の立場から見れば、この関数を、今すぐ変えてしまうと、連絡がまだ行っていない担当者のところは、昔の関数のままなので、新旧の違った引数をもったメソッドが混在し、おかしな動きになったりします。
ところが、上記のHashMapにいれる方法であれば、
HashMap VO;
// 月(tuki)日(hi)の設定
VO.put("version","1.1");
VO.put("nen",new Integer("nen"));
VO.put("tuki",new Integer(tuki));
VO.put("hi",new Integer("hi"));
// メソッドは、こんなかんじ
VO = dateToYobi(VO);
とすればいいだけなので、引数、返り値ともに、VOでかわらず、構成管理上も、新旧のメソッドが混在しても問題ありません。とくにversionがはいっているので、1.1なら、最新のものとして処理し、入ってない場合(本来は1.0とか入れておいたほうがいいけど)だったら、前のバージョンのものとして処理すれば(そのときちゃんと処理するか、エラー表示するかは、実装者がどうしたいかによる))OKです。問題ありません。
この場合、引数が変更になっても対応できるので、とりあえず、メソッド名だけをきめておいて、コーディングしておいてもらい、後から、詳細に引数と返り値を決めることもできます。変更も容易です。
さらに、引数の形式が決まっているので、すぐに、テストドライバが作れます。
モジュール名がabcなら、そのテストドライバの呼び方は
HashMap VO = new HashMap();
// ここに、引数がはいるが、あとからきめればよい。
VO = abc(VO);
なのに、きまっています。
スタブもとりあえず作る場合は
public HashMap abc(HashMap VO)
{
return VO;
}
と、すぐ作れます。引数については、あとから決まったときに追加すればいいです。
そして、テスト結果表示も、呼び出し前のVOの値と、呼出し後のVOの値を表示するだけでOKです。
上記の説明では、引数の個数が変わったケースですが、型が変わったケースでもOKです。
たとえば、上記の場合、年月日を String YYYYMMDD;のカタチであらわすことになった場合、
int yobi = dateToYobi(String YYYYMMDD);
だと、新旧の物が混じると、リンクできなくなるかもしれませんが、HashMap VOを使うケースだと
HashMap VO = new HashMap();
VO.put("version","1.2");
VO.put("ymd",YYYYMMDD);
VO = dateToYobi(VO);
となるだけなので、まったく問題ありません。
上記の説明は、Javaでしたけど、perlやPHPなら、HashMapの代わりに連想配列を使っていただければ、同じことができます。Cの場合は、上記にあげた構造体で、keyの文字列の配列と、値(val)のvoid*の配列に、値をセットしていれることになります(put,get,freeの関数は作っておくべきでしょうけど)
で、これらのことは、特別な技術を導入する必要もなく、ただ、コーディング規約を、このように決めてしまえばいいだけです。
現状では、アーキによっては、こういう仕様がくるのですが、
(ただし、本人が、このようなことを理解してやっているかどうかは疑問)
普通は、こういう仕様にならず、
int yobi = dateToYobi(int nen,int tuki,int hi);
のような仕様になるので、とーぜんのことながら、構成管理に失敗し(新旧のモジュールが混じってしまったり、前のに戻せ!(新しいのが間に合わないため)とかで、現場混乱、テストモジュールもすぐに作れず。。。とかで、えらい開発が大変になったりします。
大きなシステムになればなるほど、仕様は決まらないので、この差は大きいですね。
つまり、アーキの読み、ないしは、ウィリアムのいたずらのブログを見ているかどうかで、多くの人が残業になるかどうかがきまるということです(うん、前者はそのとおりだが、後者はそうなのか??)
なお、HashMapでなく、これをXMLのDomでやってもOKではあるのですが、Domの場合話が複雑になる(入れ子が容易にできるため、複雑な引数にされてしまう)ことがあるので、HashMapのほうが、仕様を切りやすかったりします。
とはいえ、どっちでもいいんですけどね。。。