コーディング規則「優しいコードを書こう」

More than 1 year has passed since last update.


はじめに

「優しいIT」という理念のもとITコサルタントをしている。亀井亮介で〜す

システム開発する上で、品質・保守性の向上を考えると、コーディング規則や命名規則などの「ルール」が必要です。

「資格試験勉強すればするほど社会貢献ができるe-lerning(開発中)」で利用しているコーディング規則の例です。

ソースのプログラミング言語はPHPで、フレームワークはFuelPHPを使っています。


●コーディング規則「優しいコードを書こう」


1. テストファースト(ユニットテストを先に書く)

はじめに失敗するテストを書きます。理由は、成功するテストから書いた場合にバグに気がつかないためです。

※例は実践JUnitより


2. 1関数1機能にすると、コードが短く簡潔になり、テストがしやすくなる

皆さんも「スパゲッティ・コード」を見て、ソースを見るのが嫌になったことがありませんか?

「スパゲッティ・コード」とは、関数同士が複雑に絡み合い、お互いがお互いと依存しているようなコードです。

これを極力排除するのが「1関数1機能」です。

下記は、HTMLタグと指定したタグに囲まれた中身を削除する関数で、1機能しか実現していません。


question.php

    public static function removed_tag_and_contents($body, $tag_name) {

return
preg_replace(
'{<'.$tag_name.'>(.*)</'.$tag_name.'>}'
, ''
, $body
);
}

上記に対するテストは下記の通りです。

実際の振る舞いは

    タグを除去するために作成しました。

    そのため、
      タグが除去できるかテストをしています。



question_Test.php

    public function test_removed_tag_and_contents() {

/*
* beforequestionから値を取得
*/

$questions = Controller_Question::get_before_question(2);

/*
* 選択肢を除去
*/

$conveted_question_body
/*
* ●コーディング規則「優しいコードを書こう」
* 3. 横幅は80文字以内とし、縦の線をまっすぐにする意識をすると、ソースの可読性が向上する
*/

= Controller_Question::removed_tag_and_contents(
$questions['question_body']
, 'ul'
);
/*
* 選択肢が除去されていれば、除去前と比較して異なる
*/

$this->assertNotEquals(
$conveted_question_body
, $questions['question_body']
);
}


このように1関数1機能にすると、疎結合となり、他の関数に依存せず、「スパゲッティ・コード」を回避できます。

故にソースの可読性が向上し、メンテナンスがしやすくなり、品質が高かくなります。


3. 横幅は80文字以内とし、縦の線をまっすぐにする意識をすると、ソースの可読性が向上する

下記のように横に長いと見にくくありませんか?


question.php

    $conveted_question_body = Controller_Question::removed_tag_and_contents($questions['question_body'], 'ul');


人間の目は、横に流れるのが苦手だそうです。縦に流れるのは得意だそうです。

確かに、スマートフォンは縦に流れる仕組みですよね?

プログラム・ソースのように謎の文章が羅列されていれば、なおのこと読みやすさが必要です。


question.php

    $conveted_question_body =

Controller_Question::removed_tag_and_contents(
$questions['question_body']
, 'ul'
);

読みやすさが向上していませんか?書く方は面倒ですが、3ヶ月後に自分で書いたプログラムを読むときに、「昔の俺は優しいな〜」と思えるはずです(笑)。


4. コメントは「意図を相手に伝えること」なので、簡潔に例となる値やToDo、欠陥を書く

コメントは必要最低限が望ましいです。全く書かないのも問題ですが、余計な情報があるのも問題です。

必要な情報とは?関数の引数にどういう値が入るか?

このような場合、ソースを追うと思うのですが、下記のように実際に入る値の例や役割があると「優しいな」と思いませんか?


question.php

    public static function get_question_keywords (

$round_id /* = 14 平成27年度応用情報技術者試験 */
, $question_number /* = 1 問題の番号 */
)
{
// ... 略
}

