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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
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
Kubernetesでセルフホストが簡単なNewSQLを求めて / Seeking a NewSQL Database That's Simple to Self-Host on Kubernetes
nnaka2992
0
120
モジュラモノリスにおける境界をGoのinternalパッケージで守る
magavel
0
3.5k
SourceGeneratorのマーカー属性問題について
htkym
0
200
nuget-server - あなたが必要だったNuGetサーバー
kekyo
PRO
0
250
最初からAWS CDKで技術検証してもいいんじゃない?
akihisaikeda
4
150
Ruby x Terminal
a_matsuda
7
600
AI時代のソフトウェア開発でも「人が仕様を書く」から始めよう-医療IT現場での実践とこれから
koukimiura
0
150
Ruby and LLM Ecosystem 2nd
koic
1
820
どんと来い、データベース信頼性エンジニアリング / Introduction to DBRE
nnaka2992
1
290
エラーログのマスキングの仕組みづくりに役立ったASTの話
kumoichi
0
220
The Ralph Wiggum Loop: First Principles of Autonomous Development
sembayui
0
3.7k
CDIの誤解しがちな仕様とその対処TIPS
futokiyo
0
220
Featured
See All Featured
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
How to train your dragon (web standard)
notwaldorf
97
6.6k
Building the Perfect Custom Keyboard
takai
2
710
Building Adaptive Systems
keathley
44
3k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
470
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
2
550
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
Bash Introduction
62gerente
615
210k
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
118
110k
Amusing Abliteration
ianozsvald
0
130
VelocityConf: Rendering Performance Case Studies
addyosmani
333
24k
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
1
300
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()のような処理が軽く見える名前で重い処理をしない ・複数の名前を検討する *いくつか候補を挙げ、ベストな名前を選ぶ
ご清聴、ありがとうございました