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

クックパッドがどのようにMicroservicesしてきたか/How Cookpad shifts to Microservices

adorechic
October 27, 2016

クックパッドがどのようにMicroservicesしてきたか/How Cookpad shifts to Microservices

adorechic

October 27, 2016
Tweet

More Decks by adorechic

Other Decks in Technology

Transcript

  1. ΫοΫύου͕
    ͲͷΑ͏ʹ
    .JDSPTFSWJDFTԽ͖͔ͯͨ͠
    ΫοΫύουגࣜձࣾ
    ٕज़෦։ൃج൫άϧʔϓ
    ٢઒ਸྙ

    View Slide


  2. View Slide

  3. σΠϦʔ ΞΫηεͷαʔϏε
    ͲΜͳߏ੒ʹ͠·͔͢ʁ

    View Slide


  4. ҰԠ৑௕Խͯ͠୆"QQ%#

    ਺ඦ୆·ͰΦʔτεέʔϧͰ͖Δߏ੒

    View Slide

  5. αʔϏεཁٻʹରͯ͠
    ద੾ͳߏ੒Λߟ͑Δ

    View Slide

  6. εΫϥονͰαʔϏεΛ্ཱͪ͛Δ
    ͲΜͳߏ੒ʹ͠·͔͢ʁ

    View Slide


  7. .POPMJUIJDΞʔΩςΫνϟ

    .JDSPTFSWJDFTΞʔΩςΫνϟ

    View Slide

  8. .JDSPTFSWJDFT
    ͍ͭ΍Δ΂͖ʁ

    View Slide


  9. View Slide

  10. ͜͜·Ͱඞཁʁ

    View Slide

  11. w ࠷ॳ͔Β.JDSPTFSWJDFTͰ͸ͳ͍
    w ϑΣʔζ͝ͱͷ޻෉ͷੵΈॏͶ
    w ΫοΫύουͷߏ੒ͷมભΛḷΔ

    View Slide

  12. ˞஫ҙ
    ࿩ͷྲྀΕΛΘ͔Γ΍͘͢͢ΔͨΊʹ
    τϐοΫ͝ͱͷ࣌ܥྻ͕લޙͨ͠Γ
    ͍ۙτϐοΫΛ·ͱΊͨΓ͍ͯ͠·͢

    View Slide

  13. w ᴈ໌ظ
    w ୯ҰαʔϏεɺϞσϧڞ༗ɺ༻్͝ͱͷΠϯϑϥ
    w αʔϏε֦େظ
    w ΞϓϦέʔγϣϯංେԽ΁ͷରԠͱݶք
    w ୤.POPMJUIJDظ
    w ౷Ұతͳ"1*ɺڞ௨ج൫ɺαʔϏε෼ׂ
    w .JDSPTFSWJDFTԽظ
    w αʔϏε෼ׂͷฐ֐Λղফ͢Δɺ෼ׂίετͷ௿Լ

    View Slide

  14. ᴈ໌ظ

    View Slide

  15. ୯Ұͷ3BJMT
    DPPLQBE

    View Slide

  16. ༻్͝ͱʹαʔόʔΛ෼͚͍ͨ
    w Πϯϑϥͷੑ࣭ͷҧ͍ͰΘ͚ͯ؅ཧ͍ͨ͠
    w "1*͸ผυϝΠϯͰ഑৴͢Δ
    w όοΫάϥ΢ϯυδϣϒ༻ͷαʔόʔΛΘ͚Δ
    w %#΍Ωϟογϡ؅ཧͳͲ΋ඞཁʹԠͯͦ͡ΕͧΕ෼͚͍ͨ
    w ΞϓϦέʔγϣϯͷ࣮૷͸·ͱΊ͓͖͍ͯͨ

    View Slide

  17. QVQQFUͷSPMFΛΘ͚ͯผʑʹߏ੒؅ཧ
    QVQQFU͕ΞϓϦέʔγϣϯͷDPOpHΛ഑෍
    DPPLQBE
    XFC

    DPPLQBE
    BQJ

    DPPLQBE
    CBDLHSPVOEXPSLFS

    ΞϓϦέʔγϣϯίʔυ͸શͯಉ͡ɻผϞʔυͱͯ͠ಈ࡞ͤ͞Δ

    View Slide

  18. ΞϓϦέʔγϣϯؒͰϞσϧΛڞ༗͍ͨ͠
    w ػೳ͕େ͖͘ҟͳΔΞϓϦέʔγϣϯΛ෼͚͍ͨ
    w 1$εϚʔτϑΥϯ޲͚αΠτ
    w ϑΟʔνϟʔϑΥϯ޲͚αΠτ
    w ΋ͱ΋ͱϑΟʔνϟʔϑΥϯ޲͚ผαʔϏεͩͬͨͷΛ౷߹ͨ͠
    w ελοϑ޲͚؅ཧαΠτ
    w σʔλ͸ಉ͡΋ͷΛݟͯɺϞσϧϩδοΫ΋ڞ༗͍ͨ͠

    View Slide

  19. Ϟσϧ΍ڞ௨ϥΠϒϥϦ෦෼ΛTIBSFEͱͯ͠ಠཱ
    ֤ΞϓϦέʔγϣϯ͔Β͸TZNMJOLͰࢀর
    DPPLQBE XFC BQJʜ
    DPPLQBE BENJO

    DPPLQBE
    GFBUVSFQIPOF


    View Slide


  20. TIBSFEΛؚΊશΞϓϦέʔγϣϯ͕ҰͭͷϦϙδτϦʹಉډ
    ʮຊମʯʮ[email protected]ʯͱݺ͹ΕΔ

    View Slide

  21. αʔϏε֦େظ

    View Slide

  22. ϨγϐҎ֎ͷαʔϏε͕ੜ·Ε࢝ΊΔ
    w ϨγϐΛͷͤΔɺ͕͢͞Ҏ֎ͷػೳ
    w ಛച৘ใɺྉཧڭࣨͳͲͷαʔϏεʹͭͳ͕͍ͬͯ͘
    w ϓϩτλΠϓΛ࡞ͬͯՁ஋ݕূΛ܁Γฦ͢
    w ϓϩτλΠϓͳͷͰܧଓͯ͠࢖͏͔͸ෆ໌
    w ޻਺Λ࠷খݶʹ͢ΔͨΊʹɺطଘͷࢿ࢈Λ࠷େݶ׆༻

    View Slide

  23. ผΞϓϦέʔγϣϯͱ͢Δ
    ৔߹΋TIBSFEΛڞ༗
    ຊମʹ͍͋ͷΓ
    ʢຊମ͸ڊେԽʣ
    ೝূɺܾࡁɺϩάͳͲ͸
    ຊମͷϞδϡʔϧΛ௚઀࢖͏
    ඞཁͳΒαʔϏε͝ͱͷॲཧΛ௚઀࣮૷

    View Slide

  24. $*ʹ͔͔Δ͕࣌ؒංେԽ
    w ͨͩͰ͑͞ςετ͕ͲΜͲΜ૿͕͔͔͑ͯ࣌ؒΔ
    w TIBSFEΛ௨ͯ͡શ෦ͭͳ͕͍ͬͯΔͷͰશવҧ͏ՕॴͰࢥΘ͵Өڹ͕
    ग़ͯςετ͕ࣦഊ͢Δ
    w मਖ਼ͯ͠࠶࣮ߦʹ·͕͔͔ͨ࣌ؒΔ
    w ͋ΔνʔϜ͕$*ΛGBJMͤ͞ΔͱଞͷνʔϜ΋σϓϩΠͰ͖ͳ͍
    w σϓϩΠ·Ͱͷ଴ͪ࣌ؒΛ࠷খԽ͍ͨ͠

    View Slide

  25. [email protected]
    ෳ਺୆ͷαʔόʔͰ
    ςετΛ෼ࢄ࣮ߦ
    ෼Ҏ಺ʹ
    ऴΘΔΑ͏ʹ

    View Slide

  26. ςετ͸͞Βʹ૿͑ଓ͚ͨ
    w ։ൃ͕ϐʔΫ࣌ͷςετΛ͞͹ͨ͘ΊͷϫʔΧʔ਺૿
    w Ұํٳ೔͸શવཁΒͳ͍
    w ॊೈʹ૿ݮ͍ͤͨ͞
    w ϫʔΧʔͷো֐΍ͨ·ͨ·ࣦഊ͢ΔFYBNQMFͷӨڹ૿

    View Slide

  27. 3334QFD
    w HJUIVCDPNDPPLQBESSSTQFD
    w &$εϙοτΠϯελϯεΛར༻ͯ͠ίετΛ཈͑Δ
    w ࣦഊͨ͠ςετͷࣗಈ࠶࣮ߦ

    View Slide

  28. σϓϩΠʹ͕͔͔࣌ؒΔ
    w DBQJTUSBOP
    w ཁ͢ΔʹTTI઀ଓͯ͠σϓϩΠ
    w ୆਺΋ଟ͘ճͷσϓϩΠͰ෼Ҏ্͔͔Δ
    w TTIͰࣦഊ͢Δස౓͕૿Ճ
    w ϦτϥΠ͢ΔӋ໨ʹͳΓ͞Βʹ͕͔͔࣌ؒΔ

    View Slide

  29. NBNJZB
    w HJUIVCDPNTPSBINBNJZB
    w 4FSGͰΦʔέετϨʔγϣϯ
    w $*͕௨ͬͨΒUBSCBMMʹͯ͠4ʹΞοϓ
    w ։ൃऀ͕४ຊ൪؀ڥͰಈ࡞֬ೝ͍ͯ͠Δؒʹ഑෍ͯ͠४උ
    w σϓϩΠίϚϯυͰ͸੾Γସ͑Δ͚ͩ

    View Slide

  30. ։ൃ؀ڥ͕ॏ͗͢Δ
    w खݩͰSBJMTΛىಈͯ͠τοϓදࣔ͢Δ·Ͱ෼Ҏ্͔͔Δ
    w ͱʹ͔͘HFN΍ൃߦΫΤϦ͕ଟ͗͢Δ
    w ։ൃ؀ڥͷύϑΥʔϚϯενϡʔχϯά
    w ։ൃ؀ڥͰ΋ΩϟογϡΛ׆༻͢ΔΑ͏ʹͳΔ
    w ෆཁͳίʔυ୨Է͠ͷܒ໤

    View Slide

  31. मਖ਼͕ٴ΅͢Өڹൣғ͕Θ͔Βͳ͍
    w ᴈ໌ظ͸ڞ௨Ϟδϡʔϧͱͯ͠੾Γग़ͨ͠Γ"1*Λ੔උ͢ΔͷͰ͸
    ͳ͘ɺ௚઀࢖ͬͨΓ֦ுͨ͠Γ͢Δߥʑ͍͠ελΠϧ
    w TIBSFEͰෳ਺ͷΞϓϦέʔγϣϯ͕ͭͳ͕͍ͬͯͯͲ͏࢖ΘΕ
    Δͷ͔Θ͔Βͳ͍
    w ϥΠϒϥϦ΋ϞϯΩʔύον΍ϑΥʔΫ͍ͯ͠Δ΋ͷ͕ଟ͘஌ͬͯ
    ͍Δڍಈͱҧ͏

    View Slide

  32. ػೳͷڥք͕͍͋·͍
    w ͲͷνʔϜ͕୲౰͍ͯ͠Δͷ͔͕͍͋·͍
    w ମ੍มߋͳͲͰͷҾ͖ܧ͗࿙Ε΋ൃੜ͕ͪ͠
    w ϓϩμΫτΦʔφʔ͸"νʔϜ͚ͩͲ࣮࣭ӡ༻΍࣮૷͸#νʔϜ͕
    ΍ͬͪΌͬͯΔ
    w ػೳมߋ͢Δͱ͖ʹӨڹड͚ΔνʔϜ͕ଟ͍
    w νʔϜΛ·͍ͨͩௐ੔ͱίϛϡχέʔγϣϯ͕େม

    View Slide

  33. Ͳ͏͢Ε͹ɾɾɾ

    View Slide

  34. ୤.POPMJUIJDظ

    View Slide

  35. ୤ຊମ୤TIBSFE͍ͨ͠
    w طଘͷࢿ࢈Λ࢖͑Δͱ͍ͬͯ΋ਏΈ͕ڧ͘ͳ͖ͬͯͨ
    w Ϟδϡʔϧࣗମ͕αʔϏεͱີ݁߹͓ͯ͠Γ݁ہ࠶ར༻ͮ͠Β͍
    w εΫϥονͰ࡞Ε͹ίʔυϕʔε΋খ͘͞ࡁΉ
    w ґଘ͕গͳ͘։ൃ؀ڥͷಈ࡞΍ςετ΋଎͍
    w গͳ͘ͱ΋৽نͰ࡞ΔͳΒ෼͚ͨ΄͏͕Α͍ͷͰ͸

    View Slide

  36. ೝূͳͲຊମͱͷ΍ΓͱΓ͸
    "1*Λ௨ͯ͡ߦ͏
    ίʔυ΋%#΋
    ຊମ͔Βಠཱ
    ܾࡁͷΑ͏ʹ
    ڞ௨ͯ͠ར༻Ͱ͖Δ
    ػೳΛ੾Γग़͠
    ੾Γग़͞Εͨػೳ͸
    ຊମ͔Β΋"1*࿈ܞ

    View Slide

  37. "1*Λ௨ͯ͠ϦιʔεΛѻ͏
    w J04"OESPJEΞϓϦ͕ߴػೳԽ
    w 8FC7JFXͰఏڙ͍ͯͨ͠΋ͷ΋ωΠςΟϒ࣮૷Խ
    w "1*ͰຊମͷϦιʔεΛࡉ੍͔͘ޚͰ͖ΔΑ͏ʹ͢Δ
    w ΠϯλʔϑΣΠεΛ౷Ұ͍ͨ͠
    w ϑΥʔϚοτͷҟͳΔ"1*͕ෳ਺ଘࡏ͍ͯͨ͠
    w "1*͝ͱʹYYYDMJFOU

    View Slide

  38. 3&45GVMIZQFSNFEJB"1*
    GET /v1/users/123
    {
    "id": 123,
    "name": "ύυඒ",
    "kitchen": {
    "id": 15,
    "created": "2016-03-10T10:59:24+09:00",
    }
    },
    "_links": {
    "self": {
    "href": "/v1/users/123"
    },
    "recipes": {
    "href": "/v1/users/123/recipes"
    },
    }
    }
    Ϧιʔεؒͷؔ࿈Λ
    ϦϯΫͱͯ͠දݱͰ͖Δ

    View Slide

  39. (BSBHF
    w HJUIVCDPNDPPLQBEHBSBHF
    class Employee < ActiveRecord::Base
    include Garage::Representer
    belongs_to :division
    has_many :projects
    property :id
    property :title
    property :division, selectable: true
    collection :projects, selectable: true
    link(:division) { division_path(division) }
    link(:projects) { employee_projects_path(self) }
    def self.build_permissions(perms, other, target)
    perms.permits! :read
    end
    end
    Ϧιʔεͱͯ͠ͷ
    ଐੑ΍ϦϯΫΛఆٛ
    ೝՄ৚݅΋ఆٛͰ͖Δ

    View Slide

  40. (BSBHF$MJFOU
    w [email protected]
    # GET https://garage.example.com/v1/me
    user = client.get("/me")
    user.id
    user.name
    # GET https://garage.example.com/v1/recipes
    recipes = client.get("/recipes")
    recipes.total_count
    recipes[0].id
    recipes[0].name
    ϦιʔεΛจࣈྻͰࢦఆ
    "1*ͷ࣮૷͕૿͑ͯ΋
    ΫϥΠΞϯτ͸ͦͷ··࢖͑Δ
    ͲͷαʔϏεΛ࢖͏ͱ͖΋
    ࢖͍ํ͸ಉ͡
    ֤ΤϯυϙΠϯτͷ࢓༷͚ͩ
    Θ͔Ε͹Α͍

    View Slide

  41. "VUPEPD
    w HJUIVCDPNSLBNVSBBVUPEPD
    # spec/requests/users_spec.rb
    describe "Users" do
    describe "GET /v1/me", autodoc: true do
    it "returns a current_resource_owner" do
    get "/v1/me", params: {}, headers: headers
    expect(response).to have_http_status(:success)
    expect(response.body).to be_json_as(
    id: resource_owner.id,
    name: resource_owner.name
    )
    end
    end
    end
    ςετ͔ΒυΩϡϝϯτΛ
    ࣗಈੜ੒

    View Slide

  42. ೝূɺϩάɺ௨஌ͳͲ༷ʑͳ
    ڞ௨ج൫αʔϏε͕੔උ͞Ε
    ͍ͯͬͨ
    TIBSFE࿈ܞ͍ͯͨ͠αʔϏε΍
    ຊମ಺͔Βଔۀ͢ΔαʔϏε͕
    ग़͖ͯͨ
    ຊମ͸ґଘؔ܎౳ͷ໰୊Ͱ
    HBSBHF"1*ΛผϞʔυͰىಈ
    ΞϓϦ΋ผαʔϏε΋
    ಉ͡"1*Λ࢖͏
    ֤αʔϏεؒ΋
    HBSBHF"1*Ͱ࿈ܞ

    View Slide

  43. .JDSPTFSWJDFTԽظ

    View Slide

  44. ߏ੒؅ཧ͕େม
    w 8FCόονͳͲ༻్ʹԠͯ͡ߏ੒؅ཧΛ෼͚ΔελΠϧ
    w BQQαʔόʔ͸ಠཱͨ͠SPMF
    w όονδϣϒ͸ڞ௨ͷόονϫʔΧʔͷҰ෦ͱͯ͠؅ཧ
    w ઃఆͷ഑෍࿙Ε
    w ΞϓϦέʔγϣϯ͕ಉډ͢Δͱݖݶ؅ཧ͕ࠔ೉
    w *".3PMF΍ൿಗ஋ͷ؅ཧͳͲ

    View Slide

  45. %PDLFS
    w ϙʔλϒϧͳ࣮ߦ؀ڥ
    w TUBHJOHQSPEVDUJPOόονಉ͡Πϝʔδ
    w खݩͰݕূ͢Δ͜ͱ΋Ͱ͖Δ
    w %PDLFSpMF͸ΞϓϦέʔγϣϯϦϙδτϦʹஔ͘
    w ΞϓϦέʔγϣϯݻ༗ͷ৘ใ͕ू໿
    w ؀ڥґଘ஋͸؀ڥม਺ͱͯ͠σϓϩΠ࣌ʹ஫ೖ

    View Slide

  46. FUDFOWFUDWBVMU
    w HJUIVCDPNTPSBIFUDFOW
    w FUDEͰઃఆ஋Λ؅ཧ
    w HJUIVCDPNTPSBIFUDWBVMU
    w FUDEͷ஋Λ҉߸Խ
    w ΋ͱ΋ͱFUDEʹ"$-͕ແ͔ͬͨͨΊ࡞ΒΕͨ
    w ࢦఆͷ伴Λ͍࣋ͬͯΔΠϯελϯεͰ͔͠෮߸Ͱ͖ͳ͍

    View Slide

  47. FUDXFC
    w HJUIVCDPNTPSBIFUDXFC
    8FC6*ͰશαʔϏεͷ
    ઃఆ஋ΛҰׅ؅ཧ
    ൿಗ஋Λѻ͏ͷͰ
    ݖݶΛ࣋ͭਓ͚͕ͩૢ࡞

    View Slide

  48. ,VSPLP
    w HJUIVCDPNDPPLQBELVSPLP
    w શαʔϏεͷόονδϣϒ΍ϫʔΫϑϩʔΛ؅ཧ
    w ϫʔΧʔ͕࠷৽ͷ%PDLFSΠϝʔδΛऔಘ࣮ͯ͠ߦ
    8FCͰδϣϒ؅ཧ
    ϩάӾཡ
    ࠶࣮ߦ·ͰͰ͖Δ

    View Slide

  49. #BSCFRVF
    w HJUIVCDPNDPPLQBECBSCFRVF
    w ,VSPLPಉ༷%PDLFSίϯςφͰδϣϒ࣮ߦͰ͖Δ

    View Slide

  50. %PDLFSӡ༻ͷચ࿅
    w ౰ॳ͸খ͞ͳπʔϧΛ૊Έ߹Θͤͯ؅ཧ͍ͯͨ͠
    w ౷Ұͯ͠ίϯτϩʔϧ͢Δ΋ͷ͕ͳ͍
    w ઃఆ͢Δ΋ͷ͕݁ߏଟ͍
    w ϗετͷ؅ཧͷखؒ
    w &$4ͷొ৔
    w "84ϚωʔδυͳίϯςφαʔϏε

    View Slide

  51. )BLP
    w HJUIVCDPNFBHMFUNUIBLP
    w %PDLFSΞϓϦ༻ͷσϓϩΠπʔϧ
    w ΫοΫύουͰ͸όοΫΤϯυʹ&$4Λར༻
    w ΞϓϦέʔγϣϯ͝ͱͷઃఆ͸:".-Ͱ؅ཧ
    w ؀ڥ͝ͱʹ؀ڥม਺ΛઃఆͰ͖Δ
    w ൿಗ஋ͷΈFUDFOWFUDWBVMUͰ؅ཧ

    View Slide

  52. ൥ࡶͳ؅ཧ͔Βͷղ์
    w ͱʹ͔͘%PDLFSΠϝʔδ͕͋Ε͹༷ʑͳ༻్Ͱ࣮ߦͰ͖Δ
    w Ϋϥ΢υ্ͷݖݶ؅ཧ͕γϯϓϧʹ
    w &$45BTLʹ*".3PMFͰݖݶ෇༩
    w όονδϣϒ͸σϓϩΠͷ֓೦͕ͳ͘ͳͬͨ
    w ͦͷ࣌఺Ͱ࠷৽ͷΠϝʔδΛऔಘ࣮ͯ͠ߦ͞ΕΔ
    w TTIͯ͠ϩάௐࠪ͢Δ͜ͱ͸ͳ͘ͳΓɺ8FC6*Ͱ֬ೝ

    View Slide

  53. ΞϓϦέʔγϣϯ௥Ճ͕௿ίετԽ
    w %PDLFSΠϝʔδ͕͋Ε͹0,
    w XFCCBUDIKPCRVFVFͲ͜Ͱ΋࢖͑Δ
    w [email protected]͚ͩೖΕ͓͚ͯ͹ଞͷαʔϏε͕࢖͑Δ
    w ҎલͳΒϞʔυΛΘ͚ͨΓ͍ͯͨ͠΋ͷ΋৽نͰ௥Ճͨ͠ํָ͕
    w αʔϏεͷཻ౓͸࣍ୈʹখ͘͞ͳΓɺ૿͑Δ଎౓΋૿͍ͯ͘͠

    View Slide

  54. #BDLFOE'PS'SPOUFOE
    Ϧιʔε͸ಉ͡΋ͷ
    ఏڙ͍͕ͨ͠
    ೝূํ͕ࣜҟͳΔͳͲ
    ಛघͳΫϥΠΞϯτ
    ઐ༻όοΫΤϯυ

    View Slide

  55. "1*࢓༷ͷᴥᴪʹΑΔࣄނ
    w ഁյతͳ࢓༷มߋʹΑΔࣄނ
    w ଟ͘ͷ৔߹͸ҙਤͨ͠΋ͷͰ͸ͳ͘ൃੜ
    w ҙਤ͍ͯ͠Δ৔߹΋Ͳ͔͜Βར༻͞Ε͍ͯΔͷ͔೺Ѳͮ͠Β͍
    w ςετ͸ʁ
    w ࣗಈςετͰ͸ଞαʔϏεͷ"1*͸ελϒ͍ͯ͠Δ
    w "1*ϓϩόΠμଆ͕࢓༷มߋͯ͠΋ελϒ͸ߋ৽͞Εͳ͍ͷͰݕ஌Ͱ͖ͳ͍

    View Slide

  56. WDS
    w HJUIVCDPNWDSWDS
    w ςετ࣌ʹ࣮ࡍͷ)551ͷϦΫΤετͱϨεϙϯεΛه࿥
    w ࣍ճҎ߱ͷϦΫΤετͰ͸ه࿥ͨ͠Χηοτσʔλ͔ΒڍಈΛ࠶ݱ
    ͢Δ
    w ࣮ϦΫΤετ͔ΒελϒΛੜ੒͢Δ

    View Slide

  57. 3BDL7$3
    w HJUIVCDPNNJZBHBXBSBDLWDS
    w "1*ϓϩόΠμଆ͕ࣗ਎Λςετͨ͠ΧηοτσʔλΛه࿥ɾ഑෍
    w "1*ΫϥΠΞϯτଆ͸ςετ࣌"1*ϓϩόΠμ͔ΒΧηοτσʔλ
    Λऔಘͯࣗ͠਎Λςετ͢Δࡍͷελϒͱ͢Δ
    w ΫϥΠΞϯτ͸ৗʹ࠷৽ͷڍಈͷελϒΛ࢖ͬͯςετͰ͖Δ

    View Slide

  58. $*࣮ߦස౓ͷ͕ࠩେ͖͍৔߹ͷ໰୊
    w ։ൃ͕׆ൃͰҰ೔ʹԿ౓΋$*࣮ߦʴσϓϩΠ͞ΕΔ΋ͷ΋͋Ε͹ɺ
    Ұ೔ʹҰճఔ౓͔͠$*͕࣮ߦ͞Εͳ͍΋ͷ΋͋Δ
    w 3BDL7$3͸ΫϥΠΞϯτଆͰ࣮ߦ͞Εͯ͸͡Ίͯ࢓༷͕յΕͨ
    ͜ͱΛݕ஌Ͱ͖Δ
    w ΫϥΠΞϯτଆͷ$*ස౓͕গͳ͍ͱɺ"1*ϓϩόΠμଆͷมߋΛ
    ݕ஌͢ΔલʹσϓϩΠ͞Εͯ͠·͏

    View Slide

  59. $POTVNFS%SJWFO$POUSBDUUFTUJOH
    w ΫϥΠΞϯτʢ$POTVNFSʣ͕"1*Λελϒͯ͠ςετ
    w ظ଴͢ΔৼΔ෣͍Λܖ໿ʢ$POUSBDUʣͱͯ͠"1*ଆʹ౉͢
    w "1*ϓϩόΠμଆ͸ࣗ਎͕$POUSBDUΛຬ͍ͨͯ͠Δ͔Λςετ͢
    Δ
    w "1*ϓϩόΠμଆͷ$*ͰςετͰ͖ΔͷͰɺ໰୊ʹͳΔϦϏδϣ
    ϯΛσϓϩΠ͢Δલʹݕ஌Ͱ͖Δ
    http://martinfowler.com/articles/consumerDrivenContracts.html

    View Slide

  60. 1BDU
    w HJUIVCDPNSFBMFTUBUFDPNBVQBDU
    w ΫϥΠΞϯτଆ
    w $*ͰQBDUϑΝΠϧΛੜ੒
    w "1*ϓϩόΠμଆ
    w $*ͰQBDUϑΝΠϧΛWFSJGZ
    IUUQTHJUIVCDPNSFBMFTUBUFDPNBVQBDUIPXEPFTJUXPSL

    View Slide

  61. 1BDU $POTVNFS

    describe 'get_all' do
    let(:recipe_a) { { id: Pact.like(1), name: Pact.like('Curry') } }
    let(:recipe_b) { { id: Pact.like(2), name: Pact.like('Salada') } }
    before do
    provider_app.given('there are 2 recipes').
    upon_receiving('a request for recipes').
    with(method: :get, path: '/v1/recipes').
    will_respond_with(
    status: 200,
    headers: {
    'Content-Type' => Pact.term(
    generate: 'application/json', matcher: %r{application/json}
    ),
    },
    body: [recipe_a, recipe_b]
    )
    end
    it 'returns recipes' do
    recipes = described_class.get_all
    expect(recipes.size).to eq(2)
    expect(recipes.first.name).to eq('Curry')
    end
    end
    ςετ͸௨ৗͱಉ͡
    1BDUͰελϒ

    View Slide

  62. 1BDUpMF
    {
    "consumer": {
    "name": "ConsumerApp"
    },
    "provider": {
    "name": "ProviderApp"
    },
    "interactions": [
    {
    "description": "a request for recipes",
    "provider_state": "there are 2 recipes",
    "request": {
    "method": "get",
    "path": "/v1/recipes"
    },
    "response": {
    "status": 200,
    "headers": {
    "Content-Type": {
    "json_class": "Pact::Term",
    "data": {
    "generate": "application/json",
    "matcher": {
    "json_class": "Regexp",
    "o": 0,
    "s": "application/json"
    }
    ϦΫΤετͱ
    Ϩεϙϯεͷ
    ಺༰ΛKTPOͰग़ྗ

    View Slide

  63. 1BDU 1SPWJEFS

    w "1*ଆ
    w γφϦΦʹԊͬͨηοτΞοϓίʔυ͚ͩΛ༻ҙ
    Pact.provider_states_for 'ConsumerApp' do
    provider_state "there are 2 recipes" do
    set_up do
    %w[Curry Salada].each {|name| Recipe.create!(name: name) }
    end
    end
    end

    View Slide

  64. ো֐ͷ఻೻
    w ࣮૷ʹόά͕ͳ͔Ζ͏ͱো֐͸ى͜Γ͏Δ
    w ͋ΔαʔϏε͕ো֐ʹͳΔͱͦΕΛར༻͍ͯ͠ΔαʔϏεʹ఻೻
    w ϦΫΤετ͝ͱʹλΠϜΞ΢τ·Ͱ଴ͭ͜ͱͰΫϥΠΞϯτଆ΋
    ٧·Δ
    w ΫϥΠΞϯτଆͷϦτϥΠػߏ͕"1*ϓϩόΠμʹͱͲΊΛࢗ͢

    View Slide

  65. $JSDVJU#SFBLFS
    w ฏৗ࣌ͷࣦഊ͸ΫϥΠΞϯτ͸ϦτϥΠͰ͖Δ
    w "1*ϓϩόΠμ͕μ΢ϯ͍ͯ͠Δ৔߹͸ϦΫΤετ͠ͳ͍Α͏ʹ͢Δ
    w λΠϜΞ΢τ଴ͪ΋͠ͳ͍
    w ͠͹Βͯ͘͠ϓϩόΠμ͕෮׆ͨ͠Β·ͨϦΫΤετΛ࠶։͢Δ

    View Slide

  66. &YQFEJUPS
    w HJUIVCDPNDPPLQBEFYQFEJUPS
    EXPEDITOR_SERVICE = Expeditor::Service.new(
    non_break_count: 20,
    threshold: 0.2,
    period: 10,
    sleep: 5,
    )
    def notification_counts
    Expeditor::Command.new(service: EXPEDITOR_SERVICE, timeout: 3) {
    response = client.get("/notifications/counts", params, options)
    response.notification_count
    }.set_fallback {|e|
    Raven.capture_exception(e)
    0
    }.start(current_thread: true).get
    end
    $JSDVJU#SFBLFSͷᮢ஋Λઃఆ
    Τϥʔ࣌͸ϩάΛه࿥ͯ͠
    σϑΥϧτ஋Λฦ͢

    View Slide

  67. &YQFEJUPS
    w ฏৗ࣌

    ΫϥΠΞϯταʔϏε
    ΦϓγϣϯʹԠͯ͡
    ϦτϥΠͨ͠Γ
    Ͳ͏ͯ͠΋ͩΊͳΒ
    GBMMCBDLॲཧ
    "1*ϓϩόΠμ

    View Slide

  68. &YQFEJUPS
    w ো֐࣌

    ΫϥΠΞϯταʔϏε
    ϦΫΤετͤͣ
    ࠷ॳ͔ΒGBMMCBDLॲཧ
    "1*ϓϩόΠμ

    View Slide

  69. αʔϏε෼ׂ࣌ʹࠔΔϙΠϯτ͕ղܾ͞Ε͖ͯͨ
    w "1*͕ཚཱͯ͠Ͳ͜ΛͲ͏࢖͑͹͍͍ͷ͔Θ͔Βͳ͘ͳΔ
    w (BSBHFͰͲͷαʔϏε΋ಉ͡Α͏ʹ࢖͑Δ
    w ຖճαʔόʔ࡞ͬͯߏ੒؅ཧ͢Δͷ͕େม
    w %PDLFSpMFͱ:".-Λॻ͚͹)BLPͰ؀ڥ༻ҙͰ͖Δ
    w αʔϏεڥքͰόά΍ো֐ʹͳΓ΍͍͢
    w 1BDU͕ޓ׵ੑΛ୲อ͠&YQFEJUPS͕ো֐ͷ఻೻Λ๷͙

    View Slide

  70. αʔϏεΛ෼ׂ͢Δ͜ͱͰಘΒΕΔྑ͍͜ͱ
    w ίʔυϕʔε͕খ͍͞
    w ςετ΍։ൃ؀ڥͷಈ࡞͕଎͍
    w มߋʹΑΔӨڹൣғ͕খ͍͞
    w طଘ࣮૷ʹΑΔ੍໿͕খ͍͞
    w νʔϜʹ࣮͋ͬͨ૷ϧʔϧ
    w ػೳʹదͨ͠ϥΠϒϥϦɺݴޠͷબ୒

    View Slide

  71. αʔϏεΛ෼ׂ͢Δ͜ͱͰಘΒΕΔྑ͍͜ͱ
    w γεςϜڥք͕໌֬
    w νʔϜ಺Ͱίϛϡχέʔγϣϯ͕׬݁͢Δ
    w ׬݁Ͱ͖ͳ͍৔߹ڥքͱͯ͋͠·ΓΑ͘ͳ͍

    View Slide

  72. ·ͱΊ
    w ࠷ॳ͔Βɺ͋Δ͍͸͋Δ೔ಥવ.JDSPTFSWJDFTʹͳͬͨΘ͚Ͱ͸ͳ͍
    w ͦͷ౎౓໰୊ʹͳͬͨ͜ͱʹରԠ͖ͯͨ͠ੵΈॏͶ
    w ϞϊϦγοΫͳγεςϜ͸ঃʑʹਏΈ͕େ͖͘ͳ͍ͬͯ͘
    w αʔϏεΛ෼͚Δ͜ͱͰൃੜ͢Δ໰୊͸ٕज़ͰճආͰ͖Δ
    w ςΫχοΫΛ஌ΓϑΣʔζʹԠͨ͡ઃܭΛ͢Δͷ͕ॏཁ

    View Slide