Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
はじめてのIT勉強会 #2 Readable Code Part 2
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
naoki
May 25, 2017
Programming
1.3k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
はじめてのIT勉強会 #2 Readable Code Part 2
仙台で開催した「はじめてのIT勉強会」第二回のセッションスライドです。
リーダブルコードの紹介と入門的な解説内容になっています。
naoki
May 25, 2017
Other Decks in Programming
See All in Programming
Long Living Tokens, Die, Die, Die! (or: The One Ring is Banned in Modern)
sylph01
0
310
When benchmarks go bad - what I learned from measuring performance wrong
hollycummins
0
220
3回つくってわかった、 定期実行ジョブ基盤の本質情報
takai
0
490
全ての永続トークンを、生まれる前に消し去りたい!
sylph01
2
930
AI主導のプログラミング学習アプリを作ってみた
econanringo
0
180
Kotlinの15年とServer-Side Kotlin
n_takehata
1
150
作れる、でも消せるか?──安全に「枯らして消す」機能削除術 / Drain, Then Delete
chobishiba
2
720
ジョジョの世界をXRで再現する
mofurune
0
170
作って学ぶSpring BootのAuto Configuration / JJUG Night Seminar 2026-10-19
rshindo
0
150
npm との違いを手がかりにGo の依存管理を理解したい
optim
0
490
AI時代のコードレビューは人に向けるな、仕組みに向けろ
texmeijin
5
3.7k
JIS keyboard support in Omarchy
lef237
0
120
Featured
See All Featured
Balancing Empowerment & Direction
lara
6
1.3k
What the history of the web can teach us about the future of AI
inesmontani
PRO
2
740
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
850
[SF Ruby Conf 2025] Rails X
palkan
3
1.5k
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
750
How Software Deployment tools have changed in the past 20 years
geshan
2
35k
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
460
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
56k
Why You Should Never Use an ORM
jnunemaker
PRO
61
10k
Making Projects Easy
brettharned
120
6.8k
Intergalactic Javascript Robots from Outer Space
tanoku
273
28k
Art, The Web, and Tiny UX
lynnandtonic
304
22k
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()のような処理が軽く見える名前で重い処理をしない ・複数の名前を検討する *いくつか候補を挙げ、ベストな名前を選ぶ
ご清聴、ありがとうございました