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
Pull-Requestの内容を1クリックで動作確認可能にするワークフロー
natmark
2
510
CSC509 Lecture 05
javiergs
PRO
0
300
Go Conference 2025: Goで体感するMultipath TCP ― Go 1.24 時代の MPTCP Listener を理解する
takehaya
9
1.7k
組込みだけじゃない!TinyGo で始める無料クラウド開発入門
otakakot
0
280
いま中途半端なSwift 6対応をするより、Default ActorやApproachable Concurrencyを有効にしてからでいいんじゃない?
yimajo
2
430
PHPに関数型の魂を宿す〜PHP 8.5 で実現する堅牢なコードとは〜 #phpcon_hiroshima / phpcon-hiroshima-2025
shogogg
1
230
アメ車でサンノゼを走ってきたよ!
s_shimotori
0
220
20251016_Rails News ~Rails 8.1の足音を聴く~
morimorihoge
1
360
Devoxx BE - Local Development in the AI Era
kdubois
0
130
iOSエンジニア向けの英語学習アプリを作る!
yukawashouhei
0
190
エンジニアインターン「Treasure」とHonoの2年、そして未来へ / Our Journey with Hono Two Years at Treasure and Beyond
carta_engineering
0
160
TFLintカスタムプラグインで始める Terraformコード品質管理
bells17
2
170
Featured
See All Featured
A Modern Web Designer's Workflow
chriscoyier
697
190k
[RailsConf 2023] Rails as a piece of cake
palkan
57
5.9k
jQuery: Nuts, Bolts and Bling
dougneiner
65
7.9k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
33
2.5k
Six Lessons from altMBA
skipperchong
29
4k
Done Done
chrislema
185
16k
Learning to Love Humans: Emotional Interface Design
aarron
274
41k
Rebuilding a faster, lazier Slack
samanthasiow
84
9.2k
Statistics for Hackers
jakevdp
799
220k
Music & Morning Musume
bryan
46
6.8k
VelocityConf: Rendering Performance Case Studies
addyosmani
332
24k
Code Review Best Practice
trishagee
72
19k
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()のような処理が軽く見える名前で重い処理をしない ・複数の名前を検討する *いくつか候補を挙げ、ベストな名前を選ぶ
ご清聴、ありがとうございました