ホーム
ゲーム開発
Unity
UnrealEngine
C++
ゲーム数学
ゲームAI
サウンド
アニメーション
GBDK
制作日記
3DCG
Houdini
Blender
USD
グラフィックス
テクノロジ
生成AI関連
動画制作
ツール開発
フロントエンド関連
サーバサイド関連
ソフトウェア設計
ハードウェア関連
おすすめ技術書
音楽
DTM
楽器・機材
ピアノ
その他
ブログについて
都会のエレキベア
ラーメン日記
四コマ漫画
おすすめアイテム
おもしろコラム
お問い合わせ
  • ゲーム開発
    • Unity
    • UnrealEngine
    • C++
    • ゲーム数学
    • ゲームAI
    • サウンド
    • アニメーション
    • GBDK
    • 制作日記
  • 3DCG
    • Houdini
    • Blender
    • USD
    • グラフィックス
  • テクノロジ
    • 生成AI関連
    • 動画制作
    • ツール開発
    • フロントエンド関連
    • サーバサイド関連
    • ソフトウェア設計
    • ハードウェア関連
    • おすすめ技術書
  • 音楽
    • DTM
    • 楽器・機材
    • ピアノ
  • その他
JP|EN
  1. ホーム
  2. 20210220_01

【書籍紹介】「リーダブルコード」を読んで「いいコード」を書こう!【リファクタリング】

ソフトウェア設計おすすめ技術書
2021-02-21

マイケル
マイケル
どうもこんにちは!
マイケルです!
エレキベア
エレキベア
こんにちクマ〜〜〜
マイケル
マイケル
今日は書籍の紹介をするぜ!
その名も・・・


リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック

マイケル
マイケル
リーダブルコードです!!!
エレキベア
エレキベア
なにそれクマ

リーダブルコードとは

マイケル
マイケル
言わずと知れた名著で、いいコードを書くためのテクニックが記載された書籍なんだ!
具体的にはこのようなことが載っているよ!


・読みやすいコードの記述について
 → 変数、メソッドの命名ルール
 → コメントルール

・読みやすいロジックの記述について
 → 条件式の記述、分割
 → 変数の削減、スコープの調整

・コードの再構成の方法について
 → 汎用コードの分離
 → 1関数に1つのタスク
 → コードで思いを伝える方法

マイケル
マイケル
この本が絶賛されているのは、やはり全プログラマーが必ず通るであろう
コーディング作法、「可読性・美しさ」について書かれているからだね!

美しいコードを見ると感動する。

優れたコードは見た瞬間に何をしているかが伝わってくる。

そういうコードは使うのが楽しいし、自分のコードもそうあるべきだと思わせてくれる。

リーダブルコード / はじめに

マイケル
マイケル
書籍内ではいいコードは「可読性が高く、理解しやすいコード」と書かれています!

確かに自分でいいコードを書いたと思っても、理解しやすいコードじゃないと周りからは「いいコード」と思われないし、不必要な時間を使ったりバグを生んだりしてしまうよね!

エレキベア
エレキベア
可読性がいいコード(リーダブルコード)がいいコード
ということクマね
マイケル
マイケル
いいプログラマーはやっぱり綺麗なコードを書くよね!
エンジニアはどうしても技術方面への興味に偏ってしまいがちだけど、可読性や保守性を考えてこそプロのプログラマーだと思う!

読むべき人

マイケル
マイケル
そんな本書を読むべき対象は「初心者」「ベテラン」「チーム開発者」「個人開発者」全てのプログラマーだと思っています!
エレキベア
エレキベア
初心者やチーム開発してる人はわかるクマが、ベテランや個人開発者も読むべきなのクマね
マイケル
マイケル
ある程度の経験者は無意識に身についている内容が多いけど、改めて自分のコードを見直すきっかけにもなるし、個人開発者は「自分で書いたコードをしばらくたってから見た時に理解しやすい」といったメリットがあるよ!
エレキベア
エレキベア
なるほどクマ・・・。
個人だから関係ないわけじゃないクマね
マイケル
マイケル
バイブル的にも使えるし、一つ持っておいて損はないと思います!!

リファクタリングしてみる

マイケル
マイケル
少し内容について紹介するよ!
全ては紹介しきれないけど、本の内容に沿って具体例を混えながらリファクタリングを行ってみます!
エレキベア
エレキベア
楽しみクマ〜〜〜

コードの見た目の修正

マイケル
マイケル
まずはコードの見た目の改善から!
例えば次のコードは何してるか分かるかな?
function checkKeima(c_p, m_p) {
    // 移動後の位置チェック
    if ((m_p.x != c_p.x + 1 
        && m_p.y != c_p.y - 2)
        || (m_p.x != c_p.x - 1 
            && m_p.y != c_p.y - 2)) {
            return false;
    }
    return true;
}
エレキベア
エレキベア
位置をチェックしているのはなんとなく伝わるクマ・・・
でもKeimaって何クマ??
マイケル
マイケル
これは将棋の「桂馬」の移動量をチェックしている処理なんだ!
ぱっと見で何の処理をしているか分からないよね・・・。
マイケル
マイケル
なのでまずは、変数・メソッド名を修正して、コメントを付与しましょう!


