2016/2/21(日)「JaSST東北2016準備会(仮)」:Jasst東北メンバーのモデリングハマりどころ

「テストに興味がある」という点から、JaSST東北メンバーは一般的な開発者よりはテストに詳しい(ことが期待される)のですが、今回の準備会ではいろんなところでハマりました。今回は私たちがハマったポイントをピックアップしてみます。

ツリー構造の整理方法

状況

今回の勉強会に先立ち、事前にJaSST東北メンバーでツリー構造を用いたテスト観点整理演習を行っていた。できたツリーは機能の下が操作やデータになっており、統一感がないツリーになっていた。思いつくものは出したつもりだったが、見返しても十分洗い出せたか分からず、もやもやが残ってしまった。

症状

ツリー構造で整理しているのに対して、適切な上下関係になっていなかったり、同階層の要素が揃っていなかった。そのため、MECEになっているかが設計者が自信を持てていなかった。

解決

ツリー構造で整理する場合、上下関係や粒度が妥当かを意識すると良い。

  • 上下関係であれば、inheritance*1かcomposition*2で整理すると良い。一般的にはcompositionの方が網羅しやすい。
  • 同じ階層に並ぶ要素の言葉は合わせると良い。例えば、「設定反映」と並ぶ言葉は「設定画面」より「設定表示」の方がしっくりくる。

技術者は細かいところを気にするのは得意なので、気になったところを納得がいくように変えていくと良い。良い構造になっていると、抜け漏れに気づきやすくなる。

感想

ツリー構造による整理はテストに限らず良く使っている。しかし、事前の演習では上手く整理することができなかった。上手く整理できないときは、完成形のイメージを持たないことによる不安が根本にあると感じた。今回、納得できる整理の仕方を学んだことで、完成形のイメージを持たない「未知の対象」に対しても自信を持って整理できるのではないか、と期待している。

何をテストしたいのか

状況

テスト観点の洗い出しを行った後、テスト観点を整理していた。例えば、解凍機能を持ったアプリケーションのテスト観点で「操作」が上位階層に出てきて、その下に「ダブルクリック」や「ドラッグ&ドロップ」が連なっていた。テストで確認したいものは「ダブルクリック」や「ドラッグ&ドロップ」なのか?

症状

テスト観点で洗い出したものをグルーピングはしていたが、何のためにグルーピングをしていたのかが抜け落ちていた。

解決

テスト観点を整理するときは何をテストしたいのかを常に確認すること。例えば、「操作」そのものを確認したいのではなく、その「操作」を通じて別のモノを確認したいはず。

感想

観点の洗い出しさえ済んでしまえば、グルーピングはほぼ考えずにできると思っていたのが甘かった。「今自分は何のために作業しているか」は意識しておく必要がある。各作業の意味や前後の工程とのつながりを作業前にメンバー間で確認しておくと良いかもしれない。

モデリングと現実

状況

テスト観点を整理した後に、テストコンテナ設計を実施した。テストコンテナをテストを実施する時系列順に並べて、メンバー全員でできたモデルに納得していた。にしさんに確認してもらったところ、「実務でホントにこの順番でテストするの?」との指摘を頂いた。

症状

技術的な観点では作成したモデルに全員が納得していた。しかし、経験的、実務的な観点では作成したモデルは納得できないものだった。

解決

モデリングの演習などをしていると、直観からは離れたモデルになる場合がある。モデリングに慣れていない場合は、自分達の直観に合っているかをよく検討する必要がある。逆に慣習のような利点のないデザインパターンによるモデルが構築される場合がある。良いモデリングを追及すると利点のないデザインパターンを改善できる場合がある。

感想

「練習のための練習」は本番に役に立たないことが多い。新しい技術を学ぶ場合、その技術を理解することに注力するあまり、「実務に沿っているか」から意識がずれやすい。今回、現実に沿わないモデルを作ってしまい「ヤッチマッタ」って思った。

*1:継承。ex. 人間-学生-大学生

*2:構成。ex. 人間-(頭、体、腕、足)

2016/2/21(日)「JaSST東北2016準備会(仮)」:VSTePの特徴

仙台ににしさんをおよびして、JaSST東北メンバーに対して、テスト設計を叩き込んでいただきました。
一日中テスト漬けでとても疲れましたが、とても力になる一日でした。
ありがとうございます、にしさん!

学んだ内容をブログにしようと思っているのですが、学んだことがとにかく多くて一度に出そうとすると膨大な量になります。
なので、いくつか分割してブログにしてみます。
今回は「VSTeP*1の特徴」で、にしさんが挙げた以下の2つをピックアップします。

  • VSTePは機能・データの列挙ではない
  • VSTePは設計者の満足度を高めるためモデル(図)を用いる

