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

How to say goodbye to technical debt

makicamel
October 21, 2022

How to say goodbye to technical debt

歴史あるプロジェクトのとある技術的負債を隙間プロジェクトの 210 PullRequests で倒しきった話
2022.10.21. Kaigi on Rails 2022

makicamel

October 21, 2022
Tweet

More Decks by makicamel

Other Decks in Programming

Transcript

  1. •7 ೥ؒେ͖͘ҭͬͨ Rails ΞϓϦ •਺ेਓ͕৮ΔϓϩδΣΫτ ྺ࢙͋ΔϓϩδΣΫτ +- -------------------- - +-

    ------- - +- ------ - +- ------- - +- -------- +- ---- +- ------ + | Name | Lines | LOC | Classes | Methods | M/C | LOC/M | +- -------------------- - +- ------- - +- ------ - +- ------- - +- -------- +- ---- +- ------ + | Controllers | 106768 | 84571 | 1182 | 8419 | 7 | 8 | | Jobs | 2532 | 1869 | 96 | 139 | 1 | 11 | | Models | 173665 | 125931 | 834 | 9068 | 10 | 11 | | Mailers | 515 | 444 | 10 | 11 | 1 | 38 | | Libraries | 4464 | 3134 | 37 | 313 | 8 | 8 | | … | … | … | … | … | … | … | +- -------------------- - +- ------- - +- ------ - +- ------- - +- -------- +- ---- +- ------ + | Total | 1112716 | 885175 | 2169 | 18354 | 8 | 46 | +- -------------------- - +- ------- - +- ------ - +- ------- - +- -------- +- ---- +- ------ +
  2.  class UsersController < ApplicationController before_action :new_one, only: [:new, :create]

    def new; end def create if @user.save create_success_response_to else create_error_response_to end end def new_one @user = scope.new(one_params) end def create_success_response_to respond_to do |format| format.html { flash[:notify_success] = "࡞੒͠·ͨ͠" redirect_to { action: :index } } format.json { render json: @user.to_json } end end def create_error_response_to respond_to do |format| format.html { flash[:notify_error] = "࡞੒Ͱ͖·ͤΜͰͨ͠" # … ͜͏ৼΔ෣͏ 2 ߦॻ͚ͩ͘Ͱ  class UsersController < ApplicationController include CrudController crud_controller User, [:new, :create] end
  3. ɹ͜ͷ @user ͸ҰମͲ͔͜Βʂʁ ҉໧తͳίʔϧόοΫ௥Ճ  class UsersController < ApplicationController crud_controller

    User, [:new, :create] def create if @user.save create_success_response_to else create_error_response_to end end end
  4. ϝιουίʔϧ෼ࢄ  ɹશ෦ಡ·ͳ͍ͱΘ͔Βͳ͍ 💀 class UsersController < ApplicationController include Common::UsersController

    include ActionState include ActionForm include ActionUpdate include ActionApi def set_redirect_path @create_redirect_path = users_path end end module Common::UsersController extend ActiveSupport::Concern included do crud_controller User, [:edit, :update] before_action :set_redirect_path end end
  5. ɹCrudController ͷίʔυಡ΋͏ͱͨ͠ΜͰ͚͢Ͳ 
 ɹϝλϓϩΑ͘Θ͔Γ·ͤΜ… ϝλϓϩ  def define_create_error_response_to(_clazz, _table_name, model_name)

    define_method :create_error_response_to do respond_to do |format| format.html { flash[:notify_error] = "࡞੒Ͱ͖·ͤΜͰͨ͠" create_error_response_to_html } format.json { create_error_response_to_json } end end define_method :create_error_response_to_html do render self.class.instance_variable_get(:@_create_error_action) || :new end define_method :create_error_response_to_json do render json: { errors: instance_variable_get("@#{model_name}").errors.full_messages }, status: 422 end end
  6. εΫϦϓτ 1. crud_controller .*ΞΫγϣϯ໊ ΛؚΉϑΝΠϧΛநग़ 2. 1 ͷ͏ͪରԠ͢Δςετ͕͋ΔϑΝΠϧΛநग़ 3. ίϯτϩʔϥϑΝΠϧΛจࣈྻͱͯ͠ಡΈࠐΈɺ

    
 ϝιουͷಈతఆٛΛ੩తఆٛʹมߋ 4. 3 Ͱมߋͨ͠จࣈྻΛίϯτϩʔϥϑΝΠϧʹॻ͖໭͢ 5. rubocop -a ͯ͠ίϛοτΛੵΉ جຊ͸͜Ε͚ͩ
  7. crud_controller User, [:update] 
 ͢Δͱ search_one ͕ੜ͑Δ  Πϯελϯεม਺ͷηοτ͸ 


    update ಺͕Αͦ͞͏ class UsersController < ApplicationController crud_controller User, [:update] before_action :search_one, only: [:update] before_action :update_required def update if @user.update(one_params) # ... else # ... end end def search_one @user = scope.find(params[:id]) end def update_required raise UnauthorizedError unless @user.can_update? end end มߋͷؔ৺ࣄΛগͳ͘อͭ
  8. search_one ΛΠϯϥΠϯʹͨ͠ •ɹ•  class UsersController < ApplicationController crud_controller User,

    [:update] before_action :update_required def update @user = scope.find(params[:id]) if @user.update(one_params) # ... else # ... end end def update_required raise UnauthorizedError unless @user.can_update? end end มߋͷؔ৺ࣄΛগͳ͘อͭ
  9. @user ͕ nil ʹͳͬͯΤϥʔʹͳͬͨ  class UsersController < ApplicationController crud_controller

    User, [:update] before_action :update_required def update @user = scope.find(params[:id]) if @user.update(one_params) # ... else # ... end end def update_required raise UnauthorizedError unless @user.can_update? end end มߋͷؔ৺ࣄΛগͳ͘อͭ 💀
  10. ِӄੑςετ expect ͕ͳͯ͘ݕ஌Ͱ͖ͳ͔ͬͨ  RSpec.describe 'PUT /users/:id' do # …

    it do put user_url(user), params: params end end Կ΋ςετͯ͠ͳ͍ʂʂʂ
  11. ِӄੑςετ •ʮςετ͕͋Δ != ςετ͍ͯ͠Δʯঢ়ଶͩͬͨ •expectation ͷͳ͍ it Λݕ஌͢ΔΧελϜ Cop Λ࡞ͬͨ

    NBLJDBNFMFNQUZ@FYBNQMF@DPQ 
 IUUQTHJUIVCDPNNBLJDBNFMFNQUZ@FYBNQMF@DPQ "EEA34QFD/P&YQFDUBUJPO&YBNQMFACZSLBNVSBu1VMM3FRVFTU 
 IUUQTHJUIVCDPNSVCPDPQSVCPDPQSTQFDQVMM @r7kamura ͞ΜͷύονͰ 
 rubocop-rspec ʹऔΓࠐ·Ε 
 2.13.0 ͔Βར༻Ͱ͖·͢