2015年7月28日火曜日

Test First ?

以前、テストに基づいて仕様を考えることを試してみた結果という観点での内容の文章を書きましたが、これはそれほど難しい考え方ではないということを皆さんも薄々気がついていることだと思います。
ただ、重厚長大な形式主義や単なる習慣が、こういった逆転の発想を打ち消してしまうのは少々もったいないようにも思います。

依然として、要件をまとめて、機能仕様を作成し、さらに詳細設計書まで落とし込んでやっと楽しい実装に入れるという流れも、そろそろ限界を迎えてるのではないかと、いや、とっくに限界なんだろうと考えるわけです。
なぜなら、プロジェクト後半にもなるとせっかく作成した先の成果物は、だんだんと現実から乖離してメンテナンスもままならず、役に立たなくなることがあまりにも多い。
最終的にはどうなるのか?というと、実装者の裁量にまかされるわけです。
本末転倒な話です。

さて、では、視点を変えてテスト項目から洗い出してゆくとどうなるのか?
結局は同じことなのです。
ユーザ視点になるとテストの項目で表され、開発者の視点で見ると仕様書になるわけです。
つまり、これは表裏一体。結局、同一、同じものを言っているわけです。
両者ともにウォーターフォールのV字型機構で対応して表され、インプットとアウトプットで対になるわけですから、ごく自然なことだと思います。

そのことのひとつの証明として何日間かかけてドメインを中心軸として、左右対称の形を描くユニットテスト、モックアップなどを取り上げてきたわけです。
いずれの思想も根底にあるのは、通常の習慣とは逆にモノゴトを観察する知恵なのです。

2015年7月27日月曜日

オニオンスライスのオートメーション

ふだん単体テストのオートメーションにあまりなじみのない方のために、少し具体的な話をしてみようと思います。
そして例によって具体例は先週の続きです。
以下のレコードをデータベースから取得して画面に表示するためのコンテキストをテストします。

<朝食>
     <食べたものリスト>
          <食べたもの>トースト</食べたもの>
          <食べたもの>ハムエッグ</食べたもの>
          <食べたもの>ひよこ豆とレタスとトマトのサラダ</食べたもの>
     </食べたものリスト>
     <飲み物>コーヒー</飲み物>
</朝食>

1)まずは、期待値を構成します。
listと飲み物はprivateスコープです。
var expected = new 朝食();

このオブジェクトはコンストラクタの中で次のように初期化されます。
this.list = new 食べたものリスト()
list.Add( new 食べたもの("トースト") );
list.Add( new 食べたもの("ハムエッグ") );
list.Add( new 食べたもの("ひよこ豆とレタスとトマトのサラダ") );
this.Set飲み物 ( "コーヒー" );

2) 次に被検クラスを起動して、返される値をキャッチします。
var target = ある朝に食べた朝食() ;
朝食 actual = target.Find();

3)最後に期待値と実測値が同じであるか判定します。
for ( 朝食 a : actual ) {
     for ( 朝食 e : expected ) {
          assertEquals( e.Get食べたもの, a.Get食べたもの );
          assertEquals( e.Get食べたもの, a.Get食べたもの );
          assertEquals( e.Get食べたもの, a.Get食べたもの );
     }
}
assertEquals( expected.Get飲み物, actual.Get飲み物 );

ここではじめてに期待したオブジェクトとデータベースから返却された実測値が同一であること、つまり、期待に沿ったものであるかを判定しています。
assertでかかれた比較がイコールで結ばれればテストは成功なので、グリーンシグナルとなるわけです。
ただし、正確に言うと、Listは投入された要素の順番が保証されないので、ここはもっと別の記述になるはずですが、テストの流れをシンプルにご紹介するために、あえてこのように書きましたことを注意してください。

こうやって見てみると意外と簡単ですね。
とは言え、このテストではデータベースに直接接続していますから、本来はもっと工夫が必要ですし、これでは不充分です。
加えて仕様が変化したときに、当然、このテストコードでは整合しなくなるわけですから、もっと柔軟な展開も頭の中に入れておかなければなりません。
と、いろいろ考えることは多々ありますが、それでも、この方法には価値あることが少なからずあると思います。
それを知るには実際的な体験が必要です。

よくテストコードのメンテナンスが大変だ、という意見も聞かれますが、それはテストとしての構造設計がうまくできていないことに原因があることが大半です。
変化に強い実装コードのノウハウは、そのままテストコードの柔軟性にも同じように展開できるはずです。平面的な構造設計だけでは、そもそも実装コードのメンテナンスもままなりません。ぜひ、このような視点に注意を払って挑戦してみてください。
そこではじめて単体テストのオートメーションの価値に気がつくと思います。

