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

MIXI TECH NOTE #10

MIXI TECH NOTE #10

#技術書典15 に出典された、MIXI GROUP エンジニア有志による技術書です。

<< 目次 >>
1章:UEFN で始める Verse チョットデキル入門
2章:爆速で Approve がもらえる Pull Request の作り方
3章:Haskell で線形型
4章:Flutter test 戦略
5章:漫画作品から考えるテスト観点
6章:マルチプレイゲームは何を通信しているか

<< TECH NOTE 一覧 >>
mixi tech note #01
https://speakerdeck.com/mixi_engineers/mixi-tech-note-number-01

mixi tech note #02
https://speakerdeck.com/mixi_engineers/mixi-tech-note-number-02

mixi tech note #03
https://speakerdeck.com/mixi_engineers/mixi-tech-note-number-03

mixi tech note #04
https://speakerdeck.com/mixi_engineers/mixi-tech-note-number-04

mixi tech note #05
https://speakerdeck.com/mixi_engineers/mixi-tech-note-number-05

mixi tech note #06
https://speakerdeck.com/mixi_engineers/mixi-tech-note-number-06

mixi tech note #07
https://speakerdeck.com/mixi_engineers/mixi-tech-note-number-07

MIXI TECH NOTE #08
https://speakerdeck.com/mixi_engineers/mixi-tech-note-number-08

MIXI TECH NOTE #09
https://speakerdeck.com/mixi_engineers/mixi-tech-note-number-09

MIXI TECH NOTE #10
https://speakerdeck.com/mixi_engineers/mixi-tech-note-number-10

XFLAG Tech Note Vol.01
https://speakerdeck.com/mixi_engineers/xflag-tech-note-vol-dot-01

XFLAG Tech Note vol.02
https://speakerdeck.com/mixi_engineers/xflag-tech-note-vol-dot-02

MIXI ENGINEERS

November 11, 2023
Tweet

More Decks by MIXI ENGINEERS

Other Decks in Technology

