先輩,読みやすいコードってなんスカ.
あなたと共同開発をしている友人の佐藤くんは「 a, b, i, n, temp, val 」 など,変数や関数にこういった命名をしてしまう...つい2週間前に自分で書いたコードを自分で読めないことがあるみたいです(!).
佐藤くんこれを反省していて,当面の目標はソースコードの美しさを追求することだそうです.
「読みやすいコードを書きたい」,と.ところで読みやすいコードってなんなんすかね.
そもそも,なぜ読みやすいコードがいる?
佐藤君が趣味や学生時代に研究で書いたプログラムと,エンジニアとして書くコードは根本的に違います.研究で書いたコードは,なんとか動けばいいし,不具合で困るのは自分だけですし,コードの寿命もせいぜい数年です.一方エンジニアは商品開発という目的のためにソースコードを書きます.取り巻く環境,使用言語,寿命,利用者に大きな違いがあるようです.
エンジニアのコードに求められるのは「読みやすいコード」です.この読みやすいコードとはなんでしょうか.
・誰が読んでも意図が明確
・直感的に理解ができる
・保守性や拡張性に優れる
誰がコードを利用するのか,いつまでコードが利用されるのか,エンジニア自身にはコントロールすることができません.コンパクトなコードと読みやすいコードは異なります.理解しやすいように,と追求した結果コンパクトなコードになります.
本題:名は体を表す?
さて,次のコード,どっちが読みやすいでしょうか.
for(i=0;i<max;i++){
if(toshi=="tokyo"){
cnt++;
}
}
for (index = 0; index < numCity; index++) {
if(cityName = "tokyo") {
countTokyo++;
}
}
temp,cntなどの略語はなるべく避けるべきです.temporary(一時的な)の略なのか,temperature(温度)の略なのかわかりません.count(カウント)なのかcountry(国)なのか,どっちの略なんでしょうか.日本語をローマ字で書くのも避けるべきじゃないでしょうか.例えばtoshi.都市(city)でしょうか.年(year)でしょうか.それとも歳(age)でしょうか.a, b, n, m, x, y, temp, ret, calcなどの略語は混乱を招くため,避けましょう.
色々な単語を探して使ってみましょう.
・stop → 停止はわかるが,再開するのかな?
・pause → 一時的に停止して,再開しそう!
・kill → 完全停止して,再開はなさそう!
・create → 何か作るっぽい
・generate → 自動で作ってそう!
変数は名詞を意識しましょう.
pauseCalc とか,maxVal とか,studentNum とか.
関数名は動きを意識しましょう.
get_page_number とか, calc_atom_dimension とか.
ちなみに,forやwhileのループで使う「 i 」 とか 「 k 」 とか.このようなループインテレータや一時的なバッファなどに限り許されることが多いみたいです.
命名に規則を.
変数や関数の命名にはルールがあることが多いです.大きく4種類あるみたいです.
スネークケース
snake_caes アンダーバーで繋げます.
キャメルケース
camelCase 後ろの単語を大文字にします.
パスカルケース
PascalCase. 前の単語,後ろの単語を大文字にします.
ハンガリアン
gwData
わたしは変数にはキャメルケース,関数名にはスネークケースを使います.グローバル変数であることを明示したいため,ハンガリアンの要素も軽く取り入れます.
float gAtomNum //gでグローバルを明確に.
void calclation_atom_position(int atomId, atomVelocity) {
int atomPosition = atomId * atomVelocity;
}
どうして atomNum にしたの?どうして atomval にしたの?と,問われても答えられるように頑張りましょう!
ロジックは明快に‼️
DRY原則,というものがあります.Don’t Repeat Yourself , 繰り返しを避けよ.
避けるべき記述 {
・演算式が巨大;
・記述が冗長;
・多重ループ;
・いらない変数;
・メモリを管理できていない;
}
例えば a,b,c の3つの整数のうち,最大の整数はどう求めたらいいでしょうか.
う〜〜む,こんなコードを書いてみました.
if (a > b) {
if (a > c) {
max = a;
} else {
max = c;
}
} else {
if (b > c) {
max = b;
} else {
max = c;
}
}
う〜〜〜〜〜〜む.こんなコードも書いてみました.
max = a;
if (max < b) {
max = b;
}
if (max < c) {
max = c;
}
どちらも最大値を求めることができます.が,下の方が理解しやすく,コンパクトな気がします.
スコープも大事,ですよね
前提として,グローバルな変数や関数は使うべきではありません.
・どこでどのように参照されているか把握しづらい
・ローカル変数と衝突しても気付きにくい.
グローバル変数はどこからもアクセス,書き換えができるため自由で便利です.が,そこが危険ですね.可読性,保守性,拡張性の観点からも使うべきではありません.
関数をちゃんと作りたい!
私は以下のような関数がある場合,修正の検討をします.
・呼び出すたびに異なる挙動をする
・直接関係のない複数の仕事をする
・関数外にあるコードから影響をうけやすい
関数の粒度というキーワードがあり,1つの関数で1つの明確な目的のみ持たせるようにします.SRPC(単一責任原則),ここのモジュールが請け負う責任は一つにすべきです.目安として,ディスプレイに収まるくらいの関数の長さがイイとか...例えば,input_and_output()みたいな関数は,入力も出力も,その間にある計算もしそうです.こういう時は関数を分けてみましょう〜.
コーディングスタンダード
代表的なコーディングスタンダードを紹介します.
・CERT Cコーディングスタンダード
・MISRA – C
・IPAコーディング作法
静的コード解析ツールも紹介します.
・Coverity
・LlocWork
・C++TEST
・cppCheck
・sparce
最後に
1年,2年,3年かかってでも,少しずつ身につけていきましょう.