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
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Shinichi Maeshima
September 12, 2018
Technology
7
15k
Rails Good Parts, Bad Parts
「MedBeer -Rails開発での技術的負債との付き合い方」での発表資料です
Shinichi Maeshima
September 12, 2018
Tweet
Share
More Decks by Shinichi Maeshima
See All by Shinichi Maeshima
メタプログラミングRuby問題集の活用
willnet
2
1.5k
rails g authenticationから学ぶRails8.0時代の認証
willnet
5
4.6k
What's a well-behaved Rails extension gem?
willnet
0
770
Sidekiq vs Solid Queue
willnet
14
14k
どうしてこうなった?から理解するActive Recordの関連の裏側
willnet
6
1.6k
Exceptional Rails
willnet
6
8.1k
Breaking the Flaky Test Cycle
willnet
2
2.3k
mrskで広がるインフラの選択肢
willnet
1
1.2k
アプリケーションを長期にわたって無理なく運用するためのたったひとつの方法
willnet
2
2.3k
Other Decks in Technology
See All in Technology
Amazon Bedrock AgentCoreでブラウザ拡張型AI調査エージェントを開発した話 (シングルエージェント編)
nasuvitz
2
110
三菱UFJ銀行におけるエンタープライズAI駆動開発のリアル / Enterprise AI_Driven Development at MUFG Bank: The Real Story
muit
7
14k
Java ランタイムからカスタムランタイムに行き着くまで
ririru0325
0
110
Oracle Database@Azure:サービス概要のご紹介
oracle4engineer
PRO
3
820
AWSが推進するAI駆動開発ライフサイクル入門 〜 AI駆動開発時代に必要な人材とは 〜/ introduction_to_aidlc_and_skills
fatsushi
7
4.6k
競争優位を生み出す戦略的内製開発の実践技法
masuda220
PRO
2
380
AIエージェントのメモリについて
shibuiwilliam
0
390
『誰の責任?』で揉めるのをやめて、エラーバジェットで判断するようにした ~感情論をデータで終わらせる、PMとエンジニアの意思決定プロセス~
coconala_engineer
0
1.7k
I tried making an AI manzai comedy act with "boke" and "tsukkomi" using Strands Agents
zzzzico
1
170
技術選定 したい人 したくない人
shirayanagiryuji
0
340
Oracle Database@Google Cloud:サービス概要のご紹介
oracle4engineer
PRO
3
1.1k
フルスタックGoでスコア改ざんを防いだ話
ponyo877
0
510
Featured
See All Featured
sira's awesome portfolio website redesign presentation
elsirapls
0
160
Producing Creativity
orderedlist
PRO
348
40k
Designing for Performance
lara
611
70k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
2.8k
Building Adaptive Systems
keathley
44
2.9k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
350
The browser strikes back
jonoalderson
0
730
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
350
The #1 spot is gone: here's how to win anyway
tamaranovitovic
2
960
What’s in a name? Adding method to the madness
productmarketing
PRO
24
3.9k
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
94
Statistics for Hackers
jakevdp
799
230k
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のコ ードを議論するコミュニ ティ
どのように実装するとよ いか判断に悩むときに相 談できる
皆様からの投稿お待ちし ています !
まとめ » 負債を作らないためには、べんりな機能、要注意 な機能を知ることが大事 » 要注意なものについて、チーム全体で理解できる ように詳細を詰めて周知する » 勉強と教育をがんばりましょう
判断に悩むものは一緒に 勉強していきましょう