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

フレームワークを作らない方法/How NOT to build frameworks

フレームワークを作らない方法/How NOT to build frameworks

銀座Rails#10での発表資料です

MOROHASHI Kyosuke

June 21, 2019
Tweet

More Decks by MOROHASHI Kyosuke

Other Decks in Programming

Transcript

  1. ϑϨʔϜϫʔΫΛ
    ࡞Βͳ͍ํ๏
    )PX/05UPCVJMEGSBNFXPSLT

    2019-06-21 ۜ࠲Rails#10
    ॾڮګհ @moro


    View Slide

  2. ‣ ࣸਅ



    View Slide



  3. Kyosuke MOROHASHI
    @moro

    View Slide



  4. View Slide

  5. !5
    SMS?
    What's
    SMSってなにをやってる会社なの?

    View Slide



  6. https://twitter.com/sunaot/status/1002392476492038144

    View Slide


  7. 情報インフラを構築することで、⾼齢社会を

    取り巻く⼈びと、⾼齢社会で働く⽅や事業者の⽅、
    ⾼齢者ご⾃⾝やそのご家族などがイキイキと

    ⽣活できる社会の実現を⽬指しています。
    — https://www.bm-sms.co.jp/philosophy/

    View Slide

  8. !8
    &

    View Slide

  9. 吳䒭⠓爡ؒأ
    ٥
    ؒي
    ٥
    ؒأ
    匌❨鿪庥⼒蓎Ⱅ㕦⡝⿼♶⹛欵蓎Ⱅ㕦ةٙ٦
    https://www.bm-sms.co.jp
    ؒٝآص،䱰欽؟؎
    ز
    https://careers.bm-sms.co.jp/engineer/
    join us!

    View Slide

  10. ͜Ε·Ͱͷ͋Β͢͡

    View Slide



  11. View Slide



  12. View Slide

  13. ‣ ͳͥϑϨʔϜϫʔΫʹ͠ͳ͍΄͏͕Α͍͔
    ‣ ϑϨʔϜϫʔΫΛ࡞Βͳ͍ํ๏
    ‣ ςϯϓϨʔτϝιουΛආ͚ͯ;ͭ͏ʹϝιουʹநग़͢Δ
    ‣ ςϯϓϨʔτϝιουΑΓ΋ετϥςδʔͰ֦ுͤ͞Δ
    ‣ lͪΐͬͱҧ͏ॲཧzΛදݱ͢ΔͨΊʹϒϩοΫΛड͚෇͚Δ
    ‣ ·ͱΊ੍ޚߏ଄Λ࢖͍खʹҕͶΔ

    View Slide

  14. ͳͥ

    ϑϨʔϜϫʔΫʹ͠ͳ͍
    ΄͏͕Α͍͔

    View Slide

  15. ϥΠϒϥϦͱ
    ϑϨʔϜϫʔΫ


    View Slide


  16. ͔͠͠ɺϥΠϒϥϦͰ͸ݺͼग़͠ଆ͕ϓϩάϥϜશ
    ମͷ੍ޚߏ଄ΛࢦఆͰ͖ͳ͍͕ɺϑϨʔϜϫʔΫͰ
    ͸ՄೳͰ͋Δɻ͜ͷ੍ޚͷ൓స͕ιϑτ΢ΣΞϑ
    ϨʔϜϫʔΫͷಛ௃Ͱ͋Δɻ
    https://ja.wikipedia.org/wiki/ιϑτ΢ΣΞϑϨʔϜϫʔΫ

    View Slide

  17. ‣ ʮར༻ऀ͕ݺͼग़͢ʯͷ͕ϥΠϒϥϦ
    ‣ ʮར༻ऀ ͷίʔυ
    Λݺͼग़͢ʯͷ͕ϑϨʔϜϫʔΫ
    ϑϨʔϜϫʔΫ͸੍ޚߏ଄Λࢦఆ͢Δ


    View Slide

  18. ‣ ͸͖ͬΓͱനࠇ͚ͭΒΕΔΘ͚Ͱ͸ͳ͍ɻ
    ‣ ར༻ऀͨΔΞϓϦ։ൃऀ͕ݺͼग़͢"DUJWF3FDPSE

    Ϟσϧʹఆٛͨ͠ίʔϧόοΫ͸"DUJWF3FDPSE͕ݺͼग़ͧ͢ʜ
    ‣ ར༻ऀ͕ॻ͘ίʔυͷ੍ޚߏ଄ΛͲΕ΄Ͳࢦఆ

    ͢Δ͔͠ͳ͍͔ɻ
    ˞۠ผ͸౓߹͍


    View Slide

  19. ‣ ϑϨʔϜϫʔΫ͸ɺͦͷ্Ͱͷ׆ಈΛ੍໿͢Δɻ
    ‣ ͍ΘΏΔʮϨʔϧ͔Β߱Γ͍ͨʯ໰୊
    ‣ ඞͣ͠΋ѱ͍Θ͚Ͱ͸ͳ͍ʮ੍໿͕ࣗ༝Λ΋ͨΒ͢ʯ
    ‣ ʮͦͷ্Ͱͷ׆ಈʯ͸༧ଌͰ͖ͳ͍ɻ
    ‣ ͍͍ͨͯந৅Խ͕࿙ΕΔɻ
    ‣ ࡞ऀͷؾ࣋ͪΛߟ͑Α͏ͱͯ͠΋࡞ऀ΋ߟ͑ͯͳ͍͜ͱ΋ɻ
    ͳͥϑϨʔϜϫʔΫʹ͠ͳ͍΄͏͕ྑ͍͔


    View Slide

  20. ‣ ಡΈղ͘ͷʹϝλϓϩάϥϛϯάͷ஌͕ࣝඞཁʹͳΔ͜ͱଟ͍ɻ
    ‣ ϝλϓϩάϥϛϯάֶशۂઢ
    ίʔυࣗମ͕೉͘͠ͳΓ͕ͪ


    https://www.martinfowler.com/articles/rubyAtThoughtWorks.html

    View Slide

  21. ‣ ଟ͘ͷ"1*ͱͦͷ࢖͍ํΛֶश͢Δඞཁ͋Γɻ
    ‣ ࡞ऀͷؾ࣋ͪΛߟ͑ͯΞϓϦέʔγϣϯίʔυ
    Λॻ͘ɻ
    ϑϨʔϜϫʔΫࣗମ΋ֶशίετ͕͔͔Δ


    View Slide

  22. ‣ 3VCZͰ8FCΞϓϦ։ൃ͢Δͱ͖ͷυఆ൪ͱͯ͠

    ೥ϝΠϯετϦʔϜʹ͍Δɻ
    ‣ ৭Μͳ༻్ͷʮݸผࣄ৘ʯΛίϯτϦϏϡʔτ͞Ε
    ଓ͚͖ͯͨɻ
    ‣ ʮϨʔϧͷ߱ΓํʯͳΜͯͷ·ͰؚΊͯ๲େͳ

    ϊ΢ϋ΢͕஝ੵ͞Ε͍ͯΔɻ
    3BJMT͸ϛϥΫϧ


    View Slide

  23. ‣ ࣗ෼ࣗ਎ΛؚΉ
    ະདྷͷϝϯςφʹର੍͠໿͠ͳ͍ɻ
    ‣ ະདྷʹͲ͏͍͏ιϑτ΢ΣΞʹ͍͔ͨ͠͸Θ͔Βͳ͍ɻ
    ‣ େମʹ͓͍ͯߟྀ͸ෆ଍͠ந৅Խ͸࿙ΕΔɻ
    ‣ ϥΠϒϥϦʹ͓ͯ͘͠ͱɺݺͿ΋ݺ͹ͳ͍΋ɺ

    ΋͏ݺ͹ͳ͘͢Δɺͷ΋ར༻ऀ͕ܾΊΒΕΔɻ
    ʮ;ͩΜ͸ʯϑϨʔϜϫʔΫʹ͢ΔͷΛආ͚Δ


    View Slide

  24. ͱ͸͍͑ɺ
    ศརϝιουΛॻ͖ͨ͘ͳΔ͜ͱ͸
    ͨ͘͞Μ͋ΔΘ͚Ͱ


    View Slide

  25. ‣ ͳͥϑϨʔϜϫʔΫʹ͠ͳ͍΄͏͕Α͍͔
    ‣ ϑϨʔϜϫʔΫΛ࡞Βͳ͍ํ๏
    ‣ ςϯϓϨʔτϝιουΛආ͚ͯ;ͭ͏ʹϝιουʹநग़͢Δ
    ‣ ςϯϓϨʔτϝιουΑΓ΋ετϥςδʔͰ֦ுͤ͞Δ
    ‣ lͪΐͬͱҧ͏ॲཧzΛදݱ͢ΔͨΊʹϒϩοΫΛड͚෇͚Δ
    ‣ ·ͱΊ੍ޚߏ଄Λ࢖͍खʹҕͶΔ

    View Slide

  26. ϑϨʔϜϫʔΫΛ
    ࡞Βͳ͍ํ๏

    View Slide

  27. ݴ͍׵͑Δͱ
    ੍ޚߏ଄Λ

    ࢖͍खʹҕͶΔํ๏

    View Slide

  28. ςϯϓϨʔτϝιουΛආ͚ͯ
    ;ͭ͏ʹϝιουʹநग़͢Δ


    View Slide

  29. ‣ ΦʔόʔϥΠυ͞ΕͯΔϝιουΛ࢓૊Έଆ͕ݺͿɻ
    ݺ͹ΕΔଆ͔Βߏ଄͕ݟ͑ͳ͍ɻ
    ‣ 34QFDͷMFUTVCKFDU໰୊΋ಉࠜͰ͋Δͱ΋ݴ͑Δɻ
    ‣ ۩৅ςετέʔε͔Β཭ΕͨʮϑΝΠϧͷ্ͷํʯʹ

    ߏ଄͕Ͱ͖ΔͷͰɺݟ͑ͳ͍͠ɺม͑ͮΒ͍ɻ
    ςϯϓϨʔτϝιουύλʔϯͷ໰୊


    View Slide

  30. ‣ ܧঝͯ͠͠·͏ͷͰɺϑϨʔϜϫʔΫͷ಺෦ߏ଄Λ
    ࡽͯ͠͠·͏ɻ
    ‣ ͞ΘΓͨ͘ͳΔΑͶ
    ‣ ͦͯ͠όʔδϣϯΞοϓͰ͖ͳ͘ͳΔ
    ‣ 3BJMTΞϓϦ͋Δ͋Δɻ
    ςϯϓϨʔτϝιουύλʔϯͷ໰୊


    View Slide

  31. ‣ 3BJMTࣗମ͕ϥΠϒϥϦఏڙΫϥεΛܧঝͯ͠࢖͏

    ϑϨʔϜϫʔΫͳͷͰɺࣗ෼Ͱ΋ͦ͏ॻ͖ͨ͘ͳΔɻ
    ‣ ʜΑͶ
    ‣ 999#BTF͍ͬͯ͏ந৅ΫϥεΛఆٛͨ͜͠ͱ͋Δਓ
    ‣ 3BJMT͔ͩΒͰ͖Δ͜ͱɻ


    3BJMT͸ϛϥΫϧ

    View Slide

  32. ϝιουʹநग़͠ɺࣗ෼Ͱݺͼग़͢


    View Slide

  33. ‣ Ұ࿈ͷΦϒδΣΫτάϥϑΛ࡞Δϝιο
    υʹநग़͠ɺ࡞Γ͍ͨଆ͕ݺͼग़͢ɻ
    ‣ ࠩ෼ΛҾ਺Ͱ༩͑ͭͭɺ
    ‣ ΊͬͪΌී௨ͷ͜ͱΛݴͬͯ·͢
    ϝιουʹநग़͠ɺࣗ෼Ͱݺͼग़͢


    View Slide



  34. let!(:article) { create(:article, author: author }
    # ...͜ͷؒ 30ߦ...
    context ';ͭ͏ͷϢʔβʔͷهࣄ͸Ұཡදࣔର৅' do
    let(:author) { create(:author) }
    it { expect(Article.indexable).to include(article) }
    context 'ୀձͨ͠Ϣʔβʔͷهࣄ͸Ұཡදࣔର৅֎' do
    let(:author) { create(:author, retired_at: Time.now) }
    it { expect(Article.indexable).not_to include(article) }

    View Slide



  35. def article_by(user)
    create(:article, author: author)
    end
    context ';ͭ͏ͷϢʔβʔ' do
    let(:article) { article_by(create(:user)) }
    it { expect(Article.indexable).to include(article) }
    context 'ୀձͨ͠Ϣʔβʔ' do
    let(:article) { article_by(:author, retired_at: Time.now) }
    it { expect(Article.indexable).not_to include(article) }

    View Slide

  36. ‣ BVUIPSVTFS͕Ͳ͏࡞ΒΕͲ͏࢖ΘΕΔ͔ɺॱΛ௥ͬ
    ͯಡΊΔɻ
    ‣ ϔϧύʔϝιου͕େ͖͘ͳΔଟ͘ͳΓ͗͢Δ

    ଞͷϑΝΠϧ͔Β΋࢖͍͍ͨ৔߹͸ɺී௨ʹ

    ίʔυΛ෼ׂ͢ΔͱΑ͍ɻ
    ‣ কདྷɺςετίʔυΛॻ͘ਓ͕ɺ࢖͍ํΛࣗ෼Ͱ

    ܾΊΒΕΔɻ


    View Slide

  37. ҧ͏ॲཧΛڬΈࠐΉͨΊʹ
    ετϥςδʔύλʔϯΛ࢖͏


    View Slide

  38. ‣ ڞ௨ͷલॲཧΛͯ͠ɺຊॲཧͯ͠ɺڞ௨ͷޙॲཧ͕

    ͋Δ৔߹ͳͲɻ
    ‣ ͞Βʹຊॲཧͷྫ֎ॲཧ΋ඞཁͳ৔߹ͳΜ͔͸৑௕ʹͳΓ͕ͪɻ
    ‣ ͜ͷຊॲཧ͚ͩΛม͍͑ͨɻ
    ‣ ςϯϓϨʔτϝιου࢖͍ͨ͘ͳΓ͕ͪɻ
    ϝιουͷҰ෦͚ͩม͍͑ͨ৔߹͕͋Δ


    View Slide



  39. class TwitterNotification < BaseNotification
    private
    def before_request
    authorize(@article.author)
    def request
    @user = article.author.access_token
    ...
    def after_request
    nil
    class BaseNotification
    def notify(article)
    @article = article
    before_request
    request
    after_request
    private
    def request
    raise NotImplementedError

    View Slide

  40. ετϥςδʔύλʔϯΛ࢖͏


    View Slide

  41. ‣ Ұ෦͚ͩม͍͑ͨॲཧΛɺετϥς
    δʔΦϒδΣΫτͷ஫ೖͰදݱ͢Δɻ
    ετϥςδʔύλʔϯΛ࢖͏


    View Slide



  42. class TwitterNotification < BaseNotification
    private
    def before_request
    authorize(@article.author)
    def request
    @user = article.author.access_token
    ...
    def after_request
    nil
    class BaseNotification
    def notify(article)
    @article = article
    before_request
    request
    after_request
    private
    def request
    raise NotImplementedError

    View Slide



  43. class SnsNotification
    def notify(article)
    #=> [TwitterNotification.new, FacebookNotofication.new...]
    SnsNotification.targets.each do |sns|
    sns.notify(article)

    View Slide

  44. ‣ ݺͼग़͢γʔέϯε͕ࣗ໌ʹͳΔɻ
    ‣ ݺ͹ΕΔݸʑͷετϥςδʔଆ΋ΠϯλʔϑΣʔε
    ͕͸͖ͬΓ͢Δɻ
    ‣ ৼΔ෣͍ʹӨڹΛ༩͑Δύϥϝʔλ͕໌֬ʹͳΔͷͰɺςετ΋͠΍͍͢
    ‣ ݺͼग़͠ݩείʔϓʹΞΫηεͰ͖ͳ͍
    [email protected]@DBMMFSͷ͜ͱ͸๨ΕΑ͏


    View Slide

  45. lͪΐͬͱҧ͏ॲཧzΛ

    ϒϩοΫͱͯ͠ड͚औΔ


    View Slide


  46. EPFOE·ͨ͸\^Ͱғ·Εͨίʔυͷஅย ϒ
    ϩοΫͱݺ͹ΕΔ
    ΛޙΖʹ෇͚ͯϝιουΛݺͼग़
    ͢ͱɺͦͷϝιουͷ಺෦͔ΒϒϩοΫΛධՁͰ͖
    ·͢ɻ

    ϒϩοΫ෇͖ϝιουΛࣗ෼Ͱఆٛ͢Δʹ͸ZJFME
    ࣜΛ࢖͍·͢ɻ

    View Slide

  47. ‣ ॲཧΛΦϒδΣΫτͱͯ͠ந৅Խͨ͠΋ͷɻ
    ‣ 3VCZͷಛ௃ਓؾϙΠϯτͷͭ
    ‣ ͍ΘΏΔʮߴ֊ؔ਺ʯ
    ‣ DBMMͰॲཧΛݺͼग़͢ɻ
    ϒϩοΫ


    View Slide

  48. ‣ ;ͭ͏ͷ܁Γฦ͠
    ‣ .PEFMBMMFBDIEPFOE
    ‣ ॲཧͷڥք
    ‣ .PEFMUBOTBDUJPOEPFOE
    ‣ %4-
    ‣ 3BJMTBQQMJDBUJPOSPVUFTESBXEPFOE
    ‣ 34QFDͷMFU
    3BJMTΞϓϦʹ͓͚ΔϒϩοΫ


    View Slide

  49. ‣ ϥΠϒϥϦ੍͕ޚߏ଄Λࢦఆ͍ͯ͠Δ
    ‣ ݺͼग़͠ଆͷ۩ମతͳॲཧࣗମΛϒϩοΫͱͯ͠ड͚ɺ

    ϥΠϒϥϦϑϨʔϜϫʔΫͰ४උ্ͨ͠Ͱݺͼग़͢ɻ
    ‣ Ͱ΋ɺऔΒΕͨؾ͕͠ͳ͍
    ‣ FBDI΍USBOTBDUJPO͸ී௨ʹಡΊΔ
    ϒϩοΫΛΑ͘ݟͯΈΔͱ


    View Slide



  50. model.transaction do
    model1.save!
    model2.save!
    end

    View Slide



  51. module Transactionable
    def transaction
    do_begin
    do_something
    do_commit
    rescue
    do_rollback
    class Model
    include Transactionable
    private
    def do_something
    model1.save!
    model2.save!
    NJYJOͰॻ͍ͯΈΔ

    View Slide



  52. class MyModel < AbstractModel
    private
    def do_something
    model1.save!
    model2.save!
    ςϯϓϨʔτϝιουͰॻ͍ͯΈΔ
    class AbstractModel
    def transaction
    do_begin
    do_something
    do_commit
    rescue
    do_rollback
    private
    def do_something
    raise NotImplementedError

    View Slide



  53. class SaveStrategy
    def initialize(*models)
    def do_something
    @models.each(&:save!)
    ...
    s = SaveStrategy.new(
    model1,
    model2
    )
    model.transaction(s)
    ετϥςδʔͰॻ͍ͯΈΔ
    class Model
    def transaction(strategy)
    do_begin
    strategy.do_something
    do_commit
    rescue
    do_rollback

    View Slide



  54. class Model
    def transaction(&strategy)
    do_begin
    strategy.call # or yield
    do_commit
    rescue
    do_rollback
    ϒϩοΫΛड͚෇͚Δ
    model.transaction do
    model1.save!
    model2.save!

    View Slide

  55. ‣ DBMMΛڞ௨ΠϯλʔϑΣʔεͱͨ͠ετϥςδʔͱ
    ΋ݴ͑Δɻ
    ‣ ͍ΘΏΔDBMMBCMFPCKFDU
    ‣ ϒϩοΫΛ࢖͏ͱɺΞϓϦέʔγϣϯίʔυͷಡΈ
    खͷίϯςΩετ͕ܧଓ͢Δɻ
    ‣ CJOEJOHQSZΛೖΕΔͱ͜Ζ͕ࣗ໌
    ϒϩοΫͱετϥςδʔ


    View Slide



  56. class MyModel < AbstractModel
    private
    def do_something
    model1.save!
    model2.save!
    [email protected]͕ݺ͹Εͯͳͦ͞͏ͳͱ͖Ͳ͏͢Δ
    class AbstractModel
    def transaction
    do_begin
    do_something
    do_commit
    rescue
    do_rollback
    private
    def do_something
    raise NotImplementedError

    View Slide

  57. ‣ ϒϩοΫΛड͚෇͚Δͱɺʮͪΐͬͱҧ͏ॲཧ
    Λࠩ͠ࠐ·͍ͤͨʯͱ͖ʹͷ੍ޚߏ଄Λݺͼग़
    ͠ଆʹҕͶ͍ͯΔΑ͏ʹݟͤΒΕΔɻ
    ‣ ͦ͏͍͏ؾ࣋ͪͰ࢖͑Δͷ͕େࣄɻ
    ‣ 3VCZͬΆ͍ίʔυʹ΋ͳΔɻ


    View Slide

  58. ‣ ͳͥϑϨʔϜϫʔΫʹ͠ͳ͍΄͏͕Α͍͔
    ‣ ϑϨʔϜϫʔΫΛ࡞Βͳ͍ํ๏
    ‣ ςϯϓϨʔτϝιουΛආ͚ͯ;ͭ͏ʹϝιουʹநग़͢Δ
    ‣ ςϯϓϨʔτϝιουΑΓ΋ετϥςδʔͰ֦ுͤ͞Δ
    ‣ lͪΐͬͱҧ͏ॲཧzΛදݱ͢ΔͨΊʹϒϩοΫΛड͚෇͚Δ
    ‣ ·ͱΊ੍ޚߏ଄Λ࢖͍खʹҕͶΔ

    View Slide

  59. ·ͱΊ

    ੍ޚߏ଄Λ

    ࢖͍खʹҕͶΔ

    View Slide

  60. ‣ ศརϥΠϒϥϦ͕ศརͳͷ͸ؒҧ͍ͳ͍ɻ
    ‣ ੍ޚߏ଄Λͯ͠͠ͳͯ͘΋ɺศརϝιουΛఏڙ͢Δͷ͕े෼ศར
    ‣ ʮͪΐͬͱҧ͏ॲཧʯ͸ετϥςδʔͰදݱ͢Δɻ
    ‣ ܧঝͤͯ͞ݺͼग़͢ॲཧ͚ͩΛॻ͔ͤͳ͍
    ‣ ϒϩοΫ͍͍Ϡπɻੵۃతʹ׆༻͠·͠ΐ͏ɻ
    ‣ 3VCZ͍͍ΑͶ
    ϥΠϒϥϦίʔυͱΞϓϦίʔυΛૄʹอͭ


    View Slide

  61. ‣ ϔϧύʔϝιουΛɺετϥςδʔύλʔϯΛɺϒϩοΫΛ
    ࢖͑͹Α͍Θ͚Ͱ͸ͳ͍ɻ
    ‣ 'PP'[email protected] DPOUFYU
    \^Έ͍ͨͳ
    ‣ ͍ͭɺͲ͏ݺ͹ΕΔͷ
    ‣ ʮࠓ͜ͷศརϥΠϒϥϦΛॻ͍ͯΔࣗ෼͸ɺͦΕ͕

    Ͳ͏࢖ΘΕΔ͔·ͩ஌Βͳ͍ʯͱ͍͏ؾ࣋ͪʹ޲͖߹͏ɻ
    )PXʹ͍ͭͯ࿩͠·͕ͨ͠


    View Slide

  62. ‣ ·ͩݟ͵ΞϓϦέʔγϣϯίʔυʹɺඞཁҎ্ͷ

    ੍໿Λ՝͞ͳ͍Α͏ʹ͢Δɻ
    ‣ ΞϓϦέʔγϣϯͰԿΛ͍͔ͨ͠͸ɺͦͷͱ͖ʹͳΒͳ͍ͱΘ͔Βͳ͍ɻ
    ‣ ͦͷ࣌ɺͦͷਓୡ͕ɺ޲͖߹͑Δ༨஍Λ࢒͢ɻ
    ‣ ۩ମతͳ໰୊ʹ޲͖߹͍ͬͯΔਓΛϦεϖΫτɻະདྷͷࣗ෼͔΋
    ੍ޚߏ଄Λ࢖͍खʹҕͶΔ


    View Slide