VSTePは機能・データの列挙ではない

テスト観点を洗い出す際、仕様書からキーワードなどを抽出することが多い。しかし、それは仕様書で表現したい機能やデータに関するテスト観点ばかりが出てくる。そのため、出来上がったモデルはは仕様書を構造化したものになる。大体にしてそのシステムの関心事がすべて仕様書に記載されていることはない。そのため、仕様書からテスト観点を抽出しても、そのシステムの関心事を抽出することができない。
テスト観点を洗い出すときは、一度仕様書から離れて、対象となるシステムがどういうものかを考える必要がある。特にシステムの関心事は開発者視点よりも利用者視点に立って、使う人たちはそのシステムにどのような関心を持つのかを可能な限り考えつくす必要がある。

感想

ある対象を理解するためには、その対象だけを見ているだけでは不十分であり、その対象の周りに何があるかを考える必要がある。仕様書を見ていると、仕様書が表現したい物を理解することはできる。しかし、その仕様書を元に作りたいシステムについては、仕様書からの理解では不十分ということだと感じた。仮に仕様書だけ渡された場合でも、その仕様書の上に作りたいシステムがあって、そのシステムを使いたい人がいることを考慮して、使いたい人に価値があるような設計をする必要があるんだと感じた。

VSTePは設計者の満足度を高めるためモデル(図)を用いる

テスト設計で重要なのは、テスト設計がその設計に満足すること。よくExcelにテスト観点をまとめたりするが、全体像が把握しにくい。VSTePはマインドマップなどのモデルを多用するが、それは設計者がテストの全体像を俯瞰しやすく、テスト設計の満足度が高くなりやすいから。モデル化して感じたもやもやを解消しながら満足度の高い設計を行うことが良いテスト設計に繋がる。

感想

分析や設計には「満足度」のような感情が入らない、というイメージがあった。しかし、人が作るものである以上、完璧な分析や設計は存在しない。そのため、「どこまでやるか」を人の満足で表現しているのはとてもしっくりきた。分析や設計を行うのは人間であり、「人間が行う」という現実から目を反らしていないからこその「満足度」重視なのだと思った。

*1:Viewpoint-based Software Test Engineering Process

自分棚卸

20代最後の年で自分を見つめなおす必要を感じたので、
ブログに纏めておきます。


先日、中学校の同窓会があって、懐かしい仲間と楽しい時間を過ごしたんですが、そんな中で「自分のことを相手に全然伝えられていない」と感じました。

自分を理解してもらえるような話*1が全くできていませんでした。
厄介なのは、「自分の能力には自信があること」。
大学の4年を注いだ奇術部でのエンターテインメントに対する考えや価値を出すことに力を注いだビジネスに対する考えはそれぞれ十分に自信を持っている*2し、両方持っていることは自分の強みだと胸を張って言えるんですよ。


ただ、大体の人にはそれらは価値がない。
だれもが面白い舞台を作る方法が語り合いたいわけではないし、だれもがより良い価値を生み出す仕事の仕方を語り合いたいわけではない。
なので自分のことは、分かる人にしか分からない。
エンターテインメントでもビジネスでも、できるだけ多くの人が価値を理解できる方が良いと思っている身としては、自分の残念ぶりにとてもショックを受けました。


ということで、これからは【相手に自分を伝えること】を心掛けようと思います。
これまでそれをやってこなかったのは「自分の弱みを出したくない」というところから始まり、加えて「自分を晒さなくても、良いものを作ればよい」という考えがありました。
伝わらないことに価値なんてないし、自分を晒しても良いものは作れるけど、そこから目を反らしてたら【相手に自分を伝えること】ができなくなってました。


なので、【自分再構築】のための【自分棚卸】中です。
ただ、ゼロから再構築じゃないです。
自分が自信のある分野は確かにあるので、その知見を活かして、再構築してきます。
しばらくは自分の強みを棚卸していきます。



後で見返すと絶対恥ずかしくなるタイプの文章だけど、
勢いに任せることも重要だよね。

*1:相手を理解することも重要ですが、今回はよりクリティカルな方を挙げています

*2:まだまだ精進は必要ですが…

2014年を振り返ってみる。

2014年も終わりなので、今年1年を振り返りたいと思います。

2014年にやったこと

ちなみに、2014年頭に立てた目標は「アウトプットの機会を増やす」でした。

2014年の目標 - toshimana's diary

ブログを始めた

今年は本格的にブログを始めました。
文字による表現が難しいことに気付かされました。