Transcript

  1. ·͕͖͑ ຊॻʮMIXI TECH NOTE #10ʯ͸ɺMIXI GROUP ʹॴଐ͢Δ༗ࢤୡʹΑͬͯࣥචɾ੍࡞͞Εٕͨ ज़ॻͰ͢ɻ࣮ࡍͷݱ৔Ͱ࢖ΘΕٕͨज़΍ߟ͑ํɺ·ͨɺݸਓతʹڵຯɾؔ৺ͷ͋Δ෼໺͔Βɺࢥ͍ࢥ ͍ʹࣥච͍ͨ͠·ͨ͠ɻͦͷͨΊɺ֤ষͦΕͧΕͰ׬͍݁ͯ͠Δ಺༰ʹͳ͍ͬͯ·͢ͷͰɺ޷͖ͳষ ͔Β޷͖ͳॱ൪Ͱָ͓͠Έ͍ͩ͘͞ɻ

    ·ͨɺຊॻ͸ɺMIXI GROUP ʹ͋Δٕज़త஌ݟ΍ΞΠσΞΛੵۃతʹڞ༗ɾެ։͍ͯ͘͜͠ͱ ͰɺੈͷதʹΑΓྑ͍αʔϏε͕ҲΕग़͢͜ͱΛئͬͯץߦ͞Ε͍ͯ·͢ɻܝࡌ͞Ε͍ͯΔ৘ใ͸ɺ ࣥචऀࣗ਎ͷ؀ڥͰݕূࣥ͠ච͞Εͨ΋ͷͰ͢ͷͰɺ͝ࢀߟʹ͞ΕΔࡍ͸ɺࣗ͝਎ͷ੹೚Ͱ൑அ͠ ͝׆༻͍ͩ͘͞ɻͳ͓ɺจষදݱʹ͖ͭ·ͯ͠΋ɺࣥචऀࣗ਎ͷݴ༿Ͱ఻͑ͨ͘ɺϑϥϯΫͳදݱͱ ͳ͓ͬͯΓ·͢͜ͱ͝ཧղ͍͚ͨͩΕ͹ͱࢥ͍·͢ɻ σΟϕϩούʔϦϨʔγϣϯζνʔϜҰಉ ˗ຊॻʹؔ͢Δ͓໰͍߹Θͤઌ ɹ https://twitter.com/mixi_engineers ˗ MIXI GROUP ʹ͍ͭͯ ɹ https://mixi.co.jp/ ˞ MIXI ͷ໊শɺ͜Εʹؔ࿈͢Δ঎ඪٴͼϩΰ͸ɺגࣜձࣾ MIXI ͷ঎ඪٴͼొ࿥঎ඪͰ͢ɻ·ͨɺ ֤ࣾͷձ໊ࣾɺαʔϏεٴͼ੡඼ͷ໊শ͸ɺͦΕͧΕͷॴ༗͢Δ঎ඪ·ͨ͸ొ࿥঎ඪͰ͢ɻ iii
  2. ໨࣍ ·͕͖͑ iii ୈ 1 ষ UEFN Ͱ࢝ΊΔ Verse ŧŔŕŪũƄŝſೖ໳

    1 1.1 ࢝Ίʹ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.2 Verse ʹ͍ͭͯ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.3 Verse ͸ॳֶऀ޲͚ͳͷ͔ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.4 UEFN ʹ͓͚Δ Verse ͱઃܭͱ͸ . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.5 Verse ܕ༡ͼೖ໳ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 1.6 ऴΘΓʹ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 ୈ 2 ষ ര଎Ͱ Approve ͕΋Β͑Δ Pull Request ͷ࡞Γํ 15 2.1 ·͕͖͑ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.2 ϨϏϡʔ͠΍͍͢ Pull Request . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.3 ϨϏϡʔʹઐ೦ͯ͠ؾ෇͍ͨ͜ͱ . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 2.4 ͋ͱ͕͖ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 ୈ 3 ষ Haskell Ͱઢܗܕ 25 3.1 Haskell ͷઢܗܕ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 3.2 ࢼ͢ɿιʔτ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 3.3 ऴΘΓʹ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 ୈ 4 ষ Flutter test ઓུ 35 4.1 ޮ཰తͳࣗಈςετͷߏ੒ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 4.2 Ϣχοτςετ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 4.3 ΠϯςάϨʔγϣϯςετ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 4.4 ऴΘΓʹ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 ୈ 5 ষ ອը࡞඼͔Βߟ͑Δςετ؍఺ 41 5.1 ࢝Ίʹ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 5.2 ໰୊ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 5.3 ղ౴ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 v
  3. ໨࣍ 5.4 ղ౴Λ͞Βʹਂ۷Γ͢Δ . . . . . . .

    . . . . . . . . . . . . . . . . . . . . . . . . . 44 5.5 ·ͱΊ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 ୈ 6 ষ ϚϧνϓϨΠήʔϜ͸ԿΛ௨৴͍ͯ͠Δ͔ 49 6.1 0 A. D. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 6.2 Battle for Wesnoth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 6.3 OpenRA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 6.4 Quake III Arena . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 6.5 ·ͱΊ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 ஶऀ঺հ 55 vi
  4. ୈ 1 ষ UEFN Ͱ࢝ΊΔ Verse ŧŔŕŪũƄŝſೖ໳ 1.1 ࢝Ίʹ ຊষͰ͸ɺEpic

    Games ͕ࣾఏڙ͢Δ Unreal Editor for Fortnite(Ҏ߱ UEFN) Ͱ࢖༻͞Ε͍ͯΔ ϓϩάϥϛϯάݴޠʮVerseʯʹ͍ͭͯେن໛։ൃ΍ܧଓతͳ։ൃΛߟྀ͢Δࡍʹඞཁͳߟ͑ํ΍࣮ ૷ʹ͍ͭͯ঺հ͠·͢ɻ ˙ ର৅ಡऀ • ΤϯδχΞͰ UEFN ʹڵຯ͕͋Δํ • UEFN Ͱ Verse Λ࢖ͬͨ։ൃʹڵຯ͕͋Δํ • Verse ͰόϦόϦ։ൃ͍ͯ͠Δํ ˙ ஫ҙࣄ߲ • UEFN ͸සൟʹΞοϓσʔτ͕ߦΘΕ͓ͯΓɺഁյతͳมߋ΋ଘࡏ͢ΔͨΊ͜͜ʹॻ͍ͯ͋ Δ͜ͱͷ͢΂ͯͷಈ࡞Λอূ͢Δ͜ͱ͸Ͱ͖·ͤΜ • ಈ࡞͸͢΂ͯࣥච࣌ͷ؀ڥͰߦ͓ͬͯΓɺ΋͠ڍಈ͕͓͔͍͠৔߹͸ެࣜͷυΩϡϝϯτ΍ ϑΥʔϥϜͳͲΛ͝ࢀর͍ͩ͘͞ • චऀ͸ۀ຿Ͱ UEFN ΍ Verse Λ࢖͍ͬͯΔ༁Ͱ͸ͳ͘झຯͰ։ൃ͍ͯ͠ΔͨͩͷਓؒͰ͢ • UEFN ΍ϑΥʔτφΠτʹ͍ͭͯͷઆ໌͸ಛʹ͠·ͤΜ 1.2 Verse ʹ͍ͭͯ ຊষΛಡΜͰ͍Δํͷதʹ͸ Fortnite ΋ UEFN ΋৮Εͨ͜ͱͷͳ͍ΤϯδχΞͷํ΋ଟ͍͘Βͬ ͠ΌΔͱࢥ͏ͷͰܰ֓͘ཁΛઆ໌͠·͢ɻ ˞͜ͷ͋ͨΓ͸΋͏ಡΈ๞͖ͨͥʂ ͬͯݴ͏ํ͸ಡΈඈ͹͍ͯͩ͘͠͞ʂ Verse ͸ Epic Games ͕։ൃ͍ͯ͠ΔϓϩάϥϛϯάݴޠͰɺެࣜυΩϡϝϯτͰ͸ҎԼͷΑ͏ͳ 1
  5. ୈ 1 ষ UEFN Ͱ࢝ΊΔ Verse ŧŔŕŪũƄŝſೖ໳ 1.2 Verse ʹ͍ͭͯ

    ಛ௃͕͋Δͱ͞Ε͍ͯ·͢ɻ ࠷༏ઌͷઃܭࢥ૝ • ϓϩάϥϛϯάॳֶऀֶ͕Ϳͷʹద͍ͯ͠Δγϯϓϧ͞ • ͋ΒΏΔσʔλ΍ίʔυΛදݱͰ͖Δ൚༻ੑ • ੜ࢈తͳΠςϨʔγϣϯ΍Ϛοϓߏஙɺग़ՙ͕Մೳ • ϥϯλΠϜͰͷ໰୊ΛݮΒͨ͢ΊʹίϯύΠϧ࣌ͷ੩తղੳ • ϦΞϧλΠϜɺΦʔϓϯϫʔϧυɺϚϧνϓϨΠϠʔήʔϜ͕࡞ΕΔύϑΥʔϚϯε • ֤ػೳΛந৅తʹૢ࡞Ͱ͖ΔΑ͏ʹ࣮૷͞Ε͓ͯΓϓϩάϥϚʔ͸ৄࡉͷ࣮૷Λҙࣝ͢Δ͜ͱ ͳ͘ߴϨϕϧͷ࣮૷Ͱ։ൃ͕Ͱ͖Δ • աڈͷࢿ࢈ʹݻࣥͤͣݱࡏͷχʔζ͚ͩͰͳ͘কདྷͷχʔζʹ΋దͨ͠ઃܭ Verse ͷಛ௃ • ։ൃ΍σϓϩΠͷλΠϛϯάͰΤϥʔΛݕ஌Ͱ͖ΔΑ͏ʹڧ͍ܕΛ࣋ͪ੩తνΣοΫΛα ϙʔτ • ؔ਺ܕϓϩάϥϛϯά΍ΦϒδΣΫτࢦ޲ϓϩάϥϛϯάɺ໋ྩܕϓϩάϥϛϯάͷ࠷ྑͷཁ ૉ͕٧Ίࠐ·Ε͍ͯ·͢ • σʔλ͸σϑΥϧτͰ immutable(ෆม) Ͱ͋Γಉ͡ೖྗͰ͋Ε͹ಉ͡ग़ྗͰ͋Δ͜ͱΛอূ ͍ͯ͠·͢ (Ұ෦ྫ֎తͳ࣮૷Λআ͖) • Verse ʹ͓͍ͯจͱࣜʹҧ͍͸ͳ͘ɺ͢΂͕ͯࣜͱͯ͠ѻΘΕΔͨΊ͢΂ͯʹ݁Ռ͕ଘࡏ͠ ·͢ • ࣦഊՄೳࣜ͸ࣦഊίϯςΩετͰͷΈ࢖༻Ͱ͖ɺࣦഊࣗମ੍͕ޚϑϩʔΛ୲౰͠·͢ɻͭ·Γ if จͷதͰΤϥʔ͕ൃੜͨ͠৔߹ else ʹॲཧ͕ϑΥʔϧόοΫ͞Ε·͢ • ࣦഊՄೳࣜ͸Ծ૝తʹॲཧ͕ߦΘΕɺ੒ޭ͢Δ͜ͱͰॲཧ͕֬ఆ͠·͢ɻٯΛݴ͑͹ࣦഊ͞ ΕΔݶΓࣦഊίϯςΩετ಺ʹ͓͍ͯॲཧ͸ϩʔϧόοΫ͞Ε·͢ɻ(ৄ͘͠͸ transacts Τ ϑΣΫτΛࢀর͍ͩ͘͞) • ݴޠϨϕϧͰฒྻॲཧΛαϙʔτ͓ͯ͠Γ૊ࠐΈͷฒྻॲཧࣜͰಉ࣌ʹฒྻॲཧΛ࣮ߦͰ͖ ·͢ ্هͷݴޠઃܭ͸ެࣜυΩϡϝϯτͷ຋༁ͱղऍΛࠞͥͨ΋ͷͳͷͰຊষͰओʹղઆ͢ΔҎԼʹͭ ͍ͯΠϝʔδ͍͚ͨͩΕ͹େৎ෉Ͱ͢ • ڧ͍ܕͱந৅తͳ࣮૷͕Ͱ͖ΔΑ͏ʹઃܭ͞Ε͍ͯΔ͜ͱ • ΦϒδΣΫτࢦ޲ͱؔ਺ܕϓϩάϥϛϯάͷཁૉΛ͍࣋ͬͯΔݴޠͰ͋Δ͜ͱ • ࣦഊίϯςΩετͱ͍͏֓೦͕͋Δ͜ͱ ˞ Verse ͷࡉ͔ͳݴޠ࢓༷͸ެࣜυΩϡϝϯτΛ͝ཡ͍ͩ͘͞ɻ 2
  6. ୈ 1 ষ UEFN Ͱ࢝ΊΔ Verse ŧŔŕŪũƄŝſೖ໳ 1.3 Verse ͸ॳֶऀ޲͚ͳͷ͔

    1.3 Verse ͸ॳֶऀ޲͚ͳͷ͔ ެ͕ࣜಛ௃ͱ͍ͯ͋͛ͯ͠Δ௨Γ Verse ͸ʮॳֶऀ޲͖ʯͳݴޠͱݴ͑·͢ɻ͔͠͠ɺVerse ͸γ ϯϓϧͳݴޠͰ͸͋Δͱಉ࣌ʹֶशίετ͸΄͔ͷݴޠͱ͸ҟͳΔࢥ૝΋ଘࡏ͢ΔͨΊ௿͍ͱ͸ݴ͑ ·ͤΜ ˞ͨͱ͑͹ࣦഊίϯςΩετͩͬͨΓɺม਺ʹ஋͕୅ೖ͞Ε͍ͯͳ͍ঢ়ଶΛ null ͳͲͰදݱͤͣɺ ඇ୅ೖঢ়ଶΛ false Ͱѻ͏ʢoption ܕʣ఺ͳͲ Ͱ͸ͳͥॳֶऀ޲͚ͱݺ͹ΕΔͷ͔ɺͦΕ͸ Verse ͷҎԼͷΑ͏ͳಛ௃͕ڍ͛ΒΕ·͢ ॳֶऀʹͱͬͯͷັྗᶃ: ڧྗͳܕγεςϜͱ੩తղੳ Verse ͸ɺॳֶऀʹͱͬͯ΋ັྗతͳϓϩάϥϛϯάݴޠͰ͢ɻͦͷັྗͷҰͭ͸ɺڧྗͳܕγε ςϜͱ੩తղੳͷ૊Έ߹ΘͤͰ͢ɻ͜ͷ૊Έ߹ΘͤʹΑΓɺ։ൃऀ͸ίʔυΛϥϯλΠϜ؀ڥͰ࣮ߦ ͢Δલʹɺજࡏతͳ໰୊ΛൃݟͰ͖·͢ɻ ܕγεςϜͷݫີͳධՁ Verse ͷڧྗͳܕγεςϜ͸ɺม਺ͷܕΛݫີʹධՁ͠ɺҟͳΔܕͷ஋͕ޡͬͯ୅ೖ͞ΕΔ͜ͱΛ ๷͗·͢ɻͨͱ͑͹ɺ੔਺ܕͷม਺ʹจࣈྻΛ୅ೖ͠Α͏ͱ͢Δ৔߹ɺ੩తղੳʹΑΓ VSCode ্ ͰΤϥʔͱͯ͠ݕग़͞ΕɺϏϧυ͕௨Βͳ͘ͳΓ·͢ɻ͜ΕʹΑΓɺϥϯλΠϜͰͷΤϥʔΛࣄલʹ ݕূ͠ɺमਖ਼͢Δख͕ؒল͔Ε·͢ɻ ·ͨ͜ΕΒͷܕγεςϜ͸੩తղੳʹΑΓΤσΟλ্Ͱ΋Τϥʔ͕֬ೝͰ͖ΔͨΊ։ൃऀ͸ΑΓϥ ϯλΠϜͰͷಈ࡞֬ೝΛݮΒ͢͜ͱ͕Ͱ͖·͢ɻ ˙ίϥϜ: UEFN ʹ͓͚ΔϥϯλΠϜ؀ڥ UEFN ʹ͓͚ΔϥϯλΠϜ؀ڥͱ͸ηογϣϯΛىಈ͠ήʔϜதʹͳͬͨঢ়ଶͷ͜ͱΛࢦ͠ ·͢ɻVerse ͷίʔυࠩ෼͚ͩͷ৔߹͸ʮVerse ͷมߋΛϓογϡʯػೳʹΑΓ͢͹΍͘ϥϯλ ΠϜ؀ڥΛߋ৽Ͱ͖·͕͢ɺ࢓ֻ͚ͷύϥϝʔλΛߋ৽ͨ͠৔߹΍ Verse σόΠεͷ@editable ͷύϥϝʔλΛߋ৽ͨ͠৔߹͸ʮมߋΛϓογϡʯػೳʹΑΓൺֱత௕͍ϩʔυ࣌ؒΛ࢖͏͜ͱ ʹͳΓ·͢ɻ։ൃʹ͓͍ͯ͸͜ͷϩʔυ͕࣌ؒ։ൃεϐʔυΛམͱ͢େ͖ͳཁҼʹͳΓಘ·͢ɻ ॳֶऀʹͱͬͯͷັྗᶄ: ࣦഊίϯςΩετ Verse ʹ͓͍ͯಛ௃తͳػೳͷҰ͕ࣦͭഊίϯςΩετͰ͢ɻଞͷݴޠͰݟΒΕΔΑ͏ͳྫ֎ॲཧ ͸ Verse ʹ͸ଘࡏ͠·ͤΜɻ ʢtry-catch ߏจͷΑ͏ͳʣVerse ʹ͓͍ࣦͯഊ͸੍ޚϑϩʔͰ͋Γɺࣜ ͕"ࣦഊ͢ΔՄೳੑ͕͋Δࣜ"͔Ͳ͏͔ʹΑࣦͬͯഊίϯςΩετͷ࢖͍෼͚͕ඞཁͰ͢ɻ 3
  7. ୈ 1 ষ UEFN Ͱ࢝ΊΔ Verse ŧŔŕŪũƄŝſೖ໳ 1.4 UEFN ʹ͓͚Δ

    Verse ͱઃܭͱ͸ σϑΥϧτͷࣜͰ͸ࣦഊՄೳੑ͸ߟྀ͞Ε͓ͯΒͣɺࣦഊՄೳੑͷ͋Δؔ਺΍ࣜΛهड़͢Δ͜ͱ͸ Ͱ͖·ͤΜʢ഑ྻͷΞΫηε΍ TeleportTo ؔ਺ͷΑ͏ͳʣ ˙ίϥϜ: ଞͷݴޠͷྫ֎ॲཧ - JavaScript ʹ͓͚Δྫ֎ॲཧ JavaScript ʹ͓͚ΔΤϥʔϋϯυϦϯάͷҰͭͷํ๏͸ try-catch ߏจͰ͢ɻtry ϒϩοΫͷ தʹΤϥʔ͕ throw ͞ΕΔ͜ͱʹΑΓ catch ϒϩοΫͷॲཧ͕ݺͼग़͞Ε·͢ɻ try { // Τϥʔ͕ى͜ΓಘΔؔ਺ } catch (e) { // Τϥʔ͕ى͖ͨ࣌ͷॲཧ } ͜ͷ࣮૷͸ଟ͘ͷϓϩάϥϚʔʹͱͬͯ͸ඇৗʹ׳Ε਌͠Μͩॻ͖ํͩͱࢥ͍·͢ɻ͔͜͠͠ ͷ࣮૷͸Τϥʔ͕ى͜ΓಘΔؔ਺Λ try-catch ͰғΘͣͱ΋ॲཧΛهड़Ͱ͖·͢ʢΤϥʔ͸ϥϯ λΠϜͰൃੜ͠૝ఆ֎ͷڍಈΛҾ͖ى͜͠·͢ʣVerse ʹ͓͍ͯ͸੩తղੳͷ߲໨ಉ༷ʮϥϯλ ΠϜͰͷΤϥʔΛݮΒ͢ʯ͜ͱ͕࣮ݱ͞Ε͓ͯΓɺ։ൃऀ͸໌ࣔతʹࣦഊίϯςΩετͰهड़͢ ΔͨΊʹϥϯλΠϜͰͷΤϥʔΛগͳ͘͢Δͷͱಉ࣌ʹࣦഊ࣌ͷڍಈΛ࣮૷͠ͳ͚Ε͹ͳΒͳ ͘ɺྫ֎࣌ͷΤϥʔΛهड़͠ͳ͔ͬͨ͜ͱʹΑΔ࣮૷্ͷόά΍ϥϯλΠϜ؀ڥʹ͓͚ΔόάΛ ݮΒ͢͜ͱ͕Ͱ͖ΔͷͰ͢ɻ 1.4 UEFN ʹ͓͚Δ Verse ͱઃܭͱ͸ ઃܭͷ࿩Λ͢Δલʹ UEFN ʹ͓͚Δ Verse ͷཱͪҐஔʹ͍ͭͯ੔ཧ͠·͢ɻ ͨͱ͑͹ Verse Ͱ MoveTo ؔ਺Λ࢖͑͹ΦϒδΣΫτΛಛఆͷҐஔ·ͰҠಈͰ͖·͕͢ɺখಓ۩ Ҡಈ૷ஔΛ࢖ͬͯ΋ಉ͡ػೳΛ࡞Δ͜ͱ͕Ͱ͖ΔΑ͏ʹ UEFN ͕ެ։͞Ε͔ͯΒؒ΋ͳ͍ݱ࣌఺Ͱ ͸ Verse ʹ͔͠Ͱ͖ͳ͍͜ͱ͸ͦ͜·Ͱଟ͋͘Γ·ͤΜɻ Ή͠Ζʮ࢓ֻ͚Ͱ͸Ͱ͖Δ͕ Verse Ͱ͸ରԠ͍ͯ͠ͳ͍ॲཧ͕͋Δʯ͜ͱ΍ʮ࢓ֻ͚Λ࢖੍ͬͨ࡞ ʹ׳Ε͍ͯΔΫϦΤΠλʔ͸࢓ֻ͚Ͱ࡞ͬͨํ͕ૣ͍έʔε͕͋Δʯ͜ͱ͔Β Verse Λ࢖Θͳͯ͘΋ े෼࡞Γ͍ͨౡΛ࡞Δػೳ͕͋Δͷ΋ UEFN ͷັྗͰ΋͋Γ·͢ɻ Ͱ͸ Verse Λ࢖͏΂͖γʔϯͱ͸Ͳ͏͍ͬͨঢ়گͰ͠ΐ͏͔ɻචऀ͸ҎԼͷΑ͏ͳڧΈ͕ Verse ʹ ͸ଘࡏ͢Δͱߟ͍͑ͯ·͢ɻ • ܧଓతΠϯςάϨʔγϣϯ • ࠷దԽ͞Εͨ։ൃαΠΫϧ 4
  8. ୈ 1 ষ UEFN Ͱ࢝ΊΔ Verse ŧŔŕŪũƄŝſೖ໳ 1.4 UEFN ʹ͓͚Δ

    Verse ͱઃܭͱ͸ • ςετίʔυʹΑΔ҆શͳ։ൃ • ޮ཰తͳνʔϜ։ൃ ܧଓతΠϯςάϨʔγϣϯ UEFN Ͱެ։͍ͯ͠Δౡ͸Ұ౓ެ։ͨ͠ΒऴΘΓͱ͍͏༁Ͱ͸͋Γ·ͤΜɻن໿ͷมߋ΍ Verse ͷ࣮૷ͷഁյతͳมߋʹΑΓಛఆͷ೔෇·ͰͷΞοϓσʔτ͕ඞཁʹͳΔγʔϯ΋ଘࡏ͠·͢͠ɺ ϢʔβʔʹౡΛ๞͖ͤ͞ͳ͍ͨΊʹίϯςϯπͷΞοϓσʔτ΋ඞཁ͔΋͠Ε·ͤΜɻ Ξοϓσʔτ͕ඞཁʹͳΔ࣌ɺ࢓ֻ͚Λ࢖࣮ͬͨ૷͸ෳࡶͳγεςϜʹͳΕ͹ͳΔ΄Ͳ֦ுੑ͕ࣦ ΘΕ·͕͢ Verse Λ༻͍Δ͜ͱͰ֦ுੑ΍อकੑΛҡ࣋͠ͳ͕Β։ൃͰ͖·͢ɻ ࠷దԽ͞Εͨ։ൃαΠΫϧ ϥϯλΠϜ؀ڥ΁ࠩ෼Λϓογϡ͢Δ࣌ؒ͸։ൃ࣌ؒͷଟ͘ͷ࣌ؒΛ઎Ί͍ͯ·͢ɻUEFN ʹ͓ ͚ΔϥϯλΠϜ؀ڥͱ͸Ϋϥ΢υ্ʹϫʔϧυΛੜ੒͢ΔΠϯελϯεͷΑ͏ͳ΋ͷͰΦϒδΣΫτ ΍࢓ֻ͚ͳͲ഑ஔ͍ͯ͠Δ΋ͷ͕ࣄલʹαʔόʹૹΒΕ͍ͯΔඞཁ͕͋Γɺηογϣϯͷىಈதʹ৽ ͘͠ΦϒδΣΫτͷࠩ෼Λ൓ө͢Δͷ͸৽͘͠ΠϯελϯεΛىಈͯ͠ೖΕସ͍͑ͯΔͨΊଟ͘ͷ࣌ ͕͔͔ؒΓ·͢ɻVerse Λ༻͍ͨ৔߹ɺίʔυࠩ෼ͷΈͷϓογϡͷػೳ͕ఏڙ͞Ε͓ͯΓɺͪ͜Β ͸લड़ͷࠩ෼൓өͱൺ΂ૣ͍Ͱ͢ɻ ʢମײ 5 ඵ΄ͲͰϦϩʔυ͞ΕΔʣ ςετίʔυʹΑΔ҆શͳ։ൃ ࢓ֻ͚ͷϢχοτςετ΍ෳ਺ͷ࢓ֻ͚Λ૊Έ߹Θͤͨ݁߹ςετ͸ɺ࣮૷ͷอकੑͱ֦ுੑΛ֬ อ͠·͢ɻલड़ͷ௨ΓɺUEFN ͷϥϯλΠϜ؀ڥ͸։ൃͷΠςϨʔγϣϯʹେ͖ͳӨڹΛ༩͑Δͨ ΊɺखಈͰͷಈ࡞֬ೝͰ͸ͳ͘ɺςετϥϯφʔʹΑΔࣗಈςετΛར༻͢Δ͜ͱͰɺϥϯλΠϜ্ Ͱͷखಈςετέʔεͷ࣮ߦΛճආ͠ɺޙํޓ׵Λอͪͳ͕Β։ൃऀ͸৽͍͠ػೳͷ֦ுʹूதͰ͖ ·͢ɻ ςετίʔυͷ࡞Γํ UEFN Ͱ͸ςετϥϯφʔͷΑ͏ͳ͘͠Έ͕ଘࡏͤͣɺ·ͨ Verse Λ UEFN ͷ֎Ͱ࣮ߦ͢ΔΑ͏ ͳ࣮ߦ؀ڥ΋ఏڙ͞Ε͍ͯͳ͍ͨΊςετΛ࣮ߦ͢ΔͨΊͷϨϕϧΛ࡞੒͠ɺఆظ࣮ߦ͢ΔΑ͏ͳӡ ༻Λ͍ͯ͠·͢ɻ ҎԼ͸ςετίʔυΛ࣮ߦ͢ΔͨΊͷσόΠεͱͦͷ࣮૷Ͱ͢ɻ using { /Fortnite.com/Devices } using { /Verse.org/Simulation } using { /UnrealEngine.com/Temporary/Diagnostics } testable := interface: 5
  9. ୈ 1 ষ UEFN Ͱ࢝ΊΔ Verse ŧŔŕŪũƄŝſೖ໳ 1.4 UEFN ʹ͓͚Δ

    Verse ͱઃܭͱ͸ Run(): logic testableͱͯ͠ػೳ͢ΔσόΠε testable_device := class(creative_device, testable): Run<override>(): logic = return true test_runner_device := class(creative_device): @editable TestableDevices: []testable_device = array {} OnBegin<override>(): void = var SuccessCount :int = 0 var FailureCount :int = 0 Print("==============================================") Print("There is {TestableDevices.Length} Test Devices!") for(Test : TestableDevices): Result := Test.Run() if(Result = true): set SuccessCount += 1 else: set FailureCount += 1 if(FailureCount > 0): Print("Test is Failed.") Print("Total Test Count:{TestableDevices.Length}") Print("Success Test Count:{SuccessCount}") Print("Failure Test Count:{FailureCount}") Print("==============================================") test_log_channel := class(log_channel): Expect<public>(Case: string, Logic: logic): logic = TestLogger := log{Channel := test_log_channel} if(Logic = true): TestLogger.Print(Case, ?Level := log_level.Normal) else: TestLogger.Print(Case, ?Level := log_level.Error) return Logic test_runner_device ͷ TestableDevices ʹ testable_device Λܧঝͨ͠σόΠεΛඥ͚ͮΔ͜ͱ ʹΑΓςετίʔυΛ࣮ߦ͠·͢ɻ sample_test := class(testable_device): Run<override>(): logic = return Expect("1 + 2 ͸ 3Ͱ͋Δ͜ͱ", logic { 1 + 2 = 3 }) failure_sample_test := class(testable_device): Run<override>(): logic = 6
  10. ୈ 1 ষ UEFN Ͱ࢝ΊΔ Verse ŧŔŕŪũƄŝſೖ໳ 1.4 UEFN ʹ͓͚Δ

    Verse ͱઃܭͱ͸ return Expect("1 + 2 ͸ 100Ͱ͋Δ͜ͱ", logic { 1 + 2 = 100 }) Expect ؔ਺ͷୈҰҾ਺ʹ͸Ͳ͏͍͏ςετΛ࣮ߦ͍͔ͨ͠Λهड़͠ɺୈೋҾ਺ʹ͸ςετͷ݁Ռ Λ ligic ܕͰ౉͠·͢ɻRun ؔ਺ͷத͸ࣗ༝ʹςετΛॻ͘͜ͱ͕Ͱ͖ΔͷͰෳ߹ςετͳͲ΋هड़ ՄೳͰ͢ɻ ·ͨɺtestable_device ͸ creative_device Λܧঝ͍ͯ͠ΔͨΊ testable_device ʹ editable Λ༻ ͍ͯ΄͔ͷ࢓ֻ͚ͱ૊Έ߹ΘͤͨςετΛ࡞Δ͜ͱ΋ՄೳͰ͢ɻςετϨϕϧͷηογϣϯΛىಈ ͠ɺήʔϜΛ։࢝͢Δ͜ͱʹΑΓ test_runner_device ͰࣗಈͰςετ͕։࢝͞Ε·͢ɻҎԼ͸ϩά ʹग़ྗ͞Εͨ݁ՌͰ͢ɻ ޮ཰తͳνʔϜ։ൃ UEFN ͷࠩ෼؅ཧπʔϧͰ͋ΔʮRevision Controlʯ͸தԝूݖܕͷόʔδϣϯ؅ཧγεςϜͷ ͨΊඇৗʹଟ͘ͷίϯϑϦΫτ͕ൃੜ͠·͢ɻͨͱ͑͹ A ͞Μͱ B ͞Μͷ 2 ਓͰ։ൃ͍ͯ͠Δࡍʹ 2 ਓ͕ಉ͡ΦϒδΣΫτΛૢ࡞͍ͨ͠ͱ͖ɺઌʹΦϒδΣΫτΛૢ࡞ͨ͠Ϣʔβʔͷ؀ڥͰͦͷΦϒ δΣΫτ͸ʮνΣοΫΞ΢τʯ͞Ε΄͔ͷϢʔβʔʹΑΔͦͷΦϒδΣΫτͷมߋ͸ϩοΫ͞Ε· ͢ɻήʔϜͷϩδοΫΛܾఆ͢ΔσόΠεͰ͜ͷΑ͏ͳৼΔ෣͍͸νʔϜن໛͕େ͖͘ͳΔʹͭΕͯ ։ൃͷ଎౓ʹେ͖ͳӨڹΛ༩͑·͢ɻ Verse Λద੾ʹΫϥεΛ෼ׂ͠ґଘͷগͳ͍ઃܭΛߦ͏͜ͱͰಉ͡ϑΝΠϧΛมߋ͢Δ͜ͱʹΑΔ ίϯϑϦΫτΛۃྗݮΒ͢͜ͱ͕Ͱ͖·͢ɻ͔͠͠ɺcreative_device ΫϥεΛܧঝ͢ΔΫϥε͸Ϗ ϧυ࣌ʹ࢓ֻ͚ͱͯ͠ग़ྗ͞ΕΔͨΊϫʔϧυ্ʹઃஔͨ͠৔߹Α͘ίϯϑϦΫτ͢ΔͷͰ஫ҙ͕ඞ ཁͰ͢ɻ ্هͷཧ༝ʹΑΓ Verse Λར༻͢Δ͜ͱʹΑΓେن໛ͳΞϓϦέʔγϣϯͰ΋ޮ཰తʹ։ൃͰ͖Δ ͘͠ΈΛ࡞Δ͜ͱ͕Ͱ͖·͢ɻ 7
  11. ୈ 1 ষ UEFN Ͱ࢝ΊΔ Verse ŧŔŕŪũƄŝſೖ໳ 1.4 UEFN ʹ͓͚Δ

    Verse ͱઃܭͱ͸ Verse ʹͳͥઃܭ͕ඞཁͳͷ͔ Verse ͷΈͳΒͣϓϩάϥϛϯάʹͳͥઃܭ͕ඞཁͳͷ͔ɺͱ͍͏࿩Λ࢝ΊΔͱΩϦ͕ͳ͍ͷͰ۩ ମྫͰݟ͍͖ͯ·͠ΐ͏ɻҎԼ͸ઃܭΛ͍ͯ͠ͳ͍͋Γ͕ͪͳ Verse ͷίʔυͰ͢ɻԿ͕՝୊Ͱ͠ΐ ͏͔ɻ player_manager := class(creative_device): var Players: []agent = array{} var Scores: [agent]int = map {} AddPlayer(Agent: agent): void = // PlayersʹAgentΛ௥Ճ͢Δॲཧ // PlayerͷείΞΛॳظԽ͢Δॲཧ RemovePlayer(Agent: agent): void = // Players͔ΒAgentΛ࡟আ͢Δॲཧ // PlayerͷείΞΛॳظԽ͢Δॲཧ // ϘλϯΠϕϯτΛϋϯυϦϯά͢Δؔ਺ HandleShowUIButton(Agent: agent): void = ShowUI(Agent) ShowUI(Agent: agent): void = // TODO: ϓϨΠϠʔͷUIΛදࣔ͢Δॲཧ HideUI(Agent: agent): void = // TODO: ϓϨΠϠʔͷUIΛඇදࣔʹ͢Δॲཧ AddScore(Agent: agent, Count: int): void = // TODO: ϓϨΠϠʔͷείΞΛ௥Ճ͢Δॲཧ UpdateScoreUI(Agent) UpdateScoreUI(Agent: agent): void = // TODO: είΞUIΛߋ৽͢Δॲཧ JudgeWinPlayer(): agent = // TODO: উརͨ͠ϓϨΠϠʔΛग़ྗ͢Δॲཧ // TODO: উརͨ͠ϓϨΠϠʔͷ໊લΛදࣔ͢Δॲཧ ͜ͷΫϥε͸ؔ৺ͷ෼཭ͷߟ͑ʹ൓͍ͯ͠·͢ɻ ͜ͷίʔυ͸͢΂ͯͷϓϨΠϠʔΛ؅ཧ͢Δॲཧ΍είΞΛ؅ཧ͢ΔॲཧɺUI Λදࣔ͢Δॲཧͳ Ͳ͞·͟·ͳ໾ׂΛ͓࣋ͬͯΓίʔυͷෳࡶੑΛ֦͋͛ுੑΛେ͖͘Լ͛ΔͨΊҎԼͷΑ͏ͳΫϥε ઃܭ͕๬·͍͠Ͱ͢ɻ ʢগ͠୺ં͍ͬͯΔ෦෼΋͋ΔͷͰͦͷ··Ͱ͸ಈ͔ͳ͍ͷͰ͝༰͍ࣻͩ͘͞ʣ 8
  12. ୈ 1 ষ UEFN Ͱ࢝ΊΔ Verse ŧŔŕŪũƄŝſೖ໳ 1.4 UEFN ʹ͓͚Δ

    Verse ͱઃܭͱ͸ game_player := class: Agent<public>: agent var Score: int = 0 AddScore<public>(Amount: int): void = set Score += Amount GetScore<public>(): void = return Score game_player_manager := class(creative_device): @editable PlayerUIManager: player_ui_manager = player_ui_manager{} var Players: [agent]game_player = map{} AddPlayer(Agent:agent): void = logic { Players[Agent] = game_player { Agent := Agent } } PlayerUIManager.ShowUI(Agent) RemovePlayer(Agent: agent): void = // Players͔ΒϓϨΠϠʔΛ࡟আ͢Δॲཧ PlayerUIManager.HideUI(Agent) UpdateScore(Agent: agent, Amount: int): void = if(GamePlayer := Players[Agent]?): GamePlayer.AddScore(Amount) PlayerUIManager.UpdateScoreUI(Agent, Amount) game_manager := class(creative_device): @editable GamePlayerManager: game_player_manager = game_player_manager{} // ϘλϯΠϕϯτΛϋϯυϦϯά͢Δؔ਺ HandleShowUIButton(Agent: agent): void = GamePlayerManager.AddPlayer(Agent) JudgeWinPlayer(): agent = // উརͨ͠ϓϨΠϠʔΛ൑ఆ͢Δ player_ui_manager := class(creative_device): ShowUI(Agent: agent): void = // TODO: ϓϨΠϠʔͷUIΛදࣔ͢Δؔ਺ HideUI(Agent: agent): void = // TODO: ϓϨΠϠʔͷUIΛඇදࣔʹ͢Δؔ਺ UpdateScoreUI(Agent: agent, Amount: int): void = // TODO: είΞUIΛߋ৽͢Δؔ਺() ্هͷΑ͏ͳઃܭʹ͢Δ͜ͱͰॲཧͷ໾ׂʢؔ৺͝ͱʣ͕෼཭͞Εෳ਺ͷΫϥεʹ෼ׂ͞Ε·͢ɻ Ϋϥε͕෼ׂ͞ΕΔ͜ͱʹΑΓɺ΄͔ͷϝϯόʔ͕ॻ͍ͨίʔυͷֶशίετ͕গͳ͘ͳͬͨΓίϯ ϑϦΫτϦεΫΛԼ͛Δ͜ͱ͕Ͱ͖·͢ɻ 9
  13. ୈ 1 ষ UEFN Ͱ࢝ΊΔ Verse ŧŔŕŪũƄŝſೖ໳ 1.5 Verse ܕ༡ͼೖ໳

    1.5 Verse ܕ༡ͼೖ໳ Verse ͷܕʹ͍ͭͯ ং൫Ͱॻ͍ͨ௨ΓɺVerse ͸"ڧ͍ܕ෇͚"Λಛ௃ͱͨ͠ݴޠͰ͢ɻͦͷͨΊ΄͔ͷ੩తܕ෇͖ݴޠ ͰݟΒΕΔΑ͏ͳܕਪ࿦΍ҟͳΔܕͲ͏͠ͷԋࢉΛݪଇߦ͏͜ͱ͕Ͱ͖·ͤΜɻͨͱ͑͹ҎԼͷ۩ମ ྫͷΑ͏ʹ int ܕΛ࣋ͭม਺ͱ float ܕΛՃࢉ͢Δ͜ͱ͸ݪଇͰ͖·ͤΜɻ Hoge: int = 1 Fuga: float = 1.0 Result := Hoge + Fuga <-- ʮint ͱ floatΛՃࢉ͢Δoperator͕ແ͍Αʯͱ͍͏Τϥʔ͕ग़Δ ͔͠͠ Verse Ͱ͸৽͘͠ int Λ float ʹม׵͔ͯ͠Βܭࢉ͢ΔΑ͏ͳ operator Λ৽͘͠௥Ճ͢Δ͜ ͱͰ͜ͷܭࢉ͕ՄೳͱͳΓ·͢ɻ operator’+’<public>(F:float, I:int):float= return F + I * 1.0 // IΛ1.0Ͱ৐ࢉ͢Δ͜ͱͰfloatʹม׵͍ͯ͠Δ operator’+’<public>(I:int, F:float):float= return I * 1.0 + F // IΛ1.0Ͱ৐ࢉ͢Δ͜ͱͰfloatʹม׵͍ͯ͠Δ ˞ "+"ͷࠨลӈล྆ํʹରԠ͢ΔͨΊೋͭͷoperatorΛ࡞੒͠·͢ ͜ͷίʔυΛϞδϡʔϧͱͯ͠ಡΈࠐΜͰ͓͘͜ͱͰ্هͷ int ͱ float ͷܭࢉࣜͰΤϥʔ͕ग़ͳ ͘ͳΓ·͢ʢResult ͷܕ͸ float ʹͳΓ·͢ʣ ҎԼ͸ int ͱ float ΛܭࢉͰ͖ΔΑ͏ʹ͢Δ͢΂ͯͷ operator Ͱ͢ɻ // floatʹม׵͢Δؔ਺͸ڞ௨Խ͓ͯ͘͠ Float<public>(Number : int)<varies>:float= return Number * 1.0 operator’+’<public>(I:int, F:float):float= return Float(I) + F operator’+’<public>(F:float, I:int):float= return F + Float(I) operator’-’<public>(I:int, F:float):float= return Float(I) - F 10
  14. ୈ 1 ষ UEFN Ͱ࢝ΊΔ Verse ŧŔŕŪũƄŝſೖ໳ 1.5 Verse ܕ༡ͼೖ໳

    operator’-’<public>(F:float, I:int):float= return F - Float(I) operator’/’<public>(I:int, F:float):float= return Float(I) / F operator’/’<public>(F:float, I:int):float= return F / Float(I) Α͘࢖͏ॲཧ͸ศརؔ਺ʹ͠Α͏ʂ Verse ͸ܕʹରͯؔ͠਺Λ௥Ճ͢Δ͘͠Έ͕͋Γ·͢ɻ͜ͷػೳΛ࢖ͬͯܕʹศརͳؔ਺Λੜ΍͠ ͍͖ͯ·͠ΐ͏ɻҎԼ͸ int ܕʹ 1 ΛՃࢉ͢Δؔ਺ͷྫͰ͢ɻ (Input: int).AddOne<public>(): int = return Input + 1 // 1.AddOne() ͷΑ͏ͳ࢖͍ํ͕Ͱ͖·͢ɻ͜ͷྫͷ৔߹͸2͕ग़ྗ͞Ε·͢ ·ͨɺ҉໧తͳܕҾ਺Λ࢖͏͜ͱͰෳ਺ͷܕʹରͯؔ͠਺Λ࡞੒Ͱ͖·͢ɻ ʢҎԼͷαϯϓϧ͸ೖ ྗ͞Εͨܕͷ஋Λͦͷ··ฦ͚ͩ͢ͷؔ਺Ͱ͢ʣ (Input:t where t:type).ReturnValue<public>(): t = return Input ্هͷΑ͏ͳํ๏Λ༻͍ͯචऀ͕࡞੒ͨ͠ౡͰ͋ΔʮPokerVerseʯͰ࣮ࡍʹ࢖༻ͨ͠ศརؔ਺Λ঺ հ͠·͢ɻ 1. ഑ྻ͔Β૊Έ߹ΘͤΛ࡞੒͢Δ ϙʔΧʔ͸ 2 ຕͷखࡳͱ 5 ຕͷςʔϒϧͷΧʔυத͔ΒҰ൪ڧ͍໾͕Ͱ͖ΔΧʔυ 5 ຕΛநग़͢ ΔॲཧΛ࡞Δඞཁ͕͋Γ·͢ɻͦͷॲཧͷ࣮૷ʹ࢖ͬͨ૊Έ߹ΘͤΛ࢖࣮ͬͨ૷Ͱ͢ (Input:[]t where t:type).MakeCombinations<public>(Count: int): [][]t = var Result: [][]t = array {} N := Input.Length var Stack: []tuple(int, []t) = array { (0, array{}) } 11
  15. ୈ 1 ষ UEFN Ͱ࢝ΊΔ Verse ŧŔŕŪũƄŝſೖ໳ 1.5 Verse ܕ༡ͼೖ໳

    loop: if(Stack.Length = 0): break if(Value := Stack[0]): StartIndex := Value(0) CurrentCombination := Value(1) if(set Stack = Stack.RemoveElement[0]): if(CurrentCombination.Length = Count): set Result = Result + array { CurrentCombination } else: if(StartIndex < N): for(Index := StartIndex..N): if(AddValue := Input[Index]): NewCombination := CurrentCombination + array { AddValue } set Stack = Stack + array {(Index + 1, NewCombination)} return Result ͜ͷίʔυ͸ҎԼͷΑ͏ͳ࢖͍ํ͕Ͱ͖·͢ɻೖྗͷ഑ྻͷ਺΍நग़͍ͨ͠਺ͷมߋ΋ՄೳͰ͢ɻ // 1,2,3ͷ഑ྻ͔Β2ͭͷ਺ࣈͷશͯͷ૊Έ߹ΘͤΛநग़͢Δ Result := [1,2,3].MakeCombinations(2) /* array { array {1, 2}, array {2, 3}, array {1, 3} } ͕Resultͱͯ͠ฦ͖ͬͯ·͢ */ 2.int ܕͷ഑ྻΛখ͍͞ॱʹฒͼସ͑Δ (Input: []int).Sort<public>(): []int = if(Input.Length <= 1): return Input var Left: []int = array {} var Right: []int = array {} if(Pivot := Input[0]): for(Index := 1..Input.Length): if(Item := Input[Index]): if(Item < Pivot): set Left = Left + array { Item } else: set Right = Right + array { Item } 12
  16. ୈ 1 ষ UEFN Ͱ࢝ΊΔ Verse ŧŔŕŪũƄŝſೖ໳ 1.6 ऴΘΓʹ LeftResult

    := Left.Sort() RightResult := Right.Sort() return LeftResult + array{ Pivot } + RightResult return Input Result := [4,1,3,2,6,5].Sort() // array { 1, 2, 3, 4, 5, 6 } ͕Resultͱͯ͠ฦ͖ͬͯ·͢ 3. ೚ҙͷܕͷ഑ྻͰ೚ҙͷ஋Λ഑ྻͰநग़͢Δ (Input:[]t where t: type).Where<public>(predicate: type{_(:t) : logic}):[]t = var List: []t = array{} for(Item : Input): result := predicate(Item) if(result = true): set List = List + array{Item} return List IsBiggerThan1(Input: int): logic = return logic { Input > 1 } Result := [1, 1, 4, 5, 6, 6, 1, 3, 1].Where(IsBiggerThan1) // [4, 5, 6, 6, 3] ͕Resultͱͯ͠ฦ͖ͬͯ·͢ 1.6 ऴΘΓʹ ຊষͰ͸ Unreal Editor for Fortnite(UEFN) ʹ͓͚Δ Verse ͷ঺հͱͦͷ׆༻ํ๏ʹ͍ͭͯ঺հ ͠·ͨ͠ɻ۩ମతͳ࢓ֻ͚ͷ࢖͍ํ΍࣮૷ํ๏ʹ͍ͭͯ͸঺հͰ͖ͳ͔ͬͨͰ͕͢͜Ε͔Β Verse Λ ࢖ΘΕΔํ΍͢Ͱʹ Verse Λ࢖͍ͬͯΔํʹͱͬͯগ͠Ͱ΋໾ʹཱͯͨΒͱߟ͍͑ͯ·͢ɻ Verse ͸·ͩ·ͩൃల్্ͷݴޠͳͷͰΈΜͳͰ࢖ͬͯҰॹʹ੝Γ্͍͖͛ͯ·͠ΐ͏ʂ 13
  17. ୈ 2 ষ ര଎Ͱ Approve ͕΋Β͑Δ Pull Request ͷ࡞Γํ ͜Μʹͪ͸ɺιʔγϟϧϕοςΟϯάࣄۀຊ෦։ൃࣨͷߐാͰ͢ɻຊষͰ͸ɺࣗ෼͕։ൃࣨͰߦͬ

    ͨϓϩμΫτ։ൃ࣌ͷϨϏϡʔʹ͍ͭͯͷ஌ݟΛ঺հ͠·͢ɻ 2.1 ·͕͖͑ ࣗ෼͸ 2023 ೥౓ͷ໨ඪͱͯࣗ͠਎ͷٕज़ྗ޲্ͱαʔϏεͷϦϦʔε଎౓޲্Λܝ͛ɺฏ࣌ͷՔ ಇ࣌ؒͰ͸αʔόϓϩμΫτίʔυͷϨϏϡʔΛߦ͖ͬͯ·ͨ͠ɻ େখ͞·͟·ͳ Pull Request ΛΈ͍ͯ͘தͰɺϨϏϡʔ͕࣌ؒ୹ͯ͘ࡁΜͩΓ΍ख໭Γͷগͳ ͔ͬͨΓ͢ΔʮϨϏϡʔ͠΍͍͢ʯ Pull Request ͷ܏޲͕͋Γͦ͏ͳ͜ͱ͕Θ͔Γ·ͨ͠ɻࠓճ͸ ͦ͏͍ͬͨϨϏϡʔ͠΍͢͞ʹؔΘΔ Pull Request ͷཁૉʹ͍ͭͯ؆қͳྫͱͱ΋ʹ঺հ͠·͢ɻ 2.2 ϨϏϡʔ͠΍͍͢ Pull Request ࡉ͔͍എܠͳͲ͸ͦΕͧΕͷ߲ʹ೚ͤΔͱͯ͠ɺͬ͘͟ΓϨϏϡʔ͠΍͢͞ʹؔΘΔ Pull Request ͷཁૉΛҰཡԽ͢ΔͱҎԼͷΑ͏ʹͳΓ·͢ɻ • Pull Request ͷຊจͷϑΥʔϚοτ͕౷Ұ͞Ε͍ͯΔ • ࢀߟ࣮૷ͷϦϯΫ͕͋Δ • ࡞ΔػೳʹϚονͨ͠ςετ͕هड़͞Ε͍ͯΔ • ࠶ݱੑͷ͋Δಈ࡞֬ೝํ๏΍ར༻γφϦΦ͕ॻ͍ͯ͋Δ • ػೳͷυϝΠϯ஌͕ࣝଐਓԽ͍ͯ͠Δ • ࢓༷ௐ੔ͷձ࿩͕ϦϯΫ͞Ε͍ͯͳ͍ • ςετίʔυ͕ͳ͍/ଟ͗͢Δ • ToDo ͕ଟ͍ • ػೳ͕ಠཱ͍ͯ͠ͳ͍ • Өڹൣғ͕ෆ໌ 15
  18. ୈ 2 ষ ര଎Ͱ Approve ͕΋Β͑Δ Pull Request ͷ࡞Γํ 2.2

    ϨϏϡʔ͠΍͍͢ Pull Request Pull Request ͷຊจͷϑΥʔϚοτ͕౷Ұ͞Ε͍ͯΔ ͞·͟·ͳ࢓༷ॻ΍ॻྨͳͲ͕ͦ͏Ͱ͋ΔΑ͏ʹɺϑΥʔϚοτ͸ՄಡੑΛ্͛ΔͨΊͷख๏ͱ͠ ͯ༗ޮͰ͢ɻҰఆ৑௕ͳදݱ͕ੜ·ΕͨΓෆඞཁͳ߲໨ʹ಄Λ೰·͞ΕͨΓ͢Δ͜ͱ΋͋Γ·͕͢ɺ Pull Request ΛΈͨ࣌ʹϑΥʔϚοτ͕ϨϏϡʔͷϦζϜΛ࡞Δ͜ͱͰɺϨϏϡΞʔ͸มߋͨ͠಺ ༰ΛΑΓεϜʔζʹ೺ѲͰ͖·͢ɻ ։ൃࣨͰ͸աڈͷܦݧͱଞࣾͷΨΠυ *1 ΛԠ༻ͯ͠ҎԼͷΑ͏ͳϑΥʔϚοτΛར༻͍ͯ͠·͢ɻ Ϧετ 2.1: Pull Request ςϯϓϨʔτ ## ͳͥ͜ͷมߋ͕ඞཁͳͷ͔ (why & what) ## ͲͷΑ͏ʹ࣮ݱ͢Δͷ͔ (how) ## ࣮૷্ͷݒ೦ ʢಛʹϨϏϡʔͯ͠΄͍͠෦෼ͳͲʣ ## Өڹൣғ ## ಈ࡞֬ೝखॱʢݕূ߲໨ʣ ## కΊ੾Γ೔ʢϚʔδظݶʣ ## ࢓༷ ## ࢀߟϦϯΫ ࢀߟ࣮૷ͷϦϯΫ͕͋Δ ฐϓϩμΫτͰ͸αʔόͷϓϩάϥϜίʔυͷ΄ͱΜͲΛ Go Ͱ։ൃ͍ͯ͠·͕͢ɺ΄ͱΜͲͷ։ ൃͰ͸ΞʔΩςΫνϟ΍໋໊نଇͳͲͷઃܭΛɺطଘͷίʔυͷࢥ૝Λ׆͔͠ͳ͕Β։ൃ͍ͯ͠· ͢ɻ·ͨಠࣗͷ։ൃ͕ඞཁͳέʔεͰ͋ͬͯ΋ɺ֎෦ͷࢀߟ࣮૷ΛಡΈͳ͕Βண૝ΛಘΔ͜ͱ͕΄ͱ ΜͲͰ͢ɻ ͦ͏͍࣮ͬͨ૷ऀͷഎܠ஌ࣝ͸ϨϏϡΞʔʹͱͬͯ͸ඞཁෆՄܽͳ΋ͷͱݴͬͯ΋աݴͰ͸͋Γ· ͤΜɻͨͱ͑͹ɺ10 ࿈ଓΨνϟͷ࣮૷ʹࡍͯ͠୯ൃΨνϟͷ࣮૷Λࢀߟʹͨ͜͠ͱΛ໌ه͓ͯ͘͠ ͜ͱͰɺطଘͷ࣮૷Ͱอଘɾߋ৽͞ΕΔϢʔβʔࢿ࢈΍ॲཧதʹඞཁͳϩάग़ྗΛ಄ʹೖΕͳ͕ΒϨ ϏϡʔΛߦ͏͜ͱ͕Ͱ͖·͢ɻ *1 Google Engineering Practices Documentation: https://github.com/google/eng-practices / Ұ ෦ ຋ ༁: https://mokkemeguru.github.io/eng-practices/review/developer/cl-descriptions 16
  19. ୈ 2 ষ ര଎Ͱ Approve ͕΋Β͑Δ Pull Request ͷ࡞Γํ 2.2

    ϨϏϡʔ͠΍͍͢ Pull Request ࡞ΔػೳʹϚονͨ͠ςετ͕هड़͞Ε͍ͯΔ ςετίʔυ͸ͦͷػೳ͕ԿΛ͢Δͷ͔Λཧղ͢ΔͨΊͷҰ൪ͷखॿ͚Ͱ͢ɻςετέʔε͕े෼ Ͱ͋Ε͹ͦͷػೳʹ͓͚Δਖ਼ৗܥɾҟৗܥͷೖग़ྗɺ·ͨͦΕͧΕͰى͜Δ෭࡞༻Λ೺ѲͰ͖·͢ɻ ͨͱ͑͹୯ൃΨνϟΛ࣮૷͢Δʹ͋ͨͬͯ͸ɺҎԼͷΑ͏ͳςετέʔε͕࣮૷͞Ε͍ͯΔͱϨ ϏϡΞʔ͸ॿ͔Γ·͢ɻ·ͨςετέʔεʹ͍ͭͯ͸ɺͦΕͧΕͷςετ͕ԿΛ͍ͯ͠Δͷ͔Λ໌ه ͢Δ͜ͱ͕ॏཁͰ͢ɻcase 1 ͷΑ͏ͳ໋໊ͷςετΛॻ͘ͷ͸߇͑ͨํ͕ྑ͍Ͱ͠ΐ͏ɻ • ੒ޭ: ϊʔϚϧΩϟϥΛ֫ಘ • ੒ޭ: ϨΞΩϟϥΛ֫ಘ • ࣦഊ: ΨνϟͷͨΊͷϙΠϯτ͕ෆ଍ • ࣦഊ: Ϣʔβʔ͕ BAN ͞Ε͍ͯΔ ࠶ݱੑͷ͋Δಈ࡞֬ೝํ๏΍ར༻γφϦΦ͕ॻ͍ͯ͋Δ ϨϏϡΞʔͷϨϏϡʔྗ͕଍Γͳ͍৔߹ɺ࣮ࡍʹͦͷػೳΛखݩͰࢼͨ͠ΓςετίʔυΛ௥Ճ͠ ͨ͘ͳΔ͜ͱ͕͋Γ·͢ɻͦͷࡍʹ࠶ݱੑͷ͋Δಈ࡞֬ೝํ๏΍ར༻γφϦΦ͕͋ΔͱɺखݩͰͷݕ ূ͕ΑΓεϜʔζʹͳΓ·͢ɻ ·ͨͦͷࡍͷಈ࡞֬ೝͰࠩ෼͚ͩΛϨϏϡʔ͍ͯͯ͠΋ؾ෇͘͜ͱ͕೉͍͠ɺ࣮ߦ࣌ʹඞཁͳґଘ ؔ܎ͷ஫ೖ͕Ͱ͖͍ͯͳ͍͜ͱ΍࣮૷࣌ͷߟྀ࿙ΕͳͲΛࢦఠͰ͖·͢ɻ ͞ΒʹϓϩμΫτʹ͸ΑΓ·͕͢ɺϢʔβʔ࡞੒ͳͲͷΑ͘࢖͏ςετ؀ڥΛ࡞ΔͨΊͷखଓ͖ʹ ͍ͭͯυΩϡϝϯτ΍πʔϧΛ੔උ͓ͯ͘͜͠ͱ΋ޮ཰తͳϨϏϡʔʹߩݙ͠·͢ɻ 17
  20. ୈ 2 ষ ര଎Ͱ Approve ͕΋Β͑Δ Pull Request ͷ࡞Γํ 2.2

    ϨϏϡʔ͠΍͍͢ Pull Request ػೳͷυϝΠϯ஌͕ࣝଐਓԽ͍ͯ͠Δ ܾࡁͳͲͷେن໛͔ͭॏཁͳػೳ΍؅ཧը໘ͷΑ͏ͳαʔϏεʹ௚݁͠ͳ͍γεςϜʹ͍ͭͯ͸ɺ ։ൃऀ͕ݶΒΕͯ͠·͏͜ͱͰυϝΠϯ஌͕ࣝଐਓԽ͢Δ͜ͱ͕͋Γ·͢ɻ ͦ͏ͳΔͱϨϏϡʔΛߦ͏લʹࣄલ஌ࣝΛऔΓࠐΉඞཁ͕ൃੜͨ͠Γɺͦ΋ͦ΋ࠩ෼Λঝೝͯ͠ྑ ͍ͷ͔ͷ൑அʹࠔΔ͜ͱ͕͋Γ·͢ɻ ಛʹϨϏϡʔ͕ඞཁͳέʔεͰ͸ Slack ͷΑ͏ͳࣾ಺ͷίϛϡχέʔγϣϯπʔϧΛར༻ͯ͠Ϩ ϏϡΞʔʹจ໘ͰίϛϡχέʔγϣϯΛͱͬͨΓɺ͓ޓ͍ʹޱ಄Ͱೝࣝͷ͢Γ߹ΘͤΛߦ͏ͱΑ͍Ͱ ͠ΐ͏ɻ ·ͨࣄલʹ Design Doc ͱ͍ͬͨυΩϡϝϯτͷ࡞੒ʹΑͬͯϨϏϡʔΛґཔͨ͠ϝϯόʔʹࣄલ ஌ࣝΛڞ༗͢Δ͜ͱ΋༗ޮͰ͢ɻͨͱ͑͹ҎԼͷΑ͏ͳ Design Doc Λ༻ҙ͠ࣄલʹڞ༗͓ͯ͘͜͠ ͱͰػೳͷϨϏϡʔΛߦ͍΍͘͢ͳΓ·͢ɻ Ϧετ 2.2: Design Doc 10 ࿈ଓΨνϟػೳ ## ػೳͷ֓ཁ ୯ൃΨνϟΛ֦ுͯ͠Ұ౓ʹ10ճҾ͚Δ10࿈ΨνϟΛ௥Ճ͠·͢ ## ࢓༷ॻ - [࢓༷ॻͷϦϯΫ](https://hogehoge) ## ઃܭ طଘͷ୯ൃΨνϟΛ10࿈ଓʹ֦ு͠·͢ طଘͷ୯ൃΨνϟͷ࣮૷͸ͪ͜Β https://github.com/hogehoge ͳ͓طଘͷΨνϟه࿥ͷςʔϒϧ͸୯ൃΨνϟ͔͠ରԠ͍ͯ͠ͳ͔ͬͨͷͰɺ࿈ଓΨνϟʹ଱͑ΒΕΔΑ͏ ʹ ‘play_group_id‘ ΧϥϜΛ௥Ճ͠·͢ ‘‘‘sql CREATE TABLE user_play_gachas ( user_id STRING(MAX) NOT NULL, play_id STRING(MAX) NOT NULL, // Ψνϟ݁ՌͷID char_id STRING(MAX) NOT NULL, // ΩϟϥΫλͷID play_group_id STRING(MAX), // ࿈ଓΨνϟΛάϧʔϓ͢ΔͨΊͷID created_at STRING(MAX) NOT NULL, updated_at STRING(MAX) NOT NULL, ) PRIMARY KEY(user_id, play_id); ‘‘‘ UMLਤ͸ҎԼͷΑ͏ʹͳΓ·͢ ‘‘‘mermaid // -- ຊষͰ͸লུ ‘‘‘ 18
  21. ୈ 2 ষ ര଎Ͱ Approve ͕΋Β͑Δ Pull Request ͷ࡞Γํ 2.2

    ϨϏϡʔ͠΍͍͢ Pull Request ## ࡞੒͢ΔAPI - POST /v2/gachas - ΨνϟΛҾͨ͘ΊͷAPI - ϦΫΤετύϥϝʔλ - type (enum): 10࿈Ψνϟ / ୯ൃΨνϟ Λ۠ผ͢ΔͨΊͷϑϥά - Ϩεϙϯεύϥϝʔλ - Ψνϟ࣮ߦ͝ͱʹҰҙͳID (‘play_group_id‘) - Ψνϟ݁Ռͷ഑ྻ - ΨνϟΛҾ͍ͨ͜ͱʹΑΔϘʔφεϙΠϯτ ## ݒ೦఺ ࢓༷ௐ੔ͷձ࿩͕ϦϯΫ͞Ε͍ͯͳ͍ ಛʹΞδϟΠϧ։ൃͱݺ͹ΕΔ։ൃͰ͸ɺ։ൃظؒதʹಥൃతͳ࢓༷ௐ੔͕ೖΔ͜ͱ͕͋Γ·͢ɻ ͦͯ͠೰·͍͜͠ͱʹ Design Doc Λ֬ೝͨ͠ޙ΍ Pull Request ϨϏϡʔதʹ΋ͦ͏͍ͬͨഁյత มߋ͸༰қʹࠩ͠ࠐ·Ε·͢ɻ ͜ΕΒͷมߋ͸ࠩ͠ࠐΈͰ͋Δੑ্࣭ɺ Pull Request Λ࡞ͬͨ࣌ͷจ໘ʹ͸ؚ·ΕͣɺԾʹԿΒ ͔ͷิ଍͕ͳ͚Ε͹ϨϏϡΞʔ͸ஔ͍͖ͯ΅ΓΛ͍ͨͩ͘͜ͱʹͳΓ·͢ɻ ։ൃதʹ࢓༷มߋͳͲ͕͋ͬͨ৔߹ʹ͸ɺࠩ෼ͷߋ৽ʹ߹ΘͤͯมߋՕॴʹؔΘΔίϛϡχέʔ γϣϯ΁ͷಋઢΛ༠ಋͰ͖Δͱྑ͍Ͱ͠ΐ͏ɻ 19
  22. ୈ 2 ষ ര଎Ͱ Approve ͕΋Β͑Δ Pull Request ͷ࡞Γํ 2.2

    ϨϏϡʔ͠΍͍͢ Pull Request ςετίʔυ͕ͳ͍/ଟ͗͢Δ ܁Γฦ͠·͕͢ɺςετίʔυ͸ͦͷػೳ͕ԿΛ͢Δͷ͔Λཧղ͢ΔͨΊͷҰ൪खॿ͚Ͱ͢ɻςε τίʔυ͕·ͬͨ͘ͳ͍ͱɺϨϏϡΞʔ͸ͦͷίʔυͷظ଴͢ΔڍಈΛ೴಺ɾखݩͰςετίʔυΛ ॻ͍ͯ֬ೝ͢Δ͜ͱʹͳΔ͚ͩͰͳ͘ɺ࣮૷ऀͱҧͬͨղऍΛҾ͖ى͜͢Մೳੑ͕͋Γ·͢ɻ ͨͱ͑͹ΦϯϥΠϯγϣοϓͷΧʔτΛऔಘ͢ΔҎԼͷΑ͏ͳ࣮૷Λߟ͑ͯΈΔͱɺϨϏϡΞʔ͸ Χʔτ͕ۭͷ৔߹ΤϥʔͱͳΔͷ͕ਖ਼ͳͷ͔ۭΛฦ͢ͷ͕ਖ਼ͳͷ͔Λ൑அͰ͖·ͤΜɻ Ϧετ 2.3: FetchUserCartInteractor#Execute func (i *FetchUserCartInteractor) Execute(ctx context.Context, userID string) ( []*model.UserCart, error, ) { userCarts, err := i.UserCartRepository.Find(ctx, userID) if err != nil { return nil, err } sort.Slices(s, func(i, j int) bool { return userCarts[i].PurchasedAt > userCarts[j].PurchasedAt }) return userCarts, nil } ͜͜ʹςετίʔυ͕ͻͱͭ·Έ௥Ճ͞ΕΔͱɺ࣮૷ऀ΋ϨϏϡΞʔ΋࢓༷ʹؔ͢Δڞ௨ೝࣝΛ࣋ ͭ͜ͱ͕Ͱ͖·͢ɻ Ϧετ 2.4: (better)TestFetchUserCartInteractor_Execute func TestFetchuserCartInteractor_Execute(t *testing.T) { t.Run("ਖ਼ৗܥ", { // -- }) t.Run("ҟৗܥ: Χʔτ͕ۭͷ࣌͸ UserCartEmptyError ͷΧελϜΤϥʔΛฦ͢", { // -- }) } ͱ͜Ζ͕ʮ͡Ό͋ςετ͸ͨ͘͞Μॻ͍ͨํ͕ྑ͍ΜͰ͢ͶʯͱͳΔͱɺඞͣ͠΋ͦ͏ͱ͸ݶΓ· ͤΜɻ ಛʹେ͖ͳػೳ։ൃͰ͸࣮૷͕ංେԽ͢Δ͜ͱ͕͋Γ·͕͢ɺ࣮૷Λٸ͙͋·Γ݁߹ςετͰ͢΂ ͯͷ৚݅෼ذΛ໢ཏ͠Α͏ͱ͢Δͱɺςετίʔυ͕มߋʹऑ͘ͳͬͯ෗Γ΍͘͢ͳΓ·͢ɻ ·ͨςετʹ͍࣮ͭͯ૷Λઌߦͨ݁͠Ռɺͦͷػೳ͕Կʹ࢖ΘΕΔ͔Ͱ͸ͳ࣮͘૷Ͱൃੜͨ͠৚ ݅෼ذΛ໢ཏ͢Δ͜ͱʹண໨ͯ͠͠·͏ͱɺςετίʔυ͸ϨϏϡʔ͢Δඞཁ͕ͳ͘ͳͬͯ͠·͍ 20
  23. ୈ 2 ষ ര଎Ͱ Approve ͕΋Β͑Δ Pull Request ͷ࡞Γํ 2.2

    ϨϏϡʔ͠΍͍͢ Pull Request ·͢ɻ Ϧετ 2.5: (bad)TestFetchUserCartInteractor_Execute func TestFetchuserCartInteractor_Execute(t *testing.T) { t.Run("line1: len(userCarts) > 0, err != nil", { // -- }) t.Run("line1: len(userCarts) > 0, err == nil", { // -- }) t.Run("line1: len(userCarts) == 0, err != nil", { // -- }) t.Run("line1: len(userCarts) == 0, err == nil", { // -- }) } ˙ίϥϜ: ςετίʔυͰৼΔ෣͍Λॻͨ͘Ίʹ ςετίʔυͰৼΔ෣͍Λهड़͢ΔͨΊʹ͸ɺίʔσΟϯάʹؔ͢ΔจԽ͕νʔϜͷڞ௨ج൫ ͱͯࠜ͠෇͍͍ͯΔඞཁ͕͋Γ·͢ɻօ͞Μͷॻ͍͍ͯΔϓϩάϥϜίʔυͷ΄ͱΜͲ͸ɺ͞· ͟·ͳؔ਺ͷ૊Έ߹ΘͤͰ͋Δͱࢥ͍·͕͢ɺͦΕͧΕͷؔ਺͕ͲͷΑ͏ͳೖྗʹରͯ͠ͲͷΑ ͏ͳग़ྗΛฦ͢ͷ͔ͱ͍͏఺ʹ͍ͭͯ৴པΛ࣋ͯͳ͍৔߹ɺςετίʔυ͸ (ࣗ෼ΛؚΊ) νʔ Ϝϝϯόʔͷهड़ͨ͠֎෦ؔ਺ͷڍಈʹ͍ͭͯৗʹک͑ΔඞཁʹഭΒΕ·͢ɻ ։ൃɾӡ༻Λߦ͍ͬͯ͘தͰɺίʔυ͕ύχοΫΛى͜͢৚݅΍໋໊نଇͳͲͷίʔσΟϯά ϧʔϧΛഓ͍ͬͯ͘͜ͱ͕ɺςετίʔυΛ؆ܿʹ͢ΔͨΊʹ໾ཱͭͰ͠ΐ͏ɻ ToDo ͕ଟ͍ ಛʹ։ൃͱاըͱ͕ີ઀ʹؔΘΔέʔεͰ͸։ൃ͠ͳ͕Β࢓༷Λࡦఆ͍ͯ͘͜͠ͱ͕͋Γ·͕͢ɺ ಛʹڍಈ͕ෆ໌ͳ΋ͷΛ ToDo ίϝϯτΛ͚ͭͯεΩοϓ͢Δ࣮૷͸ɺϨϏϡΞʔ͕কདྷΛ༧ଌ͢ Δඞཁ͕͋Δͱ͍͏఺ͰϨϏϡʔෛՙ͕େ͖͘ͳΓ·͢ɻ ·ͨϨϏϡΞʔ͔Βকདྷ࣮૷͢Δڍಈʹ͍࣭ͭͯ໰͞ΕΔͱ͍͏఺Ͱɺ࣮૷ऀଆ΁ͷෛ୲΋େ͖͘ ͳΓ·͢ɻ Ծʹ࢓༷ʹ͍ͭͯෆ໌఺͕͋Δ৔߹ʹ͸ɺՄೳͰ͋Ε͹ࣄલʹ֬ೝΛߦ͍ɺͦΕ͕೉͍͠৔߹Ͱ͸ Pull Request ͷઆ໌ʹิ଍͕͋Δͱྑ͍Ͱ͠ΐ͏ɻ 21
  24. ୈ 2 ষ ര଎Ͱ Approve ͕΋Β͑Δ Pull Request ͷ࡞Γํ 2.2

    ϨϏϡʔ͠΍͍͢ Pull Request ػೳ͕ಠཱ͍ͯ͠ͳ͍ େن໛։ൃͳͲͰෳ਺ͷ Pull Request ʹ෼ׂ͞Εͨͱ͖ɺςετίʔυͳͲͰͦΕͧΕͷػೳΛ ಠཱʹಈ࡞֬ೝͰ͖ͳ͍৔߹ɺଞͷ Pull Request ͷࠩ෼ΛಡΈͳ͕ΒϨϏϡʔΛߦ͏ඞཁ͕͋Γ ·͢ɻ ͢Δͱ͔ͤͬ͘ Pull Request Λ෼ׂͨ͠ͷʹϨϏϡΞʔ͕ Approve ͢Δͷ͸͢΂ͯͷ Pull Request ΛಡΜͩޙʹͳͬͯ͠·͍·͢ɻ͞Βʹ࢓༷ௐ੔΍ϨϏϡΞʔ͔Βͷࢦఠ͕ೖΔͱෳ਺ͷ Pull Request Λԣஅͯ͠मਖ਼Λߦ͏ඞཁ͕ൃੜ͠ɺ్த·ͰϨϏϡʔ͍ͯͨ͠ϨϏϡΞʔͷ࡞ۀ͸ ख໭ΓΛ༨ّͳ͘͞Ε·͢ɻ େن໛։ൃΛߦ͏ࡍʹ͸ɺࣄલʹͲͷΑ͏ʹઃܭΛਐΊ͍͔ͯ͘ͷํ਑Λݟੵ΋ͬͯॻ͖ग़͔ͯ͠ Β։ൃΛߦ͏ͱྑ͍Ͱ͠ΐ͏ɻ Өڹൣғ͕ෆ໌ େن໛ͳϓϩμΫτίʔυͰ͸ආ͚ͯ͸௨Εͳ͍ࢀরઌͷଟ͍ؔ਺ͷվमͰ͕͢ɺ͜Ε΋࣮૷ऀͱ ϨϏϡΞʔΛ೰·ͤΔ಄௧ͷछͰ͢ɻ มߋલޙͷৼΔ෣͍ͷมԽͷઆ໌΍ࣄલͷಈ࡞ݕূ΋͞Δ͜ͱͳ͕Βɺ͜͏͍ͬͨվमͰ͸ඞͣͱ ݴͬͯྑ͍΄Ͳൈ͚࿙Ε͕ൃੜ͢ΔͨΊɺϚʔδޙͷݕূ؀ڥͰͷ࠶֬ೝͷεέδϡʔϧΛ૊ΜͰ͓ ͘ͱνʔϜશମͷ৺ཧత҆શʹͭͳ͕Γ·͢ɻ ·ͨվमΛߦ͏લʹɺطଘڍಈΛมߋͤ͞ͳ͍··طଘ࣮૷ͷݟ௨͠Λྑ͘͢ΔԼ४උ΋༗ޮ Ͱ͢ɻ 22
  25. ୈ 2 ষ ര଎Ͱ Approve ͕΋Β͑Δ Pull Request ͷ࡞Γํ 2.3

    ϨϏϡʔʹઐ೦ͯ͠ؾ෇͍ͨ͜ͱ 2.3 ϨϏϡʔʹઐ೦ͯ͠ؾ෇͍ͨ͜ͱ ຊઅ͸ϨϏϡʔΛߦ͏લޙͰݸਓతͳҙࣝͷมԽ͕͋ͬͨ͜ͱʹ͍ͭͯͷײ૝ʹͳΓ·͢ɻ ϨϏϡʔʹ͸ࢥͬͨҎ্ʹ޻਺͕͔͔Δ ։ൃ෦Ͱ·Εʹ্͕Δ࿩୊ͱͯ͠ɺ։ൃ࣌ؒʹରͯ͠ Approve ͕΋Β͑Δ·Ͱͷ͕࣌ؒ௕͘ͳͬ ͯ͠·͍ϦϦʔε·Ͱͷظݶ͕ѹഭ͞Εͯ͠·͏ɺͱ͍͏͜ͱ΋ͷ͕͋Γ·͢ɻ ϨϏϡʔੜ׆Λ࢝ΊΔલ·Ͱ͸ɺϨϏϡʔࣗମͷ޻਺͕ೝ஌͞ΕͮΒ͍͜ͱ͔Βɺ։ൃ͔࣌ؒΒ Approve ͕΋Β͑Δ·Ͱͷ࣌ؒͷ΄ͱΜͲ͸ϨϏϡʔணख·Ͱͷ࣌ؒͩͱߟ͍͑ͯͨͷͰ͕͢ɺࠓ ճͷࢼΈͰϨϏϡʔணख͔ΒϨϏϡʔ׬ྃ·Ͱͷ࣌ؒ΋େ͖ͳׂ߹Λ઎Ί͍ͯͦ͏ͳ͜ͱ͕Θ͔Γ· ͨ͠ɻ ςετΛॻ͔ͳ͍ͱ͍͏બ୒ࢶ͸͋Δͷ͔ ಛʹϨϏϡʔͳͲͰख໭ΓͳͲ͸ଟ͘ൃੜ͠·͢ɻͦͯ͠ख໭ΓͷέʔεͰ͸΄ͱΜͲͷ৔߹Ͱ๲ େͳςετίʔυͷमਖ਼΋ηοτͰ࣮૷ऀʹͷ͔͔͠Γ·͢ɻ ͔ͨ͠ʹ࣮૷ํ਑΍࢓༷͕ݻ·͍ͬͯͳ͍࣌఺Ͱ࣮૷Λ༏ઌ͠ͳ͚Ε͹ͳΒͳ͍έʔεͰ͸ɺςε τέʔε͸࣮૷ऀͷෛ୲ͱͯ͠͸ඇৗʹେ͖͍΋ͷʹͳΓ·͢ɻ ҰํͰؔ਺Λ࣮૷͍ͯ͠ΔҎ্ɺΑ΄Ͳ෭࡞༻ͷڧ͍࣮૷Λ͍ͯ͠ͳ͍ݶΓೖྗͱग़ྗʹؔͯ͠͸ ݟ௨ཱ͕͍ͬͯ͠Δ͸ͣͰ͢ͷͰɺ࣮૷ऀͷҙਤͱϨϏϡΞʔͷҙਤΛͦΖ͑ΔͨΊʹɺ࠷௿ݶਖ਼ৗ ܥʹؔͯ͠͸ςετέʔεΛ༻ҙͨ͠Γɺ࣮૷ํ਑΍࢓༷͕ܾ·Δ·Ͱ͸ৼΔ෣͍ͷςετέʔεͷ εέϧτϯΛ࡞੒͓͍ͯͨ͠Γɺͱ͍ͬͨ͜ͱ͕Ͱ͖ΔͷͰ͸ͳ͍͔ͱߟ͍͑ͯ·͢ɻ 2.4 ͋ͱ͕͖ ຊষͰ͸ɺϨϏϡʔͱ͍͏؍఺͔Β Pull Request ͷ Approve Λ΋Β͍΍͘͢͢ΔͨΊͷཁૉΛ ঺հ͖ͯ͠·ͨ͠ɻ ࣗ෼͸ϨϏϡʔͱ͍͏׆ಈΛ௨ͯ͠ɺ࣮૷Λߦ͏ͨΊͷεΩϧɾϚΠϯυ΋͞Δ͜ͱͳ͕Βɺνʔ ϜͰϓϩμΫτΛ࡞Δࢹ఺Λ࣋ͪͳ͕Βઃܭɾ։ൃΛߦ͏͜ͱͷॏཁ͞Λ௧ײ͠·ͨ͠ɻ ࠓޙ͸͜͜·ͰͷֶͼΛ׆༻͢Δͱͱ΋ʹɺϨϏϡʔணख͔Β Approve ·Ͱͷ޻਺Λࢹ֮Խ͢Δ ͜ͱͰɺࢪࡦશମͷ଎౓޲্΁࣋ͪࠐΜͰ͍͘͜ͱΛ໨ඪͱ͍ͯ͠·͢ɻ 23
  26. ୈ 3 ষ Haskell Ͱઢܗܕ Haskell ͷσϑΝΫτελϯμʔυͳॲཧܥͰ͋Δ GHC ʹ͸ɺ2021 ೥

    2 ݄ʹϦϦʔε͞Εͨόʔ δϣϯ 9.0 ͔ΒʮઢܗܕʢLinear Typesʣ ʯͱݺ͹ΕΔػೳ͕௥Ճ͞Ε·ͨ͠*1ɻݱࡏʢ2023 ೥ 10 ݄ʣͷ GHC ͷ࠷৽όʔδϣϯ͸ 9.8 Ͱ͢*2ɻͭ·Γɺઢܗܕ͕ಋೖ͞Ε͔ͯΒͦͦ͜͜ͷόʔδϣ ϯ͕ܦ͍ͬͯ·͢ɻͦ͜ͰͦΖͦΖɺઢܗܕʹ͍ͭͯ೺Ѳ͓ͯ͘͠΂͖͔ͳͱࢥ͍ɺௐ΂ͯ·ͱΊΔ ͜ͱʹͯ͠Έ·ͨ͠ɻ ͕ɺͪΐ͏Ͳઢܗܕʹ͍ͭͯௐ΂Α͏ͱࢥͬͨλΠϛϯάͰʮHaskell ͸ Rust ʹͳΕΔͷ͔ʁ ᴷ ᴷ 2023 ೥ͷ Linear Haskell ମݧهʯͱ͍͏ઢܗܕͷݱࡏΛ·ͱΊͯ͘ΕͨΑ͏ͳ׬ᘳͰڀۃͳ೔ຊ ޠهࣄ͕ग़͖͖ͯͯ͘ΕͨͷͰɺਖ਼௚·ͱΊΔඞཁ͕ͳ͘ͳͬͯ͠·͍·ͨ͠*3ɻ͕ɺ͔ͤͬ͘ࢥ͍ ཱͬͨͷͰɺΊ͛ͣʹهࣄΛॻ͜͏ͱࢥ͍·͢ɻ ຊߘʹࡌ͍ͤͯΔιʔείʔυ͸͢΂ͯ matsubara0507/linear-haskell ͱ͍͏ GitHub Ϧϙδτ Ϧʹ͓͍ͯ͋Γ·͢*4ɻ 3.1 Haskell ͷઢܗܕ Haskell Ͱؔ਺ͷܕΛॻ࣌͘ʹ͸ a -> b ͷΑ͏ʹॻ͖·͢ɻa ͕͍ΘΏΔҾ਺ͷܕͰɺb ͕໭Γ ஋ͷܕͰ͢ɻGHC 9.0 ͔Βಋೖ͞Εͨ LinearTypes ݴޠ֦ு*5Λ࢖͏͜ͱͰɺؔ਺ͷܕΛ a %1-> b ͱ΋ॻ͚·͢ɻ͜Ε͕ઢܗܕʢLinear TypesʣͰ͢ɻa ͕Ҿ਺ͷܕͰ b ͕໭Γ஋ͷܕͳͷ͸มΘ Γ·ͤΜ͕ɺؔ਺ͷ͢΂ͯͷ෼ذͰʮҾ਺ΛҰ౓͚ͩඞͣ࢖͏ʯͱ͍͏੍໿Λ՝͠·͢ɻ {-# LANGUAGE LinearTypes #-} *1 https://downloads.haskell.org/ghc/9.0.1/docs/html/users_guide/exts/linear_types.html *2 https://downloads.haskell.org/ghc/9.8.1/docs/users_guide/9.8.1-notes.html *3 https://zenn.dev/konn/articles/2023-10-01-linear-haskell-in-2023 *4 https://github.com/matsubara0507/linear-haskell *5 GHC ʹ͸ݴޠ֦ுʢLanguage Extensionʣͱݺ͹ΕΔػೳ܈͕͋Γɺ͜ΕΛར༻͢Δ͜ͱͰॲཧܥͷ࣋ͭػೳΛ֦ ுͰ͖·͢ɻ୯७ͳ౶ҥߏจͷ௥ՃͷΑ͏ͳ֦ு΋͋Ε͹ɺઢܗܕͷΑ͏ͳܕγεςϜΛ͍͡ΔΑ͏ͳ֦ு΋ͨ͘͞Μ ͋Γ·͢ɻ 25
  27. ୈ 3 ষ Haskell Ͱઢܗܕ 3.2 ࢼ͢ɿιʔτ -- ʮҾ਺ΛҰ౓͚ͩඞͣ࢖͏ʯͱ͍͏ͷ͸ެࣜυΩϡϝϯτᐌ͘ f1,

    f2 :: a %1-> a f1 x = x -- Ҿ਺Λͦͷ··ฦ͔͢ f2 x = f1 x -- Ҿ਺Λઢܗؔ਺ʹ౉͢ -- ͜Ε͸μϝ -- f2’ :: a %1-> a -- f2’ x = id x -- ύλʔϯϚονΛ֤ͯ͠Ҿ਺ΛҰ౓͚ͩͣͭ࢖͏ f3 :: (a, b) %1-> (a, b) f3 (x, y) = (f1 x, y) -- ؔ਺Ͱ͋Ε͹ɺҰ౓͚ͩݺͼग़͠ɺͦͷ໭Γ஋΋1͚ͩ࢖͏ f4 :: (a -> a) %1-> a -> a f4 f x = f1 (f x) ݪ࿦จᐌ͘ɺ͜ͷ Haskell ͷઢܗܕʹ͸ҎԼͷ 2 ͭͷϢʔεέʔεʹয఺Λ౰͍ͯͯΔͦ͏Ͱ͢ɿ 1. ഑ྻͷΑ͏ͳϛϡʔλϒϧͳσʔλܕʹରͯ҆͠શͳ update-in-place Λఏڙ͢Δ 2. ϑΝΠϧ΍ιέοτͷΑ͏ͳ֎෦Ϧιʔεͷૢ࡞ʹରͯ͠ڧ੍͢ΔखஈΛఏڙ͢Δ લऀʹؔͯ͠͸ɺΠϛϡʔλϒϧͳσʔλߏ଄ΑΓϛϡʔλϒϧͳσʔλߏ଄ͷํ͕ޮ཰ྑ͘ΞΫ ηεͰ͖ΔͨΊɺΑΓޮ཰తͳॲཧΛ࣮ݱͰ͖ΔΒ͍͠Ͱ͢ɻޙऀʹؔͯ͠͸ɺޮ཰ʹ͸ؔ܎ͳ͘ɺ ܕݕࠪʹΑͬͯΑΓ҆શͳϓϩάϥϛϯάΛαϙʔτ͢Δͷ͕໨తΒ͍͠Ͱ͢ɻ 3.2 ࢼ͢ɿιʔτ લड़ͨ͠ϢʔεέʔεͷҰ͕ͭʮϛϡʔλϒϧͳ഑ྻΛ҆શʹѻ͑Δʯͱ͍͏΋ͷͰͨ͠ɻϛϡʔ λϒϧͳ഑ྻͱ͍͑͹ιʔτΞϧΰϦζϜͰ͢Ͷɻͱ͍͏͜ͱͰɺ͋·Γ࣮༻తͳྫͰ͸ͳ͍Ͱ͢ ͕ɺιʔτΛઢܗܕͰ࣮૷ͯ͠Έ·͢ɻ ϛϡʔλϒϧͳ഑ྻ ઢܗܕʹରԠͨ͠ܕ΍ؔ਺Λར༻͢Δʹ͸ linear-base ύοέʔδΛ࢖͍·͢*6ɻlinear-base ύο έʔδͷ Data.Array.Mutable.Linear Ϟδϡʔϧ͕ϛϡʔλϒϧͳ഑ྻΛද͢ Array ܕͱ࣍ͷ Α͏ͳؔ਺Λఏڙ͍ͯ͠·͢ɻ -- ࢦఆͨ͠ΠϯσοΫεͷ஋Λࢀর͢Δ Array.get :: Int -> Array a %1 -> (Ur a, Array a) *6 ຊهࣄͰ͸όʔδϣϯ 0.4.0 Λ࢖͍ͬͯ·͢ɻhttps://hackage.haskell.org/package/linear-base-0.4.0 26
  28. ୈ 3 ষ Haskell Ͱઢܗܕ 3.2 ࢼ͢ɿιʔτ -- ࢦఆͨ͠ΠϯσοΫεʹ஋Λ୅ೖ͢Δ Array.set

    :: Int -> Array a %1 -> Array a -- ഑ྻͷαΠζΛฦ͢ Array.size :: Array a %1 -> (Ur a, Array a) ઢܗܕͰ͸஋ΛҰ౓͔͠࢖͑ͳ͍ͨΊɺͲΕ΋ Array a ܕͷ஋Λฦ͓ͯ͠Γɺ͜ΕΛ਺चͭͳ͗ ͷΑ͏ʹར༻͍ͯ͘͠Θ͚Ͱ͢ɻUr ܕ͸ Unrestricted ͷུͰɺ͜Εʹแ·Εͨ஋͸ԿճͰ΋࠶ར༻ Ͱ͖·͢*7ɻ swap ؔ਺ ιʔτͰҰ؏ͯ͠࢖ΘΕΔͷ͸ 2 ͭͷΠϯσοΫεͰͷೖΕସ͑Ͱ͢ɻͳͷͰ·ͣ͸ɺࢦఆͨ͠ 2 ͭͷΠϯσοΫεͷ஋ΛೖΕସ͑Δؔ਺Λ࣮૷ͯ͠Έ·͢ɻ {-# LANGUAGE LinearTypes, NoImplicitPrelude #-} import Prelude.Linear import Data.Array.Mutable.Linear (Array) import qualified Data.Array.Mutable.Linear as Array swap :: Int -> Int -> Array Int %1 -> Array Int swap i j arr = Array.get i arr & \(Ur ival, arr’) -> Array.get j arr’ & \(Ur jval, arr’’) -> Array.set i jval (Array.set j ival arr’’) Array.get Ͱ·ͣ 2 ͭͷ஋ΛऔΓग़͠ɺͦΕΛ Array.set ͰೖΕସ͑ͯอଘ͍ͯ͠Δ͚ͩͷ࣮ ૷Ͱ͢ɻͨͩɺ਺चͭͳ͗ʹ͞Εͯ͠·ͬͯύοͱಡΈʹ͍͘Ͱ͢ʢਓʹΑΔͱࢥ͍·͕͢ʣ ɻجຊ తʹιʔτΞϧΰϦζϜ͸ Array Int Λ਺चͭͳ͗ʹ͍͚ͯͩ͘͠Ͱ͢ͷͰɺState Ϟφυʹͯ͠ ͠·͍·͠ΐ͏ɻ {-# LANGUAGE QualifiedDo #-} import Control.Functor.Linear as Linear type SArray a = State (Array a) *7 ࣮͸΍͍ͬͯΔ͜ͱ͸؆୯ͰɺUr ܕͷ஋ߏஙࢠ Ur ͕ඇઢܗͳߏஙࢠͱͯ͠એݴ͞Ε͍ͯΔ͚ͩͰ͢ɻ 27
  29. ୈ 3 ষ Haskell Ͱઢܗܕ 3.2 ࢼ͢ɿιʔτ swap :: Int

    -> Int -> SArray a () swap i j = Linear.do Ur ival <- state (Array.get i) Ur jval <- state (Array.get j) modify (Array.set j ival) modify (Array.set i jval) खଓతʹͳͬͯಡΈ΍͘͢ͳΓ·ͨ͠ʢਓʹΑΔͱࢥ͍·͕͢ʣ ɻState Ϟφυͱݴͬͯ΋࢖͏ͷ ͸ɺઢܗܕʹͨ͠ State ϞφυͰ͢ɻͦΕ͕ linear-base ͷ Control.Functor.Linear Ϟδϡʔ ϧʹ͋Γ·͢ɻ·ͨɺઢܗܕͷϞφυʹରͯ͠ do ه๏Λ࢖͏ʹ͸ QualifiedDo ݴޠ֦ு͕ඞཁʹ ͳΓ·͢ɻ όϒϧιʔτ ·ͣ͸؆୯ͳόϒϧιʔτ͔Β࣮૷ͯ͠Έ·͢ɻόϒϧιʔτ͸ɺ಄͔Βॱ൪ʹݟ͍ͯͬͯ࠷খͷ ΋ͷΛҰ൪୺ʹஷΊ͍ͯ͘Α͏ͳΞϧΰϦζϜͰ͢ɻ഑ྻΛॱ൪ʹΠϯσοΫεΞΫηε͍ͯ͘͠ͷ Ͱɺศརͳߴ֊ؔ਺Λఆ͓͖ٛͯ͠·͢ɻ upto :: Int -> Int -> (Int -> SArray a ()) -> SArray a () upto start end f = go start where go n | n > end = return () | otherwise = f n >> go (n + 1) downto :: Int -> Int -> (Int -> SArray a ()) -> SArray a () downto start end f = go start where go n | n < end = return () | otherwise = f n >> go (n - 1) start ͔Β end ·Ͱɺupto ͸ঢॱʹɺdownto ͸߱ॱʹॲཧ͍͚ͯͩ͘͠Ͱ͢ɻ͜Εͱ swap ؔ ਺Λ࢖ͬͯɺόϒϧιʔτ͸࣍ͷΑ͏ʹॻ͚·͢ɻ bubbleSort :: [Int] -> [Int] bubbleSort = execSArray $ Linear.do Ur len <- state Array.size upto 0 (len - 1) $ \i -> downto (len - 1) (i + 1) $ \j -> Linear.do Ur jval <- state (Array.get j) Ur jval’ <- state (Array.get (j - 1)) 28
  30. ୈ 3 ষ Haskell Ͱઢܗܕ 3.2 ࢼ͢ɿιʔτ if jval >

    jval’ then return () else swap j (j - 1) execSArray :: SArray Int () -> [Int] -> [Int] execSArray f xs = unur $ Array.fromList xs (Array.toList . execState f) execSArray ؔ਺͸Ϧετͱϛϡʔλϒϧͳ഑ྻͷม׵ΛΑ͍ײ͡ʹͯ͘͠ΕΔ͚ͩͷؔ਺Ͱ͢ɻ bubbleSort ؔ਺͸ɺupto ؔ਺Λ࢖ͬͯઌ಄͔Βॱʹɺ@<downto> ؔ਺Λ࢖ͬͯҰ൪࠷ޙ͔Βࣗ ෼·ͰͷؒͰ࠷΋খ͍͞஋Λ͖͍࣋ͬͯͯ·͢ɻ ώʔϓιʔτ ࣍ʹɺόϒϧιʔτΑΓߴ଎ͳώʔϓιʔτΛ࣮૷ͯ͠Έ·͢ɻώʔϓιʔτͷΞϧΰϦζϜ ͸ɺҰݴͰઆ໌͠ʹ͍͘ͷͰׂѪ͠·͕͢ɺೋ෼ώʔϓ໦ͱ͍͏σʔλߏ଄Λར༻͠·͢ɻී௨ͷ Haskell Ͱ࣮૷͢ΔͷͰ͋Ε͹ೋ෼໦Λ୅਺తσʔλܕͰදݱ࣮ͯ͠૷͢Δͷ͕Ұൠత͔ͱࢥ͍· ͢ɻઢܗܕ͸ϛϡʔλϒϧͳ഑ྻΛ҆શʹѻ͑ΔͷͰɺࠓճ͸഑ྻͷ্Ͱೋ෼໦ΛγϛϡϨʔτͯ͠ ࣮૷͠·͢ɻ ώʔϓιʔτͰ͸ɺೋ෼໦ͷதͰ͕ࠜ࠷େ஋ʹͳͬͨঢ়ଶʢ࠷େώʔϓʣΛԿ౓΋ߏங͍͖ͯ͠· ͢ɻ·ͣ͸ɺͦͷؔ਺Λఆٛ͠·ͨ͠ɻ maxHeap :: Int -> Int -> SArray Int () maxHeap root bottom = Linear.do Ur child <- maxIndex left right bottom Ur root’ <- maxIndex root child bottom if root’ == root then return () else Linear.do swap child root maxHeap child bottom where left = (root * 2) + 1 right = (root * 2) + 2 -- 2ͭͷΠϯσοΫεͷ஋Λൺֱͯ͠ɺେ͖͍ํͷΠϯσοΫεΛฦ͢ maxIndex :: Int -> Int -> Int -> SArray Int (Ur Int) maxIndex i j bottom | j > bottom = return (Ur i) | otherwise = Linear.do Ur ival <- state (Array.get i) Ur jval <- state (Array.get j) return $ Ur (if ival >= jval then i else j) 29
  31. ୈ 3 ষ Haskell Ͱઢܗܕ 3.2 ࢼ͢ɿιʔτ લड़ͨ͠௨ΓɺώʔϓιʔτͰ͸ೋ෼໦Λߟ͑·͢ɻ਌ͱ 2 ͭͷࢠͷ஋Λൺֱͯ͠ɺ࠷େ஋͕ࠜʹ

    ͳΔΑ͏ʹ஋ΛೖΕସ͍͖͑ͯɺͦΕΛ্͔Βॱ൪ʹ܁Γฦ͍ͯ͠·͢ɻ਌ࢠͷ࠷େ஋͕Ͳ͔͜Λௐ ΂ΔͨΊʹ maxIndex ؔ਺Λ࢖͍·͢ɻ͜Ε͸ɺ༩͑ͨ 2 ͭͷΠϯσοΫεͷ஋Λൺֱͯ͠ɺେ͖ ͍ํͷΠϯσοΫεΛฦ͚ͩ͢Ͱ͢ɻ ͦͯ͠ɺmaxHeap ؔ਺Λ࢖ͬͯώʔϓιʔτ͸࣍ͷΑ͏ʹॻ͚·͢ɻ heapSort :: [Int] -> [Int] heapSort = execSArray $ Linear.do Ur len <- state Array.size downto ((len - 1) ‘div‘ 2) 0 $ \n -> maxHeap n (len - 1) downto (len - 1) 1 $ \n -> Linear.do swap 0 n maxHeap 0 (n - 1) downto ͕ 2 ճग़͖ͯ·͢ɻ1 ճ໨͸ɺ͍ΘΏΔॳظԽͷΑ͏ͳॲཧͰ͢ɻ(len - 1) ‘div‘ 2 ͱ͍͏ͷ͸ɺҰ൪Լͷ਌Ͱ͢ɻҰ൪Լͷ਌͔Βॱ൪ʹ maxHeap ΛݺͿ͜ͱͰɺ࠷΋؆୯ͳ࠷େώʔ ϓΛߏங͍ͯ͠·͢ɻ࠷େώʔϓ͕ߏஙͰ͖ͨͱ͍͏͜ͱ͸ɺҰ൪্ͷ͕ࠜݱࡏͷ࠷େ஋ʹͳΔͷ Ͱɺ͜ΕΛ഑ྻͷҰ൪࠷ޙͷ஋ͱೖΕସ͑·͢ɻͦͯ͠ɺҰ൪࠷ޙͷ஋Λআ͍ͯɺ·ͨ࠷େώʔϓΛ ߏங͠௚͠·͢ɻࠓ౓͸ॳظԽͱҧͬͯ΄΅࠷େώʔϓͱಉͩͬͨ͡ͷͰɺҰճ͚ͩ maxHeap Λݺ Ϳ͚ͩͰɺͰ͖͕͋Γ·͢ɻ͜ͷ܁Γฦ͠Λ 2 ճ໨ͷ downto Ͱߦ͍ͬͯ·͢ɻ ΫΠοΫιʔτ ࠷ޙʹΫΠοΫιʔτͰ͢ɻΫΠοΫιʔτ͸ linear-base ʹαϯϓϧίʔυ͕͋Γ·͢ɻͦΕΛ State ϞφυͰஔ͖׵͑ͨ΋ͷ͕ͪ͜ΒͰ͢ɿ quickSort :: [Int] -> [Int] quickSort = execSArray $ Linear.do Ur len <- state Array.size go 0 (len - 1) where go :: Int -> Int -> SArray Int () go lo hi | lo >= hi = return () | otherwise = Linear.do Ur pivot <- state (Array.get lo) Ur ix <- partition pivot lo hi swap lo ix go lo (ix - 1) go (ix + 1) hi partition :: Int -> Int -> Int -> SArray Int (Ur Int) 30
  32. ୈ 3 ষ Haskell Ͱઢܗܕ 3.2 ࢼ͢ɿιʔτ partition pivot lx

    rx | rx < lx = return $ Ur (lx - 1) | otherwise = Linear.do Ur lval <- state (Array.get lx) Ur rval <- state (Array.get rx) case (lval <= pivot, pivot < rval) of (True, True) -> partition pivot (lx + 1) (rx - 1) (True, False) -> partition pivot (lx + 1) rx (False, True) -> partition pivot lx (rx - 1) (False, False) -> swap lx rx >> partition pivot (lx + 1) (rx - 1) ΫΠοΫιʔτ͸ɺϐϘοτͱ͍͏ᮢ஋ʹͳΔ஋Λద౰ʹܾΊͯɺϐϘοτΑΓখ͍͞΋ͷΛࠨʹ େ͖͍΋ͷΛӈʹूΊͯɺ͞ΒʹूΊͨ΋ͷͰ·ͨϐϘοτΛܾΊͯɺͱ܁Γฦ͍ͯ͘͠ΞϧΰϦ ζϜͰ͢ɻpartition ؔ਺͕ʮϐϘοτΑΓখ͍͞΋ͷΛࠨʹେ͖͍΋ͷΛӈʹूΊͯʯ͍Δײ͡ Ͱ͢ɻ ޮ཰͸ྑ͘ͳͬͨͷ͔ tasty-bench ύοέʔδΛ࢖ͬͯϕϯνϚʔΫΛऔͬͯΈ·ͨ͠*8ɻ {-# LANGUAGE BangPatterns #-} module Main (main) where import Control.Monad import System.Random import Test.Tasty.Bench import Sort import qualified Linear.Sort as L mkBench :: String -> ([Int] -> [Int]) -> [Int] -> Benchmark mkBench s f xs = bench s $ nf f xs main :: IO () main = do !r1 <- randomList 10000 10000 defaultMain [ mkBench "heap sort (10^4)" heapSort r1 , mkBench "linear heap sort (10^4)" L.heapSort r1 ] randomList :: Int -> Int -> IO [Int] randomList n boundary = replicateM n (getStdRandom (randomR (0, boundary))) *8 https://hackage.haskell.org/package/tasty-bench-0.3.5 31
  33. ୈ 3 ষ Haskell Ͱઢܗܕ 3.2 ࢼ͢ɿιʔτ ී௨ͷώʔϓιʔτ͸ࢁຊ࿨඙ࢯͷϒϩάهࣄʮؔ਺ϓϩάϥϛϯάͷָ͠Έ - ͋Ͳ͚ͳ͍࿩ʯʹ

    ͋ͬͨ΋ͷΛഈआ͠·ͨ͠*9ɻ ʮؔ਺ϓϩάϥϛϯάͷָ͠Έʯͱ͍͏ॻ੶*10ͷ࿩Λࢀߟʹͯ͠ɺ୅ ਺తσʔλܕʹΑΔ໦ߏ଄Λར༻ͨ͠ޮ཰తͳώʔϓιʔτΛ࣮૷ͨͦ͠͏Ͱ͢ɻͦͯ͠ɺ݁Ռ͕͜ ͪΒɻ % stack exec bench -- +RTS -T All heap sort (10^4): OK (1.17s) 4.54 ms ʶ 430 Жs, 19 MB allocated, 2.2 MB copied, 9.0 MB peak memory linear heap sort (10^4): OK (1.23s) 40.1 ms ʶ 3.5 ms, 275 MB allocated, 447 KB copied, 9.0 MB peak memory ͏ʔΜɺμϝͰ͢Ͷসɻࢼ͠ʹɺState ϞφυΛͳͤ͘͹ଟগૣ͘ͳΓ·͕ͨ͠ɺ͞΄ͲมԽ͸ͳ ͍ͷͰࠜຊతʹԿ͔͕ؒҧ͍ͬͯͦ͏Ͱ͢ɻ͍͢·ͤΜɻݪҼ·Ͱ͸Θ͔Βͳ͔ͬͨͰ͢ɻ ͓·͚ɿϚʔδιʔτ Ϛʔδιʔτ͸ Haskell ͷ sort ؔ਺Ͱ΋࠾༻͞Ε͍ͯΔΞϧΰϦζϜͰɺ͓ͦΒ͘ Haskell ͱ ͸͞΄Ͳ૬ੑ΋ѱ͘ͳ͍͸ͣͰ͢ɻ͔͠͠ɺઢܗܕͷಋೖͷཱ໾ऀͰ͋Δ Tweag ͱ͍͏ձࣾͷϒϩ άͰ͸ɺϚʔδιʔτʹ͍ͭͯͷهࣄ΋͋Γ·ͨ͠*11ɻ࣮͸͜ͷهࣄ͸ɺ഑ྻΛ࢖ͬͯιʔτͷύ ϑΥʔϚϯεΛྑ͘͢Δͱ͍͏࿩Ͱ͸ͳ͘ɺϦετ͕ιʔτࡁΈͱ͍͏੍໿ΛઢܗܕΛ࢖ͬͯઃ͚Δ ͜ͱͰɺΑΓ҆શͳϓϩάϥϛϯάΛ࣮ݱ͢ΔΑͬͯ࿩ͬΆ͍Ͱ͢ɻ {-# LANGUAGE ScopedTypeVariables #-} newtype SortedList a = Sorted [a] deriving (Show) fromList :: forall a. OrdL a => [a] %1 -> SortedList a fromList [] = Sorted [] fromList [a] = Sorted [a] fromList xs = go (split xs) where go :: ([a], [a]) %1 -> SortedList a go (left, right) = merge (fromList left) (fromList right) split :: [a] %1 -> ([a], [a]) split = undefined merge :: forall a. OrdL a => SortedList a %1 -> SortedList a %1 -> SortedList a *9 https://kazu-yamamoto.hatenablog.jp/entry/20100617/1276741517 *10 https://shop.ohmsha.co.jp/shopdetail/000000001859/ *11 https://www.tweag.io/blog/2018-03-08-linear-sort/ 32
  34. ୈ 3 ষ Haskell Ͱઢܗܕ 3.2 ࢼ͢ɿιʔτ merge = undefined

    Ϛʔδιʔτ͸ϦετΛద౰ʹ൒෼ʹ͍͖ͯ͠ɺ൒෼ͣͭͷϦετΛ߹ମ͢Δͱ͖ʹখ͍͞ํ͔ ΒϦετͷઌ಄ʹ࣋ͬͯ͘ΔΑ͏ͳΞϧΰϦζϜͰ͢ɻ߹ମ͢Δͱ͖ʹɺ2 ͭͷϦετ͕ͦΕͧΕͰ ιʔτࡁΈͰ͋Ε͹ઌ಄Ͳ͏͠Λൺֱ͢Δ͚ͩͰྑ͍ͷ͕ΩϞͰ͢Ͷɻͦͷιʔτ͞Ε͍ͯΔঢ়ଶΛ SortedList a ܕͰදݱ͍ͯ͠·͢ɻ·ͨɺ൒෼ʹ͢Δ split ؔ਺ͱ߹ମ͢Δ merge ؔ਺͸ઢܗ ܕʹͳ͍ͬͯΔͷͰɺཁૉ͕ࣦΘΕͨΓॏෳͨ͠Γ͍ͯ͠ͳ͍͜ͱΛอূ͍ͯ͠·͢ɻͨͩ͠ɺOrd L ܕΫϥε͸ Unrestricted ͷ෦෼ΛӅณͨ͠ Ord ܕΫϥεͰɺৄ͘͠͸ޙड़͠·͢ɻ ෼ׂͷॲཧ͸ಛʹ೉͍͜͠ͱ͸ͳͯ࣍͘ͷΑ͏ʹͳΓ·͢ɻ split :: [a] %1 -> ([a], [a]) split [] = ([], []) split [x] = ([x], []) split (x:y:z) = go (x, y) (split z) where go :: (a, a) %1 -> ([a], [a]) %1 -> ([a], [a]) go (a, b) (ax, bx) = (a:ax, b:bx) ۮ਺൪໨ͱح਺൪໨Ͱ෼͚͍ͯΔ͚ͩͰ͢ɻରͯ͠ɺ߹ମͷؔ਺͸ OrdL ܕΫϥεͱ߹Θͤͯ࣍ͷ Α͏ʹͳΓ·͢ɻ merge :: forall a. OrdL a => SortedList a %1 -> SortedList a %1 -> SortedList a merge (Sorted []) bs = bs merge as (Sorted []) = as merge (Sorted (a:as)) (Sorted (b:bs)) = go (compareL a b) (Sorted as) (Sorted bs) where go :: (Ordering, a, a) %1 -> SortedList a %1 -> SortedList a %1 -> SortedList a go (EQ, k, l) ks ls = k ‘cons‘ (l ‘cons‘ merge ks ls) go (LT, k, l) ks ls = k ‘cons‘ merge ks (l ‘cons‘ ls) go (GT, k, l) ks ls = l ‘cons‘ merge (k ‘cons‘ ks) ls cons :: a %1 -> SortedList a %1 -> SortedList a cons x (Sorted xs) = Sorted (x : xs) class OrdL a where compareL :: a %1 -> a %1 -> (Ordering, a, a) compareL ؔ਺Ͱൺֱͯ͠ɺখ͔ͬͨ͞ํΛઌ಄ʹ࿈͍݁ͯ͠Δ͚ͩͰ͢Ͷɻ͜ͷΑ͏ͳ੍໿ͱ͠ ͯͷ࢖͍ํ΋ɺҰԠͰ͖ΔΒ͍͠Ͱ͢ɻ 33
  35. ୈ 3 ষ Haskell Ͱઢܗܕ 3.3 ऴΘΓʹ 3.3 ऴΘΓʹ ͋·Γ࣮༻తͳ࣮૷͸Ͱ͖·ͤΜͰ͕ͨ͠ɺ݁ߏ༡΂ָ͔ͯͬͨ͠Ͱ͢ɻͨͩ΍͸ΓɺઢܗܕΛ༗

    ޮʹѻ͏ʹ͸͔ͳΓ೉ͦ͠͏Ͱͨ͠ʢ೉͔ͬͨ͠ʣ ɻͱ͸͍͑ࠓ౓͸ɺ΋͏ҰͭͷϢʔεέʔεͰ͋ ΔϦιʔε؅ཧʹ͍ͭͯɺFFI ΍ιέοτϓϩάϥϛϯάͳͲͰࢼ͍ͨ͠ͳͱ΋ࢥͬͯ·͢ɻ 34
  36. ୈ 4 ষ Flutter test ઓུ Flutter ΞϓϦέʔγϣϯʹ͓͍ͯɺϓϩδΣΫτن໛͕େ͖͘ͳΔʹͭΕͯίʔυͷมߋʹର͢ Δίετ͸ංେԽ͍͖ͯ͠·͢ɻCI Λ༻͍ͯ൓෮తͰద੾ͳࣗಈςετΛ૸ΒͤΔ͜ͱͰίʔυͷ

    มߋʹର͢ΔγεςϜ৴པੑͷ୲อ΍ϨϏϡʔෛՙͷܰݮΛਤΔ͜ͱ͕Ͱ͖·͢ɻ ຊষͰ͸ Flutter ΞϓϦέʔγϣϯʹ͓͚Δద੾ͳςετઓུͷߟ͑ํ΍ɺޮ཰తͳςετίʔυ Λॻ͘ํ๏ʹ͍ͭͯ঺հ͠·͢ɻ 4.1 ޮ཰తͳࣗಈςετͷߏ੒ ςετϐϥϛου ςετ਺͕૿͑Ε͹૿͑Δ΄Ͳࣗಈςετͷอकίετ͸૿େ͍͖ͯ͠·͢ɻͦ͜Ͱɺࣗಈςετ Λ͍͔ͭ͘ͷछྨʹ෼ྨ͠ɺͦΕͧΕʹ༏ઌ౓Λ͚ͭΔ͜ͱͰॆ࣮ͤ͞Δ΂͖ςετʹूதͯ͠ίε τΛׂ͚ΔΑ͏ʹ࠷దԽ͍͖ͯ͠·͢ɻ ςετ͸Ұൠతʹେ͖͘ 3 ͭͷཻ౓ʹ෼͚ΒΕɺখ͍͞΋ͷ͔ΒʮϢχοτςετʯ ʮΠϯςάϨʔ γϣϯςετʯ ʮE2E ςετʯͱ෼ྨͰ͖·͢ɻ͜ΕΒͷςετछ͸ɺҰൠతʹཻ౓ͷখ͍͞छྨͷ ςετΛΑΓॆ࣮͍ͤͯ͘͜͞ͱ͕ӡ༻ίετ࠷దԽɾγεςϜ৴པੑ୲อͷ؍఺Ͱཧ૝ͱ͞Ε͍ͯ ·͢ɻ 35
  37. ୈ 4 ষ Flutter test ઓུ 4.1 ޮ཰తͳࣗಈςετͷߏ੒ ਤ 4.1:

    ςετϐϥϛου ςετϐϥϛου͸ 70ɿ20ɿ10 ͷൺ཰Ͱߏ੒͞Ε͍ͯ·͢ɻ ςεταΠζ ςεταΠζ͸ςετର৅ͷಛ௃ʹΑͬͯ SmallɺMediumɺLarge ͷ̏λΠϓʹ෼ྨͰ͖·͢ɻ Small ͸ 100ms ະຬͰ࣮ߦ׬ྃ͠ɺDB ΍ ֎෦ API ͳͲͷ֎෦ϦιʔεʹΞΫηε͠ͳ͍ςε τͰ͢ɻMedium ͸ 2s ະຬͰ࣮ߦ׬ྃ͠ɺ֎෦ϦιʔεʹΞΫηε͢Δ͕ localhost ಺Ͱ׬݁͢Δ ςετͰ͢ɻ Large ͸ 120s ະຬͰ࣮ߦ׬ྃ͠ɺlocalhost ֎ͷ֎෦ϦιʔεͷΞΫηε΋ؚΊͨ୯ ҰΞϓϦ্ͷςετͰ͢ɻ Small ςετ͸ϞοΫ΍ελϒΛۃྗ࢖༻ͤͣɺΑΓ஧࣮ੑΛ୲อ͢Δ͜ͱΛେ੾ʹ͠·͢ɻ 36
  38. ୈ 4 ষ Flutter test ઓུ 4.2 Ϣχοτςετ 4.2 Ϣχοτςετ

    جຊతͳ dart ςετίʔυͷॻ͖ํ ςετΛॻ͘ࡍʹ͸·ͣɺςετର৅ͷؔ਺΍ϝιου͕ਖ਼͘͠ಈ࡞͢Δ͔ͷجຊతͳςετΛॻ ͘͜ͱΛਪ঑͠·͢ɻҎԼ͸ɺDart ͷςετίʔυͷجຊతͳྫͰ͢ɻ @testWidgets(’Counter increments smoke test’, (WidgetTester tester) async { await tester.pumpWidget(MyApp()); expect(find.text(’0’), findsOneWidget); expect(find.text(’1’), findsNothing); await tester.tap(find.byIcon(Icons.add)); await tester.pump(); expect(find.text(’0’), findsNothing); expect(find.text(’1’), findsOneWidget); }); ΢ΟδΣοτςετ ΢ΟδΣοτςετ͸ɺݸʑͷ΢ΟδΣοτͷڍಈΛ֬ೝ͢ΔͨΊͷςετͰ͢ɻ @testWidgets(’MyWidget has a title and message’, (WidgetTester tester) async { await tester.pumpWidget(MyWidget(title: ’T’, message: ’M’)); final titleFinder = find.text(’T’); final messageFinder = find.text(’M’); expect(titleFinder, findsOneWidget); expect(messageFinder, findsOneWidget); }); 4.3 ΠϯςάϨʔγϣϯςετ ΠϯςάϨʔγϣϯςετ͸ɺΞϓϦέʔγϣϯͷෳ਺ͷ෦෼͕࿈ܞͯ͠ਖ਼͘͠ಈ࡞͢Δ͔Λݕূ ͢ΔςετͰ͢ɻ 37
  39. ୈ 4 ষ Flutter test ઓུ 4.3 ΠϯςάϨʔγϣϯςετ @testWidgets(’Complete app

    flow’, (WidgetTester tester) async { await tester.pumpWidget(MyApp()); await tester.tap(find.byIcon(Icons.list)); await tester.pumpAndSettle(); expect(find.text(’Item 1’), findsOneWidget); await tester.tap(find.text(’Item 1’)); await tester.pumpAndSettle(); expect(find.text(’Item details’), findsOneWidget); }); ϞοΫ ϞοΫ͸ɺςετର৅֎ͷ෦෼Λ໛฿ͨ͠ΦϒδΣΫτͰɺ࣮ࡍͷڍಈΛ࣋ͨͳ͍ΦϒδΣΫτΛ ࢖༻ͯ͠ςετΛߦ͍·͢ɻͨͱ͑͹ɺ֎෦αʔϏε΁ͷϦΫΤετΛ໛฿͢ΔͨΊʹϞοΫΛ࢖༻ Ͱ͖·͢ɻ final mockService = MockService(); when(mockService.fetchData()).thenReturn(Future.value(’Mock data’)); test(’Test with mock service’, () { final result = mockService.fetchData(); expect(result, ’Mock data’); }); σβΠϯύλʔϯ PageObjectModel PageObjectModel ͸ UI ςετͷͨΊͷσβΠϯύλʔϯͰɺ֤ը໘ΛΦϒδΣΫτͱͯ͠දݱ ͠·͢ɻ͜ΕʹΑΓɺςετͷ࠶ར༻ੑͱอकੑ͕޲্͠·͢ɻ ྫͱͯ͠ɺϩάΠϯը໘ͷςετΛߟ͑·͢ɻ class LoginPage { final tester; LoginPage(this.tester); 38
  40. ୈ 4 ষ Flutter test ઓུ 4.3 ΠϯςάϨʔγϣϯςετ get emailField

    => tester.find.byKey(Key(’emailField’)); get passwordField => tester.find.byKey(Key(’passwordField’)); get loginButton => tester.find.byKey(Key(’loginButton’)); Future<void> enterEmail(String email) async { await tester.enterText(emailField, email); } Future<void> enterPassword(String password) async { await tester.enterText(passwordField, password); } Future<void> tapLoginButton() async { await tester.tap(loginButton); await tester.pumpAndSettle(); } } ςετέʔεͰ͸ҎԼͷΑ͏ʹ͜ͷ LoginPage ΦϒδΣΫτΛར༻Ͱ͖·͢ɻ testWidgets(’Login page test’, (tester) async { final loginPage = LoginPage(tester); await loginPage.enterEmail(’example@example.com’); await loginPage.enterPassword(’password123’); await loginPage.tapLoginButton(); // ͜͜ʹΞαʔγϣϯΛॻ͘ }); Robot Pattern Robot Pattern ͸ςετͷૢ࡞ͱݕূΛΧϓηϧԽ͠·͢ɻ͜ΕʹΑΓɺςετͷಡΈ΍͢͞ͱ࠶ ར༻ੑ͕޲্͠·͢ɻ class LoginRobot { final tester; LoginRobot(this.tester); LoginRobot enterEmail(String email) { tester.enterText(tester.find.byKey(Key(’emailField’)), email); return this; } 39
  41. ୈ 4 ষ Flutter test ઓུ 4.4 ऴΘΓʹ LoginRobot enterPassword(String

    password) { tester.enterText(tester.find.byKey(Key(’passwordField’)), password); return this; } LoginRobot tapLoginButton() { tester.tap(tester.find.byKey(Key(’loginButton’))); return this; } LoginRobot checkLoginSuccess() { expect(tester.find.text(’ϩάΠϯ੒ޭ’), findsOneWidget); return this; } } ςετέʔεͰ͸ҎԼͷΑ͏ʹ࿈࠯తʹϝιουΛݺͼग़͢͜ͱ͕Ͱ͖·͢ɻ testWidgets(’Login using Robot pattern’, (tester) async { final robot = LoginRobot(tester); robot .enterEmail(’example@example.com’) .enterPassword(’password123’) .tapLoginButton() .checkLoginSuccess(); }); 4.4 ऴΘΓʹ Flutter ͰͷςετઓུΛద੾ʹߏங͢Δ͜ͱͰɺ඼࣭ͷߴ͍ΞϓϦέʔγϣϯͷ։ൃΛαϙʔτ Ͱ͖·͢ɻຊষͰ঺հͨ͠ςετͷߏ੒΍σβΠϯύλʔϯΛࢀߟʹͯ͠ɺޮ཰తͳςετίʔυͷ ࡞੒ΛਐΊ͍ͯͩ͘͞ɻ 40
  42. ୈ 5 ষ ອը࡞඼͔Βߟ͑Δςετ؍఺ 5.1 ࢝Ίʹ ։ൃʹ͓͍ͯɺϓϩμΫτͷҰ෦͓Αͼશମ͕׬੒ͨ͠λΠϛϯάͰɺQA ʹΑΔςετΛ࣮ߦ͠ ·͢ɻͦͷࡍʹΤϯδχΞ͸ʮͲͷΑ͏ͳ؍఺Λ΋ͱʹςετΛߦ͏ͷ͔ʯΛߟ͑·͕͢ɺςετ؍ ఺Λߟ͑Δͷ͕ۤखɺͱ͍͏ํ΋ଟ͍ͷͰ͸ͳ͍Ͱ͠ΐ͏͔ɻຊষͰ͸ອը࡞඼Λަ͑ͳ͕Βɺϫʔ

    ΫܗࣜͰΧδϡΞϧʹղઆ͍͖ͯ͠·͢ɻ චऀ͸ QA ΤϯδχΞͷͨΊ QA ࢹ఺Ͱͷ࿩͕ϝΠϯͱͳΓ·͕͢ɺςετ؍఺Λߟ͑Δ͜ͱʹ ׳Ε͍ͯͳ͍ΤϯδχΞͷํʹ΋ͥͻಡΜͰ͍͚ͨͩΔͱ޾͍Ͱ͢ɻ 5.2 ໰୊ ͦΕͰ͸ɺͬͦ͘͞໰୊ʹҠΓ·͢ɻखݩʹϖϯ΍ࢴɺPC ϝϞாͳͲΛ༻ҙ͠ͳ͕ΒಡΈਐΊͯ Έ͍ͯͩ͘͞ɻ Q. ๭ࠃຽతອըʹొ৔͢ΔͻΈͭಓ۩ʰεϞʔϧϥΠτʱͷ඼࣭Λ୲อ͢ΔͨΊʹνΣοΫ͢Δςετ؍఺ɾςε τ߲໨Λࢥ͍෇͘ݶΓڍ͍͛ͯͩ͘͞ɻ ʰεϞʔϧϥΠτʱͷ੡඼࢓༷͸ҎԼͱͳΓ·͢ɻ * ջதి౮ͷܗΛ͍ͯ͠Δ * ຊମʹ͸ʮॖখεΠονʯ ʮ෮ݩεΠονʯ͕෇͍͍ͯΔ * ॖখεΠονΛԡԼͨ͠ࡍʹൃͤΒΕΔޫΛ෺ମʹরࣹ͢Δͱɺͦͷ෺ମ͕খ͘͞ͳΔ * রࣹ࣌ؒʹൺྫͯ͠෺ମ͕͞Βʹখ͘͞ͳΔ * ෮ݩεΠονΛԡԼͨ͠ࡍʹൃͤΒΕΔޫΛ෺ମʹরࣹ͢Δͱɺখ͘͞ͳͬͨ෺ମΛݩͷେ͖͞ʹ໭͢͜ͱ ͕Ͱ͖Δ * ࣌ؒܦաͰখ͘͞ͳͬͨ෺ମ͕ݩͷେ͖͞ʹ໭Δ ςετ؍఺ʹ͍ͭͯ͸ʮԿΛ֬ೝ͢Δͷ͔ʯΛɺ 41
  43. ୈ 5 ষ ອը࡞඼͔Βߟ͑Δςετ؍఺ 5.3 ղ౴ ςετ߲໨ʹ͍ͭͯ͸্ه؍఺Λ֬ೝ͢ΔͨΊʹߦ͏۩ମతͳςετ಺༰Λهࡌ͠·͠ΐ͏ɻ Example. ʲςετ؍఺ʳຊମͷݟͨ໨͕࢓༷௨Γ͔ ʲςετ߲໨ʳ࢓༷௨Γʹջதి౮ͷܗΛ͍ͯ͠Δ͜ͱɾεΠον͕෇͍͍ͯΔ͜ͱ

    ໰୊͕ղ͚ͨΒղ౴΁ਐΜͰ͍ͩ͘͞ɻ 5.3 ղ౴ ςετ߲໨Λߟ͑Δʹ͋ͨΓɺ·ͣ͸੡඼࢓༷ʹԊͬͨ؍఺Λߟ͑Δඞཁ͕͋Γ·͢ɻઌ΄Ͳͷ੡ ඼࢓༷͔Βॻ͖ى͜͢ͱɺҰྫͰ͸͋Γ·͕͢͜ͷΑ͏ʹͳΓ·͢ɻ ˙ςετ؍఺ • શൠ – ຊମͷݟͨ໨͕࢓༷௨Γ͔ ∗ ջதి౮ͷܗΛ͍ͯ͠Δ ∗ εΠον͕ 2 ͭ෇͍͍ͯΔ – ෺ମʹޫΛরࣹͰ͖Δ͔ ∗ ॖখ͢Δޫɾ෮ݩ͢ΔޫɺͦΕͧΕͰ֬ೝ • ॖখ – রࣹͨ͠෺ମ͕খ͘͞ͳΔ͔ – রࣹ࣌ؒʹԠͯ͡ɺ෺ମͷঢ়گʹมԽ͕͋Δ͔ • ෮ݩ – রࣹͨ͠෺ମ͕ݩͷେ͖͞ʹ໭Δ͔ – খ͘͞ͳͬͨ෺ମ͕࣌ؒܦաͰݩͷେ͖͞ʹ໭Δ͔ Ͱ͸ɺ্هͷ؍఺Λ΋ͱʹςετ߲໨Λ࡞੒ͯ͠Έ·͠ΐ͏ɻ ˙ςετ߲໨ • ຊମͷݟͨ໨ 42
  44. ୈ 5 ষ ອը࡞඼͔Βߟ͑Δςετ؍఺ 5.3 ղ౴ – ࢓༷௨Γʹջதి౮ͷܗΛ͍ͯ͠Δ͜ͱ – ॖখεΠον͕෇͍͍ͯΔ͜ͱ

    – ෮ݩεΠον͕෇͍͍ͯΔ͜ͱ • ॖখεΠον – σϑΥϧτ͸ OFF ʹͳ͍ͬͯΔ͜ͱ – ॖখεΠονΛ ON ʹͰ͖Δ͜ͱ – ॖখεΠον͕ ON ͷ৔߹ɺরࣹ෦෼͔Βޫ͕ൃͤΒΕΔ͜ͱ – ॖখεΠονΛ OFF ʹͰ͖Δ͜ͱ – ॖখεΠον͕ OFF ͷ৔߹ɺরࣹ෦෼͔Βޫ͕ൃͤΒΕͳ͍͜ͱ – ࠶౓ɺॖখεΠονΛ ON ʹͰ͖Δ͜ͱ • ෮ݩεΠον – σϑΥϧτ͸ OFF ʹͳ͍ͬͯΔ͜ͱ – ෮ݩεΠονΛ ON ʹͰ͖Δ͜ͱ – ෮ݩεΠον͕ ON ͷ৔߹ɺরࣹ෦෼͔Βޫ͕ൃͤΒΕΔ͜ͱ – ෮ݩεΠονΛ OFF ʹͰ͖Δ͜ͱ – ෮ݩεΠον͕ OFF ͷ৔߹ɺরࣹ෦෼͔Βޫ͕ൃͤΒΕͳ͍͜ͱ – ࠶౓ɺ෮ݩεΠονΛ ON ʹͰ͖Δ͜ͱ • ॖখޫΛ౰ͯͨࡍͷڍಈ – 1 ඵؒɺॖখޫʹ౰ͯͨ෺ମ͕খ͘͞ͳΔ͜ͱ – 5 ඵؒɺॖখޫʹ౰ͯͨ෺ମ͕খ͘͞ͳΔ͜ͱ – ॖখޫΛ 1 ඵؒ౰ͯͨ෺ମΑΓ 5 ඵؒ౰ͯͨ෺ମͷํ͕খ͘͞ͳ͍ͬͯΔ͜ͱ – ෺ମͷେ͖͕͞ॖখޫΛ౰ͯͨ࣌ؒʹൺྫ͍ͯ͠Δ͜ͱ • ෮ݩޫΛ౰ͯͨࡍͷڍಈ – ෮ݩޫΛ౰ͯͨ෺ମͷେ͖͕͞ݩʹ໭Δ͜ͱ • ࣌ؒܦա – ॖখޫΛ౰ͯͨ෺ମͷେ͖͕͞ݩʹ໭Δ͜ͱ 43
  45. ୈ 5 ষ ອը࡞඼͔Βߟ͑Δςετ؍఺ 5.4 ղ౴Λ͞Βʹਂ۷Γ͢Δ ͜ΕΒ͸جຊૢ࡞ͱͯ֬͠ೝ͢΂͖؍఺ɾ߲໨ͱͳΓ·͢ɻҰͭҰͭͷ࢓༷Λඥղ͍͍ͯ͘͜ͱ͕ Ͱ͖Ε͹ɺ࿙Εͳ͘ग़ͤΔΑ͏ʹͳΔͷͰ͸ͳ͍Ͱ͠ΐ͏͔ɻ 5.4 ղ౴Λ͞Βʹਂ۷Γ͢Δ

    ͯ͞ɺ͔͜͜Βઌ͸࢓༷ʹهࡌ͞Ε͍ͯͳ͍ΠϨΪϡϥʔʹؔ͢Δςετ؍఺Ͱ͢ɻ ΄ͱΜͲͷ੡඼࢓༷ʹ͸ʮ࢓༷ॻʹهࡌ͞Ε͍ͯͳ͍͕҉໧ͷྃղͰܾ·͍ͬͯΔ࢓༷ʯ ʮ࢓༷ॻ ʹهࡌ͞Ε͓ͯΒͣৄࡉ͕͍͋·͍ͳ··ͷ࢓༷ʯ͕ଘࡏ͠·͢ɻ ͦ͏͍ͬͨ࢓༷ͷ݀ʹ͸ࢥΘ͵ෆ۩߹͕Ӆ͞Ε͍ͯΔՄೳੑ͕ߴ͍Ͱ͢ɻ͔͜͜Β͸ςετ؍఺ʹ ߜͬͯݟ͍͖ͯ·͠ΐ͏ɻ ˙ޮՌൣғͷςετ • ޫΛ෺ମͷҰ෦͚ͩʹ౰ͯΔͱͲ͏ͳΔ͔ • ޫ͕ಁ͚Δ΋ͷʢ෍΍ςΟογϡͳͲʣΛ௨ͯ͠ޫΛ౰ͯΔͱͲ͏ͳΔ͔ • ޫ͕൓ࣹ͢Δ΋ͷʢڸ΍૭ΨϥεͳͲʣΛ௨ͯ͠ޫΛ౰ͯΔͱͲ͏ͳΔ͔ • 100m ઌͳͲԕ͔͘ΒޫΛ౰ͯΔͱͲ͏ͳΔ͔ ˙ॖখ཰ͷςετ • 1 ඵؒɺॖখޫʹ౰ͯͨ෺ମ͕Կˋখ͘͞ͳΔͷ͔ • ॖখݶք͸͋Δͷ͔ ˙ॖখର৅ͷςετ • ͞·͟·ͳ෺ମʹରͯ͠ద੾ʹॖখͰ͖Δ͔ – େ͖͗͢Δ΋ͷ – ௕͗͢Δ΋ͷ – ର৅͕਎ʹண͚͍ͯΔ΋ͷʢҥ෰ͳͲʣ – ௚઀ޫ͕౰͍ͨͬͯͳ͍த਎෦෼ʢശͷதʹೖ͍ͬͯΔ͓՛ࢠͳͲʣ – ӷମ – ؾମ • ࣭ྔɾॏ͞ʹมԽ͕͋Δ͔ ˙ॖখղআͷςετ • ݩͷେ͖͞ʹ໭ͬͨࡍʹෆ౎߹͕ൃੜ͠ͳ͍͔ – ࣭ྔ͕มΘΔ 44
  46. ୈ 5 ষ ອը࡞඼͔Βߟ͑Δςετ؍఺ 5.4 ղ౴Λ͞Βʹਂ۷Γ͢Δ – ܗ͕࿪Ή • ෮ݩޫΛ౰ͯͯղআͨ͠৔߹ͱɺ࣌ؒܦաͰղআͨ͠৔߹ʹ͕ࠩग़ͳ͍͔

    ˙଱ٱੑɾ৴པੑɾ҆શੑͷςετ • ܁Γฦ͠࢖༻ͯ͠΋໰୊ͳ͍͔ – ஶ͘͠ੑೳ͕௿Լͯ͠͠·͏ – ৗʹಉ݁͡Ռ͕ಘΒΕͳ͍ – ނোͯ͠͠·͏ • ࢖༻தɾ࢖༻ޙʹةݥ͕ͳ͍͔ – ੜ෺ɾਓମʹޫΛ౰ͯͨࡍʹ݈߁ඃ֐͕ൃੜͯ͠͠·͏ – ༗֐ͳ์ࣹઢͳͲ͕ग़͍ͯΔ – ޫͷ৭΍೾௕ʹΑΔӨڹ͕͋Δ – ௕࣌ؒরࣹ࣌ʹӨڹ͕͋Δ • ڧ౓ʹ໰୊͸ͳ͍͔ – ࢛࣍ݩϙέοτͰͷอ؅࣌ͷ҆શੑ – ༌ૹதͷৼಈʹΑΔഁଛ – յΕͯ͠·ͬͨ৔߹ɺอূ͸͋Δͷ͔ ˙όοςϦʔͷςετ • ి஑ࣜͳͷ͔ॆిࣜͳͷ͔ – ͲͷΑ͏ͳి஑ɾॆిγεςϜΛ࢖͍ͬͯΔͷ͔ • ిྗͷෆ଍͸ൃੜ͠ͳ͍͔ • ϓϩμΫτߏ଄ͱͯ͠ి஑։ดޱɾॆిࠩࠐޱͳͲΛಋೖͰ͖Δ͔ • όοςϦʔण໋ʹ໰୊͕ͳ͍͔ – όοςϦʔͷ͕࣋ͪஶ͘͠ѱ͘ͳ͍ͬͯΔ – ॆిࣜͷ৔߹ɺద੾ͳॆి࣌ؒͰ͋Δ͜ͱ ˙ΤϧΰϊϛΫεͷςετ • ࢖͍қ͘ͳ͍ͬͯΔ͔ – ຊମ͕ॏ͗͢Δ – ࿝एஉঁʹͱͬͯ࢖͍қ͘ͳ͍ͬͯͳ͍ – ର৅೥ྸʹଈͨ͠࢖͍΍͢͞ʹͳ͍ͬͯͳ͍ – ѲΓ΍͍͢޻෉͕͞Ε͍ͯͳ͍ʢάϦοϓͷ༗ແͳͲʣ – εΠον͕ԡ͠ʹ͍͘ʢϘλϯͷݻ͞͸ద੾͔ʣ 45
  47. ୈ 5 ষ ອը࡞඼͔Βߟ͑Δςετ؍఺ 5.5 ·ͱΊ • 2 ͭͷεΠονΛಉ࣌ʹԡ͢͜ͱ͕Ͱ͖ͯ͠·Θͳ͍͔ ˙ಛघ؀ڥԼͰͷςετ

    • ҟͳΔؾԹ৚݅ԼͰਖ਼͘͠ಈ࡞͢Δ͔ • ࣪౓ɾؾѹͷมԽʹΑΔӨڹ͸ͳ͍͔ • ଱ਫੑɾ๷ਖੑ͕͋Δ৔߹ɺਫೞΕ΍ᆍͷதͰਖ਼͘͠ಈ࡞͢Δ͔ • ւ֎Ͱ࢖༻Ͱ͖Δ͔ ˙΄͔ͷͻΈͭಓ۩ͱͷ૬ޓ࡞༻ςετ • εϞʔϧϥΠτͱϏοάϥΠτͷޫΛಉ࣌ʹ౰ͯΔͱͲ͏ͳΔ͔ • εϞʔϧϥΠτ 2 ݸΛಉ࣌ʹ࢖༻͢ΔͱͲ͏ͳΔ͔ ˙ࣾձతӨڹͷςετ • ੡଄ɾ࢖༻ɾഇغͷաఔͰ؀ڥʹѱӨڹΛٴ΅͞ͳ͍͔ • ෺ମΛখͯ͘͞͠౪ΉͳͲѱ༻͞Εͳ͍͔ • ൢചϧʔτʹҧ๏ੑ͸ͳ͍͔ • ൢച࣌ͷ޿ࠂ͕๏཯ʹͷͬͱ͍ͬͯΔ͔ • ൢച࣌ʹ͓͚ΔϦεΫϚωδϝϯτ͸ߟྀ͞Ε͍ͯΔ͔ • اۀཧ೦ʹ൓ͨ͠੡඼ʹͳ͍ͬͯͳ͍͔ 5.5 ·ͱΊ ΠϨΪϡϥʔ؍఺ΛҰ௨ΓݟͯɺͲ͏ײ͡·͔ͨ͠ʁ ɹதʹ͸ʮ͜Ε͸ςετ؍఺ʁʯ ʮΤϯδχ Ξʹ͸ؔ܎ͳ͍ͷͰ͸ʁʯͱࢥ͏΋ͷ΋͍ࠞͬͯͨ͡ͷͰ͸ͳ͍Ͱ͠ΐ͏͔ɻ ʮ඼࣭อূʢQAɿQuality Assuranceʣ ʯͱ͸ɺޮ཰ͱ඼࣭͕ٻΊΒΕΔ͋ΒΏΔ׆ಈʹ͓͍ͯɺͦ ΕΒʹอূΛ༩͑ΔͷʹඞཁͳূڌΛఏڙ͢Δ׆ಈҰൠΛࢦ͠·͢ɻϓϩμΫτͷΈʹରͯ͠ςετ Ξϓϩʔν͢Δ΋ͷͰ͸͋Γ·ͤΜɻ ޿͘ߟ͑ΔͱίϯαϧλϯτͷΑ͏ͳཱͪҐஔͰɺ၆ᛌతʹϓϩμΫτʹରͯ͠ݒ೦఺͕ͳ͍͔Λ ચ͍ग़͍ͯ͘͜͠ͱ͕ॏཁͱݴ͑·͢ɻ Ϟϊ͚ͩΛςετͯ͠͸͍͚ͳ͍ͱ͍͏ࢹ఺Λ࣋ͪɺࢹ໺Λ޿͛ͯ͞·͟·ͳ؍఺Λߟ͑ͯΈ· ͠ΐ͏ɻ ·ͨɺ͜͏͍ͬͨ؍఺ग़͠͸ QA ΤϯδχΞʹ೚͖ͤͬΓʹ͢ΔͷͰ͸ͳ͘ɺϓϩδΣΫτϝϯ όʔશһ͕ߟ͑ΒΕΔঢ়ଶ͕๬·͍͠Ͱ͢ɻςετ؍఺Λߟ͑Δ͜ͱ͸͢΂ͯͷΤϯδχΞʹͱͬͯ 46
  48. ୈ 5 ষ ອը࡞඼͔Βߟ͑Δςετ؍఺ 5.5 ·ͱΊ ඞཁͳεΩϧͱ΋ݴ͑ΔͷͰ͸ͳ͍Ͱ͠ΐ͏͔ɻ ࠓճɺອը࡞඼ͷඇ࣮ࡏΞΠςϜΛબΜͩཧ༝ͱͯ͠ɺۭ૝ྗ΍૝૾ྗΛ஁͑Δҙਤ΋ࠐΊ͍ͯ· ͢ɻॳΊ͸ອը࡞඼Λ୊ࡐʹϨΫϦΤʔγϣϯͷܗͰελʔτ͠ɺ࠷ऴతʹϓϩμΫτʹ౰ͯ͸Ίͯ ϫʔΫγϣοϓΛߦ͏͜ͱΛ͓קΊ͠·͢ɻ

    ϫʔΫγϣοϓͷਐΊํʹ͍ͭͯ͸ɺQiita ʹهࣄΛެ։͍ͯ͠·͢ͷͰͥͻ͝ཡ͍ͩ͘͞ɻ https://qiita.com/rk0802/items/c34367a9672c6dc49bc7 ͞·͟·ͳཱ৔ͷϓϩδΣΫτϝϯόʔͱسጨͳ͘؍఺ग़͕͠Ͱ͖ΔະདྷΛظ଴ͭͭ͠ɺຊߘΛక Ί͘͘Γ͍ͨͱࢥ͍·͢ɻ 47
  49. ୈ 6 ষ ϚϧνϓϨΠήʔϜ͸ԿΛ௨৴͍ͯ͠ Δ͔ ϚϧνϓϨΠήʔϜΛ੍࡞͢Δࡍʹ͸ɺ͞·͟·ͳ఺Λߟྀ͢Δඞཁ͕͋Γ·͢ɻωοτϫʔΫτ ϙϩδʔɺ௨৴ϓϩτίϧɺ௨৴಺༰ɺ௨৴ස౓ɺσʔλѹॖɺηΩϡϦςΟɺαʔόͷεέʔϥϏ ϦςΟͳͲͳͲɺ͜ΕΒͱήʔϜϩδοΫͱͷόϥϯεΛͱΓͳ͕Β։ൃ΍࠷దԽΛߦ͏͜ͱʹͳΓ ·͢ɻຊষͰ͸ɺ௨৴಺༰ʹয఺Λ౰࣮ͯͯྫΛ͋͛ͭͭɺͦͷৄࡉΛղઆ͠·͢ɻ औΓ্͛ΔήʔϜͷҰཡ͸ҎԼͷ௨ΓͰ͢ɻ

    • 0 A. D. • Battle for Wesnoth • OpenRA • Quake III Arena ্ه͸͍ͣΕ΋ެ։৘ใ͕͋Δ΋ͷΛબఆ͠·ͨ͠ɻࢀর͍ͯ͠Διʔείʔυ͸ࣥච࣌఺Ͱͷ࠷ ৽൛ͱͳ͍ͬͯΔͨΊɺϓϩδΣΫτͷਐߦʹΑͬͯ௠෗Խ͍ͯ͠ΔՕॴ͕͋Δ͔΋͠Ε·ͤΜɻ 6.1 0 A. D. 0 A. D. ͸ Wildfire Games ʹΑͬͯ։ൃ͞Ε͍ͯΔϦΞϧλΠϜετϥςδʔήʔϜͰɺAge of Empires γϦʔζʹࣅͨήʔϜγεςϜΛ͍࣋ͬͯ·͢ɻϚϧνϓϨΠͰ͸࠷େ 8 ਓͰରઓͰ͖ɺ ϓϨΠϠʔͷҰਓ͕ϗετͱͳΔαʔόɾΫϥΠΞϯτܕΛ࠾༻͍ͯ͠·͢ɻ௨৴ϓϩτίϧʹ͸ RUDP ͰɺENet ϥΠϒϥϦ͕ར༻͞Ε͍ͯ·͢ɻ 0 A. D. ͷओͳ௨৴಺༰͸Ϣʔβʔૢ࡞ͷίϚϯυͰ͢ɻ௨৴σʔλͷߏ଄͸ɺENet ϔομɺ൚ ༻ϔομɺίϚϯυຊମͷ 3 ύʔτߏ੒ͱͳ͍ͬͯ·͢ɻ ·ͣɺENet ϔομʹ͸ҎԼͷ 3 छྨͷσʔλؚ͕·Ε͍ͯ·͢ɻ • ίϚϯυछผ : 1 όΠτ • νϟϯωϧ ID : 1 όΠτ 49
  50. ୈ 6 ষ ϚϧνϓϨΠήʔϜ͸ԿΛ௨৴͍ͯ͠Δ͔ 6.2 Battle for Wesnoth • γʔέϯε൪߸

    : 2 όΠτ ࣍ʹɺ൚༻ϔομʹ͸ҎԼͷ 2 छྨͷσʔλؚ͕·Ε͍ͯ·͢ɻ • σʔλछผ : 1 όΠτ • σʔλαΠζ : 2 όΠτ ࠷ޙʹɺίϚϯυຊମ͸࣍ͷ 4 ͭͷσʔλ͔Βߏ੒͞Ε͍ͯ·͢ɻ • ΫϥΠΞϯτ ID : 4 όΠτ • ϓϨΠϠʔ ID : 4 όΠτ • λʔϯ : 4 όΠτ • ίϚϯυύϥϝʔλ : JSON ܗࣜͷจࣈྻ ίϚϯυύϥϝʔλʹ͍ͭͯ͸ɺमཧίϚϯυΛྫʹͱΔͱ࣍ͷΑ͏ͳ JSON ͱͳ͍ͬͯ·͢ɻ 0 A. D. εΫϦϓτ͔ΒҾ༻ { "type": "repair", "entities": selection, "target": action.target, "autocontinue": true, "queued": queued, "pushFront": pushFront, "formation": g_AutoFormation.getNull() } ·ͱΊΔͱ 0 A. D. ͷίϚϯυ௨৴͸ 19 όΠτͱ JSON จࣈྻ෼ͷόΠτ਺ͷσʔλͱͳΓ ·͢ɻ 6.2 Battle for Wesnoth Battle for Wesnoth ͸λʔϯ੍ετϥςδʔήʔϜͰɺWindowsɺmacOSɺLinux ʹՃ͑ iOS ΍ Android Ͱ༡Ϳ͜ͱ͕Ͱ͖·͢ɻ ௨৴ϓϩτίϧʹ͸ TCP ͕࠾༻͞Ε͍ͯ·͢ɻओͳ௨৴಺༰͸ɺWesnoth Markup Language ʢWMLʣͰఆٛ͞ΕΔίϚϯυύϥϝʔλͱͳ͍ͬͯ·͢ɻ WML ͷҰྫͱͯ͠ɺϢʔβʔҰཡΛڞ༗͢ΔίϚϯυΛ͋͛Δͱ࣍ͷΑ͏ʹͳΓ·͢ɻ ϢʔβʔҰཡίϚϯυͷྫ [users] [user] name="Alice" host="yes" 50
  51. ୈ 6 ষ ϚϧνϓϨΠήʔϜ͸ԿΛ௨৴͍ͯ͠Δ͔ 6.3 OpenRA observer="no" [/user] [user] name="Bob"

    host="no" observer="no" [/user] [user] name="Charlie" host="no" observer="yes" [/user] [/users] ্هͷΑ͏ͳ WML ͕ zlib ΍ bzip2 ʹΑͬͯѹॖ͞Εͯૹ৴͞Ε·͢ɻTCP ͷϖΠϩʔυʹ͸ɺ ѹॖޙͷσʔλαΠζʢ4 όΠτʣͱͦͷ݁Ռ͕ॱʹॻ͖ࠐ·Ε·͢ɻ 6.3 OpenRA OpenRA ͸ϦΞϧλΠϜετϥςδʔήʔϜͰɺCommand & Conquer γϦʔζʹࣅͨήʔϜ γεςϜΛ͍࣋ͬͯ·͢ɻCommand & Conquer ͱ Age of Empires ͸ࣅ௨ͬͨήʔϜγεςϜΛ ͍࣋ͬͯͯɺOpenRA ͱઌड़ͨ͠ 0 A. D. ΋γεςϜతʹ͸ࣅ͍ͯ·͢ɻ͔͠͠ɺ࠾༻͍ͯ͠Δ௨ ৴ϓϩτίϧ͸ҟͳ͓ͬͯΓɺ0 A. D. ͸ RUDP Ͱ͋Δͷʹରͯ͠ɺOpenRA ͸ TCP Λ࢖͍ͬͯ ·͢ɻաڈʹ͸ RUDP ΁ͷҠߦ͕ఏҊ͞Ε͓ͯΓɺ࠷ۙ͸ QUIC ΁ͷҠߦ΋ٞ࿦͞Ε͍ͯ·͕͢ɺ TCP ͷ࠶࣮૷ʹͳΔͱ͍͏ݒ೦͔Β٫Լ͞Ε͍ͯ·͢ɻ OpenRA ͷ௨৴಺༰΋ओͳ΋ͷ͸ίϚϯυͷ΍ΓͱΓͱͳΓ·͢ɻͨͩ͠ɺ1 ϑϨʔϜຖʹήʔϜ ঢ়ଶͷϋογϡ஋Λܭࢉ͠ɺಉظ͕ߦ͍͑ͯΔ͔νΣοΫ͞Ε·͢ɻ͜ͷϋογϡ஋͸ίϚϯυͷ௨ ৴ʹ΋෇༩͞ΕΔܗͰૹ৴͞Ε·͢ɻ͜ͷͨΊɺϖΠϩʔυͷ಺༰͸ίϚϯυຊମͱϋογϡ஋ͱ͍ ͏ߏ੒ʹͳ͍ͬͯ·͢ɻ ίϚϯυຊମʹ͍ͭͯ͸ɺσʔλαΠζʢ4 όΠτʣͱγϦΞϥΠζ͞ΕͨύϥϝʔλͱͳΓ·͢ɻ ύϥϝʔλͷαΠζ͸ 31 όΠτҎ্Ͱɺૢ࡞ର৅ʹΑͬͯ͸૿Ճ͠·͢ɻ ಉظ֬ೝͷϋογϡ஋͸ɺ஗Ԇ͍ͯͨ͠෼͕ҰׅͰॻ͖ࠐ·Ε·͢ɻϋογϡ஋ͻͱͭ͋ͨΓ͸Ҏ Լͷߏ଄ʹͳ͍ͬͯ·͢ɻ • σʔλαΠζ : 4 όΠτ • ϑϨʔϜ : 4 όΠτ • σʔλछผ : 1 όΠτ • ϋογϡ஋ : 4 όΠτ • ϓϨΠϠʔͷࢮ׆ঢ়ଶ : 8 όΠτ ϋογϡ஋Ͱͷಉظ֬ೝʹࣦഊͨ͠৔߹͸ɺήʔϜऴྃͷϑϩʔʹೖΓ·͢ɻ 51
  52. ୈ 6 ষ ϚϧνϓϨΠήʔϜ͸ԿΛ௨৴͍ͯ͠Δ͔ 6.4 Quake III Arena 6.4 Quake

    III Arena Quake III Arena ͸ϚϧνϓϨΠ FPS ήʔϜͰɺ࠷େ 16 ਓͰωοτରઓΛߦ͏͜ͱ͕Ͱ͖·͢ɻ ௨৴ϓϩτίϧʹ͸ RUDP ͕࠾༻͞Ε͍ͯͯɺओͳ௨৴಺༰͸ಉظ༻ͷεφοϓγϣοτͱϓϨΠ ϠʔͷೖྗͱͳΓ·͢ɻεφοϓγϣοτ͸ఆظతʹαʔό͔ΒΫϥΠΞϯτ΁ૹ৴͞Εɺ σϑΥ ϧτͰ͸ຖඵ 20 ճॲཧ͞Ε·͢ɻೖྗσʔλʹ͍ͭͯ͸ຖϑϨʔϜॲཧ͞ΕɺσϑΥϧτͰ͸࠷େ Ͱຖඵ 85 ճͱͳ͍ͬͯ·͢ɻ͜ͷ΄͔ɺ઀ଓɺ੾அɺνϟοτͷ௨৴΋ൃੜ͠·͢ɻ εφοϓγϣοτ εφοϓγϣοτͷ௨৴಺༰͸࣍ͷߏ੒ʹͳ͍ͬͯ·͢ɻ • ࠷ޙʹडཧͨ͠ΫϥΠΞϯτίϚϯυ൪߸ : 4 όΠτ • αʔόίϚϯυ : ACK ͕֬ೝͰ͖͍ͯͳ͍αʔόίϚϯυͷϦετɻৄࡉ͸ޙड़ɻ • εφοϓγϣοτຊମ : ৄࡉ͸ޙड़ɻ • μ΢ϯϩʔυσʔλ : ΫϥΠΞϯτ͕μ΢ϯϩʔυதͳΒ௥ه͞ΕΔɻ αʔόίϚϯυͷߏ଄͸ɺͻͱͭ͋ͨΓҎԼͷ௨ΓͰ͢ɻ • σʔλछผ : 1 όΠτ • γʔέϯε൪߸ : 4 όΠτ • ίϚϯυ಺༰ : จࣈྻ εφοϓγϣοτຊମͷߏ଄͸ • σʔλछผ : 1 όΠτ • αʔό࣌ؒ : 4 όΠτ • σϧλѹॖͷݩϑϨʔϜ൪߸ : 1 όΠτ • ϑϥά : 1 όΠτɻΫϥΠΞϯτͷ઀ଓঢ়گ΍ࠩ෼ͷ༗ແɻ • ࢹೝՄೳͳϚοϓαΠζ : 4 όΠτ • ࢹೝՄೳͳϚοϓσʔλͷϏοτϚεΫ : ௚લͷϚοϓαΠζ෼ɻ • ϓϨΠϠʔຊਓͷঢ়ଶ : σϧλѹॖͰࠩ෼͕͋ΔϑΟʔϧυͷ࠷େεϩοτ൪߸·Ͱॻ͖ࠐ· ΕΔɻ • มߋྔ : 1 όΠτɻࠩ෼͕͋ΔϑΟʔϧυͷ࠷େεϩοτ൪߸ɻ • ֤ϑΟʔϧυͷࠩ෼ • ࠩ෼ϑϥά : 1 Ϗοτɻࠩ෼͕ͳ͚Ε͹ 0 Ͱऴྃɻ͋Ε͹ 1 ͱͳΓ࣍ʹࠩ෼͕௥ه͞ΕΔɻ • ࠩ෼σʔλ : σʔλܕʹΑͬͯαΠζ͕ҟͳΔɻ • ੔਺ͳΒࢦఆαΠζ෼ͷϏοτ෼ 4, 5, 8, 10, 12, 16, 32 • ුಈখ਺ͳΒ 13 Ϗοτ͔ 32 Ϗοτ • ήʔϜ಺ͷࠩ෼σʔλ 52
  53. ୈ 6 ষ ϚϧνϓϨΠήʔϜ͸ԿΛ௨৴͍ͯ͠Δ͔ 6.4 Quake III Arena • ࠩ෼ϑϥά

    : 1 Ϗοτɻࠩ෼͕ͳ͚Ε͹ 0 Ͱऴྃɻ͋Ε͹ 1 ͱͳΓ࣍ʹࠩ෼͕௥ه͞ΕΔɻ • ϓϨΠϠʔͷεςʔλε • ࠩ෼͕ͳ͚Ε͹ 0 ͷ 1 ϏοτͷΈ • ࠩ෼͕͋Ε͹ 1 ͷ 1 Ϗοτ Λॻ͖ࠐΈɺϏοτϚεΫΛ 2 όΠτɺ࣮σʔλΛ 2 όΠτ x 16 ݸॻ͖ࠐΉ • ϓϨΠϠʔͷӬଓσʔλ • ࠩ෼͕ͳ͚Ε͹ 0 ͷ 1 ϏοτͷΈ • ࠩ෼͕͋Ε͹ 1 ͷ 1 Ϗοτ Λॻ͖ࠐΈɺϏοτϚεΫΛ 2 όΠτɺ࣮σʔλΛ 2 όΠτ x 16 ݸॻ͖ࠐΉ • ϓϨΠϠʔͷ஄ༀσʔλ • ࠩ෼͕ͳ͚Ε͹ 0 ͷ 1 ϏοτͷΈ • ࠩ෼͕͋Ε͹ 1 ͷ 1 Ϗοτ Λॻ͖ࠐΈɺϏοτϚεΫΛ 2 όΠτɺ࣮σʔλΛ 2 όΠτ x 16 ݸॻ͖ࠐΉ • ϓϨΠϠʔͷڧԽσʔλ • ࠩ෼͕ͳ͚Ε͹ 0 ͷ 1 ϏοτͷΈ • ࠩ෼͕͋Ε͹ 1 ͷ 1 Ϗοτ Λॻ͖ࠐΈɺϏοτϚεΫΛ $ όΠτɺ࣮σʔλΛ 2 όΠτ x 16 ݸॻ͖ࠐΉ ίϚϯυೖྗ ίϚϯυೖྗ͸ΫϥΠΞϯτ͔Βαʔό΁ૹ৴͞ΕΔσʔλͰɺεφοϓγϣοτʹର͢Δ ACK ΋͔Ͷ͍ͯ·͢ɻ • αʔό ID : 4 όΠτ • ࠷ޙʹडཧͨ͠αʔόίϚϯυ : 4 όΠτ • ACK ͕֬ೝͰ͖͍ͯͳ͍ΫϥΠΞϯτίϚϯυ • ͻͱͭ͋ͨΓɺσʔλछผɺγʔέϯε൪߸ɺίϚϯυ಺༰ͷ 3 ؚ͕ͭ·Ε͍ͯΔ • σʔλछผ : 1 όΠτ • γʔέϯε൪߸ : 1 όΠτ • ίϚϯυ಺༰ : จࣈྻ • ௚ۙͷΫϥΠΞϯτίϚϯυ • σʔλछผ : 1 όΠτ • ίϚϯυͷ਺ : 1 όΠτɻ࠷େ 32 ݸͰɺҎ߱ʹ௥ه͞ΕΔɻ • ίϚϯυ୯ମͷϑΥʔϚοτ • ࣌ؒࠩ෼ : 256 ະຬͳΒ 1 Ϗοτͷϑϥάͱ 1 όΠτͷࠩ෼ɻ256 Ҏ্ͳΒ 1 Ϗοτͷϑϥ άͱ 4 όΠτͷࠩ෼ɻ • ϑϥά : 1 ϏοτɻҎ߱ʹࠩ෼͕௥ه͞Ε͍ͯΔͳΒ 1 ɻ • ΦΠϥʔ֯ࠩ෼ : ֤੒෼ಉ༷ͷϑΥʔϚοτͰ௥ه͞ΕΔɻ 53
  54. ୈ 6 ষ ϚϧνϓϨΠήʔϜ͸ԿΛ௨৴͍ͯ͠Δ͔ 6.5 ·ͱΊ • ࠩ෼͕ͳ͚Ε͹ 0 :

    1 Ϗοτ • ࠩ෼͕͋Ε͹ 1 ʢ1 Ϗοτʣͱͦͷ஋ʢ2 όΠτʣ • Ҡಈ৘ใ : લޙɺࠨӈɺ্Լͷ֤੒෼͕௥ه͞ΕΔ • ࠩ෼͕ͳ͚Ε͹ 0 : 1 Ϗοτ • ࠩ෼͕͋Ε͹ 1 ʢ1 Ϗοτʣͱͦͷ஋ʢ1 όΠτʣ • Ϙλϯೖྗ • ࠩ෼͕ͳ͚Ε͹ 0 : 1 Ϗοτ • ࠩ෼͕͋Ε͹ 1 ʢ1 Ϗοτʣͱͦͷ஋ʢ2 όΠτʣ • ෢ث৘ใ • ࠩ෼͕ͳ͚Ε͹ 0 : 1 Ϗοτ • ࠩ෼͕͋Ε͹ 1 ʢ1 Ϗοτʣͱͦͷ஋ʢ1 όΠτʣ 6.5 ·ͱΊ ϚϧνϓϨΠήʔϜ͕௨৴͍ͯ͠Δσʔλʹ͍ͭͯɺ࣮ࡍͷϓϩδΣΫτ͝ͱʹ࣮૷ΛΈ͖ͯ·͠ ͨɻήʔϜ಺༰͕ҟͳΔͨΊ௨৴಺༰͕ҟͳΔͷ͸౰વͱͯ͠΋ɺ௨৴σʔλͷߏ଄΋ଟछଟ༷Ͱ͋ Δ͜ͱ͕Θ͔Γ·ͨ͠ɻ0 A. D. ͱ OpenRA ͷΑ͏ʹήʔϜγεςϜ͕ࣅ௨͍ͬͯͨͱͯ͠΋ɺप ลٕज़΍௨৴಺༰͕ҟͳ͍ͬͯΔͱ͍͏͜ͱ΋Θ͔Γ·ͨ͠ɻ શମΛ௨ͯ͠ΈΔͱɺσʔλάϥϜͱͯ͠͸σʔλͷܕ΍௕͞ͱσʔλຊମͱ͍͏ߏ଄͸සग़ύ λʔϯͰ͋Δͱݴ͑·͢ɻࡉ͔͍ͱ͜ΖͰ͸ɺՄม௕੔਺΍จࣈྻͷऔΓճ͠ʢ0 ऴ୺͔௕͞ͱͷϖ Ξ͔ʣͷҧ͍͕ݟΒΕ·͢ɻBattle for Wesnoth ͷΑ͏ͳࣗ༝ͳܗࣜͰͷσʔλઃܭͰ͸ɺ࣮૷೉ қ౓͕௿͘ͳΔҰํͰ࣮૷Օॴ͕෼ࢄ͢Δͱͱ΋ʹߏ଄ͷ೺Ѳ͕೉͘͠ͳΔҹ৅͕͋Γ·ͨ͠ɻ ຊষͰऔΓ্͛ͨήʔϜͷίʔυϦʔσΟϯάͰ͸ ChatGPT ͱ Bing Chat ʹαϙʔτͯ͠΋Β ͍·ͨ͠ɻ௨৴ઃܭ΍σʔλߏ଄ʹ͍ͭͯ௚઀ɺਖ਼֬ͳ৘ใΛҾ͖ग़͢ͷ͸ࠔ೉ͩͬͨ΋ͷͷɺίʔ υΛࢀর͠ͳ͕ΒͰ͋Ε͹ޮ཰Α͘ཧղΛਂΊΔ͜ͱ͕Ͱ͖·ͨ͠ɻҰ෦ͷήʔϜͰ͸௨৴σʔλ ͷఆ͕ٛཅʹߦΘΕ͍ͯͳ͍ʢϏϧυ࣌ʹੜ੒͞ΕΔɺXML ΍ JSON ͷΑ͏ͳߏ଄ͷࣗ༝౓͕ߴ ͍ʣ৔߹͕͋ΓɺͦͷΑ͏ͳέʔεͰ͸ࣗྗͰͷίʔυϦʔσΟϯάʹཔΔඞཁ͕͋Γ·ͨ͠ɻ· ͨɺϚϧνϓϨΠήʔϜͱ͍͏ݴ༿͕ UDP ௨৴Λ࿈૝ͤ͞ΔΑ͏Ͱɺ͜ͷ఺ʹ͍ͭͯ΋ਖ਼֬ͳ৘ใ ΛϑΟʔυόοΫͯ͠ਐΊΔ͜ͱ΋͋Γ·ͨ͠ɻ 54
  55. ஶऀ঺հ ݪ ܓ༟ (ୈ 1 ষ୲౰) ιʔγϟϧϕοςΟϯάࣄۀຊ෦ॴଐɻۀ຿Ͱ UEFN ͸৮ͬͯ·ͤΜ͕ήʔϜͱϝλόʔε ͕޷͖Ͱ͢ʂ

    ߐാ ୓࠸ (ୈ 2 ষ୲౰, GitHub: @MokkeMeguru, X: @MeguruMokke) ιʔγϟϧϕοςΟϯάࣄۀࣄۀຊ෦։ൃࣨͱ͍͏ͱ͜ΖͰɺओʹ TIPSTAR ͱ͍͏ެӦڝ ٕͷαʔϏεͷ։ൃɾӡ༻Λߦ͍ͬͯ·͢ɻιγϟήͷ՝ۚͱαʔϏε։ൃɾӡ༻Ͱੜ͖͍ͯ ·͢ɻ দݪ ৴஧ (ୈ 3 ষ୲౰) ॴଐ͸ϞϯεταʔόνʔϜͰ Ruby ΍ Go Λॻ͍ͯΔɻϓϩάϥϛϯά͕޷͖Ͱɺීஈ͸ ਪ͠ݴޠͷ Haskell Ͱ༡ΜͩΓ͍ͯ͠Δɻ ٢઒ ༐ଠ࿠ (ୈ 4 ষ୲౰, GitHub: @yutaroyoshikawa) 2021 ೥৽ଔೖࣾɻιʔγϟϧϕοςΟϯάࣄۀຊ෦ॴଐɻΠϯυΧϨʔͱΫϥΠΞϯτ։ൃ ͕޷͖Ͱ͢ɻ ޻౻ ཧܙ (ୈ 5 ষ୲౰) QA ΤϯδχΞɻϞϯετγϦʔζήʔϜࣄۀ෦ԣஅਪਐάϧʔϓʹͯɺϞϯετγϦʔζλ Πτϧશൠͷ඼࣭޲্ʹ౒Ί͍ͯ·͢ɻҰ൪ཉ͍͠ͻΈͭಓ۩͸άϧϝςʔϒϧ͔͚Ͱ͢ɻ ࡾ্ ൏ਓ (ୈ 6 ষ୲౰) σδλϧΤϯλʔςΠϯϝϯτࣄۀຊ෦ͰαʔόʔαΠυΛத৺ʹαϙʔτ΍։ൃۀ຿ʹैࣄ ͍ͯ͠·͢ɻσʔλߏ଄ͱΞϧΰϦζϜͷथւΛ͞·Α͍ͳ͕ΒɺήʔϜ։ൃϓϩδΣΫτͷ ଟ༷ੑΛ؍࡯͍ͯ͠·͢ɻ 55
  56. MIXI TECH NOTE #10 2023 ೥ 11 ݄ 11 ೔ɹॳ൛ୈ

    1 ࡮ɹൃߦ ஶɹऀ גࣜձࣾ MIXI ༗ࢤ ൃߦॴ גࣜձࣾ MIXI ҹ࡮ॴ ೔ޫاը ɹ ˜ MIXI