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
13
8.8k
どうしてこうなった?から理解するActive Recordの関連の裏側
willnet
5
940
Exceptional Rails
willnet
6
6.8k
Breaking the Flaky Test Cycle
willnet
2
2k
mrskで広がるインフラの選択肢
willnet
1
980
アプリケーションを長期にわたって無理なく運用するためのたったひとつの方法
willnet
2
2.1k
HotwireからDHHが考えるこれからのRailsとJSの付き合い方を知る
willnet
14
13k
Rails6.1で新しく入る機能について
willnet
12
15k
Concerns about Concerns
willnet
11
34k
Other Decks in Technology
See All in Technology
ハイパーパラメータチューニングって何をしているの
toridori_dev
0
140
リンクアンドモチベーション ソフトウェアエンジニア向け紹介資料 / Introduction to Link and Motivation for Software Engineers
lmi
4
300k
Python(PYNQ)がテーマのAMD主催のFPGAコンテストに参加してきた
iotengineer22
0
470
AIチャットボット開発への生成AI活用
ryomrt
0
170
【Startup CTO of the Year 2024 / Audience Award】アセンド取締役CTO 丹羽健
niwatakeru
0
950
CysharpのOSS群から見るModern C#の現在地
neuecc
2
3.1k
これまでの計測・開発・デプロイ方法全部見せます! / Findy ISUCON 2024-11-14
tohutohu
3
360
信頼性に挑む中で拡張できる・得られる1人のスキルセットとは?
ken5scal
2
530
Why App Signing Matters for Your Android Apps - Android Bangkok Conference 2024
akexorcist
0
120
スクラム成熟度セルフチェックツールを作って得た学びとその活用法
coincheck_recruit
1
140
Lambda10周年!Lambdaは何をもたらしたか
smt7174
2
110
Shopifyアプリ開発における Shopifyの機能活用
sonatard
4
250
Featured
See All Featured
Product Roadmaps are Hard
iamctodd
PRO
49
11k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
31
2.7k
Measuring & Analyzing Core Web Vitals
bluesmoon
4
120
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
44
6.8k
What's in a price? How to price your products and services
michaelherold
243
12k
Mobile First: as difficult as doing things right
swwweet
222
8.9k
Building Adaptive Systems
keathley
38
2.3k
Into the Great Unknown - MozCon
thekraken
32
1.5k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
48k
The MySQL Ecosystem @ GitHub 2015
samlambert
250
12k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
28
2k
Art, The Web, and Tiny UX
lynnandtonic
297
20k
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のコ ードを議論するコミュニ ティ
どのように実装するとよ いか判断に悩むときに相 談できる
皆様からの投稿お待ちし ています !
まとめ » 負債を作らないためには、べんりな機能、要注意 な機能を知ることが大事 » 要注意なものについて、チーム全体で理解できる ように詳細を詰めて周知する » 勉強と教育をがんばりましょう
判断に悩むものは一緒に 勉強していきましょう