ラベル anti patterns の投稿を表示しています。 すべての投稿を表示
ラベル anti patterns の投稿を表示しています。 すべての投稿を表示

2013年1月2日水曜日

どうして多読するか?

これまで、いろんな現場を渡り歩いてきて、どちらかというと自分は技術系の本を割と読んでいる方ではないかと思うに至った。あえて多読派と寡読派に分けるとすれば、どうやら前者に入るのではなかろうかと思うので、ここでちょっと見解をまとめておく。

なぜ多読するか?

もちろんIT技術の話題に触れてるのが好きだからと言うのもあるけど、仕事に関係があるからというのが、やっぱり第一義という事になる。でなければ、ジャンル的にプログラミング・パズル系の本がもっと多くなるし、逆に、オブジェクト指向やアジャイルや Java等の Algol系言語の本はあまり読まなくなると思う。

じゃあ、どんな風に多読が仕事と関係するか。

生産性を上げてかっちょいいコードを書いてチームの中で一目置かれるため---なんかでは全然ない。ましてや他人を論破したり知識量で威圧するための理論武装でもない。

むしろ逆で、ある長所をもっているのがチームの中で自分だけという状況を極力避けるためだったり、また議論の場で同僚の顔を潰すことなく一定のデリカシーを保持するためだったりする。

そもそも自分さえちゃんとできていれば良いという態度は、ある程度の職歴を経たプログラマとしてはちょっと物足りないし(それに自分だけちゃんとするためだけの最小限の読書量は、だいぶ越えてるはず)、良いプラクティスやスタイルを少しでも周りに波及させるところまで含めて仕事なのだと、個人的には思ってたりする(別に頼まれてはいないけど)。

つうわけで、自分が良かれと認識する開発習慣を広めたり、そのために必要な議論を文明人らしいものにするために、いろいろ本を読んでるというのが自分の場合は当てはまる。

例えば、他人のプラクティスやコーディング習慣を改めてもらいたい場面で、読書が足りない人はどう言うか。

「それ時代遅れですね。今どき、そういうの聞いたこと無い。」
「自分はそういうのやらないな。つか普通、誰もやらないと思う。」
「そういうのオブジェクト指向っぽくないから、自分嫌いっす。」

定義の曖昧な、「みんな」とか「普通」とかが多くなって、主観的な価値判断が随所に織り込まれる。で、相手も主観で応酬してくるから、収集がつかない。多読派の立場で見るとどっちもどっちで、客観性を欠いたアホとアホの争いでしかない。

一方、多読派はどう言うか。

「おっしゃる事に一理あると私も思うし、○○氏も2001年の著作『△△』で同じ事を述べてましたね。ただ、それとは別の意見を◎◎氏が著作『▲▲』で述べていて、ホニャホニャフレームワークの開発者の●●氏もそれを支持していたりして、2000年代後半以降はこっちが主流のように見えます。一連の議論について詳細に検討している面白い本があるので、なんなら貸しましょうか?」

とか言える。まあこんなにクドクドしく言わなくても「『▲▲』でアンチパターンとして既に批判されてますね」で終わる事もある。とにかく無駄な主観の応酬になりにくい。

もちろんサジ加減一つで相手に恥をかかせる事もできるけど、多読派は断じてそういう事やらない。なぜなら、そうした行動に見られるデリカシーの欠如の恥ずかしさをさておいたとしても、多読派は1998年の『Anti Patterns』で「Intellectual Violence」として警告されている事を、とっくの昔に読んで既に知っているから。

====

いろいろ書いたけど、自分の場合は案件ごとに雇われていろんな現場にお邪魔させてもらってるだけなので、「議論は良いから、一番偉い俺の主観的価値判断と美意識に黙って従いなさい。」みたいにしにくい立場だからってのもある。

まあ、自分がそんな権限を持ったとしても、そんなやり方はしないけど。だってアホみたいだからね。

2011年1月17日月曜日

コピペ・プログラミングの善悪の境界

コピペ・プログラムは悪い事だと言われる。

コピペ・プログラマは駄目人間だとも言われる。

一方で、実際の現場ではコピペ・プログラミングは現実によく行われている。

リーダが「追加が決まった例の機能は、コピペで済むからラッキーだね」なんて言って、PM と一緒に嬉しがったりする。