2015年7月24日金曜日

オニオンスライスの単体テスト

昨日はヘキサゴナル・アーキテクチャの紹介でした。
この実装パターンは実はモックアップの導入だけではなく、ほかの部分でも効果を発揮します。今回はそのことについて少し書こうと思いますが。

しかしながら、賛否両論の多いアイディアでもあります。

昨日、モックアップは本番実装の鏡影だということを書きましたが、ということは、ほぼ同じような特性を持ったエンティティクラスにも展開が可能だということが容易に推測できます。

それは、つまり、ユニットテストにおいてです。
たとえば、本番に使用するエンティティとして、昨日使用した 朝食クラス を使います。
このクラスはデータベースの検索結果を格納して、データベースのアクセスレイヤーを構成するモデル -> 上位のパーシステンス -> そして、画面直下のプレゼンテーション層までハンドリングされる、データの保持という役割をもったオブジェクトです。

それでは、プレゼンテーションの下層を位置づけるメソッドをテストすることを考えてみます。画面の背後で動作するこのコンテキストは、任意の朝食データを検索して返す というように動作するはずです。
このコンテキストの期待動作を確かめるにあたって、その正当性を判定するには、返されるはずの朝食オブジェクトの内容と同一のデータを保持するオブジェクトを期待値クラスとして定義すると思います。
これは、つまりユニットテストの期待値に相当します。データベースから返される実測値は、本番実装の朝食エンティティクラスのオブジェクトです。
この2つのオブジェクトが同一であれば… 同じ内容のデータを保持していて、AssertEqualで結ばれれば被検対象のコンテキストは正しく動作し、グリーンシグナルが点るはずです。

ここで気がついた方はするどいです。
被検対象のコンテキストを軸に(つまり、ここはドメインとなります)expected と actual はまったく同様のデータになる、という特性が得られます。
これがオニオンスライス、または ヘキサゴナル・アーキテクチャの特性でもあります。
ドメインは常に中心軸として捉えられ、その左右の線対称の部分に、expected のインプット(期待するデータ)と actual(実測結果)が配置され、同一の重量配分の元にバランスします。したがって、テストが成功したことを表します。
これがユニットテストにおける、ひとつの合理性とその実践アイディアです。

おそらく、なんて面倒な! と感じる方もいらっしゃるかもしれません。
そのために賛否両論が巻き起こるテーマとなり得るわけです。

このテクニックが現場の実装で成り立つのか? という議論は、少々本質を逸脱すると思いますので、それはまたの機会に。

2015年7月23日木曜日

朝食はオニオンスライス

今日は昨日の題材を使ってオニオンスライス・パターンを考えてみたいと思います。
オニオンスライスは後ほど説明するとして、目指すのはモックアップの作成です。
こんなことを想定してみます。

・明日までに任意の日に食べた朝食の内容を画面に表示するようなプレゼンが見たい。
・ただし、データベースがまだ構築されていない。
・しかしながらサンプル画面を作るのではなく、そのまま本番に流用できる精度が欲しい。
・なぜなら時間がないし、手戻りを生み出したくないから。

本当に勝手なものです。
この程度のことであれば、サクッと画面を作ってボタンか何かを押したタイミングで画面に情報が表示されるような「サンプル画面」の実装を作ってしまえるでしょう。
そこを、ほぼ同じような手軽さで、ある程度の構造を持ち、すぐに本番に流用できるようなメカニズムを考えてみましょう。
パラメータやデータベースのアクセスレイヤーは、今回の本質ではないので割愛します。
それでは、思い出す意味で、ボタンを押して画面に展開するデータは昨日提示したオブジェクトを使用します。

<朝食>
     <食べたものリスト>
          <食べたもの>トースト</食べたもの>
          <食べたもの>ハムエッグ</食べたもの>
          <食べたもの>ひよこ豆とレタスとトマトのサラダ</食べたもの>
     </食べたものリスト>
     <飲み物>コーヒー</飲み物>
</朝食>

こんな感じです。
このオブジェクトは本番用に使うとしてモックアップのデータオブジェクトのクラスを考えます。

class 朝食モックアップ extends 朝食 { … }
こんな感じです。
ついでに、朝食クラスはこんな風に定義します。

class 朝食 implements I朝食

モックアップは、本番用の朝食クラスを継承して同じ構成の朝食モックアップを定義します。
当然ながらコンストラクタはこのようになります。

