Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ある SWET エンジニアの開発プロセス改善最前線 / Story of a SWET Engineer

Kuniwak
February 06, 2019

ある SWET エンジニアの開発プロセス改善最前線 / Story of a SWET Engineer

私の所属する SWET という組織の目指すものは「テストを楽しく、賢く、価値を届けられるように」であり、私たちは日々これを達成すべく働いています。さて、このような組織に所属する私が取り組んでいるものは、テストをうまく使って開発速度の安定化や向上、より保守性の高い設計を達成することです。この発表では、私が取り組んできたテストによる開発プロセスの改善の実例をお話しします。

この発表では、以下の5つの事例を紹介する予定です:

* 現場の開発プロセスの分析
* 開発プロセスのコンサルティング
* デバッグを助けるモジュールの開発
* テスターを助けるライブラリの開発
* Jenkins クラスタの安定稼働のための移行プロジェクト

https://techcon.dena.com/2019/

Kuniwak

February 06, 2019
Tweet

More Decks by Kuniwak

Other Decks in Programming

Transcript

  1. #denatechcon   ໊લͷ༝དྷ (PPHMFͳͲʹ͓͚Δ4&5 4PGUXBSF&OHJOFFSJO5FTU Λ
 ࢀߟʹ͍ͯ͠Δɻ͜ͷଞͷϩʔϧͱͯ͠ɺ48& 4PGUXBSF &OHJOFFS

    ͱ5& 5FTU&OHJOFFS ͳͲ͕͋Δɻ ͜ͷ໋໊Λࢀߟʹ͢Δࡍʹ4&5͸48&ͷҰछͰ͋Δ
 ͱ͍͏ೝ͔ࣝΒ4&5 48&ˠ48&5΁มߋɻ ৄ͘͠͸ʮςετ͔Βݟ͑ͯ͘Δάʔάϧͷιϑτ΢ΣΞ։ൃʯΛࢀর
  2. #denatechcon   w .PCBHFͷ8FC"1*6*΁ͷ&&ςετ   w ϚϧνϓϥοτϑΥʔϜͰͷ4%,ͷςετ ʙ

     w ςετج൫ʢ45'ͳͲʣͷల։ ʙ  w ϥΠϒϥϦͷࣗಈόʔδϣϯΞοϓج൫ ʙ  w ը૾ೝࣝʹΑΔ&&ςετࢧԉج൫ ʙ  w ʜ w ͜Ε͔Βൃද͢Δ্Լ൒ظͷऔΓ૊Έ ʙ
  3. #denatechcon   ղܾํ๏ͷݕ౼ ·ͣ͸ϑΟʔυόοΫͷ଎͍୯ମςετͰղܾΛݕ౼ɻ
 ͨͩ͠ɺ݁߹ʹΑΔ͕ܽؕଟ͘༧૝͞ΕͨͨΊɺ
 ݁߹ͯ͠ඳըͨ͠ޙͷϑϨʔϜը૾Λݕࠪ͢Δ͜ͱʹɻ &&ςετ ݁߹ςετ ୯ମςετ

    ݁߹όάΛൃݟͰ͖Δ ݁߹όάΛݟམͱ͢ ϑΟʔυόοΫ͕஗͍ ϑΟʔυόοΫ͕଎͍ ݁߹όάΛݟ͚͍ͭͨ
 ͱ͖ʹ͚ͩ࢖͏ ୯ମςετͰ׬݁Ͱ͖Δ
 ͳΒͦͷํ͕Α͍
  4. #denatechcon   +FOLJOTͷϚγϯʹ৑௕ੑ͕ͳ͘ɺμ΢ϯλΠϜ͕
 ൃੜ͠΍͘͢ɺॏཁͳ࡞ۀ͕தஅ͞Ε͍ͯͨɻμ΢ϯλΠϜͷ ݪҼ͸σΟεΫ༰ྔෆ଍΍04΍πʔϧͷΞοϓσʔτͳͲɻ ౰࣌ͷߏ੒͸ɺ8JOEPXTNBD04ͦΕͧΕͰNBTUFS͕
 Ұ୆ͷΈͷߏ੒ɻ ݱ৔ͷ՝୊ 

    ͳΔ΂͘μ΢ϯλΠϜͷӨڹͷগͳ͍໷ؒʹ࣮ࢪ͢ΔͨΊ୲౰ऀ΁ͷෛ୲΋େ͖͍ɻ  8JOEPXT޲͚ͷϏϧυ͸8JOEPXTϚγϯ্ͰɺJ04NBD04޲͚ͷ
 Ϗϧυ͸NBD04্Ͱ࣮ࢪ͢Δ͜ͱΛҙਤͨ͠ߏ੒ɻ
  5. #denatechcon   +FOLJOTNBTUFS 8JOEPXTBHFOU 8JOEPXTBHFOU NBD04BHFOU NBD04BHFOU (PPHMF$MPVE1MBUGPSN ։ൃऀ

    ࣾ಺ωοτϫʔΫ ࣾ಺ωοτϫʔΫ )5514 +/-1 1FSTJTUFOU%JTL ੒Ռ෺ ແఀࢭͰεέʔϧՄೳ ߏஙͨ͠+FOLJOTΫϥελͷߏ੒
  6. #denatechcon   +FOLJOTNBTUFS 8JOEPXTBHFOU 8JOEPXTBHFOU NBD04BHFOU NBD04BHFOU (PPHMF$MPVE1MBUGPSN ։ൃऀ

    ࣾ಺ωοτϫʔΫ ࣾ಺ωοτϫʔΫ )5514 +/-1 1FSTJTUFOU%JTL ੒Ռ෺ ৑௕Խ ߏஙͨ͠+FOLJOTΫϥελͷߏ੒
  7. #denatechcon   +FOLJOTNBTUFS Քಇத 8JOEPXTBHFOU Քಇத Քಇத (PPHMF$MPVE1MBUGPSN ։ൃऀ

    ࣾ಺ωοτϫʔΫ ࣾ಺ωοτϫʔΫ )5514 +/-1 1FSTJTUFOU%JTL ੒Ռ෺ 04Ξοϓσʔτத ߏஙͨ͠+FOLJOTΫϥελͷߏ੒ ϩʔϦϯάΞοϓσʔτ͕Մೳ ੾அ
  8. #denatechcon   ͜ͷݕূαΠΫϧΛָʹ͢ΔͨΊɺ5FTU,JUDIFO΋
 ར༻Ͱ͖ΔΑ͏ʹ͍ͯ͠Δɻͨͩ͠ɺͭͳ͗෦෼ͷ
 σόοά͕໘౗ͳͨΊɺϓϥάΠϯ։ൃΛݕ౼தɻ 5FTU,JUDIFOʹΑΔݕূͷ༰қԽ Ծ૝؀ڥ Ծ૝؀ڥ Ծ૝؀ڥ

    LJUDIFODPOWFSHF
 ʢॳճద༻ͷ֬ೝʣ LJUDIFODSFBUF
 ʢԾ૝؀ڥͷ࡞੒ʣ LJUDIFODPOWFSHF
 ʢႈ౳ੑͷ֬ೝʣ LJUDIFOEFTUSPZ
 ʢԾ૝؀ڥͷഁغʣ
  9. #denatechcon   #MVF(SFFO%FQMPZNFOUͷΠϝʔδਤ ՔಇதͷNBTUFS 8JOEPXTBHFOU 8JOEPXTBHFOU NBD04BHFOU NBD04BHFOU (PPHMF$MPVE1MBUGPSN

    ։ൃऀ ࣾ಺ωοτϫʔΫ ࣾ಺ωοτϫʔΫ )5514 +/-1 %JTLͷίϐʔ ੒Ռ෺ ݕূதͷNBTUFS ӡ༻ऀ
  10. #denatechcon   ͋ΔΫϥε΍ؔ਺ͷಈ࡞ΛίʔυͰ֬ೝ͢Δ͜ͱɻ ୯ମςετͱ͸ public class ExampleBehaviourTest { [Test]

    public void TestDistance() { var vec1 = new Vector2(1.0f, 0.0f); var vec2 = new Vector2(0.0f, 1.0f); var distance = Vector2.Distance(vec1, vec2); Assert.AreApproximatelyEqual(distance, Mathf.Sqrt(2)); } } ͋·Γݱ࣮తͰͳ͍ྫ͕ͩ
 ͭͷϕΫτϧ   ͱ
   ͷڑ཭͕˽ʹͳΔ
 ͜ͱΛίʔυͰ֬ೝ͍ͯ͠Δɻ ॏཁͳͷ͸ɺ͜ͷछͷ֬ೝΛ
 ίʔυ͔ΒͰ͖Δ͜ͱɻ
  11. #denatechcon   6OJUZʹ͓͚Δςετͷ࣮ߦํ๏   ͱ   ͷ݁Ռ͸࣮ࡍʹ˽ͳͷͰɺ


    ಈ࡞֬ೝ͸੒ޭ͢Δɻ ੒ޭ͢ΔͱɺࠨͷΑ͏ʹ྘ͷνΣοΫϚʔΫ͕ͭ͘ɻ
  12. #denatechcon   ಈ࡞֬ೝʹࣦഊ͢Δ৔߹ [Test] public void TestWrong() { var

    vec1 = new Vector2(1.0f, 0.0f); var vec2 = new Vector2(0.0f, 1.0f); var distance = Vector2.Distance(vec1, vec2); Assert.AreApproximatelyEqual(distance, 100); } ಉ͡Α͏ʹ   ͱ   ͷ
 ڑ཭Λܭࢉ͍ͯ͠Δɻ
 ͨͩɺࣦഊ͢Δέʔε΋
 ͔֬ΊΔͨΊʹɺ͋͑ͯ
 ؒҧͬͨ݁Ռͱൺֱ͢Δ ਖ਼͘͠͸˽
  13. #denatechcon   ίϚϯυϥΠϯ͔Β΋࣮ߦͰ͖Δ $ /Applications/Unity.app/Contents/MacOS/Unity \ -runEditorTests \ -projectPath

    ./ \ -batchmode $ file TestResults-*.xml TestResults-xxxxx.xml: XML 1.0 document text, ASCII text, ίϚϯυϥΠϯ͔Β࣮ߦͰ͖Δͱ͍͏͜ͱ͸ɺ+FOLJOTͳͲ͔Β
 ࣗಈͰಈ࡞֬ೝΛ࣮ߦ͠΍͍͢ɻͭ·Γఆظతͳ࣮ߦͳͲ΋Մೳɻ 6OJUZ)VCΛ࢖͍ͬͯΔ৔߹͸ɺ
 ࣮ߦϑΝΠϧͷύε͕ҟͳΔͷͰ஫ҙɻ
  14. #denatechcon   ͔͜͜Β͸໛ࡧதͷ࿩ʹͳΓ·͢ ݱ ࡏ 
 ໛ ࡧ த

    ໛ࡧதͳͨΊɺਖ਼͘͠ͳ͍ચ࿅͞Ε͍ͯͳ͍෦෼΋ؚ·Ε·͢ɻ
 ήʔϜ෼໺ͷํ͸౰ͨΓલͱࢥ͏෦෼΋͋Δ͔΋͠Ε·ͤΜɻ
  15. #denatechcon   Ξ΢τήʔϜͷ୯ମςετ͠΍͢͞ ݱ ࡏ 
 ໛ ࡧ த

    ͜͜Ͱ૝ఆ͍ͯ͠Δͷ͸ʮ͋Δ࣌ؒ΍Πϕϯτ഑৴࣌
 ͷΈಋઢ͕༗ޮʹͳΔʯͱ͍ͬͨϩδοΫͷݕূɻ ͜ͷछͷϩδοΫ͸ύλʔϯ਺͕ଟ͍͕ɺ
 ୯ମςετ͸؆୯ͳ͜ͱ͕ଟ͍ɻ ͳ͓ɺ୯ମςετʹൺ΂ͯखಈϓϨΠͰͷ֬ೝ͕
 ໘౗ʢ࣌ࠁґଘɺ͋Γ͑Δύλʔϯ͕ଟ͍ʣͳͨΊɺ
 ಛʹ୯ମςετͷޮՌͷߴ͍෦෼ͩͱߟ͍͑ͯΔɻ
  16. #denatechcon   ΍͍ͬͯΔ͜ͱ·ͱΊ Ξ΢τήʔϜ ୯ମςετ͠΍͍͢ઃܭύλʔϯͷ໛ࡧͱܗࣜԽɻ ݱ ࡏ 
 ໛

    ࡧ த ΠϯήʔϜ ݁߹όάͷςετΛॻ͖΍͘͢͢ΔͨΊͷ޻෉
 ʢঢ়ଶ࠶ݱͷ؆қԽͱมߋ΁ͷݎ࿚Խʣͱɺ
 ίʔυͰදݱ͠΍͍͢ײੑͷࢦඪͷ໛ࡧͱܗࣜԽɻ
  17. #denatechcon   ͔͜͜Β͸໛ࡧதͷ࿩ʹͳΓ·͢ ݱ ࡏ 
 ໛ ࡧ த

    ܗࣜख๏ͷΞϓϩʔν΍ίʔυʹΠέͯͳ͍෦෼͕
 ͋Δ͔΋͠Ε·ͤΜ͕ɺ໛ࡧதͳͷͰ͝༰͍ࣻͩ͘͞
  18. #denatechcon   Ϙεͷߦಈύλʔϯͷ࢓༷ɿ w )1͕ҎԼͳΒม਎ w )1͕ʹͳͬͨΒࢮ๢ ͜ͷ࢓༷ʹ͸ߟྀ࿙Εͷ໰୊͕͋Δɻ ήʔϜʹ͓͚Δ࢓༷ͷ໰୊ͷྫ

    ݱ ࡏ 
 ໛ ࡧ த ΋͠ɺҰܸͰ)1͕ʹ͞Εͯ͠·ͬͨΒɺ
 ม਎͢ΔͷͩΖ͏͔ɺ͠ͳ͍ͷͩΖ͏͔ʜʁ ͜Ε͕ߟྀ͞Ε͍ͯͳ͍ͷͰɺม਎͔ͯ͠Β
 ࢮ๢͢Δͷ൱͔͕໌֬Ͱ͸ͳ͍
  19. #denatechcon   Ϙεͷߦಈύλʔϯͷ࢓༷ɿ w )1͕ҎԼͳΒม਎ w )1͕ʹͳͬͨΒࢮ๢ ͜ͷ࢓༷ʹ͸ߟྀ࿙Εͷ໰୊͕͋Δɻ ήʔϜʹ͓͚Δ࢓༷ͷ໰୊ͷྫ

    ݱ ࡏ 
 ໛ ࡧ த ͜ͷ࣌఺Ͱاըऀ͸ɺϘε͸ม਎͔ͯ͠Β
 ࢮ๢͢Δ͜ͱΛظ଴͍ͯ͠Δͱ͢Δ ͨͩɺ࢓༷ͷᐆດ͞ʹ·ͩؾ͚͓ͮͯΒͣ
 ߟྀ͔Β࿙Ε͍ͯΔঢ়گΛԾఆ͢Δ
  20. #denatechcon   mtype:bossMode = { Normal, Transformed } mtype:bossHp

    = { Full, GreaterThanHalf, LessThanHalf, Dead } inline Attack(bossHp) { if :: (bossHp > Dead) -> bossHp = bossHp - 1 :: (bossHp > LessThanHalf) -> bossHp = bossHp - 2 :: (bossHp > GreaterThanHalf) -> bossHp = bossHp - 3 fi } ݱ ࡏ 
 ໛ ࡧ த
  21. #denatechcon   mtype:bossMode = { Normal, Transformed } mtype:bossHp

    = { Full, GreaterThanHalf, LessThanHalf, Dead } inline Attack(bossHp) { if :: (bossHp > Dead) -> bossHp = bossHp - 1 :: (bossHp > LessThanHalf) -> bossHp = bossHp - 2 :: (bossHp > GreaterThanHalf) -> bossHp = bossHp - 3 fi } ݱ ࡏ 
 ໛ ࡧ த Ϙεͷঢ়ଶͷఆٛɻ௨ৗͱม਎ޙͷ͕ͭ͋Δ
  22. #denatechcon   mtype:bossMode = { Normal, Transformed } mtype:bossHp

    = { Full, GreaterThanHalf, LessThanHalf, Dead } inline Attack(bossHp) { if :: (bossHp > Dead) -> bossHp = bossHp - 1 :: (bossHp > LessThanHalf) -> bossHp = bossHp - 2 :: (bossHp > GreaterThanHalf) -> bossHp = bossHp - 3 fi } ݱ ࡏ 
 ໛ ࡧ த Ϙεͷ)1ͷఆٛɻϑϧɺ൒෼Ҏ্ɺ൒෼ҎԼɺࢮ๢ͷ͕ͭ͋Δ
  23. #denatechcon   mtype:bossMode = { Normal, Transformed } mtype:bossHp

    = { Full, GreaterThanHalf, LessThanHalf, Dead } inline Attack(bossHp) { if :: (bossHp > Dead) -> bossHp = bossHp - 1 :: (bossHp > LessThanHalf) -> bossHp = bossHp - 2 :: (bossHp > GreaterThanHalf) -> bossHp = bossHp - 3 fi } ݱ ࡏ 
 ໛ ࡧ த ඃ߈ܸʹΑΔϘεͷ)1มԽɻ͜ͷJGจͷҙຯ͸ී௨ͷݴޠͱ͸ҟͳΓɺ
 ׅހ಺ͷ৚݅Λຬͨ͢ʮ͍ͣΕ͔ʯͷจ͕࣮ߦ͞ΕΔͱ͍͏͜ͱɻͲΕ͕
 ࣮ߦ͞ΕΔ͔͸ඇܾఆతʹͳ͍ͬͯΔʢμϝʔδྔ͕೚ҙͳ͜ͱΛදݱʣ
  24. #denatechcon   ݱ ࡏ 
 ໛ ࡧ த active

    proctype Battle() { mtype:bossMode bossMode = Normal mtype:bossHp bossHp = Full do :: Attack(bossHp) od assert false } // TODO: ͜͜ʹ͸ότϧͷࢮ๢/ม਎൑ఆΛهड़͢Δɻ // ͜͜ʹ͸ 2 ௨Γͷॻ͖ํ͕͋Δɻ
  25. #denatechcon   active proctype Battle() { mtype:bossMode bossMode =

    Normal mtype:bossHp bossHp = Full do :: Attack(bossHp) od assert false } // TODO: ͜͜ʹ͸ότϧͷࢮ๢/ม਎൑ఆΛهड़͢Δɻ // ͜͜ʹ͸ 2 ௨Γͷॻ͖ํ͕͋Δɻ ࣮ࡍͷότϧͷྲྀΕͷఆٛ ݱ ࡏ 
 ໛ ࡧ த
  26. #denatechcon   active proctype Battle() { mtype:bossMode bossMode =

    Normal mtype:bossHp bossHp = Full do :: Attack(bossHp) od assert false } // TODO: ͜͜ʹ͸ότϧͷࢮ๢/ม਎൑ఆΛهड़͢Δɻ // ͜͜ʹ͸ 2 ௨Γͷॻ͖ํ͕͋Δɻ ॳظঢ়ଶͷϘεΛɺະม਎ɺ)1ϑϧʹઃఆɻ ݱ ࡏ 
 ໛ ࡧ த
  27. #denatechcon   active proctype Battle() { mtype:bossMode bossMode =

    Normal mtype:bossHp bossHp = Full do :: Attack(bossHp) od assert false } // TODO: ͜͜ʹϘεͷࢮ๢/ม਎൑ఆΛهड़͢Δɻ // ͦΕͧΕͷ൑ఆͷॱংͰ 2 ௨Γͷॻ͖ํ͕͋Δɻ ߈ܸΛ܁Γฦ͢ϧʔϓʢ50%0෦෼ͰCSFBL͞ΕΔ·Ͱ܁Γฦ͢ʣ ݱ ࡏ 
 ໛ ࡧ த
  28. #denatechcon if :: (bossHp == Dead) -> break :: else

    -> skip fi   ݱ ࡏ 
 ໛ ࡧ த Ϙεͷ)1͕ %FBEঢ়ଶʣͳΒ߈ܸΛऴྃ͢Δ൑ఆ ࢮ๢൑ఆ ม਎൑ఆ if :: (bossHp <= LessThanHalf) -> bossMode = Transformed :: else -> skip fi Ϙεͷ)1͕ͳΒม਎͢Δ൑ఆ
  29. #denatechcon if :: (bossHp == Dead) -> break :: else

    -> skip fi if :: (bossHp <= LessThanHalf) -> bossMode = Transformed :: else -> skip fi   ݱ ࡏ 
 ໛ ࡧ த ࢮ๢൑ఆΛઌʹ͢Δ৔߹ɿ if :: (bossHp <= LessThanHalf) -> bossMode = Transformed :: else -> skip fi 
 if :: (bossHp == Dead) -> break :: else -> skip fi ม਎൑ఆΛઌʹ͢Δ৔߹ɿ ࢮ๢൑ఆ ม਎൑ఆ ࢮ๢൑ఆ ม਎൑ఆ
  30. #denatechcon if :: (bossHp == Dead) -> break :: else

    -> skip fi if :: (bossHp <= LessThanHalf) -> bossMode = Transformed :: else -> skip fi   ݱ ࡏ 
 ໛ ࡧ த ࢮ๢൑ఆΛઌʹ͢Δ৔߹ɿ if :: (bossHp <= LessThanHalf) -> bossMode = Transformed :: else -> skip fi 
 if :: (bossHp == Dead) -> break :: else -> skip fi ม਎൑ఆΛઌʹ͢Δ৔߹ɿ ࢮ๢൑ఆ ม਎൑ఆ ࢮ๢൑ఆ ม਎൑ఆ ͪ͜ΒΛࢼ͢
  31. #denatechcon   active proctype Battle() { mtype:bossMode bossMode =

    Normal mtype:bossHp bossHp = Full do :: Attack(bossHp) if :: (bossHp == Dead) -> break :: else -> skip fi if :: (bossHp <= LessThanHalf) -> bossMode = Transformed :: else -> skip fi od assert false } ݱ ࡏ 
 ໛ ࡧ த 50%0෦෼Λࢮ๢൑ఆɺม਎൑ఆͷॱͰهड़
  32. #denatechcon   active proctype Battle() { mtype:bossMode bossMode =

    Normal mtype:bossHp bossHp = Full do :: Attack(bossHp) if :: (bossHp == Dead) -> break :: else -> skip fi if :: (bossHp <= LessThanHalf) -> bossMode = Transformed :: else -> skip fi od assert false } গ͠ճΓ͘Ͳ͍͕ɺৗʹΤϥʔͰऴྃͤ͞Δ͜ͱͰϘεͷঢ়ଶ͕
 ͲͷΑ͏ʹҠΓมΘΔ͔ΛπʔϧͰྻڍͰ͖Δ ݱ ࡏ 
 ໛ ࡧ த
  33. #denatechcon   $ spin -a -o2 ./boss-batle.pml $ gcc

    -DREACH -o pan pan.c $ ./pan -c0 -e
 ... State-vector 20 byte, depth reached 17, errors: 4
 ... 1SPNFMBʹରԠ͢Δ࢓༷νΣοΫπʔϧ4QJOͰ
 ܗࣜԽͨ͠ϘεઓͷͱΓ͏Δঢ়ଶભҠͷҰཡΛܭࢉ͢Δ ݱ ࡏ 
 ໛ ࡧ த BTTFSUʹҾ͔͔ͬͬͨܦ࿏͕ͭ͋ΔͷͰɺঢ়ଶભҠ͸ܦ࿏͋ΔͱΘ͔Δ
  34. #denatechcon   $ spin -t1 -p boss-battle.pml using statement

    merging 1: ... boss-battle.pml:7 ... [((bossHp>1))] 2: ... boss-battle.pml:7 ... [bossHp = (bossHp-1)] ... 16: ... boss-battle.pml:30 ... [assert(((bossMode!=2)&&(boss spin: trail ends after 16 steps #processes: 1 bossMode = Transformed bossHp = Dead ܦ࿏Λͭͣͭ֬ೝ͢ΔɻUͷޙͷ਺ࣈ͕ܦ࿏ͷ൪߸Λҙຯ͍ͯ͠Δ ݱ ࡏ 
 ໛ ࡧ த
  35. #denatechcon   $ spin -t1 -p boss-battle.pml using statement

    merging 1: ... boss-battle.pml:7 ... [((bossHp>1))] 2: ... boss-battle.pml:7 ... [bossHp = (bossHp-1)] ... 16: ... boss-battle.pml:30 ... [assert(((bossMode!=2)&&(boss spin: trail ends after 16 steps #processes: 1 bossMode = Transformed bossHp = Dead ͜ͷܦ࿏͕ͲͷΑ͏ͳঢ়ଶΛܦ༝͔ͨ͠ͷৄࡉɻӈଆ͸࣮ߦ͞Εͨίʔυ ݱ ࡏ 
 ໛ ࡧ த
  36. #denatechcon   $ spin -t1 -p boss-battle.pml using statement

    merging 1: ... boss-battle.pml:7 ... [((bossHp>1))] 2: ... boss-battle.pml:7 ... [bossHp = (bossHp-1)] ... 16: ... boss-battle.pml:30 ... [assert(((bossMode!=2)&&(boss spin: trail ends after 16 steps #processes: 1 bossMode = Transformed bossHp = Dead ࠷ऴతͳϘεͷঢ়ଶɻม਎ࡁΈ͔ͭࢮ๢͍ͯ͠Δ͜ͱ͕Θ͔Δ ݱ ࡏ 
 ໛ ࡧ த
  37. #denatechcon   $ spin -t2 -p boss-battle.pml using statement

    merging 1: ... boss-battle.pml:9 (state 5) [((bossHp>3))] 2: ... boss-battle.pml:9 (state 6) [bossHp = (bossHp-3)] 3: ... boss-battle.pml:20 (state 10) [((bossHp==1))] ... 4: ... boss-battle.pml:30 (state 25) [assert(((bossMode!=2 spin: trail ends after 4 steps #processes: 1 bossMode = Normal bossHp = Dead ॱʹ֬ೝ͍͖ͯ͠ɺ൪໨ͷܦ࿏Λ֬ೝ͢Δ ݱ ࡏ 
 ໛ ࡧ த
  38. #denatechcon   $ spin -t2 -p boss-battle.pml using statement

    merging 1: ... boss-battle.pml:9 (state 5) [((bossHp>3))] 2: ... boss-battle.pml:9 (state 6) [bossHp = (bossHp-3)] 3: ... boss-battle.pml:20 (state 10) [((bossHp==1))] ... 4: ... boss-battle.pml:30 (state 25) [assert(((bossMode!=2 spin: trail ends after 4 steps #processes: 1 bossMode = Normal bossHp = Dead ߟྀͰ͖͍ͯͳ͔ͬͨɺϘε͕ม਎͠ͳ͍··
 ࢮ๢͢Δܦ࿏Λൃݟʢܦ࿏΋ม਎͠ͳ͍ʣ ݱ ࡏ 
 ໛ ࡧ த
  39. #denatechcon   $ spin -t2 -p boss-battle.pml using statement

    merging 1: ... boss-battle.pml:9 (state 5) [((bossHp>3))] 2: ... boss-battle.pml:9 (state 6) [bossHp = (bossHp-3)] 3: ... boss-battle.pml:20 (state 10) [((bossHp==1))] ... 4: ... boss-battle.pml:30 (state 25) [assert(((bossMode!=2 spin: trail ends after 4 steps #processes: 1 bossMode = Normal bossHp = Dead ঢ়ଶભҠͷաఔ͔ΒݪҼΛ୳ΔͱɺϘεΛҰܸͰ
 ౗ͨ͠ͱ͜Ζߟྀ͍ͯ͠ͳ͍ঢ়ଶͳͬͨ͜ͱ͕Θ͔Δ ݱ ࡏ 
 ໛ ࡧ த
  40. #denatechcon   active proctype P() { mtype:bossMode bossMode =

    Normal mtype:bossHp bossHp = Full do :: Attack(bossHp) if :: (bossHp == Dead) -> break :: else -> skip fi if :: (bossHp <= LessThanHalf) -> bossMode = Transformed :: else -> skip fi od assert false } ݱ ࡏ 
 ໛ ࡧ த ઌ΄ͲܗࣜԽͨ͠࢓༷Ͱ͸ɺϘεͷม਎൑ఆͷલʹ
 Ϙεͷࢮ๢Λ൑ఆ͢Δ͜ͱʹ͍ͯͨͨ͠ΊɺҰܸͰ
 Ϙε͕౗͞Εͨ৔߹ʹະม਎ʹͳΔ
  41. #denatechcon   active proctype P() { mtype:bossMode bossMode =

    Normal mtype:bossHp bossHp = Full do :: Attack(bossHp) if :: (bossHp <= LessThanHalf) -> bossMode = Transformed :: else -> skip fi if :: (bossHp == Dead) -> break :: else -> skip fi od assert false } ݱ ࡏ 
 ໛ ࡧ த ม਎൑ఆΛࢮ๢൑ఆͷલʹҠಈ͢Δͱߟྀ࿙ΕΛͳͤ͘Δ ͜͜Ͱঢ়ଶͷྻڍΛ͢Δͱɺ͢΂ͯม਎ࡁΈͰࢮ๢͢Δ͜ͱ͕
 Θ͔ΔͷͰɺߟྀ࿙ΕͷղܾΛ֬ೝͰ͖Δ
  42. #denatechcon   ΍͍ͬͯΔ͜ͱ·ͱΊ ݱ ࡏ 
 ໛ ࡧ த

    ܗࣜख๏ʹΑͬͯɺήʔϜ࢓༷ॻͷߟྀ࿙ΕͳͲΛ
 Ͳ͜·Ͱݕ஌Ͱ͖Δ͔Λ࣮ݧ͍ͯ͠Δɻܗࣜख๏ͷछྨ͸
 ଟ͍ͨΊɺ͞·͟·ͳख๏Λ࣮ݧ͢Δ༧ఆɻ ࠷ऴతʹ͸ɺܗࣜख๏Λ࢖͏ͱɺͲͷఔ౓ͷίετͰ
 Ͳͷఔ౓ख໭ΓΛ๷͛Δ͔ͱ͍͏අ༻ରޮՌΛݕূ͍ͨ͠ɻ
  43. #denatechcon   Ξ΢τήʔϜͱΠϯήʔϜͷࠩ ݱ ࡏ 
 ໛ ࡧ த

    w Ξ΢τήʔϜ͸ײੑʹΑΒͳ͍ݕূʹ͠΍͍͢ w ྫಋઢͷ༗ޮੑͷݕূ͸ײੑʹΑΒͳ͍ w Ξ΢τήʔϜ͸৚݅෼ذΛू໿͠΍͍͢ w ྫΠϕϯτ΍ΫΤετҰཡͷߜΓࠐΈΛ૝ఆ
  44. #denatechcon   ΠϯήʔϜͷςετ͠΍͢͞ʹ͍ͭͯ ݱ ࡏ 
 ໛ ࡧ த

    ଟ͘ͷήʔϜͰ͸ͭͷίϯϙʔωϯτʹϩδοΫΛ
 ڽूͮ͠Β͍͜ͱ͕ଟ͘ɺ୯ମͰςετͯ͠΋
 ҙຯͷͳ͍͜ͱ͕ଟ͍ɻ ྫͱͯ͠ɺ෺ཧγϛϡϨʔγϣϯΛؚΉήʔϜΛߟ͑Δɻ
  45. #denatechcon   ෺ཧγϛϡϨʔγϣϯΛؚΉήʔϜͷ໰୊ ݱ ࡏ 
 ໛ ࡧ த

    ࣮ࡍʹ6OJUZͰ͘͝୯७ͳ෺ཧγϛϡϨʔγϣϯ෇͖ͷήʔϜΛ ୯ମςετͨ͠ͱ͜Ζɺ࣍ͷ໰୊Λൃݟͨ͠ɻ ෺ཧγϛϡϨʔγϣϯͰ͸ɺ͋ΔΦϒδΣΫτͷҐஔ࠲ඪΛ
 ಡΈॻ͖͢Δίϯϙʔωϯτ͕ଟ͋͘Δɿ w িಥ൑ఆϩδοΫ w ྗֶܭࢉΤϯδϯ w ΦϒδΣΫτʹ෇ਵ͢Δॲཧʢೖྗૢ࡞΁ͷ൓ԠͳͲʣ
  46. #denatechcon   ݱ ࡏ 
 ໛ ࡧ த িಥ൑ఆϩδοΫͱྗֶܭࢉΤϯδϯ

    ήʔϜΤϯδϯ΁ͷઃఆʹऴ࢝͢Δʢ෼ذ΍ϧʔϓ͕ͳ͍ʣ
 ͨΊɺ୯ମςετͰݕূ͢ΔՁ஋͸ͳ͍ɻ ෇ਵॲཧ ୯७ͳ͜ͱ͕ଟ͍͏͑ʹɺ୯ମͰͷόάΑΓ݁߹Ͱͷ
 όάʢนൈ͚΍นΊΓࠐΈ͔Βͷਧ͖ඈͼͳͲʣͷํ͕
 ࢧ഑తͰɺ୯ମςετͷϝϦοτΑΓίετͷํ͕উΔɻ ෺ཧγϛϡϨʔγϣϯབྷΈͷ୯ମςετͷՁ஋
  47. #denatechcon   ݱ ࡏ 
 ໛ ࡧ த 

    ͕࣌ؒܦͭ΄ͲৄࡉΛ๨ΕΔ  ༨ܭͳίϛϡχέʔγϣϯ͕૿͑Δ  ࢓༷ͷख໭Γ͸ޙଓλεΫΛϒϩοΫ͢Δ ख໭ΓʹΑΔੜ͡Δ໰୊
  48. #denatechcon   ݱ ࡏ 
 ໛ ࡧ த ͕࣌ؒܦͭ΄ͲৄࡉΛ๨ΕΔ

    ͜͜Θ͔Βͳ͍ͷͰ͕͢
 Ͳ͏͍͏ҙຯͰ͢ʁ ઌिߟ͑ͯͨ΍͚ͭͩͲɺ
 ͲΜͳҙຯ͚ͩͬͨͬʜʁ ࢓༷ಡΜͩਓ ࢓༷هड़ऀ
  49. #denatechcon   ݱ ࡏ 
 ໛ ࡧ த ༨ܭͳίϛϡχέʔγϣϯ͕૿͑Δ

    ͜Εໃ६ͯ͠·ͤΜ͔ʁ Ͳ͜ͷ͜ͱͰ͠ΐ͏͔ʁ ࢓༷ಡΜͩਓ ࢓༷هड़ऀ ͜ͷ"ͱ#Ͱ͕͢ʜ
  50. #denatechcon   ݱ ࡏ 
 ໛ ࡧ த ࢓༷ͷख໭Γ͸ޙଓλεΫΛϒϩοΫ͢Δ

    اը ࣮૷ ϨϏϡʔ ςετ࡞੒ ख໭ΓରԠ ࢓༷͕ݻ·Δ·Ͱ࡞ۀͮ͠Β͍ اը ։ൃ 2" தஅ தஅ ࣮૷ ςετ࡞੒
  51. #denatechcon   $ spin -a -o2 ./boss-batle.pml $ gcc

    -DREACH -o pan pan.c $ file ./pan pan: Mach-O 64-bit executable x86_64 1SPNFMB͸ɺݕࠪ΍ՄࢹԽͷͨΊͷπʔϧͰ͋Δ
 4QJOͰղੳͰ͖Δɻ4QJOΛ࣮ߦ͢Δͱ$ͷίʔυ͕
 ੜ੒͞ΕΔͷͰɺίϯύΠϧ࣮ͯ͠ߦͰ͖ΔΑ͏ʹ͢Δ ੜ੒͢ΔόΠφϦ͸QBOͱ͍͏׳ྫతͳ໊લʹ͢Δ͜ͱ͕ଟ͍
 ʢQBO͸1SPUPDPM"/BMZ[FSͩͬͨͱ͍͏ྺ࢙తܦҢ͕͋Δʣ ݱ ࡏ 
 ໛ ࡧ த
  52. #denatechcon   $ ./pan -D digraph p_Battle { size="8,10";

    GT [shape=box,style=dotted,label="Battle"]; GT -> S22; S22 -> S2 [color=black,style=bold,label="( S22 -> S4 [color=black,style=bold,label="( S22 -> S6 [color=black,style=bold,label="( ... QBO͔Βঢ়ଶભҠਤΛEPUܗࣜͰग़ྗͰ͖Δ ݱ ࡏ 
 ໛ ࡧ த
  53. #denatechcon   EPUܗࣜͷਤ͸(SBQIWJ[ͰඳըͰ͖Δ ભҠલͷঢ়ଶ 4 4 YYY ঢ়ଶભҠΛൃੜͤͨ͞ίʔυ ঢ়ଶ

    ঢ়ଶભҠͷ໼ҹ
 ʢઢͷࡉ͞͸ࣗಈੜ੒Λҙຯʣ ભҠޙͷঢ়ଶ ੜ੒͞Εͨঢ়ଶભҠਤͷಡΈํ ݱ ࡏ 
 ໛ ࡧ த