11
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-07-10

はじめに

「優しい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を使いサーボモータを動かす

11
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?