public 朝食モックアップ() { super() }
つまり、実態は本番と同じということになります。
これを返却用のオブジェクトとして使用することにします。

次にビヘイビア(ふるまい)を表す検索用オブジェクトを考えてみます。
まず、本番用はこのようになります。

class ある朝に食べた朝食()  implements I食事 { … }

そして、こんな検索メソッドを持ちます。

public virtual I朝食 Find() { return 本来はデータベースから取り出すのだ! }

次にモックアップ用のビヘイビアを定義します。

class ある朝に食べた朝食モックアップ() extends ある朝に食べた朝食() { … }

本番用のビヘイビアを継承するわけです。
したがって、検索メソッドはオーバーライドされ、朝食を表すモックアップエンティティを返すように定義します。

public overrides I朝食 Find() {
     return new 朝食モックアップ()
}

この部分で、つまり、朝食モックアップのコンストラクタの中で、画面にプレゼン用として表示すべきデータを与えて初期化します。
ここまでで本番用とモックアップ用の2種類の検索メカニズムを定義しました。
2種類とはいえ、構造的にはまったく同様のことを表現しています。
これを比喩的なメタファーとして、オニオンスライスと言います。
または、ちょうど鏡を挟んで線対称として捉えることができることから、ヘキサゴナル・アーキテクチャと呼ばれたりもします。
本質は、モックアップは本番の鏡影として表します。

さて、最終段階として画面に結果として表示するコンテキスト(文脈)の部分を定義します。

class I朝食 朝食Repository(I食事 behavior) { … }

このコンテキストはこんな風に使います。
まずは、モックアップを使う場合。

var context = new 朝食Repository( new ある朝に食べた朝食モックアップ() );
var 結果 = context.Find();

これで、モックアップの朝食を表すエンティティが返されるので、それを使って画面に描きます。これで明日のプレゼンは乗り切ることができますね。
本番に切り替えるときは、以下のようになります。

var context = new 朝食Repository( new ある朝に食べた朝食() );
var 結果 = context.Find();

パラメータとして渡すビヘイビアを変更するだけです。
画面の中も変更する必要もないし、ビジネスロジックも変更する必要はありません。
そもそも本番とモックアップを分岐させる If DEBUG のようなロジックさえ存在しません。
コンテキスト、ビヘイビア、エンティティの構造に置き換えられてしまったのです。
このように大局的な視点でロジックを構造に置き換える作業は、データベースシステムだけではなく、制御などの分野でも有効です。
ぜひ、試してみてください。

2015年7月22日水曜日

朝食は頭の体操

いきなりですが、あなたの今朝の朝食を教えてください。

冒頭から不躾な質問で申し訳ありませんが、これをオブジェクトとして表してみましょう。
参考までに自身の今朝の朝食はこんなふうに表現してみます。

<朝食>
     <食べたものリスト>
          <食べたもの>トースト</食べたもの>
          <食べたもの>ハムエッグ</食べたもの>
          <食べたもの>ひよこ豆とレタスとトマトのサラダ</食べたもの>
     </食べたものリスト>
     <飲み物>コーヒー</飲み物>
</朝食>

簡単ですね。
当然ながら、個々のセンスや捉え方によって表現はいろいろあると思います。
もちろん、それでよいわけです。
ここで示した表現は、食べたもの という視点を集合で捉えて、すなわち、コレクションとして表してします。あえて何か特記するならそれだけです。

では、今度は、これをクラスに置き換えてみます。

class 朝食 { … }
これだけです。最小の構成です。

少し工夫を加えて汎用的にしてみます。

class 朝食 extends 食事 { … }

superクラスはこんな風に表してみます。

class 食事 implements I食事 { … }

こうすることによって昼食と夕食を表すことができますね。
もちろん、人によっては、上に提示した概念モデルに <時刻></時刻> のようなタイムスタンプを付与したり、<いつ></いつ> のような更なるオブジェクトの汎用表現を加えるかもしれません。もちろん、それもOKです。

今度は、もう少し視点を拡げてコンテキストを表現します。つまり、ふるまいの部分を与えます。たとえば、食べる、摂取する、という行為を概念モデルとして考えます。
こんな感じはどうでしょう?

class 食べるコンテキスト { … }

上記のクラスのコンストラクタで、さきほどの朝食クラスを生成してインジェクトします。

食べるコンテキスト c = new 食べるコンテキスト( new 朝食() );
c.Execute();

これにより、コンテキストに食事インタフェースの規約を実装したクラスを与えることにより、表現が汎用的になりました。

