Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Rails Good Parts, Bad Parts
Search
Shinichi Maeshima
September 12, 2018
Technology
7
14k
Rails Good Parts, Bad Parts
「MedBeer -Rails開発での技術的負債との付き合い方」での発表資料です
Shinichi Maeshima
September 12, 2018
Tweet
Share
More Decks by Shinichi Maeshima
See All by Shinichi Maeshima
Sidekiq vs Solid Queue
willnet
14
11k
どうしてこうなった?から理解するActive Recordの関連の裏側
willnet
6
1.4k
Exceptional Rails
willnet
6
7.3k
Breaking the Flaky Test Cycle
willnet
2
2.1k
mrskで広がるインフラの選択肢
willnet
1
1k
アプリケーションを長期にわたって無理なく運用するためのたったひとつの方法
willnet
2
2.1k
HotwireからDHHが考えるこれからのRailsとJSの付き合い方を知る
willnet
14
13k
Rails6.1で新しく入る機能について
willnet
12
16k
Concerns about Concerns
willnet
11
34k
Other Decks in Technology
See All in Technology
Go の analysis パッケージで自作するリファクタリングツール
kworkdev
PRO
1
420
Proxmox VE超入門 〜 無料で作れるご自宅仮想化プラットフォームブックマークする
devops_vtj
0
160
ウェブアクセシビリティとは
lycorptech_jp
PRO
0
280
20250326_管理ツールの権限管理で改善したこと
sasata299
1
390
ルートユーザーの活用と管理を徹底的に深掘る
yuobayashi
6
730
スケールアップ企業のQA組織のバリューを最大限に引き出すための取り組み
tarappo
4
960
データベースで見る『家族アルバム みてね』の変遷 / The Evolution of Family Album Through the Lens of Databases
kohbis
2
440
お問い合わせ対応の改善取り組みとその進め方
masartz
1
370
Vision Language Modelを活用した メルカリの類似画像レコメンドの性能改善
yadayuki
9
1.3k
ソフトウェアプロジェクトの成功率が上がらない原因-「社会価値を考える」ということ-
ytanaka5569
0
130
一人QA時代が終わり、 QAチームが立ち上がった話
ma_cho29
0
290
技術好きなエンジニアが _リーダーへの進化_ によって得たものと失ったもの / The Gains and Losses of a Tech-Enthusiast Engineer’s “Evolution into Leadership”
kaminashi
0
210
Featured
See All Featured
Understanding Cognitive Biases in Performance Measurement
bluesmoon
28
1.6k
Measuring & Analyzing Core Web Vitals
bluesmoon
6
320
Automating Front-end Workflow
addyosmani
1369
200k
GraphQLとの向き合い方2022年版
quramy
45
14k
Unsuck your backbone
ammeep
670
57k
Building Adaptive Systems
keathley
41
2.5k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.2k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
Designing for humans not robots
tammielis
251
25k
Build your cross-platform service in a week with App Engine
jlugia
229
18k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
47
5.3k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Transcript
Rails Good Parts, Bad Parts @willnet
自己紹介 » 前島真一 aka @willnet or @netwillnet » ginza.rb から来ました
» メドピアさんで技術顧問しています » https://github.com/willnet » https://twitter.com/netwillnet » https://blog.willnet.in
技術顧問として 主に負債を減らしたり、負債の増加を防ぐために頑 張っています !
技術顧問について詳しく知りたい方は こちらをどうぞ » Rails Developers Meetup で喋った » https://speakerdeck.com/willnet/ji-shu-gu- wen-toiudong-kifang
» ブログ書いた » https://blog.willnet.in/entry/ 2018/04/09/101808
今日のテーマは技術的負 債 !
負債へのアプローチは2 つ
できてしまった負債を減 らす⬇
新規開発で負債を増やさ ない⬆ !
今日は負債を増やさない 話をします
負債の増加を防ぐにはど うしたらよいか
Railsのレールに乗る
レールに乗る、とは? » みんなよく言ってるけどふわっとした概念 » レールについてきちんと説明している文章がない ように見える
Railsが提供しているべんりな機能を活 用する = レールに乗る ここではこういう定義とします
Railsのべんりな機能 » たくさんある » こういうメソッドないかな?と思って調べると大 抵定義済み
べんりな機能を知らずに スクラッチで実装して微 妙な感じになるケースが よくある !
べんりな機能の具体例 » あまり知られていない&&知ってると便利なもの » 複数のお手伝い先で何回も言ってるやつ
has_many
みんな知ってる
定義することで使えるよ うになる機能がたくさん ある
has_manyで使えるようになるものたち collection collection<<(object, ...) collection.delete(object, ...) collection.destroy(object, ...) collection=(objects) collection_singular_ids
collection_singular_ids=(ids) collection.clear
has_manyで使えるようになるものたち collection.empty? collection.size collection.find(...) collection.where(...) collection.exists?(...) collection.build(attributes = {}, ...)
collection.create(attributes = {}) collection.create!(attributes = {}) collection.reload
全種類知ってますか?
collection=(objects), collection_singular_ids=(ids) » 既存のcollectionをいい感じに置き換える » has_many through の場合は中間テーブルを置き 換える
合わせ技でつかえるview helper » collection_check_boxes これらをスクラッチで書いてしまう人めっちゃ多い (当社比)
コード例 ビールの銘柄にタグ付けをするコードを考えてみま す
None
modelはこんな感じ class Beer < ApplicationRecord has_many :taggings has_many :tags, through:
:taggings end
素直に書くと <% Tag.all.each do |tag| %> <%= form.label tag.name do
%> <%= check_box_tag 'beer[tag][id][]', tag.id, beer.tags.find { |t| tag.id == t.id } %> <%= tag.name %> <% end %> <% end %>
素直に書くと def update @beer = Beer.find(params[:id]) @beer.attributes = beer_params original_taggings
= @beer.taggings taggings_ids = params[:beer][:tag][:id] delete_taggings = original_taggings.reject { |bt| taggings_ids.include?(bt.tag_id.to_s) } delete_taggings.each(&:destroy) add_tags = taggings_ids.reject { |id| original_taggings.map(&:tag_id).include?(id.to_i) } add_tags.each do |tag_id| @beer.taggings.build(tag_id: tag_id) end if @beer.save redirect_to @beer, notice: 'Beer was successfully updated.' else render :edit end end private def beer_params params.require(:beer).permit(:name) end
一瞬では読めないです ね… !
既存のタグと入力値との 差分を見て、必要なもの だけinsert, deleteして いる
読みづらいしバグも入り 込みやすそう
便利メソッドたちを使うと <%= form.collection_check_boxes :tag_ids, Tag.all, :id, :name %>
便利メソッドたちを使うと def update @beer = Beer.find(params[:id]) if @beer.update(beer_params) redirect_to @beer,
notice: 'Beer was successfully updated.' else render :edit end end private def beer_params params.require(:beer).permit(:name, tag_ids: []) end
普通に書ける beer.tag_ids = params[:beer][:tag_id] » has_many :tagsでtag_ids=メソッドが生えてい る » いい感じに差分を見て中間テーブルをinsert,
deleteしてくれる
これ、初めて知った人 ✋
どうやってべんりな機能を知るのか » 公式のドキュメントやRailsガイドを読みましょ う » もしくは強い人にレビューやペアプロしてもらい ましょう
ここまでの話をまとめる と
Railsが提供するべんり な機能を使えば負債を作 らずに開発できる!
なんですけど…
Railsが提供している機能が全部無条件 に便利というわけではない » 安易に使うとやけどする機能もある » ググるといろいろでてくるはず » callback » default_scope
» nested attributes
gemも似たように、安易に採用すべきで はないものがある » devise » simple_form » activeadmin » etc
この手のやつ、どう取り扱うべきか » チーム開発のときは特に慎重になったほうが良い » 禁止にしておいたほうが無難なことも多い » 利用シーンやチームの状況によって使えることも あるので、できれば吟味して決めたい
例えばwebpacker » 最近よくdisられている » しかしフロントエンド専任がおらず、片手間でjs を書く&&とりあえずes6使いたい、というケース だと大変便利 » フロントエンド専任がいて、webpackの設定をち ゃんとしたい、というケースでは必要ない
例えばdevise » 昔からよくdisられている » devise wayから外れるとつらい » 管理画面だけ認証が必要、などdevise wayで問題 ないならサッと導入できて便利
要注意なものは » なぜ注意が必要なのか » どう避けるか » どういうときなら使ってもよいのか を把握してまとめておくと良い
例えばhas_manyのcollection<<は要注 意 class User has_many :posts end これはイマイチな書き方 user.posts <<
Post.new(title: 'hello world!')
なぜか collection<<は、レシーバのオブジェクトがDBに 保存済みか否かで挙動が異なる(クエリが発行され たり発行されなかったりする)
どう避けるか user.posts.build(title: 'hello world!') user.posts.create(title: 'hello world!') のように書いたほうが可読性が高く、事故りにくい
どういうときなら使ってもよいのか collection.build や collection.createが適切 でない、かつチームメンバー全員が挙動を理解して いればギリギリOKかと tag = Tag.create(name: 'Ϗʔϧ')
Beer.each { |beer| beer.tags << tag }
(こうも書けるのであんまり例が良くな い) tag = Tag.create(name: 'Ϗʔϧ') Beer.each { |beer| beer.taggings.create!(tag:
tag) }
このように » なぜ注意が必要なのか » どう避けるか » どういうときなら使ってもよいのか を把握してチーム内で共有したい
負債を作らないために は、負債になりそうな要 素の対応法をみんなが理 解している必要がある
少なくとも、レビューで 負債になりそうな要素を 止められるようにしてお きたい
負債を作らないイコール 社内教育を頑張る
メドピアでは » 社内読書会 » ペアプロ » ふりかえり会 などしています
ところで、さっきの例は 簡単すぎ
現実ではもっと判断に悩 むケースが多い
判断に悩む例: コールバックをどう回 避するとよいか? » フォームオブジェクト? » サービスクラス? » その他 ↑方針を決めたとして、具体的にどうやって作ると
いいの?
なるべく具体的に「こう だ!」と道を示さない と、それぞれ思い思いの 実装になってそれが負債 につながる
しかし選択するのが難し い
そこで clean-rails.org ですよ
可読性の高いRailsのコ ードを議論するコミュニ ティ
どのように実装するとよ いか判断に悩むときに相 談できる
皆様からの投稿お待ちし ています !
まとめ » 負債を作らないためには、べんりな機能、要注意 な機能を知ることが大事 » 要注意なものについて、チーム全体で理解できる ように詳細を詰めて周知する » 勉強と教育をがんばりましょう
判断に悩むものは一緒に 勉強していきましょう