良いコードを書く技術 -読みやすく保守しやすいプログラミング作法 という書籍呼んだので読了後のメモを残します。
浅く広く良いコードとは何かをざっくり理解したいプログラミング初心者の方にはおすすめの本です。
サンプルコードもあり、この本で良いコードの概要はつかめるかと思います。
良いコードとは
■本書で定義されている良いコードとは
-
保守性が高い
- コードは作り手が想像しているよりも長く使われる。他人が後からみてもわかりやすいコードであるべき
-
すばやく効率的に動作する
- 良いコードは適切なパフォーマンスで動作する
-
正確に動作する
- 確実に動作し、信頼性が高い、バグが起きない
-
無駄な部分がない
- 無駄が無いコードは理解しやすく、修正する手間がかからない
名前付け
適切な名前付け(メソッド名、クラス名、変数名など)を行うことで、コードの保守性があがります。
名前付けが適切であればあるほど、理解しやすいコードとなり、無駄なコメントを残す必要がなくなります。
■説明的で意図・意味を表した名前付けをする
///消費税をカンマ区切りに変換
String s = fmt(value);
///整形済み消費税出力
out.println(s);
変数名s、valueとメソッド名fmtが短すぎてわかりずらい
以下のようにするべき
String formattedConsumptionTax =
insertGroupingSeparators(consumptionTax);
out.println(formattedConsumptionTax);
名前で意味を表しているのでコメントがいらなくなる。
■一貫性を保つ
コード全体を通して、一貫したポリシーで名前付けを行う
begin/end
write/read
writing/reading
right/left
open/close
スコープ
ある変数や関数が特定の名前で参照される範囲のこと。変数、メソッド、クラスなどが、プログラミング上使かえる範囲のこと。使えるとは、つまり言い換えると依存しているということです。スコープを上手く使うことで、依存する範囲を絞る事ができる。依存が大きければ大きいほど、デバック時に調査する範囲が広くなりるので、保守性に大きな影響を及ぼす。
スコープ=見える範囲=使える範囲=依存する範囲=保守性に影響を与える範囲
public boolean isClosing(Date now) {
Date open = null;
Date close = null;
...
for(Timetable table : tables){
open = getDate(table.openDateString());
close = getDate(table.closeDateString());
if(contains(now, open, close)){
...
}
}
return true;
}
上記だとスコープはメソッドの中のどこからでも参照できてしまう。
public boolean isClosing(Date now) {
...
for(Timetable table : tables){
Date open = getDate(table.openDateString());
Date close = getDate(table.closeDateString());
if(contains(now, open, close)){
...
}
}
return true;
}
これでスコープをfor文の中だけに限定できる。
つまりローカル変数の影響範囲が小さくなる。
コードの分割・集約
コードの重複箇所を分割・集約して無駄を無くすことで、読みやすくかつ修正箇所の少ないコードにすることが出来る。
以下のコードでは文字列が空かどうかの判定が二回出てくる。
public class StoreAction extends BaseAction {
public void store(Account account) {
if(account.getFirstName() == null || account.getFirstName().length()== 0) {
return;
}
if(account.getlastName() == null || account.getLastName().length() == 0) {
return;
}
}
}
該当箇所を別メソッドにすることで、まとめる事ができる。
public class Store extends BaseAction {
public void store(Account account){
if(isEmpty(account.getFirstName())){
return;
}
if(isEmpty(account.getLastNAme())) {
return;
}
}
public boolean isEmpty(String str) {
return str == null || str.length() == 0;
}
}