当のプログラマも、「任務遂行のためならコピペも辞さない俺って、なんて冷徹なプロだろう」てな感じで、どこか得意げだったりする。

どう言う事か?コピペは良いのか悪いのか。

より正しく言うと、悪いのはコピペ自体ではなく、コピペにより生ずる重複コードの放置だと言える。古来より、共通コードはサブルーチン化すべしと言われてきたし、近年においても Merciless な Refactoring が強く推奨されている。

要は、結果的に重複が解消されて、保守性が下がる事もリスクが増える事もなくなれば、コピペそのものは別にどうって事ない。

もちろん現場の緊急事態においては、コピペ解消に要する数分~数十分を惜しんで保守性を犠牲にしリスクを高め、従って後になって無駄にコストばかり膨れ上がるという高利の負債を受け入れてもなお、一時も早くコミット/リリースせざるを得ない状況もある。

しかしだからと言って、TODO コメントで重複コードである旨を表示して、後続のプログラマの注意を喚起するくらいの事ができないわけはない。

それすらやらないという事こそ、もう言い逃れのできない不作為、無知、鈍感と言わざるを得ない。プログラムの仕事が分かってないという事になるのではないか。

★まとめ
  • コピペしない ← OK
  • 作業の流れで一旦コピペしても、重複は残さない ← OK
  • やむを得ず重複を残したが、他人が怪我しないように手は打った ← ギリOK
  • コピペでコードを重複させましたが、何か? ← 悪


★豆知識
  • かなり古い本だが『AntiPatterns』でも、"Cut-And-Paste Programming"として、Clipboard Coding、Software Propagationといった別名と共に紹介されている。
  • 『Refactoring』 では、Code Smellのうちの"Code Duplication"として紹介されている。
  • 以下、元祖 wikiwiki から
    • OnceAndOnlyOnce:「書くべきコードは一度だけ、ただ一度きりのみ書きましょう」と言う、おそらく最も有名な重複防止の標語。
    • Refactoring Mercilessly:昔から XP で言われているプラクティス。特にコードの重複の解消を念頭においていると考えても良い。
    • Duplicated Code:言わずと知れたコードの重複。CodeSmell(駄目なコードの兆候)の最たるものとされている
    • Copy And Paste Programming:ずばり今回のテーマ。冒頭で一応、プログラミング手法の一つとして中立的に紹介された後、なぜこれが駄目なのかと延々と批判が続く

2011年1月16日日曜日

C# のアンチイディオム

ソフトウェア開発の様々なテーマについて、それぞれパターンやイディオムやベストプラクティスがあるけど、まずはアンチパターンを避ける事が優先度が上で順序も先だと常々思う。

というわけで、書いてはいけない C#コードを『Effective C#』と『More Effective C#』から抜粋してみた("m"が付いた番号が "More"の方)。

Item 09: Avoid Conversion Operators in Your APIs
  • 変換演算子の定義は避ける事。

Item 26: Avoid Returning References to Internal Class Objects
  • オブジェクトが保持している別のオブジェクトを外に晒すのは避ける事
  • 特にコレクションなんかで、C#に限らず散々言われ続けてきた悪いコーディング

Item 16: Avoid Creating Unnecessary Objects
  • 無駄なオブジェクトの生成を避ける事
  • 文字列の構築での string の使用 ⇒ StringBuilder を使う事
  • 高頻度で呼ばれるメソッド内でのオブジェクト生成 ⇒ メンバ変数や定数への格上げを検討する事

Item 32: Avoid ICloneable
  • ICloneableの実装は避ける事
  • パッと見の印象ほどには意外と使えないインターフェイスだったりする
  • どうしても使うときは、基底クラスでコピーコンストラクタを定義した上で、sealed クラスのみで使う事。

Item 33: Use the new Modifier Only to React to Base Class Updates
  • new モディファイアの使用は避ける事
  • 外部のライブラリに含まれる基底クラスの変更により、それを継承している派生クラスで定義の衝突が生じるような稀なケースなどもあるが、そのときでもなるべく避ける事。

