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
読みやすいコード
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Takumi Shotoku
December 05, 2019
Technology
1
770
読みやすいコード
Omotesando.rb #53
https://omotesandorb.connpass.com/event/157355/
Takumi Shotoku
December 05, 2019
Tweet
Share
More Decks by Takumi Shotoku
See All by Takumi Shotoku
Automatically generating types by running tests
sinsoku
4
13k
滅・サービスクラス🔥 / Destruction Service Class
sinsoku
8
2.7k
テストを書かないためのテスト/ Tests for not writing tests
sinsoku
1
280
ドメインの本質を掴む / Get the essence of the domain
sinsoku
2
330
"型"のあるRailsアプリケーション開発 / Typed Rails application development
sinsoku
10
3k
Let's get started with Ruby && Rails Tips
sinsoku
0
470
LTの敷居を下げる / Lower the threshold for LT
sinsoku
2
410
CircleCIの高速化🚀 / CircleCI faster
sinsoku
3
1.5k
Railsアプリと型検査 / Rails app and type checking
sinsoku
5
1.6k
Other Decks in Technology
See All in Technology
クレジットカード決済基盤を支えるSRE - 厳格な監査とSRE運用の両立 (SRE Kaigi 2026)
capytan
6
2.8k
What happened to RubyGems and what can we learn?
mikemcquaid
0
300
Bill One急成長の舞台裏 開発組織が直面した失敗と教訓
sansantech
PRO
2
380
OCI Database Management サービス詳細
oracle4engineer
PRO
1
7.4k
データの整合性を保ちたいだけなんだ
shoheimitani
8
3.1k
ブロックテーマ、WordPress でウェブサイトをつくるということ / 2026.02.07 Gifu WordPress Meetup
torounit
0
190
日本の85%が使う公共SaaSは、どう育ったのか
taketakekaho
1
220
SREじゃなかった僕らがenablingを通じて「SRE実践者」になるまでのリアル / SRE Kaigi 2026
aeonpeople
6
2.5k
ブロックテーマでサイトをリニューアルした話 / 2026-01-31 Kansai WordPress Meetup
torounit
0
470
Context Engineeringが企業で不可欠になる理由
hirosatogamo
PRO
3
600
会社紹介資料 / Sansan Company Profile
sansan33
PRO
15
400k
顧客との商談議事録をみんなで読んで顧客解像度を上げよう
shibayu36
0
250
Featured
See All Featured
Heart Work Chapter 1 - Part 1
lfama
PRO
5
35k
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
1
53
Statistics for Hackers
jakevdp
799
230k
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
430
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.4k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
61k
BBQ
matthewcrist
89
10k
How to train your dragon (web standard)
notwaldorf
97
6.5k
The agentic SEO stack - context over prompts
schlessera
0
640
The untapped power of vector embeddings
frankvandijk
1
1.6k
Groundhog Day: Seeking Process in Gaming for Health
codingconduct
0
93
Transcript
読みやすいコード 表参道.rb #53 2019/12/05(Thu) 1
自己紹介 名前: 神速 会社: メドピア株式会社 GitHub: @sinsoku (アイコン右上) Twitter: @sinsoku_listy
(アイコン右下) 2
コードを読みやすく書きたい 3
読みやすいコードとは何か 4
考えてみた • 短いコード • 条件分岐の少ないコード • 適切な命名の変数、クラス、メソッド...etc • メソッド呼び出しのネストが浅い 5
メソッド呼び出しのネストが深い例 def index set_user end private def set_user user_name =
get_user_name_from_api @user = User.find_or_initialize(user_name: user_name) end def get_user_name_from_api api = Sugoi::API.new(token: ENV['SUGOI_TOKEN']) user_name = api.get_user_name convert(user_name) end def convert(user_name) user_name.gsub('-', '_') end 6
浅くした例 def index user_name = api.get_user_name converted_user_name = user_name.gsub('-', '_')
@user = User.find_or_initialize(user_name: converted_user_name) end private def api @api ||= Sugoi::API.new(token: ENV['SUGOI_TOKEN']) end 7
話を戻して... 8
読みやすいコードの条件(主観) • 短いコード • 条件分岐の少ないコード • 適切な命名の変数、クラス、メソッド...etc • メソッド呼び出しのネストが浅い 9
RuboCopでだいたい検出できる • Metrics/AbcSize • Metrics/ClassLength: • Metrics/MethodLength 10
これで読みやすいコードになる! 11
しかし、現実は... # rubocop:disable Metrics/AbcSize Metrics/MethodLength def index # rubocop:enable Metrics/AbcSize
Metrics/MethodLength set_user set_blogs if params[:new] @users = User.where(foo: params[:foo]) .foo .bar .buz elsif params[:create] @users = User.where(foo: params[:foo]).piyo else # ർΕͨͷͰུ end end 12
Metrics/AbcSize を下げるテクニック 1. 変数を定義しない 2. Array(Enumerable)のメソッドを駆使する 3. クラスを抽出する 13
1. 変数を定義しない # bad def count_blogs(users) result = {} users.each
do |user| next unless user.active? result[user.id] = uesr.blogs.size end result end 14
1. 変数を定義しない # good def count_blogs(users) {}.tap do |result| users.each
do |user| next unless user.active? result[user.id] = uesr.blogs.size end end end 15
2. Array(Enumerable)のメソッドを駆使する • if/unlessよりselect/reject # good def count_blogs(users) # active_users
= users.select { |user| user.active? } ͱಉ͡ active_users = users.select(&:active?) {}.tap do |result| active_users.each do |user| result[user.id] = uesr.blogs.size end end end 16
2. Array(Enumerable)のメソッドを駆使する • このケースは to_h で良い # good def count_blogs(users)
users.select(&:active).to_h { |user| [user.id, user.blogs.size] } # ruby 2.5 ͩͱ͜Ε # users.select(&:active).map { |user| [user.id, user.blogs.size] }.to_h end 17
2. Array(Enumerable)のメソッドを駆使する • eachで範囲を-1/+1する必要はない (1..10).to_a #=> [1, 2, 3, 4,
5, 6, 7, 8, 9, 10] (1...10).to_a #=> [1, 2, 3, 4, 5, 6, 7, 8, 9] [:a, :b, :c].each.with_index(1).to_a #=> [[:a, 1], [:b, 2], [:c, 3]] 18
2. Array(Enumerable)のメソッドを駆使する • group_by と transform_values users_per_status = User.find_each.group_by(&:status) #=>
{ "pending" => [<User>, ...], "active" => [<User>, ... } users_per_status.transform_values { |users| users.map(&:user_name) } #=> { "pending" => ["sinsoku", ...], "active" => ["yuki3738", ... } 19
3. クラスを抽出する # app/models/user/ranking.rb class User class Ranking def initialize(user)
@user = user end end def rank score = calculate_score # ུ end private def calculate_score # ུ end end 20
モジュールにするのは # app/models/concerns/rankingable.rb module Rankingable def rank # ུ end
private def calculate_score # ུ end end class User include Rankingable end User.new.private_methods.include?(:calculate_score) #=> true 21
ここから追記 発表に間に合ったのはここまでだった... 22
Class vs Module • Classのprivateメソッドのスコープは狭い • リファクタリングしやすい • Moduleだと影響範囲の調査が少し面倒 •
Moduleは少ないメソッドに依存させるべき • Enumerableは each のみに依存してる • Moduleを上手く使うのは難しい 23
まとめ • RuboCopの指摘はリファクタリングの目安 • 安易に rubocop:disable しない • Arrayのメソッド一覧を読むのがおすすめ •
https://docs.ruby-lang.org/ja/latest/class/Array.html • ModuleよりClassの方がおすすめ 24