言ってみれば、これは頭の体操です。
いろいろなものをモデルに置き換えてみましょう。

毎朝の通勤ルート
今週末に観に行く予定の映画
今夏の長期的気象予想
などなど…

なんでもよいです。
ほんの少しの時間が出来たときにでも、頭の体操をしつつ柔軟な思考を持つべく練習をしましょう。

ポートフォリオマネージメント

システムやソフトウェアを作成するにあたり、最初にやるべきこととして要求の聞き取りがあると思います。お客様が目指したまだ形のないモノを作成するにあたり、この作業の実施はとても重要な期間でもあります。
この要求は、具体性と実現性を検証されて、やがて要件定義へと結実します。
この過程で私たちはいったいどんなことに注意をはらうでしょうか?
お客様の声に耳を傾け最大限聞き漏らすまいと努力をするでしょうか?
あるいは、なんとか抜けのない資料を作成するべく力を注ぐでしょうか?

どれも重要なことではありますが、固執すべきではありません。
ここで注意しなければならないのは形式ではなく「何か」を掬い上げるのにどのような仕事が効果を上げるのか? というざまざまな改善ポイントが隠されていることを積極的に察知することだと思います。

果たして、ビジネスがどこに向かおうとしているのか?

これは極めて重要な命題です。もちろん、これはプロダクト・オーナーの目的であるわけですが、私たちモノ作りに従事する立場からも大きな関心ごとであるはずです。なぜなら 「見通し」 が重要だからです。見通しとは、つまり、計画であり、もっと正確に言うならばライフサイクルを大きく決定づける動機でもあります。
これらの材料から、私たちは優先順位の提案をし、開発を段階的に進めていくことに一定の価値を見つけることが出来るかもしれません。
これは、きっと方向性のミクロな視点なのだと思います。

では、もっと大きな視点で、パースペクティブを示すことができる点があるとすれば
それは、きっと 何を作るか? ではく、何を解決するのか? もっと言ってしまえばどんな悩みを解決するのか? という観点に行き着くのだろうと思います。

2015年7月17日金曜日

エクセルの概念モデル

X軸とY軸の表現の集積は、誰にも直観的でわかりやすいものだと思います。
たまに、表現の枠組みを打開すべくセルを連結して、ひとつ下の階層を表してやることは誰にでも経験があることだろうと思います。
これは、つまり表の限界です。当然ながら表は二次元配列が基本なので、それよりも下の階層や、あるいは「Z軸」の要素を表そうと思えば、これは最早、表の限界を超えることになるでしょう。
しかし、我々エンジニアはエクセルを単なる表として捉えるのは少々乱暴すぎると思います。
もう少し本質に迫る必要がありそうに思えます。
では、表を分解して行の視点で捉えるとします。すると、行は1行のコレクションを表すことになります。

List<Row>
こんな感じです。

次に、行が保持する要素は? というと…

同じように List<Column> という表現になると思います。
これでセルの集合を表すことができました。

セルまで行き着いたところで、このセルがどのようにして表になり得るのか? を表します。

<Rows>
     <Row>
          <Columns>
               <Column>セルに格納するデータ</Column>
          </Columns>
     </Row>
</Rows>

ここまで到達すればオブジェクトに簡単にマッピングできますね。
つまり、これはノードとエレメント、親と子の関係でもあるわけです。
ここで思慮深く観察したいのは、あくまでも二次元配列のベクトルで捉えるのではなく、入れ子のイテレーションです。こうすることにより、より抽象度が高まることが実感できると思います。
良いデータ表現というのは、ノードの再帰的表現に他ならないのです。
もし、データの関連をオブジェクトで表そうと思えば、ルートノードは必ずひとつになるはずです。もし、そうならなかったならスコープを逸脱した設計になることがすぐにわかると思います。と、同時に人が頭脳で捉えられる臨界点を超えてしまうことにもなるでしょう。


2015年7月16日木曜日

テストエンジニア

残念なことに、我が国においてはテスト実施に従事する人は総じて地位が低く、エンジニアとして認識されない風潮さえ存在します。本来テストエンジニアとして高い能力を発揮する局面で、向上心や知識といった何ものにも代えがたい価値が削がれてしまっているのが現実だと言えます。
視点を変えて組織という単位で見てみると、こちらも同じような現象が起きていると言えます。評価や品質を考察するしくみが整備されていないために、必要な技術や経験知が整理されずに場当たり的に処理されているのが、また同じような現実だと言えます。
これらは、品質保証という観点から非常にかけ離れた遠い世界です。

