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
はじめてのIT勉強会 #2 Readable Code Part 2
Search
naoki
May 25, 2017
Programming
1
1.1k
はじめてのIT勉強会 #2 Readable Code Part 2
仙台で開催した「はじめてのIT勉強会」第二回のセッションスライドです。
リーダブルコードの紹介と入門的な解説内容になっています。
naoki
May 25, 2017
Tweet
Share
Other Decks in Programming
See All in Programming
Oracle Database Technology Night 92 Database Connection control FAN-AC
oracle4engineer
PRO
1
440
ファインディ株式会社におけるMCP活用とサービス開発
starfish719
0
1.5k
デザイナーが Androidエンジニアに 挑戦してみた
874wokiite
0
470
Reading Rails 1.0 Source Code
okuramasafumi
0
220
為你自己學 Python - 冷知識篇
eddie
1
350
Navigating Dependency Injection with Metro
zacsweers
3
770
[FEConf 2025] 모노레포 절망편, 14개 레포로 부활하기까지 걸린 1년
mmmaxkim
0
1.6k
さようなら Date。 ようこそTemporal! 3年間先行利用して得られた知見の共有
8beeeaaat
3
1.4k
はじめてのMaterial3 Expressive
ym223
2
740
概念モデル→論理モデルで気をつけていること
sunnyone
2
190
1から理解するWeb Push
dora1998
7
1.9k
🔨 小さなビルドシステムを作る
momeemt
4
680
Featured
See All Featured
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
1.6k
The Cult of Friendly URLs
andyhume
79
6.6k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
48
9.7k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
8
920
Building a Scalable Design System with Sketch
lauravandoore
462
33k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
188
55k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
30
9.7k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
61k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
15
1.6k
The Art of Programming - Codeland 2020
erikaheidi
56
13k
Transcript
Readable Code Part 2: 誤解されない名前 Study session in SENDAI
私について
誤解されない名前?
results := datastore.Query().Filter("year <= 2011") このコードの実行結果は?
results := datastore.Query().Filter("year <= 2011") このコードの実行結果は? A: 2011年以前のデータを取得する B: 2011年以前のデータを除いて取得する
「どっちの意味だっけ?」 と思ったら、 それは誤解されるコード
POINT 自問自答して積極的に「誤解」を探し ていけば、曖昧な名前を見つけること が出来る。
1.間違ってないけど曖昧な名前
修正前のコード results := datastore.Query().Filter("year <= 2011")
修正前のコード results := datastore.Query().Filter("year <= 2011") A: 2011年以前のデータを取得する results :=
datastore.Query().Select("year <= 2011")
修正前のコード results := datastore.Query().Filter("year <= 2011") A: 2011年以前のデータを取得する results :=
datastore.Query().Select("year <= 2011") B: 2011年以前のデータを除いて取得する results := datastore.Query().Exclude("year <= 2011")
// textの末尾を切り落として、「…」をつける func clip(text string, length int) string
// textの末尾を切り落として、「…」をつける func clip(text string, length int) string clipped :=
clip("Hello, readable code!", 6)
// textの末尾を切り落として、「…」をつける func clip(text string, length int) string // 後ろの6文字を切り落とし?
(remove:取り除く) assert.Equal(t, "Hello, readable...", clipped) clipped := clip("Hello, readable code!", 6)
// textの末尾を切り落として、「…」をつける func clip(text string, length int) string // 後ろの6文字を切り落とし?
(remove:取り除く) assert.Equal(t, "Hello, readable...", clipped) clipped := clip("Hello, readable code!", 6) // 6文字までで切り落とし? (truncate:切り詰める) assert.Equal(t, "Hello,...", clipped)
// textの末尾を切り落として、「…」をつける func clip(text string, length int) string なんの長さ? バイト数
maxBytes 文字数 maxChars 単語数 maxWords
// textの末尾を切り落として、「…」をつける func clip(text string, length int) string なんの長さ? バイト数
maxBytes 文字数 maxChars 単語数 maxWords // 修正例 func truncate(text string, maxChars int) string
2.誤解される限界値
const CART_TOO_BIG_LIMIT int = 10 // ショッピングカート内のアイテムが10件より多い場合はエラー if len(shoppingCart) >=
CART_TOO_BIG_LIMIT { return errors.New("カートにある商品が多すぎます。") }
const CART_TOO_BIG_LIMIT int = 10 // ショッピングカート内のアイテムが10件より多い場合はエラー if len(shoppingCart) >=
CART_TOO_BIG_LIMIT { return errors.New("カートにある商品が多すぎます。") } このコードにはバグがあります。
const CART_TOO_BIG_LIMIT int = 10 // ショッピングカート内のアイテムが10件より多い場合はエラー if len(shoppingCart) >=
CART_TOO_BIG_LIMIT { return errors.New("カートにある商品が多すぎます。") } このコードにはバグがあります。 Ans:ショッピングカートに9件しか入らない。
LIMITでは 「未満(限界値を含まない)」なのか 「以下(限界値を含む)」なのかが 曖昧になってしまう。
//修正版 const MAX_ITEMS_IN_CART int = 10 // ショッピングカート内のアイテムが10件より多い場合はエラー if len(shoppingCart)
> MAX_ITEMS_IN_CART { return errors.New("カートにある商品が多すぎます。") }
POINT 限界値を明確にするためには、 MINやMAXを使用する。
3.範囲の指定
// 指定した範囲の数値を取得する func intRange(start int, stop int) []int iRange :=
intRange(2, 4)
// 指定した範囲の数値を取得する func intRange(start int, stop int) []int iRange :=
intRange(2, 4) iRangeの値は何が入る?
// 指定した範囲の数値を取得する func intRange(start int, stop int) []int iRange :=
intRange(2, 4) iRangeの値は何が入る? [2, 3]? [2, 3, 4]?
Startは明確だけど、Stopは 「未満(限界値を含まない)」なのか 「以下(限界値を含む)」なのかが 曖昧になってしまう。
最後の要素まで含む範囲なら firstとlastを使う ↓first ↓last 1 2 3 4 5
// 修正版 func intRange(first int, last int) []int iRange :=
intRange(2, 4) // [2, 3, 4] maxとminを使用しても良い
最後の要素まで含まない範囲なら beginとendを使う 1 2 3 4 5 ↓begin ↓end //
指定した範囲の数値を取得する func intRange(begin int, end int) []int iRange := intRange(2, 4) // [2, 3]
4.ブール値の名前
readPassword := true どんな意味かわからないブール値 パスワードを 「読み込む必要がある」のか、 「もう読み込んだ」のか...etc
「読み込む必要がある 」 「 も う 読 み 込 ん だ
」 :needPassword :isAuthenticated
disableSsl := false ブール値の否定形は避ける
disableSsl := false ブール値の否定形は避ける enableSsl := true
POINT ブール値は頭にis, has, can, should などをつけて、分かりやすく 否定形は避ける
5.ユーザーの期待に合わせる
この処理のコストは? mean := staticsController.getMean() getterなので一般的にO(1)と考える...
// 実装 type StaticsCollector struct{} func (s *StaticsCollector) addSample(x float64)
{} func (s *StaticsCollector) getMean() float64 { // 全てのサンプルをイテレートして、total / num_samples を返す。... } 実装はO(n)だった... もしサンプルが1000万件あったらorz
get*()からcompute等へ変更する // 実装 type StaticsCollector struct{} func (s *StaticsCollector) addSample(x
float64) {} func (s *StaticsCollector) computeMean() float64 { // 全てのサンプルをイテレートして、total / num_samples を返す。... } あるいは処理を工夫してO(1)になるようにする
POINT 読み手の期待に反しない 名前をつける
6.複数の名前を検討する
exprimentId = 100 description = "フォントを14ptに上げる" fontSize = 14pt ...
// 複数の設定項目 trafficFraction = 5% ある実験をするための設定ファイル
exprimentId = 101 description = "フォントを13ptに上げる" fontSize = 13pt ...
// 複数の設定項目 [再利用する実験ID] = 100 同じような実験をする必要があるが、 設定ファイルをコピペして作るのは嫌なので... こんなふうに書けるようにしたい
experimentId = 100 template = 100 名前を考えてみよう 1.template テンプレートは抽象的な穴あきの項目に具体的な 値を埋め込んで使用するもの。
具体的な実験IDを再利用しているので、誤解を招く。
experimentId = 100 reuse = 100 名前を考えてみよう 2.reuse reuseだけだと「100回再利用可能」と誤解される可 能性がある。
reuseIdにすれば多少よくなるけど、「再利用ID」とい う別のなにかに勘違いされるかもしれない。
experimentId = 100 copy = 100 名前を考えてみよう 3.copy copyだけだと「この実験を100回コピーする」のかと 勘違いされてしまうかも。
copyExperimentIdとすると何をコピーしているかが すぐに理解できる。
experimentId = 100 inherit = 100 名前を考えてみよう 4.inherit 継承という言葉はプログラマになじみがあるので理 解しやすい。
inheritFromExprimentIdとすれば継承元が何かすぐ にわかる。
この章のまとめ
誤解されない名前をつけるには ・名前が他の意味に捉えられないか自問自答する *filterよりselect、limitよりmaxなど、より意図が明確な名前 ・限界値や範囲は慣習に従う *限界値はmin/max、範囲はfirst/lastやbegin/endなど使い分ける ・ブール値の名前に気をつける *それがブール値だと分かるようにis, hasなどを使う *disableSslのような否定形を極力使わない ・読み手の期待を裏切らない
*get*()やsize()のような処理が軽く見える名前で重い処理をしない ・複数の名前を検討する *いくつか候補を挙げ、ベストな名前を選ぶ
ご清聴、ありがとうございました