・変数名の修正
 →変数から意味が読み取れるよう、「c_p」「m_p」から「current_position」「move_position」に修正。

・メソッド名の修正
 →メソッド名から処理内容が分かるよう、「checkKeima」から「checkMoveKeimaPosition」に修正。

・コメントの付与
 →メソッドコメント及び処理内容のコメントを追加。

マイケル
マイケル
上記を反映したコードが以下になります。
/**
 * 桂馬の移動後位置チェック
 * @param {Position} current_position 現在の位置
 * @param {Position} move_position    移動後の位置
 * @return {Boolean} 移動後位置が正しい:True 移動後位置が正しくない:False
 */
function checkMoveKeimaPosition(current_position, move_position) {
    // 移動後の位置が下記の場合、エラー
    // ① X方向に 1、Y方向に-2移動していない かつ
    // ② X方向に-1、Y方向に-2移動していない
    if ((move_position.x != current_position.x + 1 
        && move_position.y != current_position.y - 2)
        && (move_position.x != current_position.x - 1 
            && move_position.y != current_position.y - 2)) {
            return false;
    }
    // 上記以外の場合、正常
    return true;
}
↑コードの見た目修正後
エレキベア
エレキベア
だいぶ分かりやすくなったクマ〜〜〜〜
マイケル
マイケル
名前やコメントだけでも印象がかなり変わってくるね!

ロジックの修正

マイケル
マイケル
次に気になるのは判定文のところだね・・・。
条件に「否定(!)」を使っているため、何のチェックかが分かりにくくなっています。
マイケル
マイケル
条件文は極力肯定にした方が分かりやすいです!
ド・モルガンの法則を使って修正しましょう!
ド・モルガンの法則とは
  • !(A || B) = !A && !B
  • !(A && B) = !A || !B
  • で成り立つ法則のことである!

エレキベア
エレキベア
かつ と または は言い換えることができるクマね
マイケル
マイケル
今回の場合は Aでない かつ Bでない場合エラー という条件だから、
AまたはBでない場合エラー と言い換えることができるね!
そして、条件を肯定にするために、AまたはBの場合正常 という処理にしてみましょう!
/**
 * 桂馬の移動後位置チェック
 * @param {Position} current_position 現在の位置
 * @param {Position} move_position    移動後の位置
 * @return {Boolean} 移動後位置が正しい:True 移動後位置が正しくない:False
 */
function checkMoveKeimaPosition(current_position, move_position) {
    // 移動後の位置が下記の場合、正常
    // ① X方向に 1、Y方向に-2移動 または
    // ② X方向に-1、Y方向に-2移動
    if ((move_position.x == current_position.x + 1 
        && move_position.y == current_position.y - 2)
        || (move_position.x == current_position.x - 1 
            && move_position.y == current_position.y - 2)) {
            return true;
    }
    // 上記以外の場合、エラー
    return false;
}
↑if条件修正後
エレキベア
エレキベア
さっきよりも分かりやすくなったクマ〜〜
マイケル
マイケル
そしてもう一つ、if文の中の条件が多いため2つに分割してみましょう!
/**
 * 桂馬の移動後位置チェック
 * @param {Position} current_position 現在の位置
 * @param {Position} move_position    移動後の位置
 * @return {Boolean} 移動後位置が正しい:True 移動後位置が正しくない:False
 */
function checkMoveKeimaPosition(current_position, move_position) {
    // 移動後の位置が下記の場合、正常
    // ① X方向に 1、Y方向に-2移動
    if (move_position.x == current_position.x + 1 
        && move_position.y == current_position.y - 2) {
            return true;
    }
    // ② X方向に-1、Y方向に-2移動
    if (move_position.x == current_position.x - 1 
        && move_position.y == current_position.y - 2) {
            return true;
    }
    // 上記以外の場合、エラー
    return false;
}
↑if条件分割後
エレキベア
エレキベア
これならぱっと見でもある程度分かりそうクマね
マイケル
マイケル
可読性はロジックによっても変わってくるんだね・・・。

コードの再構成

マイケル
マイケル
そして最後はコードの再構成!
汎用的な処理を抜き出して分割してみましょう!
マイケル
マイケル
今回記述したコードは、似たような位置チェックが2つ並んでいるね。
この「移動処理後の位置チェック」処理を汎用コードとして抜き出してみましょう!
/**
 * 桂馬の移動後位置チェック
 * @param {Position} current_position 現在の位置
 * @param {Position} move_position    移動後の位置
 * @return {Boolean} 移動後位置が正しい:True 移動後位置が正しくない:False
 */