ただ、この状況はあくまで私たちの所属する分野という世界での極端な例かもしれません。
では、産業という観点まで視座を拡げてみましょう。家電業界、自動車、重工業、交通、医療といった分野は、品質評価や信頼性評価、耐久試験などの知見がきちんと整備されています。おそらく、当たり前ではないかという感想が聞こえてくると思いますが、こと、ITの分野となるとやはりこの界隈での弱さを感じてしまう印象がぬぐえません。
これは、いったいどうしたことでしょうか?

ひとつには、私たちの分野はまだ歴史が浅いため、信頼性という高みにまでまだ熟成していないのかもしれません。
モノづくりは完成をもって完了というわけにはいきません。もっと言ってしまえば、世の中に出始めて、そこがスタート地点となるわけです。初期不良や使い勝手などが改善され、製品が熟成されていきます。
ここに重要なポイントが隠されています。
製品が熟成されるということは、つまり、生産ラインが改善され、作業手順が改善されます。常に振り返りながら、生産品質や作業品質を見直すのです。こうした地道な努力が安定した品質の製品を世の中に送り出す原動力となるのです。

ふたつめに文化の熟成があげられます。
見える化やQC、あるいはルールの強化、そして 作業者の自主的な改善活動。これらはすべて文化という地平に存在する事象だと思います。

こういった技術の裏側の部分(とは言え、これらもまぎれもない技術である)に目を向けてみるのも興味深いことだと思います。

2015年7月15日水曜日

問題意識とイノベーション

問題を解決するより、問題を察知するほうが遥かに難しい。
とはよく言われる言葉だが、
もっと正確に言ってしまえば、「問題を解決するより、問題を察知するほうが高い能力が必要だ。」と表すこともできると思う。
しかしながら、人は問題を察知する能力を潜在的に持っているようにも思う。このことをいかに表面に導出してやるか、あるいは、顕在化するように促すか? というのは個々やチームの特性に左右される部分が大きいようにも思う。

我が国は儒学の文化がしっかりと根付いているので、それはそれで素晴らしいことではあるけれど、上に示したナイーブな類の取り扱いがことさらに難しい。
人は誰でもいやな話は聞きたくないし、いやなことが起こりうることさえ目を背けてしまいがちだ。
もっと悪いことに、このような問題の発露は人間関係にも影響を及ぼす。

問題意識という言葉がある。
簡単な言葉だ。しかし、常にこのことを意識しながら仕事に取り組むには、かなりの集中力が必要だ。と同時に強い信念が必要だ。

少し視点を移動してみる。
イノベーションと言えば、誰でも耳を傾ける気にもなるし、画期的なことのようにも思えてくる。しかしこれは錯覚ではない。おろらくは正しい認識なのだと思う。
では、再び問題意識という言葉を持ち出してみる。とたんに気持ちが沈み重々しい雰囲気になってくるだろう。そして、これもおそらくは正しい認識なのだろう。
さて、両者を比較してみると実は目指している方向には大差がないことが見えてこないだろうか?
気持ちの持ちようなのだろうか?

自身はそれほど単純なものではないと考えている。

プロジェクトが死ぬとき

「とりあえず…」
この言葉が使われたときは、注意信号である。
とりあえず、仮の実装でもしておけばよいとでも言うのだろうか?
明確な方針が存在しないときに、この表現が使用される頻度が高くなる。マネージャクラスがこのような言い回しを多用する場合、十中八九、全体を把握するのが困難な状況に陥っている証拠である。それならまだしも、口癖にまで「昇華」している場合があるので、そうなったら改善するのは非常に困難だ。注意されたし。

ルールが明確でない。
ドキュメントの体裁から、保管場所、変更管理、エビデンス。
これらはビジネスの問題だ。軽く考えてはいけない。
にわか体質のチームは、まずこの問題を克服しなければ何も始まらないと考えてもよい。
わかればよいと言う人が少なからず存在するが、課題に直面しているであろう刹那だからわかることであり、半年後、一年後、あるいはまだ見ぬ人々がメンテナンスにあたることを想像したときに、今と同じように理解し得るだろうか?

誰が何をしているのかわからない。
誰が何を担当しているか?を把握していればよいのは管理者だけの「特権」ではない。
コードの競合は事前に察知したいと誰でも考えるし、実際に手がけた人に確認したいこともあるだろう。進捗管理と言いながらも言い値で見積もったグラフを描いているだけで、実際の状況を何ら反映していない不正確な代物だ。