Item 34: Avoid Overloading Methods Defined in Base Classes
  • 基底クラスで宣言されたメソッドをオーバーロードするのは避ける事
  • こんなコードで、、、
    class B1 {}
    class D1: B1 {}
    class B2 { void Foo(D1 p) {...} }
    class D2: B2 { void Foo(B1 p) {...} }
    、、、D2.Foo() に D1 オブジェクトを渡すと、どっちが実行されるか意外と迷う。更に generics が絡むともっと面倒になる。

Item m07: Do Not Create Generic Specialization on Base Classes or Interfaces
  • generic メソッドを特化するオーバロードは避ける事
  • 例えば以下のようなコードで、、、
    class Base {}
    class Derived : Base {}
    class Foo {
    public static void DoSomething(Base b) { ... }
    public static void DoSomething(T b) { ... }
    }
    、、、DoSomething() に Derived インスタンスを渡すとどちらが実行されるか、意外と分かりにくい。DoSomething(Base b)を加える代わりに DoSomething(T b)の中で型チェックをすると、分かり易さも使い勝手も向上する。

Item m33: Avoid Modifying Bound Variables
  • クロージャの中でのローカル変数の変更は避ける事
  • 遅延実行絡みの分かりにくいエラーが生じやすい

Item m35: Never Overload Extension Methods
  • 拡張メソッドのオーバーロードは避ける事
  • 別々の namespace に異なる実装を書くと、拡張メソッドをオーバーロードした感じになるが、拡張メソッドの使い方としては間違い
  • 別の識別子で別途定義すべき

Item m39: Avoid Throwing Exceptions in Functions and Actions
  • シーケンスを操作する LINQ コードの中での例外送出は避ける事

Item m41: Avoid Capturing Expensive Resources
  • クロージャがリソースをつかみっぱなしになるのを避ける事
  • クロージャが、IDisposable なローカル変数を参照するコードを書くと、クロージャの生存期間や遅延実行がからんで面倒な事になりがち

Item m48: Avoid Calling Virtual Functions in Constructors
  • コンストラクタで仮想関数を呼ばない事

Item m15: Avoid Calling Unknown Code in Locked Sections
  • 未知のコードを lock ブロックの中で実行しない事
  • 例えば、パラメータで渡されたりイベントに追加されたデリゲートや、オーバーライドされた仮想メソッドなどが、デッドロックを発生させる事がある

Item m24: Declare Only Nonvirtual Events
  • virtual なイベントは避けること
  • ほとんど意味が無く誰も得しない

Item m47: Limit Array Parameters to Params Arrays
  • 可変引数以外では、配列を受け取るメソッドシグネーチャは避ける事
  • covariance のせいで実行時に面倒くさいエラーが起こりがち
  • シーケンスを渡すときは配列ではなく、IEnumerable を使う
  • 中身を変更するときはIEnumerable を返す

中には FxCop とかで検出可能なものもあるらしいが、そうでないものも含めてコーディング規約とかガイドラインにも載せて、開発メンバで共有できるようにしたい。

2010年6月27日日曜日

AntiPatterns over DesignPatterns

日ごろからデザインパターンよりアンチパターンの方にこそ着目すべきだと、常々考えている。

GoFのデザパタ本の最終章で、デザイン・パターンこそがリファクタリング(再分解)に方向性を与えるといった有名な記述があって、後にファウラーのリファクタ本が出た時に、みんな読み返して「やっぱデザパタだね」なんて頷いたりしたが、それでも自分は、アンチパターン(の回避)こそがリファクタリングの指針としても優先されるべきだと思う。だからこそリファクタ本でも先にCodeSmell が語られていたはずだし。

さらに古い話だけど、コプリエンの『C++プログラミングの筋と定石』というのが出たときにも、イディオムの記述もさることながら、やってはいけない事について割と力をいれて書いていたのが、非常に有益だった(業界でもそれで高評価を得ていたような記憶があるし)。

こういう、アンチパターンへの感覚は、日常生活においての「格好いい事を主張する以前に、まずは人並みであるべき」という常識だとか、学歴やスキルの高さ以前に犯罪歴や暴力性向が無いことが前提とされたりする事のような、ごく当たり前の感覚にも通じていると思う(芸術家は別だけど)。

