理解にかかる時間を最小化する、俺的コーディングルール

SE業務中で、こんな風に書いたら読みやすい！と発見したことをまとめていきます。

あくまで一個人の意見ですので、良いと思ったらご自身のポリシーに採用してみてください。

リーダブルコードが未読だったら、こんな記事読んでないで、まずそっちを買いましょう笑
https://job-draft.jp/articles/434

# １．条件分岐

## 1.1　if
###左辺に変数（値が変わる）、右辺に定数（値が変わらない）

~~~java
int score = 80;
// 獲得点数が60点以上だったら、合格 → 直感的に理解できる
if (score >= 60) {
    System.out.println("合格");
}

// 60以上の点数を獲得したら、合格 　→ 同じ意味だが、やや直感的でない
if (60 <= score){
    System.out.println("合格");
}
~~~
参考：[「リーダブルコード」を読む (第7章「制御フローを読みやすくする」](https://msyksphinz.hatenablog.com/entry/2017/11/22/020000)



マジックナンバーや文字リテラルで、明らかに定数だとミスは起こりにくいが、
両方とも変数名だとうっかり左右を間違えるので気をつける。


~~~java
int[] array = { 1, 2, 3, 4, 5 };
int search = 3;
for (int val : array) {
    // 好みでない書き方（左辺に固定値）
    if( search == val ){  // 右辺に固定値が来る方(val == search)が理解しやすい
        break;
    }
}
~~~
定数を左辺に書くの（ヨーダ記法）は、NullPointerExceptionを回避する意味もあるので、
メリット・デメリットを考慮するのが大事。
参考：[【Java】Stringのequalsで定数を左側にする理由](https://loglog.xyz/programming/javaconstleft)


###複雑になるようなら、説明変数を用意する

~~~java
// ありがちな書き方
if( !("認証アクション".equals(action)
        && ("ログイン画面を開く".equals(command)
                || "ログインを実行中".equals(command)))) {  // 最後の4重閉じかっこなんて、誰が読みたいの
    hogehoge();
}


// 説明変数を用意するとロジックを理解しやすくなる。()の数も減る。
boolean loginAction  = action .equals("認証アクション");
boolean loginCommand = command.equals("ログイン画面を開く")
                    || command.equals("ログインを実行中");   // ヨーダ記法も解消。ただし、ぬるぽ考慮は必要。
// ログインに関するページ以外を表示しようとした場合
if ( !( loginAction && loginCommand ) ) {
    hogehoge();
}
~~~
参考：[リーダブルコードまとめ(８章巨大な式を分割する)](https://qiita.com/fkrw/items/7646563a2b238fbcff9a#８章巨大な式を分割する)


## 1.2　switch文
~~~java
// よくある記法1（インデントを2段にする）
switch (intVal) {
    case 1:
        // ifで書いたときと比べて、インデントが1段余計に深くなってしまう
        foo();
        break;
    default:
        break; 
}

// よくある記法2（case, default節の始まりでインデントしない）
switch (intVal) {
// case, default節が、なんとなく詰まって見える
case 1:
    foo();
    break;
default:
    break;
}
~~~

参考：[Qiita - 皆さん、なんでswitch文のcaseをインデントするんですか？](https://qiita.com/hirohero/items/fe68e4e2f88731cf6e51)

オススメしたい記法

~~~java
switch (intVal) {
  case 1:  // case, default節のときだけはスペース2つでインデントするのはどうだろう
    foo();
    break;
  default:
    break;
}
~~~

###### 余談
switch禁止！という過激な意見もありますが、自分はむしろ使えるときは積極的に使います。
ifでも書けるのにわざわざswitch文で書く＝ switch文が適用できるくらい簡単な分岐だから、
気負わず読んでね、というメッセージを込めています。

## 1.3　三項演算子
読みやすい方を採用する。FizzBuzz問題、どちらが見やすい？

~~~java
for(int i = 1; i <= 100; i++){
    String str = "";
    if(i % 3 == 0){
        str += "Fizz";
    }
    if(i % 5 == 0){
        str += "Buzz";
    }
    if(str.equals("")){
        str = i.toString();
    }
    System.out.println(str);
}
~~~

自分はこれくらい単純なプログラムなら、三項演算子使う派です。
でも可読性でいうとif使った方がいいかも。

~~~java
for(int i = 1; i <= 100; i++){
    // 表示する文字列を組み立てる
    // 3の倍数ならFizz、5の倍数ならBuzz、15の倍数ならFizzBuzz
    String str = (i % 3 == 0 ? "Fizz": "")
               + (i % 5 == 0 ? "Buzz": "");

    // それ以外の数字はそのまま表示
    System.out.println(str.equals("") ? i : str);
}
~~~

参考：[「リーダブルコード」を読む (第7章「制御フローを読みやすくする」7.3 参考演算子](https://msyksphinz.hatenablog.com/entry/2017/11/22/020000)


# ２．垂直インデント
終わらないテーマですが、自分はする派です。
https://softantenna.com/wp/software/vertically-align-my-code/

~~~java
// 「=」の位置で揃えない
int robert_age = 32; // ロバート
int anna_age = 25; // アンナ
// 「=」と//」の位置で縦を揃える
int robert_age = 32; // ロバート
int anna_age   = 25; // アンナ
// だって長い名前の変数が増えたら修正が大変じゃん（ ← わかる）
int Aristoteles_age = 62; // アリストテレス
~~~

プロトタイプで作成中のプログラムにまで適用するのはコストが割高という気もします。笑


垂直インデント読みやすくてええやん！派の同志は、
手前味噌で恐縮ですが、拙作のサポートツールの利用も検討ください。
（この宣伝のためにQiita書いてるまである笑）
http://www.vector.co.jp/soft/winnt/prog/se523105.html


## 2.1　SQL

~~~SQL
-- 予約語は大文字かつ右揃え
--    ↓ ここに必ず半角スペースが来る。右辺（予約語）と左辺（値）の区切りをわかりやすくする。
SELECT Id
     , Name             -- SELECT項目の改行についてはどちらでも。読みやすければOK。
     , CorporateStatus
     --, Country          -- コメントアウトもやりやすい
  FROM Account
 WHERE Name = 'AAA株式会社'
   AND (    CorporateStatus = '法人'
         OR Country         = '日本'
       ) -- WHERE句にかっこが必要なときの記述は難しいが、自分はこんな感じで書いてる
 ORDER BY Id
 --GROUP BY Id
 LIMIT 1
; --セミコロンだけの行で、SQLの終わりを分かりやすくしたい。
~~~
ここまで厳密にインデントする必要がないシンプルなSQLもありますし、そのときは多少崩して書いてもOKかと思います。

よくある記法

~~~SQL
SELECT  -- 否定はしませんが、SELET, FROMに2行も使う必要ある？って思います。
    *
FROM 
    tab1
WHERE
    col1='01'         --ここの条件の開始位置が揃っていないのも気になる
    AND col2 ='AAAAA'
    AND col3 =10000;
~~~

副問合せやCASE句などもありますが、経験が少ないので割愛させてください。てへぺろ



## 2.2　カンマの位置
~~~apex
Account acc = new Account(
      Name            = 'AAA株式会社'
    , CorporateStatus = '法人'
    //, Country         = '日本' // 区切り文字が文頭にあると、コメントアウトもやりやすい
);
~~~

よくある記法

~~~apex
Account acc = new Account(
    Name            = 'AAA株式会社',
    CorporateStatus = '法人'//, ← ここもコメントアウトしないとなのがイヤ
    //Country       = '日本'
);
~~~

参考：[SQLプログラミング作法　5．カンマ（ , ）](http://mickindex.sakura.ne.jp/database/db_manner.html#LocalLink-comma) 

<br>

_以上です。Happy Coding！_