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. ྺ࢙͋ΔϓϩδΣΫτͷͱ͋Δٕज़తෛ࠴Λ
    伱ؒϓϩδΣΫτͷ
    1VMM3FRVFTUTͰ౗͖ͬͨ͠࿩
    2022.10.21.


    Kaigi on Rails 2022


    @makicamel

    View Slide

  2. w!NBLJDBNFM઒ݪສق
    w3VCZͱϏʔϧɹɹͱ͓ञ͕޷͖
    w޷͖ͳ73ήʔϜ
    w
    ࣗݾ঺հ
    ࠓ೔ͷ࿩

    View Slide

  3. ٕज़తෛ࠴


    ͋Γ·͔͢ʁ

    View Slide

  4. ٕज़తෛ࠴


    ฦͯ͠·͔͢ʁ

    View Slide

  5. ٕज़తෛ࠴ͷฦ٫
    •ܭըΛཱͯͯઓུతʹ౗͢ͷ͕ηΦϦʔ


    •ͱ͸ݴ͑ޙճ͠ɾ์ஔ͞Εͯརଉ͕๲ΒΈ͕ͪ


    •։࢝͸ൺֱత༰қ


    •ܧଓɾ׬਱͸೉қ౓ߴ
    େ͖ͳ

    View Slide

  6. Ͱ΋ɺ΍Γ͍ͨ

    View Slide

  7. ྺ࢙͋ΔϓϩδΣΫτͷͱ͋Δٕज़తෛ࠴Λ
    伱ؒϓϩδΣΫτͷ
    1VMM3FRVFTUTͰ౗͖ͬͨ͠࿩

    View Slide

  8. ྺ࢙͋ΔϓϩδΣΫτͷͱ͋Δٕज़తෛ࠴Λ
    伱ؒϓϩδΣΫτͷ
    1VMM3FRVFTUTͰ౗͖ͬͨ͠࿩

    View Slide

  9. •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 |
    +- --------------------
    -
    +- -------
    -
    +- ------
    -
    +- -------
    -
    +- -------- +- ---- +- ------ +

    View Slide

  10. •ෳࡶͳઃܭɾ࣮૷


    •ਆςʔϒϧɾਆϞσϧɾڊେίϯτϩʔϥɾڊେείʔϓ…


    •ΦϨΦϨϑϨʔϜϫʔΫ


    •etc …


    ૊Έ߹ΘͤͰΑΓෳࡶԽ
    ٕज़తෛ࠴

    View Slide

  11. •։ൃॳظΛࢧ͑ͨΦϨΦϨϑϨʔϜϫʔΫ


    •ΞϓϦͷ੒௕ʹ͋Θͤͨϝϯς͕͞Εͣෛ࠴Խ


    •ANDPAD ͷͭΒΈτοϓϥϯΧʔ


    •2019 ೥ळɿࣾ಺هࣄͰ՝୊ͱ঺հ


    •2020 ೥य़ɿఫഇͷखॱॻ͕ॻ͔ΕΔ΋ղফ͸ਐ·ͣ
    CrudController

    View Slide


  12. 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


    View Slide

  13. •include ͢ΔͱΫϥεϝιου crud_controller ͕ੜ͑Δ


    •ΞΫγϣϯϝιουΛΑ͠ͳʹఆٛͯ͘͠ΕΔ


    •search_one, scope ͳͲΑ͠ͳʹϝιου͕ੜ͑Δ


    •ϝιουΛΦʔόʔϥΠυͯ͠ϨεϙϯεΛΧελϜͰ͖Δ


    CrudController

    View Slide

  14. •λΠϓ਺ܹݮʂ


    •΂ΜΓʂʂ


    …΄Μͱ͏ʹʁ


    ͔ΜͨΜ

    View Slide

  15. ͭΒΈྫ

    View Slide

  16. ɹϝιουఆ͕ٛͳ͍ͷʹͳΜ͔ಈ͘ʂʁ
    ҉໧తͳϝιουఆٛ
    class UsersController < ApplicationController


    crud_controller User, [:new, :create]


    end


    View Slide

  17. ɹ͜ͷ @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

    View Slide

  18. ϝιουίʔϧ෼ࢄ

    ɹશ෦ಡ·ͳ͍ͱΘ͔Βͳ͍ 💀
    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


    View Slide

  19. ɹ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


    View Slide

  20. ෳࡶ
    •όάΛੜΈ΍͍͢


    •ίʔϧόοΫॱংʹґଘ͕ൃੜ͢Δ


    •੬ऑੑΛੜΈ΍͍͢ঢ়ଶ


    •CrudController ֶशίετ͕ߴ͍


    •ϝλϓϩͰՄಡੑ͕௿͍


    •ೝ஌ίετ͕ߴ͍


    •ϝιουͷΦʔόʔϥΠυͰ࣮ࡍͷఆ͕ٛΘ͔ΓͮΒ͍


    •Fat controller ͱ૊Έ߹Θ͞ΔͱΑΓΩπ͍

    View Slide

  21. େྔ
    •ར༻ίϯτϩʔϥ͸ 300 ऑ


    View Slide

  22. ྺ࢙͋ΔϓϩδΣΫτͷͱ͋Δٕज़తෛ࠴Λ
    伱ؒϓϩδΣΫτͷ
    1VMM3FRVFTUTͰ౗͖ͬͨ͠࿩

    View Slide

  23. ౗͖͠ΔͨΊʹ
    •εΫϦϓτԽ


    •มߋϦεΫΛݮΒ͢


    •νʔϜઓʹ͢Δ


    •ϞνϕʔγϣϯΛอͭ


    View Slide

  24. ౗͖͠ΔͨΊʹ
    •εΫϦϓτԽ


    •มߋϦεΫΛݮΒ͢


    •νʔϜઓʹ͢Δ


    •ϞνϕʔγϣϯΛอͭ


    View Slide

  25. εΫϦϓτԽ
    •ख࡞ۀͷఫഇ͸ແཧ


    •࣌ؒͱࠜؾͱूதྗ͕ඞཁ


    •͋͘·Ͱ伱ؒ࣌ؒͷऔΓ૊Έ


    •ఫഇखॱॻ͕ॻ͚ΔͳΒεΫϦϓτԽͰ͖Δ


    View Slide

  26. ɹॻ͍ͨ

    View Slide

  27. εΫϦϓτ
    1. crud_controller .*ΞΫγϣϯ໊ ΛؚΉϑΝΠϧΛநग़


    2. 1 ͷ͏ͪରԠ͢Δςετ͕͋ΔϑΝΠϧΛநग़


    3. ίϯτϩʔϥϑΝΠϧΛจࣈྻͱͯ͠ಡΈࠐΈɺ

    ϝιουͷಈతఆٛΛ੩తఆٛʹมߋ


    4. 3 Ͱมߋͨ͠จࣈྻΛίϯτϩʔϥϑΝΠϧʹॻ͖໭͢


    5. rubocop -a ͯ͠ίϛοτΛੵΉ جຊ͸͜Ε͚ͩ


    View Slide

  28. εΫϦϓτ
    1. crud_controller .*ΞΫγϣϯ໊ ΛؚΉϑΝΠϧΛநग़


    όοΫΫΦʔτͰ

    ίϚϯυ࣮ߦ

    View Slide

  29. 1. 1 ͷ͏ͪରԠ͢Δςετ͕͋ΔϑΝΠϧΛநग़


    2. 1 ͷ͏ͪରԠ͢Δςετ͕͋ΔϑΝΠϧΛநग़
    εΫϦϓτ
    ίϯτϩʔϥͷ

    Ϋϥε໊Λऔಘ

    View Slide

  30. 1. 1 ͷ͏ͪରԠ͢Δςετ͕͋ΔϑΝΠϧΛநग़


    2. 1 ͷ͏ͪରԠ͢Δςετ͕͋ΔϑΝΠϧΛநग़
    εΫϦϓτ
    ΫϥεʹରԠ͢Δ spec ͕͋Δ

    ίϯτϩʔϥΛબͿ

    View Slide

  31. 1. 1 ͷ͏ͪରԠ͢Δςετ͕͋ΔϑΝΠϧΛநग़


    2. 1 ͷ͏ͪରԠ͢Δςετ͕͋ΔϑΝΠϧΛநग़


    3. ίϯτϩʔϥϑΝΠϧΛจࣈྻͱͯ͠ಡΈࠐΈɺ

    ϝιουͷಈతఆٛΛ੩తఆٛʹมߋ


    εΫϦϓτ
    File.read ͯ͠

    จࣈྻͱͯ͠ѻ͏

    View Slide

  32. 1. 1 ͷ͏ͪରԠ͢Δςετ͕͋ΔϑΝΠϧΛநग़


    2. 1 ͷ͏ͪରԠ͢Δςετ͕͋ΔϑΝΠϧΛநग़


    3. ίϯτϩʔϥϑΝΠϧΛจࣈྻͱͯ͠ಡΈࠐΈɺ

    ϝιουͷಈతఆٛΛ੩తఆٛʹมߋ


    εΫϦϓτ
    จࣈྻΛ੾ΓషΓ

    View Slide

  33. 2. 1 ͷ͏ͪରԠ͢Δςετ͕͋ΔϑΝΠϧΛநग़


    3. .rb ϑΝΠϧΛจࣈྻͱͯ͠ಡΈࠐΈɺ


    4. 3 Ͱมߋͨ͠จࣈྻΛίϯτϩʔϥϑΝΠϧʹॻ͖໭͢


    εΫϦϓτ
    File.write Ͱ্ॻ͖

    View Slide

  34. 3. .rb ϑΝΠϧΛจࣈྻͱͯ͠ಡΈࠐΈɺ


    4. 3 Ͱมߋͨ͠จࣈྻΛ .rb ϑΝΠϧʹॻ͖໭͢


    5. rubocop -a ͯ͠ίϛοτΛੵΉ


    εΫϦϓτ

    View Slide

  35. εΫϦϓτԽ
    ΧελϜ Cop Λ࡞ͬͯ

    autocorrect ͢Δͷ΋ྑͦ͞͏

    View Slide

  36. ܧଓతͳෛ࠴ฦ٫
    •伱ؒ࣌ؒͰߦ͑ΔΑ͏ʹ͢Δ


    •ίϚϯυΛଧ͚ͭͩͰ diff ͷ࡞੒͕׬ྃ


    •͓खܰ


    •ॻ͍ͨ௨Γಈ͘


    •ूதྗෆཁ
    MTG લʹ 10 ෼

    ۭ͍ͨ࣌ͱ͔

    View Slide

  37. ܧଓతͳෛ࠴ฦ٫
    GitHubActions ͳͲͰ

    PR ͷ࡞੒·Ͱ

    ࣗಈԽ͢Δͷ΋Αͦ͞͏

    View Slide

  38. •εΫϦϓτʹ͢Δͱ࡞ۀखॱΛ๨ΕΒΕΔ


    •͍ͭͰ΋΍ΊΒΕΔ


    •ຊۀ͕๩͘͠ͳͬͨ࣌


    •͍ͭͰ΋࠶։Ͱ͖Δ


    •ϋʔυϧ͕௿͍
    ࣮ࡍ్தͰ

    1 ೥ऑ์ஔͨ͠
    ܧଓతͳෛ࠴ฦ٫

    View Slide

  39. ౗͖͠ΔͨΊʹ
    •εΫϦϓτԽ


    •มߋϦεΫΛݮΒ͢


    •νʔϜઓʹ͢Δ


    •ϞνϕʔγϣϯΛอͭ


    View Slide

  40. มߋϦεΫΛݮΒ͢
    •ϘʔΠεΧ΢τɾϧʔϧ


    ϘʔΠεΧ΢τɾϧʔϧcϓϩάϥϚ͕஌Δ΂͖ͷ͜ͱ

    IUUQTϓϩάϥϚ͕஌Δ΂͖ͷ͜ͱDPNΤοηΠϘʔΠεΧ΢τϧʔϧ
    lj✣ǟƎw㢟ŧx҆ٳƵҗźƂơơƎżƮŶƋƒa

    NJǵƵ೑Ű೛ƬżƑƋ๝ŻŲƬŧa

    ഠ߶֥Ǝ൳ŴೆƯůƂŧŶƋƊżb

    ⅅŮƬᾖƉƥwźƉƒƍƬƍŧŶƋxƍƑƊżb

    View Slide

  41. •ϘʔΠεΧ΢τɾϧʔϧΛकΒͳ͍


    ϘʔΠεΧ΢τɾϧʔϧcϓϩάϥϚ͕஌Δ΂͖ͷ͜ͱ

    IUUQTϓϩάϥϚ͕஌Δ΂͖ͷ͜ͱDPNΤοηΠϘʔΠεΧ΢τϧʔϧ
    lj✣ǟƎw㢟ŧx҆ٳƵҗźƂơơƎżƮŶƋƒa

    NJǵƵ೑Ű೛ƬżƑƋ๝ŻŲƬŧa

    ഠ߶֥Ǝ൳ŴೆƯůƂŧŶƋƊżb

    ⅅŮƬᾖƉƥwźƉƒƍƬƍŧŶƋxƍƑƊżb
    มߋϦεΫΛݮΒ͢

    View Slide

  42. มߋͷؔ৺ࣄΛগͳ͘อͭ

    View Slide

  43. 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


    มߋͷؔ৺ࣄΛগͳ͘อͭ

    View Slide

  44. 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


    มߋͷؔ৺ࣄΛগͳ͘อͭ

    View Slide

  45. @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


    มߋͷؔ৺ࣄΛগͳ͘อͭ
    💀

    View Slide

  46. •ίʔυ඼࣭ʹؔ৺͕͋Δਓ΄Ͳ͍ͭͰͰ௚ͯ͠͠·͍͕ͪ


    •ؔ৺ࣄ͕૿͑Δͱόάͷࠞೖʹؾ͖ͮʹ͘͘ͳΔ


    ࣍ͷมߋͰ௚ͦ͏
    มߋͷؔ৺ࣄΛগͳ͘อͭ

    View Slide

  47. มߋϦεΫΛݮΒ͢

    View Slide

  48. มߋϦεΫΛݮΒ͢
    ো֐Λىͨ͜͠

    View Slide

  49. มߋϦεΫΛݮΒ͢
    ͔ͨ͠ʹมߋྔ͸

    ଟ͔͚ͬͨͲ
    ςετ͕͋ͬͨͷʹ

    Ͳ͏ͯ͠

    View Slide

  50. ِӄੑςετ
    expect ͕ͳͯ͘ݕ஌Ͱ͖ͳ͔ͬͨ



    RSpec.describe 'PUT /users/:id' do


    # …


    it do


    put user_url(user), params: params


    end


    end


    Կ΋ςετͯ͠ͳ͍ʂʂʂ

    View Slide

  51. ِӄੑςετ
    •ʮςετ͕͋Δ != ςετ͍ͯ͠Δʯঢ়ଶͩͬͨ


    •expectation ͷͳ͍ it Λݕ஌͢ΔΧελϜ Cop Λ࡞ͬͨ


    [email protected]@DPQ

    [email protected]@DPQ
    "EEA34QFD/P&YQFDUBUJPO&YBNQMFACZSLBNVSBu1VMM3FRVFTU

    IUUQTHJUIVCDPNSVCPDPQSVCPDPQSTQFDQVMM
    @r7kamura ͞ΜͷύονͰ

    rubocop-rspec ʹऔΓࠐ·Ε

    2.13.0 ͔Βར༻Ͱ͖·͢

    View Slide

  52. •PR Λখ͘͢͞Δͷ͸جຊ


    •ϨϏϡʔ͠΍͘͢͢ΔͨΊ


    มߋྔΛগͳ͘อͭ

    View Slide

  53. •ػցతͳมߋ΋ PR Λ෼ׂ͢΂͖͔ʁ


    •҆શੑͱίετͷόϥϯε


    •ࠓճ͸҆શੑΛͱͬͨ


    •ো֐͸ϞνϕʔγϣϯΛԼ͛Δ
    มߋྔΛগͳ͘อͭ
    ςετ͕ͳ͍ॴ΋͋Γ

    ࣌ʑख࡞ۀ΋͋ͬͨͷͰ

    View Slide

  54. •҆શͳมߋΛ્֐͢ΔཁҼΛ஍ಓʹഉআ͢Δ


    •ϨϏϡʔΞϒϧʹ͢Δ


    •ؔ৺ࣄΛগͳ͘อͭ


    •มߋΛগͳ͘อͭ


    •ِӄੑͷςετΛ๷͙
    มߋϦεΫΛݮΒ͢

    View Slide

  55. ౗͖͠ΔͨΊʹ
    •εΫϦϓτԽ


    •มߋϦεΫΛݮΒ͢


    •νʔϜઓʹ͢Δ


    •ϞνϕʔγϣϯΛอͭ


    View Slide

  56. νʔϜઓʹ͢Δ
    •🙅 ίʔυ඼࣭ʹؔ৺͕ߴ͍ਓʹϨϏϡʔґཔ


    •🙆ίʔυͷΦʔφʔͬΆ͍νʔϜʹϨϏϡʔґཔ


    •ෛ࠴ฦ٫͕ʮίʔυ඼࣭ʹؔ৺͕ߴ͍ͱݟΒΕ͍ͯΔਓʯͷ

    ؔ৺ࣄʹͳΔ


    •ෛ࠴ΛʮΈΜͳͷؔ৺ࣄʯʹ͢Δ

    View Slide

  57. νʔϜઓʹ͢Δ
    rake λεΫʹͯ͠୭Ͱ΋औΓ૊ΊΔΑ͏ʹ͢Δ

    View Slide

  58. νʔϜઓʹ͢Δ
    •ϝϯόʔ͕खΛڍ͛ͯ͘Εͯ 2 ਓͰऔΓ૊Ή͜ͱʹ


    •ϨϏϡʔ͕ര଎ͰճΔ


    •ਐΊํͷվળ΋ఏҊͯ͘͠Εͯഒ଎Ͱఫഇ͕ਐΉ


    •ਓͱҰॹʹ΍Δͱָ͍͠

    View Slide

  59. ౗͖͠ΔͨΊʹ
    •εΫϦϓτԽ


    •มߋϦεΫΛݮΒ͢


    •νʔϜઓʹ͢Δ


    •ϞνϕʔγϣϯΛอͭ


    View Slide

  60. ϞνϕʔγϣϯΛอͭ
    •๞͖Δ


    •׆ಈͷҙٛʹٙ໰Λ࣋ͪ࢝ΊΔ


    ΋͏ࠔ͍ͬͯΔਓ

    ͍ͳ͍ͷͰ͸ʁ

    View Slide

  61. ϞνϕʔγϣϯΛอͭ
    •ਐḿΛݟ͑ΔԽ͢Δ


    •Կ % ऴΘ͔ͬͨ


    ਺ࣈ͸ڧ͍

    View Slide

  62. ϞνϕʔγϣϯΛอͭ
    •๙Ίͯ΋Β͏


    View Slide

  63. ๙Ίͯ΋Β͏

    View Slide

  64. ๙Ίͯ΋Β͏
    ڵຯؔ৺Λ

    ࣋ͬͯ͘ΕͯͨΜͩͳ͊
    ։ൃຊ෦ࣗຫେձͰ

    CrudController ఫഇ׬ྃΛࣗຫͨ࣌͠ͷ൓Ԡ

    View Slide

  65. 👋

    View Slide

  66. ·ͱΊ
    ҆શʹɾָ͘͠Ͱ͖Δํ๏Λ୳͢
    ܧଓੑ

    View Slide

  67. )BQQZ)BDLJOH

    View Slide

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

    View Slide