elmでやってみるシリーズ2: ●を往復させる
import Window import Debug (log) -- 旧速度vと、現在位置xから、新しい速度を求める。(はじっこだったら速度を反転する) newv : Int -> Int -> Int newv v x = if (x<= -10 || 10<=x) then -v else v -- 状態を表わす(現在位置、速度)のタプルに対して、次の状態をシグナル(fps 20)のタイミングで累積的に計算しなおすということを繰り返す。初期状態は(0,1)。結果得られるのは、(現在位置,現在の速度)を表現するシグナルである。 pos = foldp (\it (x,v) -> let nv = (newv v (log "x" x)) in (x+nv, nv) ) (0,1) (fps 20) -- 指定位置x,yを中心に●を書く(半径20の円を書いて赤で塗り潰す)。 drawCircle : Float -> Float -> Form drawCircle x y = move (x,y) <| filled red (circle 20) -- 一連の背景線を書く drawMatrix : [Form] drawMatrix = map (\x -> drawLine <| x*10) [-10..10] -- 背景線を1本書く drawLine : Float -> Form drawLine x = traced (solid blue) ( segment (x,-100) (x,100) ) -- 「一連の背景線と、●を書いたコラージュを生成する純粋関数f」に、現在位置(posタプルの第一要素)をシグナル化したまま取り出してリフト適用 main : Signal Element main=let f = \w h p-> collage w h ([drawCircle ((toFloat p)*10) 10]++drawMatrix) in f <~ Window.width ~ Window.height ~ (fst <~ pos)
解説的な何か
- foldpのpは、pastのpで、その意味は実際に「過去から現在までのシグナルの履歴値を畳み込む」です。しかし、foldp使用に伴なうオーダーは実行開始時刻から現在までの時間経過には依存せず、O(1)です。実際には、シグナルの更新1回ごとに1回呼び出される関数を登録するというものです。foldpの第一引数の関数の第二引数(上で言う(x,v))は前回のfoldpの返り値を保持しています。この値が、いわゆる状態を保持・更新するためのelmにおいての唯一の手段です。
- Debug.logは、JavaScriptでいうConsole.logを呼び出します。正格評価だからその時点の値が普通に出ます。
続く。
elmでやってみるシリーズ1: ●を動かす
elmでやってみるシリーズ1: ●を動かす。
import Window pos : Signal Int pos =let f = \tmp -> (tmp `mod` 30) - 10 in f <~ foldp (\it acc-> acc + 1) 0 (fps 50) drawCircle : Float -> Float -> Form drawCircle x y = move (x,y) <| filled red (circle 20) drawMatrix : [Form] drawMatrix = map (\x -> drawLine <| x*10) [-10..10] drawLine : Float -> Form drawLine x = traced (solid blue) ( segment (x,-100) (x,100) ) main : Signal Element main=let f = \w h p-> collage w h ([drawCircle ((toFloat p)*10) 10]++drawMatrix) in f <~ Window.width ~ Window.height ~ pos
続く。
感想
関連エントリ
Grails 3.0先取り!? Spring Boot入門ハンズオン
次回G*Workshopは、8/1 「Grails 3.0先取り!? Spring Boot入門ハンズオン」です。
ふるってのご参加をお待ちしております。
Grails 3.0先取り!? Spring Boot入門ハンズオン
申し込みはこちらから>
Grails 3.0先取り!? Spring Boot入門ハンズオン
予定の内容
Grailsの次期バージョン3.0でベースになることが予定されている、Spring界隈の新しいトレンド"Spring Boot"のハンズオンを通じて、Spring Bootのイメージを掴んでもらいたいと思います。内容は以下の通りです。
Spring Boot概要説明
Spring Bootを用いて簡単なアプリケーションを実際に作ってみる
(合計で約二時間弱)
「プログラムでシダを描画する」をelmで描画する
やや乗り遅れているネタとして、シダを描くというのを、elm言語でやってみました。
(追記: 改良版も作りました)
elm言語は、基本はHaskellライク文法(サブセット方向)に、F#とOCaml風味の演算子・文法を振り掛けた、ヒンドリーミルナー型推論・純粋関数型・正格評価の言語で、repl上もしくは主にJSにコンパイルしてブラウザ内で実行します*1。特徴はFRP,ファンクショナルリアクティブプログラミングをサポートする言語だということです。
以下がシダを描画するelmコード。もっといい書き方あると思うので気付いたらご指摘お願いします。
import Mouse import Generator import Generator.Standard sida_width=500 sida_height=500 randomSeed = 12346789 gen = Generator.Standard.generator randomSeed main = collage (sida_width*2) (sida_height*2) <~ ((f0 13 0 0 gen) <~ (flip (/) sida_width <~ (toFloat <~ Mouse.x))) -- Original: w1x x y = 0.836 * x + 0.044 * y w1x x y n = n * x + (1-n) * y w1y x y = -0.044 * x + 0.836 * y + 0.169 w2x x y = -0.141 * x + 0.302 * y w2y x y = 0.302 * x + 0.141 * y + 0.127 w3x x y = 0.141 * x - 0.302 * y w3y x y = 0.302 * x + 0.141 * y + 0.169 w4x x y = 0 w4y x y = 0.175337 * y f0 k x y gen0 n = let (seq, _)=f k x y gen0 n in [(move (0,0)) (filled black <| rect (sida_width*2) (sida_height*2)) ]++seq f k x y gen0 n = if (0 < k) then let (rnd1, gen1) = Generator.int32 gen0 (seq1, gen2) = (f (k - 1) (w1x x y n) (w1y x y) gen1 n) (seq2, gen3) = if (rnd1 `mod` 3 == 0) then (f (k - 1) (w2x x y) (w2y x y) gen2 n) else ([], gen2) (seq3, gen4) = if (rnd1 `mod` 3 == 1) then (f (k - 1) (w3x x y) (w3y x y) gen3 n) else ([], gen3) (seq4, gen5) = if (rnd1 `mod` 3 == 2) then (f (k - 1) (w4x x y) (w4y x y) gen4 n) else ([], gen4) in (seq1 ++ seq2 ++ seq3 ++ seq4, gen5) else ((plot (x * sida_width * 0.98) (y * sida_height * 0.98)), gen0) plot x y = [move (x,y) (filled green <| rect 1 1)]
リアクティブプログラミングというのは、私の理解では、時間経過とかマウスクリックとか、なんらかの(外部/外部)イベントに刻々と反応することの記述を容易にできるってことです(雑すぎる説明)。それがファンクショナルなのは、関数型ってことで、elmはさらにピュア・ファンクショナルなので副作用は記述できません。Signalというのが「変化する値」を表わしていて、これはHaskellのIOアクションが副作用を一手に背負っているようなものです。SignalはしかしモナドではなくArrowで、これでFRPを実現しているのを Arrowized FRPと呼ぶとか。ただそこらへんの詳しいことはわからなくても書けます*2。
上記のコードは、マウスのx座標で反応するようにしました。FRPなのはmainだけであとは全部ピュアな関数です。x座標に対応して、シダの図のどのパラメータをどう動かすかは、適当にやったので動きは不自然です。あと再帰の深さを深くすると非常に遅くなります。Canvasに書き捨ててるんじゃなくて、描画命令(Form,形状)をリストで持ってるからです。
以下にはコンパイル結果のJSを登録しましたので、ブラウザ上で実際に動かして試すことができます。マウスを左右に動くとなんか動くわけです。
以下は、静止画像のスナップショットです(なので動きません)。
枝ぶりが貧弱なのは、速度上の問題ですorz。
以下はelm_dependencies.jsonの内容。標準関数以外には、random generatorというのを使っています。
{ "version": "0.1", "summary": "concise, helpful summary of your project", "description": "full description of this project, describe your use case", "license": "BSD3", "exposed-modules": [], "elm-version": "0.12.3", "dependencies": { "jcollard/generator": "0.3" }, "repository": "https://github.com/USER/PROJECT.git" }
elmについては別途紹介記事を書くつもり。
Groovyのtraitを使い倒す!
JGGUG G*Workshopに久々に参加しまして、GroovyのTraitについて、以下を話してきました!
盛況でした。いくにんかAndroid開発をされている人もいらっしゃったようで、Groovy on Androidが注目されているのも理由かもしれませんね。
http://togetter.com/li/682540
http://jggug.doorkeeper.jp/events/11365
SpockにおけるMock、Stub、Spyの違い
テスティングフレームワークSpockで相互作用中心のテストをする場合、いわゆるテストダブルとして、MockとStubとSpyの3種類を使えます。それぞれの意味などを簡単に解説します。
Spock全体含め詳しい解説はこちらなどを参照ください。
Mockに関しては、id:yamkazu 氏によるこちらのJGGUG G*Workshopの資料も秀逸です。
Stubとは
最初に、Stub(GroovyStub)についてです。Stubは後述Mockの低機能版であり、具体的には「モッキングができないMock」がStubです。StubができることはMockでできるので、本来Stubを使う必要はありません。モッキングしないことを明示したいなら、使えば良いでしょう。なお、Spock用語の「スタビング」とは別のものです(スタビングおよびモッキングについては後述)。
Mockとは
Mock(もしくはGroovyMock)は、テスト対象が使うクラスを指定して、そのクラスのインスタンスの真似をするオブジェクト(モックオブジェクト)を作ります。真似をするというのは、「元のクラスにあるのと同じシグネチャのメソッドを、モックオブジェクトに対して呼び出したりできる」ということです。Mockのメソッドを呼んでも、Mock元になったオブジェクトの本物のメソッドは呼び出されません。
たとえると、モックは「代役」です。本人は楽屋かなにかで休んでおり、リハーサル(テスト)では代役が呼び出しに応じて努めます。
以下、Mockの使用の例です:
class TestUnit3Spec extends UnitSpec { def test00() { setup: def bean = Mock(SomeBean3) when: def result = bean.methodOfSomeBean() println result then: 1 * bean.methodOfSomeBean() >> 123 result == 123 } } class SomeBean3 { int methodOfSomeBean() { println "hoge" 100 } }
上の例では、実際のメソッド methodOfSomeBean では「100」を返しているのにもかかわらず、あるいは"hoge"を出力しているのにもかかわらず、帰ってくる値は「123」だし(assert result=123)、println "hoge"は実行されず、当然"hoge"も出力されません。
ではその代役(モック)は何をするのか?というとですね、モックは、自身のメソッドが呼び出されたときに、「どんなメソッドがどんな引数で呼び出されようとしたか」を記録しており、期待するものだったかどうかを後でチェックできるようになっています。以下がそのチェック部分です.
1 * bean.methodOfSomeBean() >> 123
この場合、methodOfSomeBeanが1回、呼ばれるならチェックが成功します。
利点としては、上の場合SomeBean3のメソッドが実装されているかどうか、どのように実装されているか、正しいかバグがあるかと関係なく、シグネチャさえ決まっていれば「SomeBean3を使うコード」の試験ができることです。本来「単体試験」というのはかくあるべきだと思いますね。
注意
上の例では、SomeBean3をMockしてますが、「試験対象クラス」がSomeBean3だという想定ではありません。その意味で、上は、試験対象を試験してないテストという変な例です。「試験対象クラスが使用するクラス」に代役を立てることができるのであって、試験対象クラスそのものに代役をたてたら意味ありません。コラボレータとよばれる、「試験対象クラスの動作に必要なクラス」、脇役とか背景の群集とかに、代役を立てるってことです。
Mockまとめ:
- Mockは代役であり、本人の代りを務める。
- なので本番オブジェクトのメソッドができあがってなくても、それを使うオブジェクトの試験ができる。
- Mockに行なわれたメソッド呼び出しの有無と回数、引数などを記録をしてくれる機能ももっている
- それを後で確認できる。試験がはかどるわ〜。
Spyについて
これに対して、Spy(もしくはGroovySpy)は、その対象とするオブジェクトが、実際に存在する必要があります。偽物だけではなく、本物インスタンスが存在していることが必要です。
Spyの役割りは、「横からメソッド呼び出しの様子を監視し、その呼び出しメソッドや引数を記録するというものです。加えて、最後にその記録された情報、どんなメソッドがどんな回数呼びだされたかをチェックすることができます。Mockと同じようですが、Spyでは戻り値の「本当の値」でのチェックができます。反面、試験対象オブジェクト以外のコラボレータの振舞いに結果が左右され得ることになるので、単体試験としてはどうなんでしょう、という感じもします。
たとえると、スパイは「善意のマンインザミドル攻撃」のようなものです。呼び出し側と対象オブジェクトの間に挟まった代理人で、あとから整合性を確認するための記録を取ってくれます。
なお、Spyでは、スタビング指定すると、実際の値以外の値を返させ、元メソッドを呼ばない動作をさせることもできます。(メソッド個別にMockのように動作させることもできる)。
Spyまとめ:
- Spyは、本人とのやりとりを横から監視してやりとり記録する
- なので本番オブジェクトは必要。本番オブジェクトのメソッドの呼び出しの実際の実行、およびその返り値を使っての試験ができる。
- 本番オブジェクトのメソッドを呼ばずに、特定の別の値を返すこともできる(スタビング指定する)。
- 本番オブジェクトのメソッドを呼び、かつ、特定の別の値を返すこともできる(スタビングでクロージャ指定, callRealMethod使用)。
- なので本番オブジェクトは必要。本番オブジェクトのメソッドの呼び出しの実際の実行、およびその返り値を使っての試験ができる。
- 自身に行なわれたメソッド呼び出しの有無と回数、引数などを記録をしてくれる機能ももっている
- それを後で確認できる。試験がはかどるわ〜。
MockとSpyの違いと使い分け
MockとSpyの実用上の最も大きな違いは、Mockの場合はメソッドの返り値がテキトーなもの、0とかnullとかになるということです。実体がないからしょうがありませんね。試験の都合のために、Mockでそれらしい特定の値が返ってほしいときは>>で返り値を明示指定します(スタビング)。
Spyは実際の値がかえるから、>>をする必要はありません。あえて>>しても良いですけれども。
どちらをどのようなときに使い分ければ良いか、という指針ですが、SpockのドキュメントにはSpyについて「(この機能を使用する前に一度考えなおしてください。もしかすると仕様対象のコード設計自体を見なおしたほうが良いかもしれません。)」とのことです。なので、
「なるべくMockで、それでなんらかの不都合があるならSpyで」
でしょうか。
なお、SpockのMock,Spy,Stubという機能は、世に一般的に言う、モック、スパイ、スタブの説明とは微妙な違いがあるかもしれません。上はあくまでSpockのそれらの説明です。
おまけ: モッキングとスタビング
モッキング
Spockにおいて、モッキングとは、テスト対象クラスに対するMock, Spy, Stubのいずれかで、発生を期待するイベントすなわち「どんな引数でのメソッド呼び出しが何回、どんな順序で発生するか」の期待を記述しておくことを言います。
ジョセフ・ジョースターで言えば、「おまえは次に〜する!」「おまえは次に〜言う!」と予告のことです。テストが成功したら、「ハッやってしまったぁ〜!!」と言わねばなりません。
こういう感じになります(以下、こちらより引用)。(*)のところで「1 * ...」しているところがモッキング。
次の例を見てください。def "should send messages to all subscribers"() { when: publisher.send("hello") then: 1 * subscriber.receive("hello") // (*) 1 * subscriber2.receive("hello") // (*) }文章としてコードを読んでみると「publisher が ‘hello’ のメッセージを send したとき、 それぞれの subscriber は 1回 message を receive すべき」になります。
スタビング
スタビングは、メソッド呼び出しの返り値を(上書き)指定します。
こちらからまた引用しますが、以下のコード例の (**)のところで>>指定しているのがスタビングです。
固定の値を返す
すでにここまでの例の中で出てきましたが、固定の値を返すには算術右シフト(>>)演算子を使用します。subscriber.receive(_) >> "ok"呼び出し毎に異なる値を返すには、それぞれ個別のインタラクションとして定義します。
subscriber.receive("message1") >> "ok" // (**) subscriber.receive("message2") >> "fail" // (**)これは"message1"を受信すると"ok"を返し、"message2"を受信すると"fail" を返します。返す値に制限はありませんが、メソッドの戻り値型の制約を外れることはできません。
スタビングとモッキングは同時に行うことも可能です。
1 * subscriber.receive("message1") >> "ok"
モッキングはMockに、スタビングはStubに、という対応はありません。
ただし、Stubはモッキングができず、スタビングのみが行えます。
つまり以下のとおりです。
スタビング | モッキング | |
---|---|---|
Mock | ○ | ○ |
Spy | ○*1 | ○ |
Stub | ○ | × |
*1:固定値を指定してSpyをスタビングすると元メソッドの呼び出しは抑制される。
オブジェクト指向だけじゃない開発宣言
Manifesto for Not Only Object-Oriented Development、オブジェクト指向だけじゃない開発宣言、というのが出てましたのでごにょと訳してみました*1。
オブジェクト指向だけじゃない開発宣言
私たちは、ソフトウェア開発の実践
あるいは実践を手助けをする活動を通じて、
よりよい開発方法を見つけだそうとしている。
この活動を通して、私たちは以下の価値に至った。
価値とする。すなわち、左記のことがらに価値があることを認めながらも(但しnullは除くが)、私たちは右記のことがらにより価値をおく。
内容は、「今どきのオブジェクト指向開発宣言」と名乗ってもあんまり違和感ないっす。
ただし、null、おめーは別だ。
追加希望
正格評価よりも、非正格評価を、
チューリングマシンではなく、SKコンビネータを、
追記:この翻訳が本家の日本語訳に採用されました。