ブログに書きたいことのイメージがあっても、それを文字で表現することがとても難しい。
元々簡単とは思っていなかったけど、
実際にやってみて、こんなに難しいのか、と気付くことができました。

文字による表現力はブログ以外でも必要になるので、
これからもブログは続けていきたいと思いました。

作りたい物を作れるようになった

C++を使ってプログラミングをすることが多いですが、
今年はGUIを作るため、Qtを覚えました。
色々なツールを作れるように、プログラミングによるもの作りにやっと手が届くようになりました。
まだまだ、運用の面など、実用的なものを作れるだけの知識、技能がないので、精進が必要なところです。

勉強会で初めて発表した

「JAZUG仙台 - JAZUG4周年を祝う会 in 仙台」にてAzure Machine Learningについて
発表させていただきました。
それまで機械学習について、ほとんど理解がなかったのに、
それで発表することになっておりました。*1

20140920 jazug ml

ランニングを始めた

夏ごろからランニングを始めました。*2
ランニングは情報も多いし、自分のペースで進められるので、
普段運動しない自分には始めやすかったです。
高校時代まではある程度運動していたのですが、走り始めは全然走れなくてビックリしました。
とりあえず、今年は20Kmは走れるようになったので、
翌年は距離をもう少し伸ばすか、走るペースを上げられるようにしたいと思います。*3

振り返り

KPTにしたがって見ると、KPは以下のようになります。

Keep

今年始めたブログやプログラムでのモノづくりは自分の表現力を鍛えるためにも、
これからも続けたいと思います。
勉強会での発表も、翌年の発表は1つ決まっています。機械学習以外でも機会があれば狙っていきたいですね。
ランニングも来年も継続していきたいと思います。*4

Problem

活動できたことについては、それほど問題がなかったと思います。
しかし、活動できなかった時期が今年は多かったかと思います。
もう少しコンスタントに結果を出せるようにしたいです。

まとめ

大した成果を残せなかった1年かと思ったけど、
振り返ってみると、結構動きがあったことに驚いてます。
来年も新しいことに常々挑戦していきたいですね。

それでは、良いお年を!

*1:だいたい、@nnasakiのせい

*2:痩せるためです。

*3:走っているのは痩せるためです。

*4:今年中に目標体重に満たなかったため

TDDへの不満とその対応について考えてみた。

「Code Retreat in Sendai」に参加してきたのですが、その時に、TDDに対して感じた問題点とそれへの対応策について考えてみました。

2014/12/13(土)「Code Retreat in Sendai」に参加しました。 - toshimana's diary

※今回はGUIを持たないものを想定してます。GUIテスト自動化は、難しい。

TDDへの不満

「テストを同時に書くために処理が書きあがるまでの時間は増えるが、バグが少なくなるために総開発時間は短くなる」ことがTDDの主張と理解しています。
そのために、どうもアジャイル的ではないのではないか、と思うところがあります。

末端側からの実装を優先するため、変更に弱い

上記TDDの主張は、設計が適切に行われていることや、開発の途中で変更が起こらない場合に成り立つ、と感じています。
TDDはレッド・グリーン・リファクタリングのサイクルを回すため、小さいところ(末端側)から開発を始めがちです。
TDDで時間をかけたことにより末端側のソースコードが充実していることで、上流側の変更が、既に実装済みの末端側のコードを活用する方向に引っ張られること、また、それにより、不適切な設計になるのでは、と危険を感じます。
そのため、TDDはウォーターフォール開発に向いていて、アジャイル的ではない、と感じています。

TDDのテストは品質保証を目的としていない

TDDのテストは開発者のテストのためであり、品質保証のテストとは別物、というのがよく言われる話です。
開発者のテストが、そのまま品質保証のテストになりえないのは同意です。
しかし、品質保証のテストを使ってTDDをすればいいのではないか、と思っています。
(品質保証のテストと開発者のテストの違いを明確に理解できていないからの発言かもですけど。)

LazyTDD(仮)

TDDよりも上流側からシステムを作れるような工夫を検討してみました。
ここでは仮にLazyTDDとしたいと思います。
TDDが先行評価っぽいイメージを受けたので、Haskellの遅延評価っぽいTDDができないか、と考えてみました。
できる限り、品質保証に使えるテスト、壊れにくいテストの作成を作ることを優先し、品質保証に使えない、壊れやすいテストの作成を可能な限り抑制することを目的としています。

1.最も上流側のテスト(受け入れテストやシステムテストレベルのテスト)を書く。

実現したい機能の動作が確認できるレベルのテストを真っ先に用意します。

