はじめに
名書と呼ばれる例の本を読んだらやっぱり名書だったので残そうと思いました。
が、学んだ内容活かして1冊まるまるタイトルに詰め込んだらまとまっちゃいました。
もうこれでいいでしょうか。
本の要約とかは皆さん書かれているので、
○章 → ○○ とかじゃなく
こういう悩みがあって、、 → これで解決できるかも?
のように書こうと思います。具体的な感想はブログにでも書きます。
覚えたことを一語一句模写するわけじゃないので、
読みたい人は以下から、または周りの先輩へダッシュ。
リーダブルコード
背景
チームにアサインされたらだいたい先輩から最初に提案される文献のようですね。
未経験でオレオレ開発上がりの私は以下のことで少し悩んでいました。
- コードは動くんだけど、なんだかレビューされがち
- 良いと思ってやるけど、実はよくなかった
- チーム開発わかるけど、具体的にどうしたらいいの
これらの悩みを解決に導いてくれそうな書籍でした(今読み終わったので実践はこれからだ!)。
原因と答えはもうタイトルにもありますが本当にその通りで、
チームへ愛情をもち、メンバーへ思いやりを持って書きなさい。さすれば未来のあなたもそれに救われます。
でした。
では悩みの原因と改善提案を少しまとめます。
問題解決と本書での解決策
ではリーダブルコードに書いてあることを意識すると、上記のような問題や疑問の解決策がどのように見えてくるか、一つ例を出して考えてみます。
問題
見出しの用のラベルが一つあるとします。そこへレイアウトが未確定だけどもう一つラベルを下に追加したいなぁという修正が来ました。(これならできそうだぜ!)
何かしらの方法で追加すると思うんですが、ほぼコピーのような実装なのであなたは閃きます。
せや、イテレーションで同じ処理まとめたらええやん!
class menuCell: UITableViewCell {
let beer = UILabel()
let edamanme = UILabel()
func configure(beer: String, edamame: String) {
self.beer = beer
self.edamame = edamame
}
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
let titles = [beer, edamame]
for title in titles {
addSubview(title)
title.textColor = .black
title.font = UIFont.systemFont(ofSize: 16, weight: .regular)
title.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(12)
}
if title == titleLabel_1 {
title.text = "beer"
title.snp.makeConstraints { make in
make.top.equalToSuperview().offset(12)
}
} else {
title.text = "edamame"
title.snp.makeConstraints { make in
make.bottom.equalToSuperview().offset(15)
}
}
}
}
}
for
文でループ処理、いかにもプログラミングっぽいですね。
これ進○ゼミで見たやつだ!とご満悦です。
でも却下です。新人、タイキック〜です。
原因
コードは動きますし、間違いでもないはずです。ではなぜふさわしくないのか。
1. まず修正タスクの内容をしっかり考慮しましょう
タスク要件のレイアウトが未確定だけど~
がポイントじゃないでしょうか。要は、今後この暫定的対応が変更される余地があるということ。
ということは、出来るだけ変更に対応しやすくした方がいいです。
2. 安直なイテレーションは余計なだけで分かりづらい
初見で上から読み手の気持ちでこれを見た場合、
-
for
があるから何かが繰り返されてるな? -
if
があるから何かが分岐しているな?
と2回も思考停止ポイントが生まれています。
このようなイテレーションの使い方はありますが、配列に組み込む場合はもっとインスタンスが多い場合に有用でしょう。
そして文章読解よりも、目に入った瞬間に情報処理ができる絵のような形の方が脳の理解は早いです。
解決策と本書より抜粋
この問題を解消するための良いアイデアが本書にいくつかあります。
美しさを保つ
- 似ているコードは似ているように、シルエットを似せる
- 関連コードはまとめてブロック化
- 流し読みで理解できるコードが良い
イテレーションとロジック
- イテレーションはコードを量を減らせる、だが分かりにくくなる
- 繰り返しや分岐は理解の妨げ
- 少しだけ長くなっても良いから、見栄えを良くする
上記のようなコードだと、共通点
とそうじゃない部分
を良い感じに分けた感はありますが、
短くprogrammaticallyに書くことによる、「私うまく書けたかも感」は読み手への妨げ
になりかねないところです。
上記を考慮してみると
class menuCell: UITableViewCell {
let beer = UILabel()
let edamanme = UILabel()
func configure(beer: String, edamame: String) {
self.beer = beer
self.edamame = edamame
}
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
addSubview(beer)
addSubview(edamame)
beer.textColor = .black
beer.font = UIFont.systemFont(ofSize: 16, weight: .regular)
beer.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(12)
make.top.equalToSuperview().offset(12)
}
edamanme.textColor = .black
edamanme.font = UIFont.systemFont(ofSize: 16, weight: .regular)
edamanme.snp.makeConstraints { make in
make.left.right.equalToSuperview().inset(12)
make.bottom.equalToSuperview().offset(15)
}
}
}
あ、上がbeer
のラベルで下がedamame
のラベルっぽいなって一瞬でなんとなく認識できますね。
頭を使わなくても理解できるコードが本書リーダブルコードが提唱する分かりやすいコードです。
こういうコピペっぽいコードを見ると「冗長性を排除しなきゃ、、、」と思うかもしれませんが、
この場合レイアウトが未確定だけど~
という未来の変更を加味して
それぞれ編集しやすいように対応しています。
私が読み手で理解する側なら、確実に後者のが嬉しいですもんね。
まとめ、他の名台詞
上記ではピンと来やすい部分を抜粋して考えてみましたが、他にも
- 命名規則をしっかり守り、読み手の理解を助ける(誤解させない)
- コメントの必要性を考え、読み手のキャッチアップを補助するコメントを書く
- ネストを浅くすることで、読み手の思考をストップさせない
- 何もないコードが一番良い!
といったようなことが書いてありました。
要約するとやはり
チームに愛と思いやりを持とう!
が今回私が悩んでいたものを改善してくれるかもしれない一言ですね。
相手のことを考えて書いたものが、ゆくゆくは自分のことも助けてくれるなんてとても素敵
他にも修正やテストに対応しやすくするとか色々あるんですが、、、
このような一歩引いて考えるスキルは都度行うものではなく、習慣化して当たり前にするものだと最後に書いてありました。
染み込むまで頑張ります。
あとリーダブルコードを考えないと、お汚いコードを読む相手がどう思うか一言書いてあったんですが
それが結構胸にグサッと来ました。
自分だけが読みやすいコードを書いているという状況はとてもつらい。他の人がコード を書くたびに読みづらいコードが入ってくる。掃除しているそばからゴミを捨てられ ているような感覚だ。