コミュニケーション不足
ここまで来ると最早末期的症状を呈し始める。あちらこちらに問題が山積し、深く結びつき、絡みついた糸をほぐすのは困難だ。まして、実際に手を動かすメンバーが口を閉ざし始めると、どこにどんな問題があるのかさえ見えなくなる。
かなりの高確率で休日がつぶされるようになる段階だろう。

逆の見方をすれば、これらの事柄は貴重な経験になる。
経験した人でしかわからない重要な問題の息吹と戦いの歴史だ。
それにめげずに改善を続けよう。

2015年7月14日火曜日

MDD

マニュアル駆動開発。
もちろん造語である。そしてまだどこにも存在していないものと思われる。
以前から結合テストとシステムテストの中間的なドキュメント(もちろんテスト仕様になるわけだ)を先に作成して、その後に実装に入るということを何度か試している。
これは、案外 良好なスタイルだと思っていて、かなりの精度で見えない部分をあぶりだすことにも効果があるし、設計のブレを抑制することに一定の効果を上げることを確認している。

しかしながら、万全というわけにもいかないということも体験的にわかっている。
システムやソフトウェアの特性に左右される部分が大きいからだ。特性とは性格を表す内部特性ではなくビジネスゴールにおける特性だ。
リリースされる成果物はきまぐれで、時として根幹を揺るがすような強力な反乱部隊を送り込んでくることがある。つまり、外観的な視覚特性が明らかになったところで、夢を語りだす悪魔が身を潜めていることに注意しなければならないということだ。
「この機能は、ここをチェックしてこっちのボタンをクリックしたときのほうがいいなぁ。」
現代の実装はできるだけスコープを狭く、シナリオでクローズすることが望ましいとされる。そのような工夫が、この時点で仇となり一気に反乱を起こすということだ。
この時点で実装を見直さなければならないことが高確率で予想できるし、テストで確認した点がすべて無効となるわけだ。
このような問題に関する有効な回答を探していたところで、ふと思いついたのが冒頭の言葉である。

マニュアル、つまり「取扱説明書」をまず先に作る。

ふざけているだろうか?
もちろん効果も確認していないし、精度も測定していない。第一試してみたこともない。
しかし、目の前に取扱説明書が提示されたなら、具体的なイメージを余すところなく掴めるはずだ。これはエンドユーザのみならず我々作る側の人間も同じだと思う。
作るものの明確なゴールが見えたところで、もっと突っ込んだ話ができるのも大きな利点だと思う。

それは、セキュリティ、ポテンシャル、スケール、耐久性、拡張性 といった非機能要件である。

この部分を具体的に詰めるのはとても難しい。
プロジェクトによってはざっくり切り捨てなんてことも珍しくないだろう。
そのような中で最も効果が上がるのを期待しているのは

見積もりである。

2015年7月11日土曜日

ニューウェーブ

技術を習得すること自体、実はそれほど難しいことではありません。
ほんの少しのやる気と、根気があれば、年齢を問わず学び続けていくことは可能です。それに加えて体系立てた技術として習得することすら困難ではありません。
しかし、その技術を使って仕事をする以上、これは本質ではありません。

習得した技術をどのように生かしたらよいでしょう。
いろいろな技術には、向き不向きがあるのは当然で、どのようなバックグランドのもとにそのような技術が生まれてきたのか、を知ることは重要なことです。
ここを見誤ると、新しい技術を試してみたいがために大きな失敗を起こしてしまうことにもなりかねません。
しかし、だからと言って新しい技術の習得に及び腰になるのも、とても残念なことです。
技術の本質をつかみとるのは難しいことではありますが、ぜひとも、そういう視点を持ち続けて学んでほしいと思います。

このような背景の中で新しい技術に目を向けていくのは、技術者にとってとても刺激になる体験となると思います。

2015年7月10日金曜日

発行者と購読者

現代の実装は確実にスコープを狭めるという方向に向かっています。

この言葉に、ピンと来ない方は少し視点をずらして構造を観察してみることをお薦めします。コードの観察ではなく、構造の観察です。
pub-sub実装は、もしかしたら、おそろく気がつかないところでその恩恵を受けていると言ってもいいと思います。

たとえば、XAMLで画面を作成する場合、この種の作り方としては最も鋭角的なスタイルの実装になるかもしれません。ここではデータの流れをラッピングする形で覆い隠してしまいます。まるで細かいことに固執するなよと言わんばかりです。

たとえば、JavaScriptのMVVM系の一連のスタックは非常にしなやかにデータの流れを隠しています。ここにはアウトプットの「視点」は存在しません。と言ったら言い過ぎかもしれませんが、非常にうまくラッピングされてると言えます。