2.コードを書く。

必要な処理は可能な限り関数化する。関数はインターフェースのみの実装とする。
この時点では設計としてのコード実装の意味合いが強い。

3.作成した関数のコードを書く。

この際、必要であれば、その関数のためのテストを書く。
必要な場合として、例えば、

  • その関数をテストする際に、同じレベルに存在する関数との問題の切り分けが困難と感じたとき
  • 上流のテストでは、実行に時間がかかり過ぎるとき

テストを実装するときは、末端側のテストは上流のテストでカバーされる範囲でなければならない。
上流側に影響が表れないのなら、その機能(テスト)は不要だと考えている。

4.3で作成したテストをテストするときは、1のテストを一時的に無効化する。

3で書いたテストがグリーンになった時に、再度1のテストを有効化する。

5.1~4を繰り返す。

まとめ

TDDはプログラマが意図したものを作れる素晴らしい技術だと思います。
しかし、その分、プログラマが必要なもの、顧客が欲しいものに、プログラマが目を向け続けないと、異なる方向に進んでしまう技術とも思いました。
LazyTDD(仮)は私が適当に考えたものなので、同じような技術とかご存じの方がいらしたら教えてください。

関数型プログラミングとオブジェクト指向について思うこと

大学時代に関数型言語を扱っていたため、私は関数型プログラミングが大好きです。
そのため、現代のプログラミングの標準であるオブジェクト指向プログラミング(以下、OOP)にあまり興味が湧いてきませんでした
しかし、2014年はGUIプログラミングに手を伸ばした過程で、OOP関数型プログラミングの棲み分けについて思うところがありました。今回はそれを書き留めてみようと思います。

関数型プログラミング

関数型プログラミング」の言葉の意味はwikipediaを見てください。関数型プログラミングにおける“関数”は、数学の“関数”です。
http://ja.wikipedia.org/wiki/%E9%96%A2%E6%95%B0%E5%9E%8B%E8%A8%80%E8%AA%9E

関数型プログラミングの魅力

非関数型の言語を使う方でも分かりやすい魅力として、「副作用のない関数」を扱うスタイルが挙げられます。
副作用のない関数によりプログラムを組み上げることにより、「扱う状態を少なくする」ことと「実行順序に依存しない処理を書ける」ことで、バグを少なくすることができます。

扱う状態を少なくする

副作用のない関数によってプログラムを組み立てる関数型プログラミングでは、オブジェクト指向と比較して、状態の重要性が小さいです。
扱う状態数が多くなるほど、その管理が難しくなります。状態の管理を誤るとプログラムになることから、プログラムの状態を少なくすることはバグを少なくすることに繋がる、と言えます。

実行順序に依存しない処理を書ける

Haskellで遅延評価が実現できるように、関数型プログラミングでは「どのような順序で処理するか」はあまり重要視されていません。
オブジェクト指向(というよりも手続き型言語)では、状態を処理する順序によって、得られる結果が変わる場合があるため、本来不要な実行順序の制約が処理に付与される場合があります。そのため、必要以上に実行順序の制約が入りやすくなり、処理の組換えなどが困難になる傾向にある、と思われます。
関数型プログラミングでよく使われる副作用のない関数は、入力が等しいなら得られる結果も等しいことが保障されます。そのため、処理の組換え、部品化が容易です。また、実行順序にとらわれない処理が明確になるため、並行化できる領域も抽出しやすくなります。

オブジェクト指向関数型プログラミングよりも優れている点

以下は私の感覚です。

オブジェクト指向が得意とする領域は、以下のような点が挙げられる、と考えています。
・状態を扱う必要がある領域
・実行順序を制御する必要がある領域
これは、画面(GUI)制御やデバイス制御がこれにあたります。

実世界に近い部分(人が触る部分(=GUI)や機械が触る部分(=デバイス制御))はオブジェクト指向プログラミングが向いている領域と考えています。実世界における個々の状態を、オブジェクトの状態として容易に表現できます。
対して、状態を管理する必要がない領域はできる限り論理的に、数学的に記載することで、バグを少なくできます。関数型プログラミングビジネスロジックを記載することに向いていると考えます。
Separated Presentationにおける、プレゼンテーションロジックはオブジェクト指向(+手続き型プログラミング)で、ビジネスロジック関数型プログラミングで記載すると良いのでは、と考えています。

まとめ