function checkMoveKeimaPosition(current_position, move_position) {
    // 移動可能な移動量[X, Y]リスト
    let chk_position_list = [[1, -2], [-1, -2]];
    // 移動後位置チェック
    return checkMovePosition(current_position, move_position, chk_position_list);
}

/**
 * コマ共通の移動後位置チェック
 * @param {Position} current_position 現在の位置
 * @param {Position} move_position    移動後の位置
 * @param {Array.<Array.<Integer>>} can_move_list 移動可能な移動量[X, Y]リスト
 * @return {Boolean} 移動後位置が正しい:True 移動後位置が正しくない:False
 */
function checkMovePosition(current_position, move_position, can_move_list) {
    // 移動後位置が移動可能な位置に含まれるかチェックする
    for (let i = 0; i < can_move_list.length; i++) {
        // 移動後の位置 = 現在の位置 + 移動可能量 である場合、正常
        if (move_position.x == current_position.x + can_move_list[i][0]
            && move_position.y == current_position.y + can_move_list[i][1]) {
                return true;
        }
    }
    // 上記以外の場合、エラー
    return false;
}
↑汎用コード分割後
マイケル
マイケル
コードは少し長くなったけど、これで「移動後の位置チェックをする」という小さなタスクに分解することができました!
エレキベア
エレキベア
これなら他のコマが追加された時も共通で使えそうクマね
マイケル
マイケル
共通化できるのは大きいね!
例えば「歩」「銀」のチェックは下記のようになるよ!
/**
 * 歩の移動後位置チェック
 * @param {Position} current_position 現在の位置
 * @param {Position} move_position    移動後の位置
 * @return {Boolean} 移動後位置が正しい:True 移動後位置が正しくない:False
 */
function checkMoveFuPosition(current_position, move_position) {
    // 移動可能な移動量[X, Y]リスト
    let chk_position_list = [[0, -1]];
    // 移動後位置チェック
    return checkMovePosition(current_position, move_position, chk_position_list);
}

/**
 * 銀の移動後位置チェック
 * @param {Position} current_position 現在の位置
 * @param {Position} move_position    移動後の位置
 * @return {Boolean} 移動後位置が正しい:True 移動後位置が正しくない:False
 */
function checkMoveGinPosition(current_position, move_position) {
    // 移動可能な移動量[X, Y]リスト
    let chk_position_list = [[-1, -1], [0, -1], [1, -1], [-1, 1], [1, 1]];
    // 移動後位置チェック
    return checkMovePosition(current_position, move_position, chk_position_list);
}
↑桂馬以外のチェック処理追加
エレキベア
エレキベア
簡潔にかけるし処理としても分かりやすいクマ〜〜
マイケル
マイケル
最初のコードと比べたらだいぶ進化したね・・・。

おわりに

マイケル
マイケル
というわけで今回はリーダブルコードの紹介とリファクタリング例でした!
どうだったかな?
エレキベア
エレキベア
少し意識を変えるだけでコードが見違えるようになって感動したクマ〜〜〜〜
マイケル
マイケル
俺の周りの人で「コードは芸術だ」と言ってる人がいたけど、俺は「デザイン」に近いものだと思う!
マイケル
マイケル
芸術は「自己表現で分かる人には分かるもの」でセンスが必要だけど、デザインは「人に伝わりやすく設計するもの」でセンス云々よりも覚えるもの・・・。
エレキベア
エレキベア
何か深いクマ・・・。
マイケル
マイケル
つまりはいいコードは覚えることで書くことができるということだね!
いいコードを書けるよう、共に切磋琢磨していきましょう!!
エレキベア
エレキベア
いい話クマ〜〜!!
マイケル
マイケル
それでは今日はこの辺で!
アデュー!!
エレキベア
エレキベア
クマ〜〜〜〜〜

【書籍紹介】「リーダブルコード」を読んでいいコードを書こう!【リファクタリング】 〜完〜


ソフトウェア設計おすすめ技術書
2021-02-21
記事をSNSで共有する
X
Facebook
LINE
はてなブックマーク
Pocket
LinkedIn
Reddit

著者の各種アカウント
フォローいただけると大変励みになります!

関連記事
【書籍紹介】「コンピュータグラフィックス」に出てくる用語をまとめる【CGエンジニア検定】
2024-07-13
【書籍紹介】「ゲーム制作者になるための3Dグラフィックス技術」に出てくる用語を簡潔にまとめる
2022-12-15
【書籍紹介】「達人プログラマー 第2版」の内容をカテゴリ分けして感想をまとめる
2022-10-29
【Unity】DIコンテナの概要とVContainerの使い方について
2022-09-14
【Unity】ServiceLocatorを使ってサービスクラスをまとめる
2022-02-27
【ソフトウェア開発】基本のデザインパターン36種類を簡単に整理する【GoF + Game Programming Patterns】
2022-02-19
【ソフトウェア開発】設計の目的とSOLID原則についてまとめる【クリーンアーキテクチャ】
2022-01-29