Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
フレームワークを作らない方法/How NOT to build frameworks
Search
MOROHASHI Kyosuke
June 21, 2019
Programming
1.4k
4
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
フレームワークを作らない方法/How NOT to build frameworks
銀座Rails#10での発表資料です
MOROHASHI Kyosuke
June 21, 2019
Transcript
62 slides
ϑϨʔϜϫʔΫΛ ࡞Βͳ͍ํ๏ )PX/05UPCVJMEGSBNFXPSLT 2019-06-21 ۜ࠲Rails#10 ॾڮګհ @moro
‣ ࣸਅ
Kyosuke MOROHASHI @moro
!5 SMS? What's SMSってなにをやってる会社なの?
https://twitter.com/sunaot/status/1002392476492038144
“ 情報インフラを構築することで、⾼齢社会を 取り巻く⼈びと、⾼齢社会で働く⽅や事業者の⽅、 ⾼齢者ご⾃⾝やそのご家族などがイキイキと ⽣活できる社会の実現を⽬指しています。 — https://www.bm-sms.co.jp/philosophy/
!8 &
吳䒭⠓爡ؒأ ٥ ؒي ٥ ؒأ 匌❨鿪庥⼒蓎Ⱅ㕦⡝♶⹛欵蓎Ⱅ㕦ةٙ٦ https://www.bm-sms.co.jp ؒٝآص،䱰欽؟؎ ز https://careers.bm-sms.co.jp/engineer/
join us!
͜Ε·Ͱͷ͋Β͢͡
‣ ͳͥϑϨʔϜϫʔΫʹ͠ͳ͍΄͏͕Α͍͔ ‣ ϑϨʔϜϫʔΫΛ࡞Βͳ͍ํ๏ ‣ ςϯϓϨʔτϝιουΛආ͚ͯ;ͭ͏ʹϝιουʹநग़͢Δ ‣ ςϯϓϨʔτϝιουΑΓετϥςδʔͰ֦ுͤ͞Δ ‣ lͪΐͬͱҧ͏ॲཧzΛදݱ͢ΔͨΊʹϒϩοΫΛड͚͚Δ
‣ ·ͱΊ੍ޚߏΛ͍खʹҕͶΔ
ͳͥ ϑϨʔϜϫʔΫʹ͠ͳ͍ ΄͏͕Α͍͔
ϥΠϒϥϦͱ ϑϨʔϜϫʔΫ
“ ͔͠͠ɺϥΠϒϥϦͰݺͼग़͠ଆ͕ϓϩάϥϜશ ମͷ੍ޚߏΛࢦఆͰ͖ͳ͍͕ɺϑϨʔϜϫʔΫͰ ՄೳͰ͋Δɻ͜ͷ੍ޚͷస͕ιϑτΣΞϑ ϨʔϜϫʔΫͷಛͰ͋Δɻ https://ja.wikipedia.org/wiki/ιϑτΣΞϑϨʔϜϫʔΫ
‣ ʮར༻ऀ͕ݺͼग़͢ʯͷ͕ϥΠϒϥϦ ‣ ʮར༻ऀ ͷίʔυ Λݺͼग़͢ʯͷ͕ϑϨʔϜϫʔΫ ϑϨʔϜϫʔΫ੍ޚߏΛࢦఆ͢Δ
‣ ͖ͬΓͱനࠇ͚ͭΒΕΔΘ͚Ͱͳ͍ɻ ‣ ར༻ऀͨΔΞϓϦ։ൃऀ͕ݺͼग़͢"DUJWF3FDPSE Ϟσϧʹఆٛͨ͠ίʔϧόοΫ"DUJWF3FDPSE͕ݺͼग़ͧ͢ʜ ‣ ར༻ऀ͕ॻ͘ίʔυͷ੍ޚߏΛͲΕ΄Ͳࢦఆ ͢Δ͔͠ͳ͍͔ɻ ˞۠ผ߹͍
‣ ϑϨʔϜϫʔΫɺͦͷ্Ͱͷ׆ಈΛ੍͢Δɻ ‣ ͍ΘΏΔʮϨʔϧ͔Β߱Γ͍ͨʯ ‣ ඞͣ͠ѱ͍Θ͚Ͱͳ͍ʮ੍͕ࣗ༝ΛͨΒ͢ʯ ‣ ʮͦͷ্Ͱͷ׆ಈʯ༧ଌͰ͖ͳ͍ɻ ‣ ͍͍ͨͯநԽ͕࿙ΕΔɻ
‣ ࡞ऀͷؾ࣋ͪΛߟ͑Α͏ͱͯ͠࡞ऀߟ͑ͯͳ͍͜ͱɻ ͳͥϑϨʔϜϫʔΫʹ͠ͳ͍΄͏͕ྑ͍͔
‣ ಡΈղ͘ͷʹϝλϓϩάϥϛϯάͷ͕ࣝඞཁʹͳΔ͜ͱଟ͍ɻ ‣ ϝλϓϩάϥϛϯάֶशۂઢ ίʔυࣗମ͕͘͠ͳΓ͕ͪ https://www.martinfowler.com/articles/rubyAtThoughtWorks.html
‣ ଟ͘ͷ"1*ͱͦͷ͍ํΛֶश͢Δඞཁ͋Γɻ ‣ ࡞ऀͷؾ࣋ͪΛߟ͑ͯΞϓϦέʔγϣϯίʔυ Λॻ͘ɻ ϑϨʔϜϫʔΫࣗମֶशίετ͕͔͔Δ
‣ 3VCZͰ8FCΞϓϦ։ൃ͢Δͱ͖ͷυఆ൪ͱͯ͠ ϝΠϯετϦʔϜʹ͍Δɻ ‣ ৭Μͳ༻్ͷʮݸผࣄʯΛίϯτϦϏϡʔτ͞Ε ଓ͚͖ͯͨɻ ‣ ʮϨʔϧͷ߱ΓํʯͳΜͯͷ·ͰؚΊͯେͳ ϊϋ͕ੵ͞Ε͍ͯΔɻ
3BJMTϛϥΫϧ
‣ ࣗࣗΛؚΉ ະདྷͷϝϯςφʹର੍͠͠ͳ͍ɻ ‣ ະདྷʹͲ͏͍͏ιϑτΣΞʹ͍͔ͨ͠Θ͔Βͳ͍ɻ ‣ େମʹ͓͍ͯߟྀෆ͠நԽ࿙ΕΔɻ ‣ ϥΠϒϥϦʹ͓ͯ͘͠ͱɺݺͿݺͳ͍ɺ ͏ݺͳ͘͢Δɺͷར༻ऀ͕ܾΊΒΕΔɻ
ʮ;ͩΜʯϑϨʔϜϫʔΫʹ͢ΔͷΛආ͚Δ
ͱ͍͑ɺ ศརϝιουΛॻ͖ͨ͘ͳΔ͜ͱ ͨ͘͞Μ͋ΔΘ͚Ͱ
‣ ͳͥϑϨʔϜϫʔΫʹ͠ͳ͍΄͏͕Α͍͔ ‣ ϑϨʔϜϫʔΫΛ࡞Βͳ͍ํ๏ ‣ ςϯϓϨʔτϝιουΛආ͚ͯ;ͭ͏ʹϝιουʹநग़͢Δ ‣ ςϯϓϨʔτϝιουΑΓετϥςδʔͰ֦ுͤ͞Δ ‣ lͪΐͬͱҧ͏ॲཧzΛදݱ͢ΔͨΊʹϒϩοΫΛड͚͚Δ
‣ ·ͱΊ੍ޚߏΛ͍खʹҕͶΔ
ϑϨʔϜϫʔΫΛ ࡞Βͳ͍ํ๏
ݴ͍͑Δͱ ੍ޚߏΛ ͍खʹҕͶΔํ๏
ςϯϓϨʔτϝιουΛආ͚ͯ ;ͭ͏ʹϝιουʹநग़͢Δ
‣ ΦʔόʔϥΠυ͞ΕͯΔϝιουΛΈଆ͕ݺͿɻ ݺΕΔଆ͔Βߏ͕ݟ͑ͳ͍ɻ ‣ 34QFDͷMFUTVCKFDUಉࠜͰ͋Δͱݴ͑Δɻ ‣ ۩ςετέʔε͔ΒΕͨʮϑΝΠϧͷ্ͷํʯʹ ߏ͕Ͱ͖ΔͷͰɺݟ͑ͳ͍͠ɺม͑ͮΒ͍ɻ ςϯϓϨʔτϝιουύλʔϯͷ
‣ ܧঝͯ͠͠·͏ͷͰɺϑϨʔϜϫʔΫͷ෦ߏΛ ࡽͯ͠͠·͏ɻ ‣ ͞ΘΓͨ͘ͳΔΑͶ ‣ ͦͯ͠όʔδϣϯΞοϓͰ͖ͳ͘ͳΔ ‣ 3BJMTΞϓϦ͋Δ͋Δɻ ςϯϓϨʔτϝιουύλʔϯͷ
‣ 3BJMTࣗମ͕ϥΠϒϥϦఏڙΫϥεΛܧঝͯ͠͏ ϑϨʔϜϫʔΫͳͷͰɺࣗͰͦ͏ॻ͖ͨ͘ͳΔɻ ‣ ʜΑͶ ‣ 999#BTF͍ͬͯ͏நΫϥεΛఆٛͨ͜͠ͱ͋Δਓ ‣ 3BJMT͔ͩΒͰ͖Δ͜ͱɻ
3BJMTϛϥΫϧ
ϝιουʹநग़͠ɺࣗͰݺͼग़͢
‣ Ұ࿈ͷΦϒδΣΫτάϥϑΛ࡞Δϝιο υʹநग़͠ɺ࡞Γ͍ͨଆ͕ݺͼग़͢ɻ ‣ ࠩΛҾͰ༩͑ͭͭɺ ‣ ΊͬͪΌී௨ͷ͜ͱΛݴͬͯ·͢ ϝιουʹநग़͠ɺࣗͰݺͼग़͢
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) }
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) }
‣ BVUIPSVTFS͕Ͳ͏࡞ΒΕͲ͏ΘΕΔ͔ɺॱΛͬ ͯಡΊΔɻ ‣ ϔϧύʔϝιου͕େ͖͘ͳΔଟ͘ͳΓ͗͢Δ ଞͷϑΝΠϧ͔Β͍͍ͨ߹ɺී௨ʹ ίʔυΛׂ͢ΔͱΑ͍ɻ ‣ কདྷɺςετίʔυΛॻ͘ਓ͕ɺ͍ํΛࣗͰ ܾΊΒΕΔɻ
ҧ͏ॲཧΛڬΈࠐΉͨΊʹ ετϥςδʔύλʔϯΛ͏
‣ ڞ௨ͷલॲཧΛͯ͠ɺຊॲཧͯ͠ɺڞ௨ͷޙॲཧ͕ ͋Δ߹ͳͲɻ ‣ ͞Βʹຊॲཧͷྫ֎ॲཧඞཁͳ߹ͳΜ͔ʹͳΓ͕ͪɻ ‣ ͜ͷຊॲཧ͚ͩΛม͍͑ͨɻ ‣ ςϯϓϨʔτϝιου͍ͨ͘ͳΓ͕ͪɻ ϝιουͷҰ෦͚ͩม͍͑ͨ߹͕͋Δ
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
ετϥςδʔύλʔϯΛ͏
‣ Ұ෦͚ͩม͍͑ͨॲཧΛɺετϥς δʔΦϒδΣΫτͷೖͰදݱ͢Δɻ ετϥςδʔύλʔϯΛ͏
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
class SnsNotification def notify(article) #=> [TwitterNotification.new, FacebookNotofication.new...] SnsNotification.targets.each
do |sns| sns.notify(article)
‣ ݺͼग़͢γʔέϯε͕ࣗ໌ʹͳΔɻ ‣ ݺΕΔݸʑͷετϥςδʔଆΠϯλʔϑΣʔε ͕͖ͬΓ͢Δɻ ‣ ৼΔ͍ʹӨڹΛ༩͑Δύϥϝʔλ͕໌֬ʹͳΔͷͰɺςετ͍͢͠ ‣ ݺͼग़͠ݩείʔϓʹΞΫηεͰ͖ͳ͍ ‣
CJOEJOH@PG@DBMMFSͷ͜ͱΕΑ͏
lͪΐͬͱҧ͏ॲཧzΛ ϒϩοΫͱͯ͠ड͚औΔ
“ EPFOE·ͨ\^Ͱғ·Εͨίʔυͷஅย ϒ ϩοΫͱݺΕΔ ΛޙΖʹ͚ͯϝιουΛݺͼग़ ͢ͱɺͦͷϝιουͷ෦͔ΒϒϩοΫΛධՁͰ͖ ·͢ɻ ϒϩοΫ͖ϝιουΛࣗͰఆٛ͢ΔʹZJFME ࣜΛ͍·͢ɻ
‣ ॲཧΛΦϒδΣΫτͱͯ͠நԽͨ͠ͷɻ ‣ 3VCZͷಛਓؾϙΠϯτͷͭ ‣ ͍ΘΏΔʮߴ֊ؔʯ ‣ DBMMͰॲཧΛݺͼग़͢ɻ ϒϩοΫ
‣ ;ͭ͏ͷ܁Γฦ͠ ‣ .PEFMBMMFBDIEPFOE ‣ ॲཧͷڥք ‣ .PEFMUBOTBDUJPOEPFOE ‣ %4-
‣ 3BJMTBQQMJDBUJPOSPVUFTESBXEPFOE ‣ 34QFDͷMFU 3BJMTΞϓϦʹ͓͚ΔϒϩοΫ
‣ ϥΠϒϥϦ੍͕ޚߏΛࢦఆ͍ͯ͠Δ ‣ ݺͼग़͠ଆͷ۩ମతͳॲཧࣗମΛϒϩοΫͱͯ͠ड͚ɺ ϥΠϒϥϦϑϨʔϜϫʔΫͰ४උ্ͨ͠Ͱݺͼग़͢ɻ ‣ ͰɺऔΒΕͨؾ͕͠ͳ͍ ‣ FBDIUSBOTBDUJPOී௨ʹಡΊΔ ϒϩοΫΛΑ͘ݟͯΈΔͱ
model.transaction do model1.save! model2.save! end ྫ
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Ͱॻ͍ͯΈΔ
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
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
class Model def transaction(&strategy) do_begin strategy.call # or
yield do_commit rescue do_rollback ϒϩοΫΛड͚͚Δ model.transaction do model1.save! model2.save!
‣ DBMMΛڞ௨ΠϯλʔϑΣʔεͱͨ͠ετϥςδʔͱ ݴ͑Δɻ ‣ ͍ΘΏΔDBMMBCMFPCKFDU ‣ ϒϩοΫΛ͏ͱɺΞϓϦέʔγϣϯίʔυͷಡΈ खͷίϯςΩετ͕ܧଓ͢Δɻ ‣ CJOEJOHQSZΛೖΕΔͱ͜Ζ͕ࣗ໌
ϒϩοΫͱετϥςδʔ
class MyModel < AbstractModel private def do_something model1.save!
model2.save! ྫEP@TPNFUIJOH͕ݺΕͯͳͦ͞͏ͳͱ͖Ͳ͏͢Δ class AbstractModel def transaction do_begin do_something do_commit rescue do_rollback private def do_something raise NotImplementedError
‣ ϒϩοΫΛड͚͚Δͱɺʮͪΐͬͱҧ͏ॲཧ Λࠩ͠ࠐ·͍ͤͨʯͱ͖ʹͷ੍ޚߏΛݺͼग़ ͠ଆʹҕͶ͍ͯΔΑ͏ʹݟͤΒΕΔɻ ‣ ͦ͏͍͏ؾ࣋ͪͰ͑Δͷ͕େࣄɻ ‣ 3VCZͬΆ͍ίʔυʹͳΔɻ
‣ ͳͥϑϨʔϜϫʔΫʹ͠ͳ͍΄͏͕Α͍͔ ‣ ϑϨʔϜϫʔΫΛ࡞Βͳ͍ํ๏ ‣ ςϯϓϨʔτϝιουΛආ͚ͯ;ͭ͏ʹϝιουʹநग़͢Δ ‣ ςϯϓϨʔτϝιουΑΓετϥςδʔͰ֦ுͤ͞Δ ‣ lͪΐͬͱҧ͏ॲཧzΛදݱ͢ΔͨΊʹϒϩοΫΛड͚͚Δ
‣ ·ͱΊ੍ޚߏΛ͍खʹҕͶΔ
·ͱΊ ੍ޚߏΛ ͍खʹҕͶΔ
‣ ศརϥΠϒϥϦ͕ศརͳͷؒҧ͍ͳ͍ɻ ‣ ੍ޚߏΛͯ͠͠ͳͯ͘ɺศརϝιουΛఏڙ͢Δͷ͕ेศར ‣ ʮͪΐͬͱҧ͏ॲཧʯετϥςδʔͰදݱ͢Δɻ ‣ ܧঝͤͯ͞ݺͼग़͢ॲཧ͚ͩΛॻ͔ͤͳ͍ ‣ ϒϩοΫ͍͍Ϡπɻੵۃతʹ׆༻͠·͠ΐ͏ɻ
‣ 3VCZ͍͍ΑͶ ϥΠϒϥϦίʔυͱΞϓϦίʔυΛૄʹอͭ
‣ ϔϧύʔϝιουΛɺετϥςδʔύλʔϯΛɺϒϩοΫΛ ͑Α͍Θ͚Ͱͳ͍ɻ ‣ 'PP'SBNFXPSLOBOUPLB@QSPD DPOUFYU \^Έ͍ͨͳ ‣ ͍ͭɺͲ͏ݺΕΔͷ
‣ ʮࠓ͜ͷศརϥΠϒϥϦΛॻ͍ͯΔࣗɺͦΕ͕ Ͳ͏ΘΕΔ͔·ͩΒͳ͍ʯͱ͍͏ؾ࣋ͪʹ͖߹͏ɻ )PXʹ͍ͭͯ͠·͕ͨ͠
‣ ·ͩݟ͵ΞϓϦέʔγϣϯίʔυʹɺඞཁҎ্ͷ ੍Λ՝͞ͳ͍Α͏ʹ͢Δɻ ‣ ΞϓϦέʔγϣϯͰԿΛ͍͔ͨ͠ɺͦͷͱ͖ʹͳΒͳ͍ͱΘ͔Βͳ͍ɻ ‣ ͦͷ࣌ɺͦͷਓୡ͕ɺ͖߹͑Δ༨Λ͢ɻ ‣ ۩ମతͳʹ͖߹͍ͬͯΔਓΛϦεϖΫτɻະདྷͷ͔ࣗ ੍ޚߏΛ͍खʹҕͶΔ
More Decks by MOROHASHI Kyosuke
See All by MOROHASHI Kyosuke
Event is what happens
moro
2
4.7k
Railsの気持ちを考えながらコントローラとビューを整頓する/tidying-rails-controllers-and-views-as-rails-think
moro
5
630
dynamic!
moro
11
24k
Identifying User Idenity
moro
23
31k
Simplicity on Rails -- RDB, REST and Ruby
moro
19
21k
ちょうどよい Rails E2E テスト/enough-good-rails-e2e-test
moro
6
2.8k
全体がいい感じになるために、私たちRailsをホームにするWeb技術者ができること/let-our-whole-system-grow
moro
2
2.1k
フォームオブジェクトとの向き合い方/Grow Form Objects up
moro
1
2.3k
チームによるいきいきとしたソフトウェア開発/an-alive-team-grows-software
moro
3
3.6k
Other Decks in Programming
See All in Programming
React Native에 현대적인 빌드 도구 더하기: Rollipop 구현기
leegeunhyeok
0
180
私なりのハーネスエンジニアリング ~独自の言語処理系の開発を通して~
seosoft
0
200
Goコンパイラを作ってGoをもっと理解する / Build a Go compiler to better understand Go
ikura_hamu
0
130
우리의 Nitro Modules는 당신의 Turbo Modules보다 아름답다
l2hyunwoo
0
260
Snowflake Openflow Connector利用の勘所 / 20261024developersio2026tokyo-snowflake-openflow
kasacchiful
PRO
0
340
[Kotlin Fest 2026] eBPF Tracing for Kotlin
takehaya
0
130
複数ドメインを一つのアプリに統合するFlutterの設計と運用_FlutterKaigi2026登壇資料(須永高弘)
takahirosunaga
0
180
Performance Optimization With LLMs
xleitix
0
260
AIで開発が速くなった先で、開発チームは何を目指すか
shihochan
1
2k
Secure Your Coding Agent Like It’s Malware (v1.5) 🇬🇧 @Code.talks 2026
richargh
0
150
React Native経験者が Flutterを30⽇間触って驚いたこと
3saito
0
180
當我們開始不讀 Code - AI Agent 時代,Code Review 與 Clean Code 還剩下什麼?
jame2408
1
370
Featured
See All Featured
Designing Experiences People Love
moore
143
24k
Code Review Best Practice
trishagee
74
20k
Un-Boring Meetings
codingconduct
0
500
Joys of Absence: A Defence of Solitary Play
codingconduct
1
570
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
[RailsConf 2023] Rails as a piece of cake
palkan
59
7.1k
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
3
300
Amusing Abliteration
ianozsvald
1
390
GraphQLとの向き合い方2022年版
quramy
50
15k
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.7k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
Optimising Largest Contentful Paint
csswizardry
37
4k