思ったことのまとめ。
分かりやすコードを書くために、これだけ守っててば普通にOK。
フロントやサーバ全てで対象です。
自分が今まで見た現場のコードで読むのが辛かったものリストでもある。
チェックリスト
特に重要
以下の二つが守れていれば、自然と「読みやすく、テストが書きやすく、移行もしやすく」なる。
・関数には、1個の役割だけ持たせる。
複数箇所から呼び出すと、内部でifとか付けたくなるけど、付けずに我慢する。
複数の関数に分けないと、どんどん関数が肥大化してしまう。
以下の例のように、「呼び出し元で分岐させる」と「最低限の役割」で処理を実行できる。
・複数の役割を持ってる場合
// Adminだったら、「adminName」、違ったら「userName」を返す
func GetUser(isAdmin bool) string {
if isAdmin {
return "adminName"
}
return "userName"
}
// 呼び出し元
func GetUserDetail() string {
isAdmin := getIsAdmin()
return GetUser(isAdmin)
}
・役割で関数を分割した場合
// Adminの情報を返す
func GetAdmin() string {
return "adminName"
}
// Userの情報を返す
func GetUser() string {
return "userName"
}
//呼び出し元
func GetUserDetail() string {
isAdmin := getIsAdmin()
if isAdmin {
return GetAdmin()
}
return GetUser()
}
上のように「呼び出し元」で、処理を分岐させることによって、最低限にできる。
・変数には、1個の役割だけ持たせる。
気付いたら複数の役割を持っていることがある。
変数の影響範囲を小さくして、なるべく外部から呼び出せないようにする。
かなり重要
・1つのクラスに関数が増えすぎたら、「private変数/関数の効果」が薄れるので、中の役割を見てクラスを分割する。
だいたい「役割が複数存在する」ので分けれる。
・複雑なロジックは関数に分ける。
複数箇所から呼び出されなくても分ける。
・フォルダでは処理の役割を、わかりやすい単位で分ける。
例:データ取得、変換、整形、保存、出力
・staticは基本的に使わない。
使う場合は、一個のフォルダに全てまとめておく。
めっちゃ重要
・使ってない処理は全て消す。その後使う可能性あっても徹底的に消す。
・継承は滅多に使わないはずなのに、気軽に使えてしまうので封印。
・例外出さずに、エラーは引数で返す。(これは言語によるが、できれば)
・public, privateは必ずつける。
・DBを扱う処理は、全てフォルダにまとめて外部に出さないでおく。
次に重要
・グローバル変数っぽいものは、複数の役割を持ちやすくなってしまうので、なるべく一番上の階層から、下に受け渡していく。
・なるべくnullは使わない。
(何もないという曖昧な役割を持っているため。)
・変数名は簡単な英単語にする。
・「bool型の変数や関数」は「is,isNot,can,has,〜Exist」などを使う。
・インターフェースは、無理やり使わなくてもおk。
・コメントは、「何のために、何をしている」まで書く。
「コメントと処理」で「情報量が同じ」ならコメント書かない。
これが守れてれば、普通に読みやすいコードになる。
普通に重要
・「複雑なロジック」や「エラーしたら会社が倒産する処理」は、関数にして、テストを書く。
・interfaceで依存性の逆転は、めっちゃ関数が増えたり状態が変わるものにつける。
(不変なものには付けなくてもおk)
・テストする時のモックは、「テストが通るモック」を書かないようにする。
なぜ必要
自分のためではなく、新しく参加する人のために必要です。
自分で書く分には、全体の構成を覚えているのできれいに書かなくてでも問題ないと自分は思います。
きれいに役割で分割されていると、新しく入ってきた人への説明が不要になったりその人の無駄な時間を削減できます。
ただ、きれいに役割で分割されているとテストは書きやすいです。
こだわりすぎなくてもおk
最初から無理に分割しなくても、書いてみてからわかることがあるので、一段落してから綺麗にする。
使われないと意味がないので、初期は開発速度の方が、圧倒的に大事。
読みやすさに関しては、新しい人が参加する前に直ってればおk。でも新しい人はだいたい突然入ってくるので、やっぱたまにリファクタ大事。
まとめ
後から誰でも参加できるように、手直し大事。