そんな自分の思いに反して、アンチパターン系の知識は、パターンやベストプラクティスが歓迎されるほどには省みられない。当たり前すぎて語られないのならまだしも、そもそも知られていなかったり、無視され、読み飛ばされてしまっている。減点方式っぽい思考法なので日本人に向いているような気がするけど、現実は逆だったりする。

それどころか、こういう割と普通の感覚が、既に動いているプロジェクト・チームに新たに参入した時に、場合によっては地雷を踏むきっかけになったりする。

アンチパターンを解消するには、まずはそれを発見する事から始まるが、上手くやらないと、上から目線であら捜しをしていると捉えられる。また、現行メンバの仕掛中作業を妨げないように、自分がリファクタリングや後付テストコード記述をするなんて申し出たりしても、自分だけ手を汚さずに当て付けがましい事をしているように見られる事もある。(もちろん「お前ら全員今からリファクタしろ」なんてストレートに言うと、さらに楽しくない状況になる。つうか、そんな事言えない。)

門外漢には、そんな子供っぽい現場は滅多にないだろうと思われるかもしれないが、プロジェクトが1年も続くといろいろな事があるし、特に一旦火を噴いてやっと沈静化しかけた頃のような現場だと、かなりのメンバの心の中に、大人でもなかなか笑って水に流せないトラウマがわだかまっていて、至るところ地雷だらけだったりする。

まあでも、自分が最近、途中から参入した現場はそんな危険な雰囲気も少なく、アンチパターン/ワーストプラクティス/コードスメルが大量にある割には、メンバの精神状態もおおむね良好で割と気楽なんだけど、それでも油断できない。上の人間は早く成果を出せと思っているっぽいが、やはりここは、ゆっくり慎重に行こうと思う。

本当に技術者ってデリケートなんだよなあ・・・

2010年6月14日月曜日

The Test Smells

『xUnit Test Patterns』 に載っている、CodeSmell の xUnit バージョン。

どうもこの本は、まとめ方が若干惜しい。掲載されているテストのノウハウは、量も多く網羅的で、プログラマなら(特にプログラマのリーダ的な立場の人は)、知って置きたいテクニックが満載なんだけど、見せ方がいまいち。

自分は、特に「Test Smell」のパートがこの本の中でも重要な部分だと思っているけど、ここも違和感がある。一個の Test Smell のカタログ項目として、複数の Causes(原因)が列挙されているが、これら自体が Test Smell だったりして、何だかややこしい。

以下のような Test Smells が掲載されている。
  • Project Smells
    • Production Bugs:
      公式なテストで(開発チームの手を離れてからのテスト)、または出荷した後に見つかるバグが多すぎる
    • Buggy Tests:
      テスト自体にバグが多い
    • Developers Not Writing Tests:
      テストコードが書かれていない
    • High Test Maintenance Cost:
      メンテするのが大変すぎる
  • Behavior Smells
    • Fragile Test:
      テスト対象コードに含まれない、他所の部分の改修によって、テストが通らなくなる
    • Assertion Roulette:
      テストメソッド中の、どのアサーションが失敗してるのか分かりにくい
    • Erratic Tests:
      その時々で、あるテストが通ったり通らなかったりする
    • Frequent Debugging:
      テストが通らない原因が、いちいち手動デバッグしないと分からない
    • Slow Tests:
      テストの実行に時間かかりすぎる
  • Code Smells
    • Obscure Test:
      何がどうなる事を検証しているのかが不明瞭
    • Conditional Test Logic:
      テストロジックの中に条件分岐があって、場合によって実行パスが通ったり通らなかったりする
    • Hard-to-Test Code:
      テスト対象コードのテスタビリティが低すぎて、テストが書けない
    • Mannual Intervention:
      いちいち手作業で何らかの介入をしないと進まない
    • Test Code Duplication:
      テストコードが重複している
    • Test Logic in Production:
      製品コードにテストコードが含まれてしまっている

xUnit に慣れているプログラマなら、上記のほとんどの Test Smells について、常識だと思うかもしれないけど、熟練者がいないチームで暗中模索しながら書かれたテストコードなんかだと、かなりの頻度で遭遇するアンチパターンだったりする。

2010年6月6日日曜日

Systems thinking のパターン