そのプログラムの修正点(今は直す必要がないけど、後日直したほうがいいと思う点)を@TODOとして残したり…

「伝えたいこと」を書くを意識すれば自ずと的確なコメントになります。


5. 条件式 左側は調査対象(変化する)右側は比較対象(変化しない)

例は後日


6. if/else 肯定形を使う。単純な条件や目立つ条件を先に書く

例は後日


7. 基本はifとforeach/forを使い、case, whileやwhile doは原則使わない

経験の浅いプログラマでもプログラムが読めるように、記述を統一します。

利便性は犠牲になりますが、分岐はif文のみ、ループはforかforeachに統一します。

Webアプリケーションの開発であれば、十分だと考えられます。

(場面によってはcaseは便利なので悩みどころです。)


8. 早めにreturnし、関数から抜ける

関数のreturnは1つにしたくありませんか?かつて、私も「関数のreturnは1つだけ」と思っていました。

その方がソースの可読性が上がると考えていたからです。

しかし、最近のフレームワークの仕様を見ていると、関数の値は早めに返していました。

理由は簡単で、returnすべき箇所を通過した後は、「どうでもいいプログラム」です。ここでは既に終了している場合の振る舞いも考慮する必要があり、バグの温床になります。

そう考えると、可読性は少々犠牲になるかもしれませんが(思いのほかならない)、returnは早めに返すほうが品質が向上します。

下記に例を示します。


question.php

    /**

* create_choices
* 選択肢(4つ)を生成
*
* @param int $question_last_id question.id
* @return boolean
*/

private function create_choices($question_last_id) {
/*
* IPA系の試験は選択肢は4つある
*/

for($choice_num = 1; $choice_num run())
{
/*
* 問題を追加するINSERT(もしくはUPDATE)を生成
*/

$choice = Model_Choice::forge(array(
'question_id' => $question_last_id, // 問題番号(固定)
'choice_num' => $choice_num, // 選択肢番号
'correct_flag' => $correct_flag, // 正解
'choice_body' => Input::post('choice_body_'.$choice_num), // 選択肢
));

if (!($choice and $choice->save()))
{
Session::set_flash('error', '選択肢を追加できませんでした。');
/*
* ●コーディング規則「優しいコードを書こう」
* 8. 早めにreturnし、関数から抜ける
*/

return false;
}
} else
{
Session::set_flash('error', $choice_validation->error());
/*
* ●コーディング規則「優しいコードを書こう」
* 8. 早めにreturnし、関数から抜ける
*/

return false;
}
}
return true;
}



おすすめ本

リーダブルコード

レガシーコード改善ガイド


サイトマップ(未投稿あり)


理念・価値・ビジョン・使命


テスト駆動開発を重点においた規則

コーディング規則「優しいコードを書こう」(FuelPHP)

命名規則「3ヶ月後の自分自身に優しく、チームに優しく、まだ見ぬメンバーに優しく」


Docker+PythonでWebアプリケーション開発

Docker上のCentOSにPython3と、関連ライブラリpip, virtualenvとフレームワークDjango, bottle, Flaskのインストール!これらをまとめたDockerfile付き!


開発しやすい環境構築(Docker+PHP)

Dockerを利用しApacheにPHP環境 + Eclipseを連携

Dockerを利用したFuelPHP開発環境構築

Docker利用したFuelPHP開発環境の初期設定とscaffoldを利用してCRUDスケルトン作成

FuelPHPのデータベースマイグレーション


Raspberry Pi 3 (ラズパイ)とpythonで遊ぼう

Raspberry Pi 3インストール→無線LAN→日本語入出力→Macから操作

Raspberry Pi 3でプログラミングをする Node-REDと普通にプログラミング

Raspberry Pi 3でpythonを使いLEDを光らせる(Hello World)

Raspberry Pi 3でスイッチの状態を検出する

Raspberry Pi 3でpythonを使いサーボモータを動かす