2010年4月23日金曜日

BPEL×code smell

BPELコードの良し悪しを判断するガイドラインぽいのが無いかと探してみたが、これと言った物が見当たらない。こんな時に一から自分で考えるのはたいてい愚策なので、既存のものを叩き台にしてみる。

特に「良し悪し」の「悪し」の判別に役立つもの、つまりアンチパターンが欲しいので、まずは Refactoring に載っている CodeSmell を検討してみる。BPEL がオーケストレーション言語であるのに対して、CodeSmell は 主に OOP分野の話だから、そもそも異質ではあるけど、まあ業界の常識だし自分でもよく知っているので出発点としては適当。そんなわけで、Refactoring に載ってる 22個の CodeSmell から、BPEL でも当てはまりそうなものをピックアップしてみる。

============
まずは、CodeSmell がもたらす開発作業への悪影響が BPEL でも大きそうなものから

■ Duplicated Code
一般に CodeSmell の最たるものされているのがこの「重複コード」。BPEL 開発でも頻出で、例えば複数のプロセスで共通的に使う変数の初期化コードだとか、フォルト・ハンドラだとかがコピペで書かれると、この CodeSmell が生じる。

ただし、普通のALGOL系OO言語ならば、小さな重複を1~3行程度の小さなメソッドに切り出すような"mercilessly" なリファクタリングもいたって普通だけど、BPEL はそういうの向いてない。例えば、同じ<assign>アクティビティが重複しているからといって、「別プロセスに切り出して」なんてのは無理があるので、多少の重複は仕方なかったりする。

それでもやっぱり何とかしたいとなったら、こんな回避策になるだろうか
  • XSLT で書けるような重複ロジックは *.xsl ファイルに切り出して、<assign>中の doXslTransform() で実行する
  • Xpath 式に組み込めそうな部分で、且つ、使っている BPEL 製品 がXpath 関数を拡張 する仕組みを持っているなら、BPELエンジンに組み込んでXpathから字呼び出す。

■ Long Method/Large Class
BPEL だと長すぎるプロセスがこれに相当するだろうか。

原因には、プロセス設計の問題とコーディングの問題の2つの側面があると思う。前者なら例えば、本来は2つ以上の連続するプロセスを一本のものとして捉えてしまっている場合などで、後者なら、重複コード等、他の CodeSmell によるBPELコードの肥大化などが考えられる。

まあ、一見長すぎに見えても妥当なプロセス設計も当然あるはずなので一概には言えないが、ただし肥大化の原因が以下のような場合、解消の必要がありそう
  • 重複コードや不要コードなど、他の CodeSmell によるプロセス肥大化
  • BPELプロセスで、ループや条件分岐を含むデータ加工をしている。

■ DivergentChange/ShotgunSurgery
変更の影響に関する二つの CodeSmell。

DivergentChange はあるプログラム要素(クラスとかメソッド)が、いろんな種類の仕様/設計変更から影響を受けすぎているというもの。ShotgunSurgery は逆に、一つの仕様/設計変更が、余りに多くのプログラムの部分に影響を与えているというもの。

前者は BPEL での例がちょっと思い浮かばないが、後者の ShotgunSurgery は、例えばプロジェクト共通のフォルトハンドリングの方法が変わって、それに準拠している全てのプロセスの faulthandler を書き直すようなケースで、現場でもよくある。

■ Lazy Class
BPEL でも、仕様変更に対応してるうちに、あるプロセスが使われなくなったりする。また、プロセスが使っていた XSLT ファイルや XMLSchema ファイルなども同様のことが起こる。これも無駄な保守コストがかかるのでまずい。

■ TemporaryField
オリジナルの CodeSmell は、特定の状況でしか使わないデータを、メソッド・パラメータとかローカル変数ではなく、インスタンス変数にしちゃってるというアンチパターン。

BPELプロセスだと、局所的に使うだけの変数をグローバルに宣言したりして、無駄に広いスコープを与えているコードがこれに近いと思う。(IDE によっては、変数を宣言する時にデフォルトでグローバル変数にしているものがあり、結構良く見かける。このグローバル変数を使いまわしたりすると、本当にひどい難読コードになる。)

変数のスコープはなるべく短くすべしという基本は、やはりBPELでも成り立つと思う。

■ Incomplete Library Class
オリジナルは、いまいちニーズを充足しきれていない、惜しいライブラリを指す。BPEL でいうとベンダ独自の拡張機能あたりにそういう事があるかもしれない。

■ Comments
諸説あるが OOPでのコメントのつけ方の有力なガイドラインとして、メソッドの頭のコメント(JavaならJavaDocコメント)だけ書いて、メソッドの中では原則コメントを書かず、コメントなんかを書く労力をコメント無しでも理解しやすいコードを書くことに向けるべしというのがある。

ただ BPEL の場合、コードだけ(たとえばアクティビティの命名の工夫とか)でそれをやるのは難しいので、無理せずコメントを書いた方が良い場合が多いかも。(もちろんコメントがなくても分かるように書けるならそれにこしたことはないが。

============
以下、敢えて書こうと思えば書けるけど、実際には発生しにくそうな CodeSmell

■ SpeculativeGenerality
「現状で必ずしも必要ないが常識的に考えて必要だろう」というノリのコーディングを指す。YAGNI 違反という事になって、KISS原則にも抵触するからまずい。

BPEL だと余り無いような気がするが、敢えてそういうコードを書こうとしたら多分書けてしまうので、人によってはこういうの多いかも。

■ Alternative Classes with Different Interfaces
入力か出力の型が違うだけの理由で別々の BPEL プロセスを書いたりしたら、このCodeSmellに該当するだろうか。ただしサービスとして BPEL を呼ぶ前に XSLT で変換するようにすれば良いだけなので、実際にはなさそう。

■ MiddleMan
まあ他のBPELプロセスを呼ぶだけのBPELプロセスなんて、誰も書かないだろうけど、不可能ではない。


============
以下、あまり BPEL と関係ない CodeSmell

■ Long Parameter List
入力 XMLデータの大きさは BPEL の問題ではない

■ FeatureEnvy
オブジェクトの話なので関係ない

■ DataClumps
やり取りするデータの話なので、XMLSchema の問題

■ PrimitiveObsession
これも強いて言えば XMLSchema の問題

■ SwitchStatements
オリジナルはswitch の代わりに多態を使えというものだが、BPELでは関係ない

■ ParallelInheritanceHierarchies
継承の話なので関係なし

■ MessageChains
オリジナルはあるデータにアクセスするためのオブジェクトの経路に、クライアントが全面的に依存してしまっている「デメテルの法則」違反を指しているが、BPEL プロセスで XPath を用いてアクセスするのは問題ない。

■ InappropriateIntimacy
オブジェクト指向でのクラスの凝集性の話で関係ない

■ DataClass
オブジェクト指向でのカプセル化の話なので関係ない
※本質的な意義を持たないという意味では、サービスをinvoke しないプロセスとか

■ RefusedBequest
オブジェクト指向での継承に関する話なので関係ない

0 件のコメント:

コメントを投稿