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 ༗ࢤɹஶ
    2023-11-11 ൛ גࣜձࣾ MIXI ൃߦ

    View full-size slide

  2. ·͕͖͑
    ຊॻʮMIXI TECH NOTE #10ʯ͸ɺMIXI GROUP ʹॴଐ͢Δ༗ࢤୡʹΑͬͯࣥචɾ੍࡞͞Εٕͨ
    ज़ॻͰ͢ɻ࣮ࡍͷݱ৔Ͱ࢖ΘΕٕͨज़΍ߟ͑ํɺ·ͨɺݸਓతʹڵຯɾؔ৺ͷ͋Δ෼໺͔Βɺࢥ͍ࢥ
    ͍ʹࣥච͍ͨ͠·ͨ͠ɻͦͷͨΊɺ֤ষͦΕͧΕͰ׬͍݁ͯ͠Δ಺༰ʹͳ͍ͬͯ·͢ͷͰɺ޷͖ͳষ
    ͔Β޷͖ͳॱ൪Ͱָ͓͠Έ͍ͩ͘͞ɻ
    ·ͨɺຊॻ͸ɺMIXI GROUP ʹ͋Δٕज़త஌ݟ΍ΞΠσΞΛੵۃతʹڞ༗ɾެ։͍ͯ͘͜͠ͱ
    ͰɺੈͷதʹΑΓྑ͍αʔϏε͕ҲΕग़͢͜ͱΛئͬͯץߦ͞Ε͍ͯ·͢ɻܝࡌ͞Ε͍ͯΔ৘ใ͸ɺ
    ࣥචऀࣗ਎ͷ؀ڥͰݕূࣥ͠ච͞Εͨ΋ͷͰ͢ͷͰɺ͝ࢀߟʹ͞ΕΔࡍ͸ɺࣗ͝਎ͷ੹೚Ͱ൑அ͠
    ͝׆༻͍ͩ͘͞ɻͳ͓ɺจষදݱʹ͖ͭ·ͯ͠΋ɺࣥචऀࣗ਎ͷݴ༿Ͱ఻͑ͨ͘ɺϑϥϯΫͳදݱͱ
    ͳ͓ͬͯΓ·͢͜ͱ͝ཧղ͍͚ͨͩΕ͹ͱࢥ͍·͢ɻ
    σΟϕϩούʔϦϨʔγϣϯζνʔϜҰಉ
    ˗ຊॻʹؔ͢Δ͓໰͍߹Θͤઌ
    ɹ https://twitter.com/mixi_engineers
    ˗ MIXI GROUP ʹ͍ͭͯ
    ɹ https://mixi.co.jp/
    ˞ MIXI ͷ໊শɺ͜Εʹؔ࿈͢Δ঎ඪٴͼϩΰ͸ɺגࣜձࣾ MIXI ͷ঎ඪٴͼొ࿥঎ඪͰ͢ɻ·ͨɺ
    ֤ࣾͷձ໊ࣾɺαʔϏεٴͼ੡඼ͷ໊শ͸ɺͦΕͧΕͷॴ༗͢Δ঎ඪ·ͨ͸ొ࿥঎ඪͰ͢ɻ
    iii

    View full-size slide

  3. ໨࣍
    ·͕͖͑ 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

    View full-size slide

  4. ໨࣍
    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

    View full-size slide

  5. ୈ 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

    View full-size slide

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

    View full-size slide

  7. ୈ 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

    View full-size slide

  8. ୈ 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

    View full-size slide

  9. ୈ 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

    View full-size slide

  10. ୈ 1 ষ UEFN Ͱ࢝ΊΔ Verse ŧŔŕŪũƄŝſೖ໳ 1.4 UEFN ʹ͓͚Δ Verse ͱઃܭͱ͸
    Run(): logic
    testableͱͯ͠ػೳ͢ΔσόΠε
    testable_device := class(creative_device, testable):
    Run(): logic =
    return true
    test_runner_device := class(creative_device):
    @editable
    TestableDevices: []testable_device = array {}
    OnBegin(): 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(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(): logic =
    return Expect("1 + 2 ͸ 3Ͱ͋Δ͜ͱ", logic { 1 + 2 = 3 })
    failure_sample_test := class(testable_device):
    Run(): logic =
    6

    View full-size slide

  11. ୈ 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

    View full-size slide

  12. ୈ 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

    View full-size slide

  13. ୈ 1 ষ UEFN Ͱ࢝ΊΔ Verse ŧŔŕŪũƄŝſೖ໳ 1.4 UEFN ʹ͓͚Δ Verse ͱઃܭͱ͸
    game_player := class:
    Agent: agent
    var Score: int = 0
    AddScore(Amount: int): void =
    set Score += Amount
    GetScore(): 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

    View full-size slide

  14. ୈ 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’+’(F:float, I:int):float=
    return F + I * 1.0 // IΛ1.0Ͱ৐ࢉ͢Δ͜ͱͰfloatʹม׵͍ͯ͠Δ
    operator’+’(I:int, F:float):float=
    return I * 1.0 + F // IΛ1.0Ͱ৐ࢉ͢Δ͜ͱͰfloatʹม׵͍ͯ͠Δ
    ˞ "+"ͷࠨลӈล྆ํʹରԠ͢ΔͨΊೋͭͷoperatorΛ࡞੒͠·͢
    ͜ͷίʔυΛϞδϡʔϧͱͯ͠ಡΈࠐΜͰ͓͘͜ͱͰ্هͷ int ͱ float ͷܭࢉࣜͰΤϥʔ͕ग़ͳ
    ͘ͳΓ·͢ʢResult ͷܕ͸ float ʹͳΓ·͢ʣ
    ҎԼ͸ int ͱ float ΛܭࢉͰ͖ΔΑ͏ʹ͢Δ͢΂ͯͷ operator Ͱ͢ɻ
    // floatʹม׵͢Δؔ਺͸ڞ௨Խ͓ͯ͘͠
    Float(Number : int):float=
    return Number * 1.0
    operator’+’(I:int, F:float):float=
    return Float(I) + F
    operator’+’(F:float, I:int):float=
    return F + Float(I)
    operator’-’(I:int, F:float):float=
    return Float(I) - F
    10

    View full-size slide

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

    View full-size slide

  16. ୈ 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(): []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

    View full-size slide

  17. ୈ 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(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

    View full-size slide

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

    View full-size slide

  19. ୈ 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

    View full-size slide

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

    View full-size slide

  21. ୈ 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

    View full-size slide

  22. ୈ 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

    View full-size slide

  23. ୈ 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

    View full-size slide

  24. ୈ 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  27. ୈ 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

    View full-size slide

  28. ୈ 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

    View full-size slide

  29. ୈ 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

    View full-size slide

  30. ୈ 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

    View full-size slide

  31. ୈ 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 ؔ਺Λ࢖ͬͯઌ಄͔Βॱʹɺ@ ؔ਺Λ࢖ͬͯҰ൪࠷ޙ͔Βࣗ
    ෼·ͰͷؒͰ࠷΋খ͍͞஋Λ͖͍࣋ͬͯͯ·͢ɻ
    ώʔϓιʔτ
    ࣍ʹɺόϒϧιʔτΑΓߴ଎ͳώʔϓιʔτΛ࣮૷ͯ͠Έ·͢ɻώʔϓιʔτͷΞϧΰϦζϜ
    ͸ɺҰݴͰઆ໌͠ʹ͍͘ͷͰׂѪ͠·͕͢ɺೋ෼ώʔϓ໦ͱ͍͏σʔλߏ଄Λར༻͠·͢ɻී௨ͷ
    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

    View full-size slide

  32. ୈ 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

    View full-size slide

  33. ୈ 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

    View full-size slide

  34. ୈ 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

    View full-size slide

  35. ୈ 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

    View full-size slide

  36. ୈ 3 ষ Haskell Ͱઢܗܕ 3.3 ऴΘΓʹ
    3.3 ऴΘΓʹ
    ͋·Γ࣮༻తͳ࣮૷͸Ͱ͖·ͤΜͰ͕ͨ͠ɺ݁ߏ༡΂ָ͔ͯͬͨ͠Ͱ͢ɻͨͩ΍͸ΓɺઢܗܕΛ༗
    ޮʹѻ͏ʹ͸͔ͳΓ೉ͦ͠͏Ͱͨ͠ʢ೉͔ͬͨ͠ʣ
    ɻͱ͸͍͑ࠓ౓͸ɺ΋͏ҰͭͷϢʔεέʔεͰ͋
    ΔϦιʔε؅ཧʹ͍ͭͯɺFFI ΍ιέοτϓϩάϥϛϯάͳͲͰࢼ͍ͨ͠ͳͱ΋ࢥͬͯ·͢ɻ
    34

    View full-size slide

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

    View full-size slide

  38. ୈ 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

    View full-size slide

  39. ୈ 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

    View full-size slide

  40. ୈ 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

    View full-size slide

  41. ୈ 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 enterEmail(String email) async {
    await tester.enterText(emailField, email);
    }
    Future enterPassword(String password) async {
    await tester.enterText(passwordField, password);
    }
    Future tapLoginButton() async {
    await tester.tap(loginButton);
    await tester.pumpAndSettle();
    }
    }
    ςετέʔεͰ͸ҎԼͷΑ͏ʹ͜ͷ LoginPage ΦϒδΣΫτΛར༻Ͱ͖·͢ɻ
    testWidgets(’Login page test’, (tester) async {
    final loginPage = LoginPage(tester);
    await loginPage.enterEmail(’[email protected]’);
    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

    View full-size slide

  42. ୈ 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(’[email protected]’)
    .enterPassword(’password123’)
    .tapLoginButton()
    .checkLoginSuccess();
    });
    4.4 ऴΘΓʹ
    Flutter ͰͷςετઓུΛద੾ʹߏங͢Δ͜ͱͰɺ඼࣭ͷߴ͍ΞϓϦέʔγϣϯͷ։ൃΛαϙʔτ
    Ͱ͖·͢ɻຊষͰ঺հͨ͠ςετͷߏ੒΍σβΠϯύλʔϯΛࢀߟʹͯ͠ɺޮ཰తͳςετίʔυͷ
    ࡞੒ΛਐΊ͍ͯͩ͘͞ɻ
    40

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  45. ୈ 5 ষ ອը࡞඼͔Βߟ͑Δςετ؍఺ 5.3 ղ౴
    – ࢓༷௨Γʹջதి౮ͷܗΛ͍ͯ͠Δ͜ͱ
    – ॖখεΠον͕෇͍͍ͯΔ͜ͱ
    – ෮ݩεΠον͕෇͍͍ͯΔ͜ͱ
    • ॖখεΠον
    – σϑΥϧτ͸ OFF ʹͳ͍ͬͯΔ͜ͱ
    – ॖখεΠονΛ ON ʹͰ͖Δ͜ͱ
    – ॖখεΠον͕ ON ͷ৔߹ɺরࣹ෦෼͔Βޫ͕ൃͤΒΕΔ͜ͱ
    – ॖখεΠονΛ OFF ʹͰ͖Δ͜ͱ
    – ॖখεΠον͕ OFF ͷ৔߹ɺরࣹ෦෼͔Βޫ͕ൃͤΒΕͳ͍͜ͱ
    – ࠶౓ɺॖখεΠονΛ ON ʹͰ͖Δ͜ͱ
    • ෮ݩεΠον
    – σϑΥϧτ͸ OFF ʹͳ͍ͬͯΔ͜ͱ
    – ෮ݩεΠονΛ ON ʹͰ͖Δ͜ͱ
    – ෮ݩεΠον͕ ON ͷ৔߹ɺরࣹ෦෼͔Βޫ͕ൃͤΒΕΔ͜ͱ
    – ෮ݩεΠονΛ OFF ʹͰ͖Δ͜ͱ
    – ෮ݩεΠον͕ OFF ͷ৔߹ɺরࣹ෦෼͔Βޫ͕ൃͤΒΕͳ͍͜ͱ
    – ࠶౓ɺ෮ݩεΠονΛ ON ʹͰ͖Δ͜ͱ
    • ॖখޫΛ౰ͯͨࡍͷڍಈ
    – 1 ඵؒɺॖখޫʹ౰ͯͨ෺ମ͕খ͘͞ͳΔ͜ͱ
    – 5 ඵؒɺॖখޫʹ౰ͯͨ෺ମ͕খ͘͞ͳΔ͜ͱ
    – ॖখޫΛ 1 ඵؒ౰ͯͨ෺ମΑΓ 5 ඵؒ౰ͯͨ෺ମͷํ͕খ͘͞ͳ͍ͬͯΔ͜ͱ
    – ෺ମͷେ͖͕͞ॖখޫΛ౰ͯͨ࣌ؒʹൺྫ͍ͯ͠Δ͜ͱ
    • ෮ݩޫΛ౰ͯͨࡍͷڍಈ
    – ෮ݩޫΛ౰ͯͨ෺ମͷେ͖͕͞ݩʹ໭Δ͜ͱ
    • ࣌ؒܦա
    – ॖখޫΛ౰ͯͨ෺ମͷେ͖͕͞ݩʹ໭Δ͜ͱ
    43

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  49. ୈ 5 ষ ອը࡞඼͔Βߟ͑Δςετ؍఺ 5.5 ·ͱΊ
    ඞཁͳεΩϧͱ΋ݴ͑ΔͷͰ͸ͳ͍Ͱ͠ΐ͏͔ɻ
    ࠓճɺອը࡞඼ͷඇ࣮ࡏΞΠςϜΛબΜͩཧ༝ͱͯ͠ɺۭ૝ྗ΍૝૾ྗΛ஁͑Δҙਤ΋ࠐΊ͍ͯ·
    ͢ɻॳΊ͸ອը࡞඼Λ୊ࡐʹϨΫϦΤʔγϣϯͷܗͰελʔτ͠ɺ࠷ऴతʹϓϩμΫτʹ౰ͯ͸Ίͯ
    ϫʔΫγϣοϓΛߦ͏͜ͱΛ͓קΊ͠·͢ɻ
    ϫʔΫγϣοϓͷਐΊํʹ͍ͭͯ͸ɺQiita ʹهࣄΛެ։͍ͯ͠·͢ͷͰͥͻ͝ཡ͍ͩ͘͞ɻ
    https://qiita.com/rk0802/items/c34367a9672c6dc49bc7
    ͞·͟·ͳཱ৔ͷϓϩδΣΫτϝϯόʔͱسጨͳ͘؍఺ग़͕͠Ͱ͖ΔະདྷΛظ଴ͭͭ͠ɺຊߘΛక
    Ί͘͘Γ͍ͨͱࢥ͍·͢ɻ
    47

    View full-size slide

  50. ୈ 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

    View full-size slide

  51. ୈ 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

    View full-size slide

  52. ୈ 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

    View full-size slide

  53. ୈ 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

    View full-size slide

  54. ୈ 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

    View full-size slide

  55. ୈ 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

    View full-size slide

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

    View full-size slide

  57. MIXI TECH NOTE #10
    2023 ೥ 11 ݄ 11 ೔ɹॳ൛ୈ 1 ࡮ɹൃߦ
    ஶɹऀ גࣜձࣾ MIXI ༗ࢤ
    ൃߦॴ גࣜձࣾ MIXI
    ҹ࡮ॴ ೔ޫاը
    ɹ
    ˜ MIXI

    View full-size slide