『システム・シンキング入門』という本で、「システムの原型」として把握される5つのパターンが紹介されている、。ソフトウェア開発プロジェクトの分析にも、大いに使えそうなので、以下にまとめておく。

■ 応急処置の失敗
・対症療法が予期せぬ悪影響を発生させて、問題が悪化していく因果ループ
・分類:悪化ループ

開発現場で実によく見かけるもの。例えば「時間が無い」という「問題」に対して、「応急処置」として何かのタスクを省略したりすると、大抵このパターンにはまって後で大変な事になる。

あと切羽詰ったプロジェクトで、下手に増員して却って火に油を注ぐのも、ほぼこのパターン(ほんの少し構造が違うが)。

■ 問題の転嫁
・対症療法による目先の効果により、本来必要な根本的対応が先送りされてしまう因果ループ
・分類:悪化ループ
これもよくある。例えば、「根本的な解決策」がアーキテクチャの変更を伴うような場合に、重い作業を避けてベタな暫定対応に逃げたりすることが良くあるが、やればやるほどコードのメンテ性が低下して、抜本対応が遠のいていったりする。

■ エスカレーション
・双方の行為が脅威となって、互いに行動をエスカレートしていく因果ループ
・分類:悪化ループ
システム開発プロジェクトでは、意外と見ないかも。ちょっと思いつかない。現実の社会では、軍拡競争など、分かりやすいサンプルが豊富。

■ 成功の限界
・拡張プロセスがバランスプロセスに変化して、勢いを失い進歩が止まる因果ループ
・分類:停滞ループ
リファクタリングが実践されていないチームでは、機能追加/変更によるアプリケーションの成長の陰で、重複コードの増殖やメソッドの長大化により変更コストが増加して、結局アプリケーションの成長も鈍っていく事になる。開発者なら分かりやすいパターンだと思う。

あと、組織やユーザが大きくなればなるほど、それ自身の重さが進化を鈍らせるという点では、昨今、Java がパターンにはまっているような気がしないでもない。

■ 成功が成功を生む
・両立すべき事柄の一方での成功が、他方に一層の失敗をもたらす事になる因果ループ
・分類:悪影響ループ

Java と .NET の間で、このパターンが生じる事がある。Java にも .NET にも、それぞれ長所短所があるので、合理的に使い分けられるのが理想だけど、ある局面での Java の選択は、Java 技術のスキル向上を促す一方で、.NET 技術の スキル低下を引き起こす事にもなり、次の局面での Java の選択圧力を強める。これがループして、Java/.NET 間の格差が一定限度を超えると、.NET を使えば低コストに開発できるような場面でも、スキル的に Java しか選択できなくなったりもする(逆も成立する)。結構、優秀な技術者でもこうなってる人が意外と多い。

====
アンチ・パターン/プラクティスのうち、プロジェクト管理や開発プロセスの領域に該当するものは、Systems Thinking の方法を使うと統一的に現象を記述できるような予感。因果ループ図を取り入れて、アンチ・パターンのカタログを再編集してみるのも良いかも。

2010年4月26日月曜日

BPEL×AntiPatterns

以前のポストでは CodeSmell の BPEL への適用を調べてみた。同じ要領で、AntiPatterns の「ソフトウェア開発のアンチパターン」について、一個一個考えてみる。

尚、★印は5段階に分類した要注意の度合いで、発生頻度×影響度って感じ(感覚ベースの脳内統計だが・・・)。

■ Spaghetti Code ★★★★★

BPEL の言語的性質から、実行パスがもつれたり絡んだりする事はそれほど無くて、古典的な意味でのスパゲティにはならないが、グローバル変数がらみの広義のスパゲティになる事が多い。

グローバル・スコープに変数を定義して、複数のアクティビティで上書きしながらワーク領域として使いまわしているコードがあったりすると、可読性が落ちるわ潜在バグの温床になるわで、生産性と品質の両面に大きなダメージがある。


■ The Blob ★★★★
オリジナルは、与えられた責務が多すぎてオブジェクトが肥大化している状態を言うが、BPEL でもプロセスが長すぎて困るのは良くある。

長いからその分いろんな改修や仕様変更の影響を受けやすく、複数担当者で作業対象がカブる率が高くなり、生産性にかなり悪影響がある(担当者のアサインの仕方にもよるが)。

