Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥
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.2k
はじめてのIT勉強会 #2 Readable Code Part 2
仙台で開催した「はじめてのIT勉強会」第二回のセッションスライドです。
リーダブルコードの紹介と入門的な解説内容になっています。
naoki
May 25, 2017
Tweet
Share
Other Decks in Programming
See All in Programming
안드로이드 9년차 개발자, 프론트엔드 주니어로 커리어 리셋하기
maryang
1
110
SwiftUIで本格音ゲー実装してみた
hypebeans
0
380
バックエンドエンジニアによる Amebaブログ K8s 基盤への CronJobの導入・運用経験
sunabig
0
160
connect-python: convenient protobuf RPC for Python
anuraaga
0
410
非同期処理の迷宮を抜ける: 初学者がつまづく構造的な原因
pd1xx
1
720
ViewファーストなRailsアプリ開発のたのしさ
sugiwe
0
470
C-Shared Buildで突破するAI Agent バックテストの壁
po3rin
0
390
WebRTC と Rust と8K 60fps
tnoho
2
2k
Why Kotlin? 電子カルテを Kotlin で開発する理由 / Why Kotlin? at Henry
agatan
2
7.2k
WebRTC、 綺麗に見るか滑らかに見るか
sublimer
1
180
俺流レスポンシブコーディング 2025
tak_dcxi
14
8.8k
UIデザインに役立つ 2025年の最新CSS / The Latest CSS for UI Design 2025
clockmaker
18
7.5k
Featured
See All Featured
Into the Great Unknown - MozCon
thekraken
40
2.2k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.5k
jQuery: Nuts, Bolts and Bling
dougneiner
65
8.3k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
55
3.1k
BBQ
matthewcrist
89
9.9k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
34
2.6k
Bootstrapping a Software Product
garrettdimon
PRO
307
120k
Reflections from 52 weeks, 52 projects
jeffersonlam
355
21k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
9.8k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.3k
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()のような処理が軽く見える名前で重い処理をしない ・複数の名前を検討する *いくつか候補を挙げ、ベストな名前を選ぶ
ご清聴、ありがとうございました