これらの構造は、GoFのカタログにある古典的なオブザーバー・パターンの思想がベースになっています。まさに先人たちの知恵の賜物です。
現代の要求は非常に複雑になっています。従来のような命令を発行してパラメータを渡す。命令の中はブラックボックスでやがて返却値として回答が返る。受け取った回答をたとえば画面に反映する。と言ったような一連の流れでは難しくなり過ぎています。
この難題を確実に解決するにはどのような工夫が効果を上げるでしょうか?

冒頭に示したようにスコープの分断が有効な手段であることを確認してみてください。
つまり、画面からの入力はパラメータとして処理のブラックボックスに渡します。ここで気を使うべきは、いかに正しい入力をブラックボックスに渡すか?という一点です。
何が返されるか? といったシナリオの終着点は最早存在しません。なぜならスコープの外だからです。
そしてもうひとつの視点が返却されたデータです。ここでは回答が取り出される部分がインプットにあたるという立場をとります。画面には、たとえば DataSource のようなインスタンスの参照を持ち、取り出された回答は DataSource にインプットします。考え方としては入力という視点です。画面にどのように反映されるのかは、ここでは注意を払いません。

画面の制御は極めて難しいものと言っていいと思います。その複雑さにおいて人が注意を払える限界点を超えたところでバグに汚染されてゆくのです。
したがって、私たちはその複雑さを軽減すべく、スコープを分断して注意を払うべき対象を狭めていくのが現代の工夫なのです。

2015年7月8日水曜日

恣意的なロギングの価値とは?

よく恣意的なログを見かけることがあります。
まるで粒度が揃っていなくて何に主眼を置いているのか理解に苦しむ類です。
さらに悪いことに、巷では通称エラーログと呼ばれたりもします。
果たしてこのようなログが役に立つのでしょうか。
エラーを抑え込んでログとして担保されているのであれば、論理的に障害など起こるはずがないと考えるのは、実は自然なことです。
システムやソフトウェアに何か予期しない障害が起きて、ログを調べることが多くあると思いますが、「なんでこんなにも役に立たない情報ばかり出力しているんだ!」と憤然とした経験を持っている方も多いと思います。

このような事象の原因は多くの場合ロギングポリシーを策定していないことが大半だと思われます。そのような状況で各実装の担当者に頼りきってしまえば、属人的なロギングコードが記述されるのは明らかです。チームプレーの場合は悲惨です。

そもそもログにはどんな情報を出力するのが有益でしょうか。
エラー時の内容を示す文言でしょうか。
果たして、エラーとは何を示すものなのでしょうか。
想定した値を得られず処理を中断してユーザにメッセージを導出するプロセスを考えてみた場合、概ねこのような現象をエラーとして取り扱うことが多いと思います。
ユーザ視点で立てばこのような考え方は間違いないと思います。では、ロギングの観点で考えてみた場合、これは果たして適切なのでしょうか。
たとえば、上記の想定で処理は中断されエラー・パスを通り、想定通りユーザにメッセージを通知しました。そして、ログにはそのような手続きの結果を文言として具体的な内容を出力しました。
このような充分想定されたパスを踏んだ手続きをログから読み取ったところで、どのような意味があるのでしょう。確かに、ユーザ向けにエラーとして処理されました。という証拠にはなるでしょう。
しかし、ログの重要性や有益性はもっと別なところにあるはずです。
想定しない制御が起こり、調べる段階でこのようなわかりきった記録を読んだところで、実際はほとんど役に立つことがありません。
なぜならば、客観性に乏しい記録に他ならないからです。
そうです。ロギングのポイントはシステム内のデータを客観的な視点で淡々と出力することが望ましいのです。
おそらくここが難しいポイントでもあるのだろうと思います。
開発者の視点でロギングコードを記述すると、つい当たり前のポイントに目がいかなくなります。障害というのは当たり前のデータの流れの中で起こるものなのです。その当たり前だろうと思っている材料を失うと、それは大きな損失に繋がります。

ぜひ、皆さんも自身のチームのロギングポリシーをいまいちど考察してみてください。

テストの終わりとは?

よくこんな相談を持ち掛けられます。
「どこでテストを終えればよいのか?」
「品質の可否はどこで見極めればよいのか?」

実は、これは見当違いな質問に思えます。
なぜならば、テストは極めて能動的な行為であるからです。
正確に言うならばテストに終わりはありません。理論的には、いつかは、どこかのポイントで終わりを迎えることになると思いますが、そこまでに到達するには天文学的なテストケースを導き出さないとならないでしょう。
もちろん、これは現実的ではありません。