改善のためには BPELコーディングの面よりも、主にプロセス設計の面からのアプローチが有効と考えられる。例えば、プロセスを分割するとか、サブプロセスとして別サービスに括りだすとか。
■ Functional Decomposition ★★★★
オリジナル AntiPatterns では、オブジェクト指向開発なのに非オブジェクト指向で書かれたコード、例えばポリモーフィズムを使うべきところで if文や switch文を使っているなどの悪習を指す。

言語の本来の性質や目的に合っていないコーディングという意味では、BPEL の場合だとサービスのオーケストレーションに寄与していないコードが怪しい。例えば<assign> しか含まないループや分岐は、BPEL ではなく XSLT で書くべきケースが多い(書き易さの面でも)。
■ Cut-and-Paste_Programming ★★★★
BPEL でも重複コードは頻出で、やはり大体コピペで作られる。ただし BPEL 自体、小さなサブルーチンに細かく分割するのに向いてる言語ではないため、普通のALGOL系言語より重複しやすい。

そういった仕方の無い面もあるにせよ、やはり度が過ぎると、たった一つの変更が何十個所もの改修に及んだりしてダメージが大きいため、できるものなら解消したい。

やり方は、xpath 関数を拡張するとか、XSLT に切り出して再利用するとか、プロセスの一部を別サービスに切り出すなど。いずれのやり方も自明でも無いし常に適用可能でもないので、工夫と妥協が必要。
■ Input Kludge ★★★★
都合の良い入力条件でしかまともに動かないプログラムを指したアンチパターン。

オブジェクト指向開発だと xUnit や TDD が高度に発達して、既にかなり普及しているけど、それらのノウハウを BPEL に適用するのは現状ではなかなか難しい。入出力XMLデータの検証くらいは簡単にできるけど、途中の Web サービスとのやり取りまで含む検証は、意外と手間がかかるしシナリオの想定も難しい。

あと厳密に Input Kludge に該当するか分からないが、開発環境で本物の Webサービスの代わりに使うスタブでも同様の問題が生じる。スタブ化しようとするサービスのドキュメントの不備や解釈のブレによって、なかなか実物のサービスと開発者の想定が一致しない。で、スタブでは動いたが実サービスを繋いだテストでは不具合が出るということになる。

プロジェクトの性質によって対処法はまちまちだろうけど、なるべく早いフェーズでテストと実装(特にスタブ)の戦略は立てておく必要がある。


■ Lava Flow ★★★
使われなくなったコードのことで、デッドコードとも言われる。仕様変更の対応などに伴って BPEL でもよく発生する。あるBPELプロセスの全体、またはその部分、或いはBPELから使用している*.xslファイルや*.xsdファイルなどが、いつの間にか使われなくなったりする。

これについても、無駄なメンテナンスが発生するので、なるべく早く削除すべき。(ちなみにコメントアウトして残す癖のある人もいるが、良い習慣ではない。)
■ Golden Hammer ★★★
オリジナル AntiPatterns では、ある特定の解法や技術を何にでも盲目的に適用してしまう事を指す。ややキツ過ぎる言い方になるが、日本語だと「バカの一つ覚え」ってところだろうか。

BPEL 開発でも、知識が足りないまま作業開始して手探りで進めているようなプロジェクトで、頻繁に生じる。過去に見かけて印象に残った例だと、BPEL外部の XMLファイルの内容にアクセスするために、標準 xpath 関数のdocument() を使えばいい事を知らずに、無理やり orcl:lookup-xml()を使っていたコードなどがあった。
■ Ambiguous Viewpoint ★★★
分析の視点と実装の視点の混同、特に分析・設計時に実装の問題を混入させてしまう事を指す。

BPELの場合、OO言語を用いた開発に比べて、実装に先立つ設計作業の比重が大きかったりするが、ここでワーク変数の扱いだとかデータ加工の具体的ロジックなどまで含めてしまうのは、本当に百害あって一利なしなのでやめるべき。


■ Continuous Obsolescence ★★
準拠する仕様や基盤となる製品のバージョンアップにともなって、既存コードが絶え間なく陳腐化していく現象を指す。BPEL開発 の場合、まず BPEL、XSLT、XPATHといった標準仕様、またそれらについて各製品独自に拡張した部分、さらに 基盤となる BPEL/SOA 製品などについて、各々、時間の進行に伴ってバージョンが上がって行く事になる。

