7年目を迎えたRails アプリケーションの傾向と対策/Rails Developers Meetup 2019 Day1

Ff07ba188f0dccc30e7a90a5ebd1a386?s=47 taogawa
March 22, 2019

7年目を迎えたRails アプリケーションの傾向と対策/Rails Developers Meetup 2019 Day1

Rails Developers Meetup 2019でお話した「7年目を迎えたRails アプリケーションの傾向と対策」のスライドです。

Ff07ba188f0dccc30e7a90a5ebd1a386?s=128

taogawa

March 22, 2019
Tweet

Transcript

  1. ೥໨Λܴ͑ͨ3BJMT ΞϓϦέʔγϣϯͷ܏޲ͱରࡦ ࣦͦͯ͠ഊ 3BJMT%FWFMPQFST.FFUVQ גࣜձࣾΩονϋΠΫখ઒߶

  2. %))৴ऀͷΈͳ͞Μ ͜Μʹͪ͸ʂ

  3. ࢲ΋Ͱ͢ʂ

  4. ࣗݾ঺հ w גࣜձࣾΩονϋΠΫΤϯδχΞ w খ઒߶ (JU)VCUBPHBXB  w αʔόʔαΠυΛओʹ୲౰͍ͯ͠·͢ɻ

  5. %))৴ऀͱͯ͠ͷ Ξ΢τϓοτ

  6. IUUQTUFDILJUDIIJLFDPNFOUSZ

  7. ຊ೔ͷςʔϚ

  8. ຊ೔ͷςʔϚ Ϩʔϧ͔Βগ͠֎Εͨઌͷ ύλʔϯ

  9. ͸͡Ίʹ

  10. 3BJMT͸ ʮͷιϦϡʔγϣϯͰ ໰୊ͷΛղܾͰ͖Δʯ ϑϨʔϜϫʔΫ ʮ3VCZPO3BJMT%))ͷΠϯλϏϡʔʯ IUUQTLENTOSDPNUSBOTMBUJPOTJOUFSWJFXXJUIEII ຋༁

  11. ͦͷͱ͓Γɺ େମͷ͜ͱΛ؆୯ʹ͢͹΍͘ Ͱ͖ΔΑ͏ʹͳ͍ͬͯΔ

  12. ͷιϦϡʔγϣϯͰ໰୊ͷΛղܾͰ͖Δ w $P$ ઃఆΑΓن໿ Ͱ൥ࡶͳઃఆϑΝΠϧΛল ུ w .PEFMͱςʔϒ ϧͷಉҰࢹ "DUJWF3FDPSEύλʔ

    ϯ ͰϚοϐϯάΛγϯϓϧʹ w ͳͲͳͲɾɾɾ3BJMTͷ͢͹Β͠͞ͷͻͱͭ͸ɺ ͦͷେ୾ʹׂΓ੾ͬͨઃܭࢥ૝
  13. ͍ͬΆ͏ͰϨʔϧ͔Β֎ΕΔͱ͖͍ͭ w ్୺ʹϋʔυϧ্͕͕Δ w "ͦ΋ͦ΋ϨʔϧΛ͸ͣΕΔͷ͕ؒҧ͍ͬͯΔ w ʮͷػೳʙʯΛߟ͑Δͱਖ਼࿦ w ͚ΕͲɺن໛͕େ͖͘ͳͬͯ͘ΔʹͭΕͯɺ΍ͬ ͺΓ3BJMTͷϨʔϧ͚ͩ͡Όݫ͍͠ɺͪΐͬͱ͸

    ͣΕ͍ͨέʔε͕ग़ͯ͘Δ
  14. ͦΜͳͱ͖Ͳ͏͢Δ͔

  15. ͍͔ͭ͘ͷʮϨʔϧΛͪΐͬͱ͸ͣΕͨʯ ఆ൪ύλʔϯ͕͋Δ w ංେԽͨ͠"DUJWF3FDPSEϞσϧΛϦϑΝΫλϦϯά͢ Δͭͷํ๏ w IUUQTUFDISBDIPCQTJODKQ IBDIJ@@ ຋༁ 

    w IUUQTDPEFDMJNBUFDPNCMPHXBZTUP EFDPNQPTFGBUBDUJWFSFDPSENPEFMT ݪจ  w ೥Ҏ্લ͚ͩͲݹͼͳ͍ఆ൪ͷهࣄ
  16. Ͳ͔͜Ͱฉ͍ͨ͜ͱͷ͋Δύλʔϯୡ w 7BMVF0CKFDU w 4FSWJDF0CKFDU w 'PSN0CKFDU w 2VFSZ0CKFDU w

    7JFX0CKFDU w 1PMJDZ0CKFDU w %FDPSBUPS
  17. Ͱ΋࣮ࡍͲ͏͔ͭ͑͹͍͍ͷ w ͜ΕΒͷύλʔϯͷมछΛɺ৭Μͳਓ͕গ͠ ͣͭҧ͔ͬͨͨͪͰݴ͍ͬͯΔΑ͏ʹݟ͑Δ w ݁ہɺ࣮ࡍʹऔΓೖΕΔஈͰɺͲ͏࣮૷͢Δ ͔໎ࢠʹͳͬͯ͠·͏

  18. ੈͷதʹ ʮͪΐͬͱ͸ͣΕͨϨʔϧʯ ͷݱ৔Ͱͷ࣮ྫ͕ ·ͩ·ͩදʹग़͍ͯͳ͍

  19. ͳΒ͹ Φʔϓϯʹ͢Δ͔͠ͳ͍

  20. ࠓճ͸͜͏ͨ͠ύλʔϯΛ ΩονϋΠΫͰ Ͳ͏࢖͖͔ͬͯͨɺ ࣦഊ΋ؚΊͯ ͝঺հ͠·͢

  21. ࠓճ͝঺հ͢Δύλʔϯ w 7JFX.PEFM w 'PSN.PEFM w 4FSWJDF0CKFDU

  22. ͦͷ·͑ʹ

  23. ΩονϋΠΫͷίʔυ w ೥݄3BJMT͔Β։ൃελʔτ w ೥݄αʔϏεϩʔϯν w Ҏ߱਺೥ؒɺdਓ͘Β͍Ͱ։ൃ w ೥݄ݱࡏ w

    σβΠφʔਓ w ϓϩάϥϚʔਓ w ೥໨Λܴ͑ɺͦΕͳΓʹྺ࢙͋Δίʔυʹͳ͖ͬͯͨ
  24. ΩονϋΠΫͷίʔυ w ݱࡏͷόʔδϣϯ w 3VCZ ૣ্͍͛ͨ͘  w 3BJMT ૣ্͍͛ͨ͘

     w .POHPJE w .POHP%#
  25. ΩονϋΠΫͷίʔυ w $POUSPMMFS w $MBTTFT -0$ w .PEFMT w $MBTTFT

    -0$ w খن໛Ͱͳ͘ͳͬͨେ͖͞
  26. ͦͷ 7JFX.PEFM

  27. Ϣʔεέʔε w දࣔͷΈʹ࢖͏Α͏ͳϩδοΫ w ෳ਺Ϟσϧʹ·͕ͨΔදࣔϩδοΫ w ஔ͖৔ॴʹࠔΔͳ͜Εɾɾɾ w ଥڠతͳબ୒͔ΒϏϡʔʹॻ͔ΕɺϏϡʔ͕͝ ͪΌͪ͝Όͯ͘͠Δ

  28. ͜Μͳͱ͖ # 表示にだけ必要な日付フォーマット = @event.start_at.strftime('%Y/%m/%d %H:%M') # 複数のモデルが関連する表示ロジック - if

    @user.paid_member? && @product.member_only_discount? = @product.discount_price - else = @product.price
  29. ରࡦ͜͜Ͱ7JFX.PEFMͷग़൪ w දࣔϩδοΫΛ$POUSPMMFSͰ΋ͳ͘ɺ7JFXͰ ΋ͳ͘ɺ7JFX.PEFMʹॻ͘ w ͦΕ༻ͷ(FN΋͋Δ "DUJWF%FDPSBUPS΍ %SBQFS  w

    1030Ͱ΋े෼
  30. 7JFX.PEFM 1SFTFOUFS ͷఆٛ class ProductPresenter # ... def price discount?

    ? @product.discount_price : @product.price end def discount? @user.paid_member? && @product.member_only_discount? end end
  31. 7JFX͕͖ͬ͢Γʂ # before - if @user.paid_member? && @product.member_only_discount? = @product.discount_price

    - else = @product.price - end # after = @product_presenter.price
  32. ͪͳΈʹ w ʮදࣔϩδοΫ༻ͷϞσϧʯ͸͍Ζ͍Ζͳݺ ͼํ͕͋Δ w 7JFX.PEFM 7JFX0CKFDU %FDPSBUPS  1SFTFOUFSɾɾɾ

    w ͲΕ͕ਖ਼͍͠ͱ͍͏ͷ͸ͳ͍͕ɺνʔϜ಺Ͱೝ ࣝΛ߹Θ͓ͤͯ͘ͷ͕٢
  33. ͪͳΈʹ w ΩονϋΠΫͰ͸ҎԼͷΑ͏ʹݺͼ෼͚͍ͯ Δ w ૯শʮ7JFX.PEFMʯ w ୯ҰϞσϧ༻ʮ%FDPSBUPSʯ w ෳ਺Ϟσϧ༻ʮ1SFTFOUFSʯ

  34. Ϡολʔ 7JFX.PEFM ࠷ߴ

  35. None
  36. ͦͯ͠ɺམͱ݀͠

  37. ௐࢠʹ৐Γ࣮͗ͨ͢ྫ w ΋ͬͱԠ༻Ͱ͖ΔͷͰ͸ʁͱࢥࣦͬͯഊͨ͠ ࣮ྫ w Ϩίʔυͷछྨ͝ͱʹࢀর͢ΔϞσϧ͕ҧ͏ ͓஌ΒͤΛ࣮૷͠Α͏ͱͨ͠ͱ͖ͷ͜ͱ

  38. ͓஌Βͤը໘ w ͓஌Βͤͷ৘ใ͸छྨ͝ͱ ʹ͍ΖΜͳςʔϒ ϧ͔Βσʔ λΛऔΔඞཁ͕͋Δ w ҰํɺදࣔΠϯλʔϑΣʔ ε͸ڞ௨ w

    ͓஌Βͤ༻ςʔϒϧ࡞Βͳ ͯ͘΋ɺ1SFTFOUFSͰ͍͚ ΔͷͰ͸ʁ
  39. Ͳ͏ͳ͔ͬͨ w ୺తʹݴࣦͬͯഊͩͬͨ w / ໰୊͕ൃੜɻ͔͠΋ɺߏ଄తʹ௚ͮ͠Β͍ w ࢀর͢Δςʔϒϧ͕Ϩίʔυ͝ͱʹҧ͏͔Β FBHFS@MPBEͮ͠Β͍ w

    ૉ௚ʹςʔϒϧ࡞Ε͹Α͔ͬͨͷʹɾɾɾ
  40. 7JFX.PEFMͷֶͼ w 7JFX.PEFM͸1030ͳͷͰ৭ʑ༥௨͕ར͖΍ ͍͢ w ͕ͩɺ.PEFM͔Βੜ੒͢ΔͷͰɺσʔλΞΫη εͷ໰୊͕ى͖΍͍͢ w ಛʹҰཡܥͰ͸ཁ஫ҙ

  41. ͦͷ 'PSN.PEFM

  42. Ϣʔεέʔε w Ϟσϧʹඥ෇͔ͳ͍ϑΥʔϜΛѻ͏έʔε w ӬଓԽ͠ͳ͍߲໨͕͋Δ w ෳ਺Ϟσϧʹ·͕ͨΔ w ϦΫΤετύϥϝʔλΛ$POUSPMMFS಺Ͱ͋͋ͨ͠Γɺ ͜͏ͨ͠Γɾɾɾ

    w $POUSPMMFS಺ͷίʔυ͕ͪ͝Όͪ͝Όͯ͘͠Δ
  43. Α͋͘Δ֬ೝνΣοΫ w ϝοηʔδ͸%#ʹ อଘͷඞཁ͕͋Δ͕ɺ ֬ೝνΣοΫ͸อଘ ෆཁ

  44. Α͋͘Δ֬ೝνΣοΫ # view = form_for(@event, url:foo_path(@event), method: 'patch') do |f|

    = f.hidden_field :event_id = text_area_tag :body = check_box_tag :confirmed # 確認チェック = f.submit "予約をキャンセル" # controller # パラメータのチェックが複数あると見通しが悪くなる if params[:confirmed] == "1" # ... else # ... end
  45. ରࡦ͜͜Ͱ'PSN.PEFMͷग़൪ w Ϟσϧʹඥ෇͔ͳ͍ɺϑΥʔϜઐ༻ͷϞσϧΛ ఆٛ͢Δ w ϦΫΤετύϥϝʔλͷνΣοΫͳͲ͸'PSN .PEFM಺Ͱߦ͏

  46. 'PSN.PEFMͷఆٛ class EventCancellationMessageForm include ActiveModel::Model attr_accessor :event_id, :body, :confirmed validates

    :body, presence: true validates :confirmed, acceptance: true # ... end
  47. $POUSPMMFS͕͖ͬ͢Γʂ # before if params[:confirmed] == "1" # ... else

    # ... end # after @event_cancellation_form = EventCancellationMessageForm.new(cancellation_message_params) # パラメータチェックが複数あってもFormModel内で処理できる if @event_cancellation_form.valid? # ... end
  48. 'PSN.PEFMͷఆٛ w "DUJWF.PEFM.PEFMΛJODMVEF w GPSN@XJUI GPSN@GPSͰ௨ৗͷϞσϧͷΑ͏ʹѻ͑Δʂ w ϑΥʔϜʹඥ෇͔ͳ͍όϦσʔγϣϯΛ'PSN.PEFM ಺Ͱ͖ͬ͢Γॻ͚Δ w

    ʮ֬ೝ͠·ͨ͠ʯνΣοΫ w ෳ਺Ϟσϧʹ·͕ͨΔόϦσʔγϣϯ
  49. ͞ΒʹɺԠ༻΋ར͘ΜͰ͢ # view = form_for @bulk_schedule_form, url:schedules_path, method: "post" do

    |f| = f.fields_for :schedules do |s| # ... =f.submit "一括登録" # form_model class BulkScheduleForm includes Activemodel::Model attr_accessor: schedules # ... def schedule_attributes=(attributes) self.schedules = attributes.map do |schedule_attributes| schedule.new(schedule_attributes) end end end
  50. Ұׅొ࿥'PSNʹ΋࢖͑Δ w গ͠खΛՃ͑Ε͹Ұׅొ࿥'PSNͳͲʹ΋Ԡ༻ ͕ར͘ w ࢠϨίʔυͷߋ৽΋ؚΉ৔߹ɺ BDDFQUT@OFTUFE@BUUSJCVUFT@GPS΋ͳͤ͘Δ

  51. Ϡολʔ 'PSN.PEFM ࠷ߴ

  52. None
  53. ͦͯ͠ɺམͱ݀͠

  54. 'PSN.PEFMଠΓ͕ͪ໰୊ w 'PSN.PEFM͕ଠͬͯ͠·ͬͨ w όϦσʔγϣϯ͕ෳࡶԽ w ͜Ε͸Ϟσϧʹॻ͚͹͍͍ͷͰ͸ʁͳόϦσʔ γϣϯ·Ͱ'PSN.PEFMʹॻ͔Εͯ͠·ͬͨ

  55. 'PSN.PEFMͷֶͼ w 'PSN.PEFM͸Ԡ༻΋ར͍ͯ΂ΜΓ w 'PSN.PEFM͸ബ͘ɻ͋͘·Ͱओ໾͸.PEFM w όϦσʔγϣϯͳͲͷ੹຿͸ɺ.PEFMʹۃྗ࣋ ͨͤͯɺ'PSN.PEFM͸ͦΕΛݺͼग़͚ͩ͢ʹ ͠Α͏

  56. ͦͷ 4FSWJDF0CKFDU

  57. Ϣʔεέʔε w ͋Δखଓ͖Λͻͱ·ͱ·Γʹ͍ͨ͠ͱ͖ w ෳ਺ͷϞσϧʹର͢Δॲཧ w %#ͷτϥϯβΫγϣϯ w ϕλʹ$POUSPMMFSʹॻ͍͍ͯͬͯɺ$POUSPMMFS ͷݟ௨͕͠ѱ͘ͳΔ

  58. ରࡦ͜͜Ͱ4FSWJDF0CKFDUͷग़൪ w 4FSWJDF0CKFDUʹͻͱ·ͱ·ΓͷॲཧΛҠಈ͞ ͤΔ w BQQTFSWJDFTҎԼʹ4FSWJDF0CKFDUΛఆٛ w ݴޠ໰Θͣఆ൪ͷύλʔϯ

  59. 4FSWJDF0CKFDUͷఆٛ # service_object class EventCreateService def initialize(params) # ... end

    def call # ... end end # controller service = EventCreateService.new(event_params) service.call if service.success? # ... end
  60. 4FSWJDF0CKFDUͷఆٛ w ίϯετϥΫλҎ֎ɺQVCMJDϝιου͸جຊͻͱͭͷΈ w DBMMͱ͔FYFDVUFͱ͔ w $PNNBOEύλʔϯͬΆ͍ w ඞཁʹԠͯ͡εςʔτϦʔμʔΛఆٛ w

    $POUSPMMFSʹϕλॻ͖͞ΕͨϏδωεϩδοΫΛ 4FSWJDF0CKFDUʹఆٛͯ͠ɺ$POUSPMMFSΛ͖ͬ͢Γ
  61. 4FSWJDF0CKFDUͷఆٛ w ϝδϟʔͳύλʔϯͳͷͰɺ044΋ࢀߟʹ͠΍͍͢ w .BTUPEPOͳͲ w ΩονϋΠΫͰ͸ҎԼΛࢀߟʹ͍ͯ͠Δ w 3BJMTͰॏཁͳύλʔϯQBSU4FSWJDF0CKFDU w

    IUUQTUFDISBDIPCQTJODKQ IBDIJ@@ ຋༁
  62. Ϡολʔ 4FSWJDF0CKFDU ࠷ߴ

  63. None
  64. ͦͯ͠ɺམͱ݀͠

  65. αʔϏεͷ֓೦޿͗͢໰୊ w 4FSWJDFͷޠ͕Ұൠత͗ͯ͢ɺ͍ΖΜͳఆ͕ٛ ͋Δ w ΈΜͳͷ;Θͬͱͨ͠ײ֮ͰΫϥεΛ௥Ճ͠ ͍ͯ͘ͱɺBQQTFSWJDFTσ ΟϨΫτϦҎԼ͕ଠͬ ͍ͯ͘

  66. ͋ͳͨͷαʔϏε͸ͲͷαʔϏεʁ w ͦ΋ͦ΋&SJD&WBOTͷ%%%ຊͰͷαʔϏεఆ͕ٛ෯޿͍ w ΞϓϦέʔγϣϯαʔϏε w υϝΠϯαʔϏε w ΠϯϑϥετϥΫνϟαʔϏε w

    1PG&""ͷαʔϏεϨΠϠʔ w ͍͍ײ͡ͷศརϝιουͱͯ͠4FSWJDF͕࢖ΘΕΔ w ͜ͷ఺Λҙ͍ࣝͯ͠ͳ͍ͱɺ࿩͕͔Έ߹Θͳ͍
  67. ͞Βʹɺམͱ݀͠

  68. τϥϯβΫγϣϯεΫϦϓτ໰୊ w 4FSWJDF0CKFDUʹϞϦϞϦϩδοΫΛॻ͍ͯ͠ ·͏ w ݁Ռɺ$POUSPMMFSͷ͔ΘΓʹ4FSWJDF0CKFDU ͷݟ௨͕͠ѱ͍͚ͩʹͳΔ w υϝΠϯϞσϧශ݂঱

  69. ֓೦Λ੔ཧ͢Δ w ΩονϋΠΫͰͷαʔϏε͸ΞϓϦέʔγϣ ϯαʔϏεͱͯ͠ఆ͍ٛͯ͠Δ w ͱ͸͍͏΋ͷͷɺ৭ʑͳαʔϏε͕ࠞࡏͯ͠ ͍ͯಓ൒͹

  70. αʔϏε͸ബ͘ w ϩδοΫ͸Ϟσϧʹॻ͘ w 4FSWJDF0CKFDU͸ͦΕΛݺͼग़͚ͩ͢ w αʔϏεΫϥεʹͭͷ࢓ࣄ w ಈࢺ ໊ࢺ

    4FSWJDF w ྫ$SFBUF&WFOU4FSWJDF
  71. 4FSWJDF0CKFDUͷֶͼ w 4FSWJDFͷڞ௨ೝࣝΛνʔϜ಺Ͱڞ༗͓ͯ͘͠ w ڞ௨ͨ͠ਖ਼ղͱ͍͏΋ͷ͸ͳͦ͞͏ w ஔ͖৔΍໋໊نଇɺΠϯλʔϑΣʔεΛͪΌΜͱ੔උ ͠Α͏ w 4FSWJDF͸ബ͘ɻ͋͘·Ͱओ໾͸.PEFM

    w υϝΠϯϩδοΫ͸ɺ.PEFMʹۃྗ࣋ͨͤͯɺ4FSWJDF 0CKFDU͸ͦΕΛݺͼग़͚ͩ͢ʹ͠Α͏
  72. ·ͱΊ

  73. ϨʔϧΛͪΐͬͱ֎Εͨ ఆ൪ύλʔϯͨͪɺ ศརͰ͢Α

  74. ͚ΕͲ ੈͷதʹ͸·ͩ·࣮ͩྫ͕଍Γͳ͍ ݱ৔ͷ஌ݟ͕޿·Βͳ͚Ε͹ ύλʔϯ͸ఆண͠ͳ͍

  75. ͜ΕͰ3BJMT͸ େ͖ͳΞϓϦέʔγϣϯʹ࢖͑ͳ͍ ͳΜͯݴ༿͸ෆຊҙͰ͸ʁ

  76. ΋ͬͱ΋ͬͱ ࣗ෼ͨͪͷ औΓ૊ΈΛɺࣦഊΛɺ Φʔϓϯʹ͢Δ ͦΜͳ3BJMTίϛϡχςΟ΁ͷ ߩݙ΋͋ΔͷͰ͸

  77. ΋ͬͱ΋ͬͱ Έͳ͞Μͷ ݱ৔ͷ஌ݟΛΦʔϓϯʹ

  78. ͝ਗ਼ௌ ͋Γ͕ͱ͏͍͟͝·ͨ͠