では、最初の質問にあえて答えるとするならば、テストの終わりはどこにあるのでしょうか。
テストの終わりははじめに決めておくべきことなのです。
別の表現を借りるならば、この答えはテストの方針です。品質のスコープと着地点を明確にしておかなければ可否の判断などできないのです。

しかし、ある人は 「それでは、本当に品質をクリアしているのか判断できないではないか。」 と言うかもしれません。
合理的な根拠をもった指標を決めないと、こういう意見がでるのも当然だと思います。さらに言うならば、テストのモニターを怠っているからこその感覚だとも言えます。

もう一度言います。テストは極めて能動的な行為なので、テストをこなしさえすれば品質を稼げるという発想は止めるべきです。
システムやソフトウェアに完璧な状態などあり得ないのです。そのためにポイントを明確にした品質の観点や領域で少しでも指標に近づく努力に力を注ぐべきなのです。

2015年7月7日火曜日

あせるべからず…

仮に  Result オブジェクトで任意の情報(もちろん結果)をプレゼンテーションに返却することを仮定してみます。
Result オブジェクトにはフィールドとして ResultType を保持しているとします。その ResultType が取り得る値は、
Unknown: 初期値
Success: 成功
Failure: 失敗
と定義するとします。
さらに Result オブジェクトは、Results<IEntity> というパブリックアクセサを通じて、内部に保持する「結果」のコレクションにアクセスすることを定義します。
つまり、これらの情報によりプレゼンテーションでは、問い合わせの成功/失敗、そして得られた結果の集合を取得できるようになりました。

一見、理路整然とした構造のように見えます。
では、Aさんにプレゼンテーション層の実装をお願いして、Bさんにモデル層の実装をお願いすることにします。
例題として、蔵書管理の中から任意の作家に関する書籍のレコードの集合を取り出すことを考えてみます。
正常系として、想定した書籍のレコード群が取り出されるわけですが、当然ながら 0件以上  n件 というレコードの集合が取り出されることが考えられます。

では、まずプレゼンテーション担当のAさんの視点で捉えてみます。
たとえば、10件のレコードを取得することができました。ResultType = Success で結果は成功です。同様に1件のレコードのみを取得できました。これも成功です。ここまでは何も問題はありません。
次に0件のレコード、すなわち、検索の結果がマッチせずに結果が返されることを想定します。レコードが返されないので処理は失敗とみなし、ResultType = Failure と考えました。
同じシナリオを、今度はモデル層を担当するBさんの視点で捉えてみます。Bさんは何件のレコードを取得できようが結果は Success で定義できる、という考えをポリシーとして持っていました。つまり、結果0件であろうと、処理そのものを失敗しているわけではないので、ResultType には Success をセットしたのです。
ここに1件のバグが入り込みました。

この場合、どちらの実装が正しいのでしょうか?

答えは、どちらも正しいです。
そして、どちらも間違っています。

両者には、大局的な視点での実装方針を確認しあう 「ゆとり」 が、ほんの少しだけ欠けていたのです。

2015年7月4日土曜日

失敗の経験値

経験を積むとはいったいどういうことなのでしょうか。
たとえば、何かのプロジェクトに参画をしたことにより、それは経験につながるのでしょうか。
正確に言うと、経験を積むとは失敗を重ねるということに他なりません。
ただし、注意しなければならないのは、失敗を重ねることの字面をそのまま受け取ってはいけないということです。失敗は単なる失敗でしかないからです。
重要なのは、失敗の背後にはたくさんのヒントが隠れていることを認識することだと思います。
わかりやすく言えば、失敗の経験を基に成功が導き出されるのです。逆の言い方をすれば、つまり、失敗は成功の根拠になるのです。
成功を表すには根拠が必要です。その根拠とは失敗の裏返しです。
何かの仕事で成功を勝ち取ったとしましょう。しかし、その根拠を言い表すことが出来なければ単なる「まぐれ」です。失敗の理由すらそこから導き出すことはできません。
言い換えると、それは経験には至っていないと考えなければなりません。

もし、皆さんが現在従事しているプロジェクトがあるならば、その仕事を終えたときに、チームのメンバーとともに、ぜひとも反省会を開いてみてください。
そして出来るだけたくさんの失敗談を列挙してみてください。
その失敗はなぜ起こったのか? どこに原因があるのか? 必ず分析をしてみてください。
そこではじめて経験を積んだことになるのです。