まあ、そもそも疎結合が SOA の謳い文句なので、外部サービスのバージョンアップの影響は余り受けずに済む。サポート期限などは別にして、陳腐化についてはそれほど神経質にならなくてもいいかも。

尚、開発を始める段階でなるべく新鮮は最新版の製品を使えば、陳腐化までの時間を長引かせる事はにはなるが、下記の Walk through a Minefield には注意する必要がある。
■ Walk through a Minefield ★★
リリース後間も無い未知のバグを含む新製品を採用して、問題解決に困ってしまうというアンチパターン。

これは発生頻度もダメージも、プロジェクトや製品ごとにまちまち。対策としては、プロトタイピングとか、反復型プロセスで早期に問題を燻り出したりとか、まあ普通のリスク回避策しかないか。開発に取り掛かった時点で「枯れている」製品を選ぶのも一つの手だが、これも気をつけないと陳腐化リスクが大きくなる。
■ Poltergeists ★★
存在意義があまりないクラス。

BPEL の場合だと、例えばサービスを一個呼ぶだけのプロセスなど単にコンポジットから呼び出せば済むような、オーケストレーションが無いプロセスはこれに当たると考えられそう。
■ Mushroom Management ★★
エンドユーザから隔離されたデベロッパが、十分な要件定義も与えられないまま、想像でコーディングするしか無い状況に追い込まれること。まあ BPELに限らずシステム開発プロジェクトの初歩的な問題なので割愛。


■ Boat Anchor ★
現在の開発対象システムには不要と思われる贅沢な機能を満載したソフトやハード。

単にお金が掛かるというだけなら、自分の金じゃないし払う方の勝手だけど、そのために本当に必要なリソースが圧迫されるとしたら、PM かステークホルダに具申する必要がある。

また OSS の軽量な製品で事足りるのに、重すぎて扱いにくい商用製品が使われてたりすることもよくある。開発端末ではありえないレベルの高スペック・サーバマシンじゃないと動作しないような BPEL 製品だとか、そういうのは本当に生産性が落ちるから、極力避けたい。
■ Dead End ★
他所から入手した再利用コンポーネントを部分変更した後、サポートを受けられなくなってしまうこと。
まあ、あまり起こりそうに無いし、気にしなくてもいいか。

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
オブジェクト指向での継承に関する話なので関係ない

2010年1月25日月曜日

CI のアンチパターン

Continuous Integration のアンチパターンというのを見つけた。
『Automation for the people: Continuous Integration anti-patterns』

Infrequent check-ins
現象:チェックインの頻度が少ないせいでIntegration が遅れる。Integration が遅れてリアルタイム性が低下すると、後の是正措置の手間が大きくなり、CI の恩恵が減ってくる。
対策:ちょっとずつ細かくチェックインする。少なくとも1日一回、できれば何度も。

Broken builds
現象:ビルド失敗が長時間放置される。その間、他のメンバが更新・チェックアウトできない状態も続く。
対策:コミット前にローカルでビルドする。ビルドの前に一度 update することも忘れずに行う。

Minimal feedback
現象:ビルド失敗通知を設定していなかったり、あるいは通知が地味過ぎて誰も気づかない。
対策:適切なフィードバック手法を使って、ビルド失敗が担当者に確実に認識されるように工夫する。

Spam feedback
現象:Minimal feedback とは逆に、ビルド結果のフィードバックが多すぎて、誰も注意を払わなくなる。
対策:メンバーのロールに応じて通知条件を設定して、無関係な人にスパムメール的な通知が送られないようにする。

Slow machine
現象:マシン性能が低すぎてビルドに時間がかかりフィードバックが遅れる
対策:使えるブツを調達する

Bloated build
現象:一つのビルドプロセスに静的解析やらパフォーマンステストやら、何もかも詰め込みすぎている。そのため時間がかかり過ぎてリアルタイム性が低下している。
対策:ビルドプロセスを段階的に構成し、総ビルド時間の20%でエラーの80%を補足するようなビルドを第一段階に持ってくる。