オブジェクト指向だけでも、どんなアプリケーションでも作ることができます。しかし、オブジェクト指向では万物がオブジェクトであれば、それを管理しするプログラマは神でなければならないのか、とも思います。
全てのオブジェクトを一切のミスなく管理するには、まさに神のような能力が必要になると思います。しかし、それは多くの人には困難です。
現実世界における科学の如く、関数型プログラミングはプログラムの世界をより抽象化し、人間に扱いやすくできると考えています。
オブジェクト指向、手続き型、関数型プログラミングが得手不得手があるので、どれか一つを覚えれば十分、ではなく適材適所に扱えることが必要なのだと思いました。

2014/12/13(土)「Code Retreat in Sendai」に参加しました。

プログラマ向けイベント「CodeRetreat」が仙台で初開催とのことなので、行ってきました。

CodeRetreatは「コンウェイライフゲーム」をテーマに、
主にペアプログラミング、TDDの学習を行うイベントです。

1回45分のセッションを6回行う、なかなかハードなイベントです。
セッション後には毎回コードを削除して、次ははじめから行ったり、
セッションごとにペアや使用する言語を変えて行うため、
新しい考え方に触れることができます。

セッションごとのテーマ

セッションごとにテーマが設定されており、
同じライフゲームを記述するにも、毎回悩まされました。

Session1.特に制約なし
Session2.テストコードとプロダクトコードの入力者を分ける。
Session3.5分ごとに入力者を交代する。(後に、2分ごとに変更)
Session4.プリミティブな値の使用禁止。
Session5.if文,Switch文使用禁止。for文,while文使用禁止。
Session6.変数はすべてimmutableにする。

関数型言語を使って

使う言語に特に制約がなかったため、Haskellの使用を提案したら、
意外と周りの食いつきが良かったです。
割と適当な説明ばかりしていたと思うので、
皆さんに十分に関数型言語の魅力を伝えられなかったと大いに反省しています。

あと、Session4~6のテーマはオブジェクト指向開発に合わせたテーマでしたね。
関数型言語では、再帰関数を積極的に使う文化があるため、Session5のfor, while文使用禁止はほとんど影響ありません。
Session6の「変数すべてimmutable」については、Haskellの場合、デフォルトで変数がimmutableなので、普段通りにコードを書けます。mutableな変数を扱う方が大変です。

オブジェクト指向派の方との意見のギャップは良い刺激になりました。
オブジェクト指向的な設計がどのようなものなのか、
他の人の話を聞いて、普段とは違う考え方に触れられました。

テストの粒度

TDDの初手として、
今回のテーマで最も上流となる(と思っている)テストから書き始めました。
ライフゲームの初期状態を受けとり、
次の状態を返す関数のテストを書きました。
しかしそれだと、テストの粒度が大きすぎて、
テストが通るまでに時間がかかり過ぎる、と指摘を頂きました。

確かに、「このテストでは粒度が大きすぎて、そのテストが通った時点でほぼ実装が完了している」と思いました。
ですが、「粒度を細かくした時の、分割が妥当であることをどのように保障するのか」という疑問が浮かびました。

TDDの基本として「プロダクトコードを書く前にテストコードを書く」というものがあります。
しかし、この前提として、「設計が十分にされていること」があるのではないか、と思いました。

HaskellにおけるTDD

Haskellだと、TDDに設計フェーズをプラスして、サイクルを回せるのでは、と考えてます。
ここの考えはまだ試作です。

Haskellの場合、「型を基づく設計」が可能です。
関数を定義する際に、実装をundefinedにして、型のみを定義することができます。

そのため、以下のような手順によって「設計⇒テスト⇒実装」のサイクルが回せるのではないか、と考えています。
1.作成したい関数の型を定義する。
2.1の関数を実行するときのテストを用意する。(テストは失敗する)
3.1の実装を記載する。必要であれば、新しい関数を型のみ定義する。
4.3で定義した関数のテストを用意する。(テストは失敗する)
5.2のテストを無効化(コメントアウト)する。
6.3の実装を記載する。
7.4のテストが通ったなら、5で無効化したテストを有効化する。

まとめ

いざ、書いてみたら、全然考えがまとまっていないことがよく分かりました。
オブジェクト指向と関数型の違い」や「関数型言語とTDD」は興味深いところなので、
一度整理してみたい話です。

あまり、CodeRetreatの参加レポートっぽくはありませんでしたが、
お題となった「コンウェイライフゲーム」のHaskellコードをイベント後に作成してみました。
TDDでの開発ではないので、テストが若干おろそか気味。

toshimana/lifegame · GitHub

Code Retreatでは、思考をpanic zoneに持っていくことで普段より多くの学びを得ることを目的としていますが、イベントが終わった今がまさにpanic zoneに陥ってます。
このpanic状態をうまく解決して、よりよい開発ができるようになりたいです。