コードの可読性と数式

# はじめに
「読みにくいコードを書いてやろう」という人はいないと思います。
誰もが、読みやすいコードを書こうとしている事でしょう。

ところで、読みやすいコードとは何でしょうか。
どういうコードが読みやすいか自分なりに考えてみました。

>If you can't explain it to a six-year-old, you don't understand it yourself.
6歳の子どもに説明できなければ、理解したとは言えない。

とアインシュタインも言っている通り、6歳は極端ですがプログラムを少しかじった程度の人でも理解できるようなコードが読みやすいコードだと考えています。

# コードと数式
「コード」と「数式」には似たところがあります。
ということで、「読みやすいコード」を「読みやすい数式」に置き換えて考えてみます。

### 問１：どちらの計算式が見やすいですか。
```math
\begin{flalign}
(1)\quad102 \times 98 &= (100 + 2) \times (100 - 2) = 100^2 - 2^2 = 10000 - 4 = 9996 &\\
\end{flalign}
```
```math
\begin{flalign}
(2)\quad102 \times 98 &= (100 + 2) \times (100 - 2) &\\
&= 100^2 - 2^2 \\
&= 10000 - 4 \\
&= 9996 \\
\end{flalign}
```

計算は縦に繋ぐと見やすいです。
コードに例えると…
```C#
// (1) 横に繋ぐ
if (!string.IsNullOrEmpty(code) && !string.IsNullOrEmpty(sei) && !string.IsNullOrEmpty(mei) && !string.IsNullOrEmpty(seiKana) && !string.IsNullOrEmpty(meiKana))
{
    SaveData(code, sei, mei, seiKana, meiKana)
}

// (2) 縦に繋ぐ
if (!string.IsNullOrEmpty(code)
 && !string.IsNullOrEmpty(sei)
 && !string.IsNullOrEmpty(mei)
 && !string.IsNullOrEmpty(seiKana)
 && !string.IsNullOrEmpty(meiKana))
{
    SaveData(code, sei, mei, seiKana, meiKana)
}
```
のようになります。
縦に長くなりすぎても読みにくくなるので、その辺りはいい感じに書きましょう。
ただ、横スクロールが発生するほどの幅は「読みにくい」と思います。

### 問２：どちらの計算式が分かりやすいですか。
```math
\begin{flalign}
(1)\quad\int_{0}^{2} 5x(x - 1)^4 dx &= \int_{0}^{2} 5x(x^2 - 2x + 1)^2 dx &\\
&= \int_{0}^{2} 5x(x^4 - 4x^3 + 6x^2 - 4x + 1) dx \\
&= \int_{0}^{2} (5x^5 - 20x^4 + 30x^3 - 20x^2 + 5x) dx \\
&= \Big[\frac{5}{6}x^6 - 4x^5 + \frac{15}{2}x^4 - \frac{20}{3}x^3 + \frac{5}{2}x^2 \Big]_{0}^{2} \\
&= \frac{160}{3} - 128 + 120 - \frac{160}{3} + 10 \\
&= 2 \\
\end{flalign}
```
```math
\begin{flalign}
(2)\quad\int_{0}^{2} 5x(x - 1)^4 dx &= \int_{-1}^{1} 5(t + 1)t^4 dt \qquad \big(x - 1 = t \quad \therefore dx = dt \big) &\\
&= \int_{-1}^{1} (5t^5 + 5t^4) dt \\
&= \int_{0}^{1} (10t^4) dt \\
&= \Big[2t^5 \Big]_{0}^{1} \\
&= 2 \\
\end{flalign}
```

置き換えて計算しよう
コードに例えると…
```javascript
// (1) nowのみで設定する
const now = new Date();

document.querySelector('.sec').style.animationDelay = - now.getSeconds() + 's';
document.querySelector('.min').style.animationDelay = - (now.getMinutes() * 60 + now.getSeconds()) + 's';
document.querySelector('.hour').style.animationDelay = - (now.getHours() * 3600 + now.getMinutes() * 60 + now.getSeconds()) + 's';


// (2) nowをs、m、hに置き換える
const now = new Date();
const s = now.getSeconds();
const m = now.getMinutes() * 60;
const h = now.getHours() * 3600;

document.querySelector('.sec').style.animationDelay = - s + 's';
document.querySelector('.min').style.animationDelay = - (m + s) + 's';
document.querySelector('.hour').style.animationDelay = - (h + m + s) + 's';
```
のようになります。
(2)の方がステップ数は多いですが、分かりやすくなります。

### 問３：どちらの計算式が分かりやすいですか。
```math
\begin{flalign}
(1)\quad\frac{17}{15} \div 0.85 \times \frac{7}{4} - \left( \frac{14}{15} + 1.2 \right) &= \frac{13}{5} &\\
\end{flalign}
```
```math
\begin{flalign}
(2)\quad\frac{17}{15} \div 0.85 \times \frac{7}{4} - \left( \frac{14}{15} + 1.2 \right) &= \frac{\cancel{17}}{\cancel{15}_3} \times \frac{\cancel{20}^\cancel{5}}{\cancel{17}} \times \frac{7}{\cancel{4}} - \left( \frac{14}{15} + \frac{6}{5} \right) &\\
&= \frac{7}{3} - \frac{14 + 18}{15} \\
&= \frac{35 - 14 + 18}{15} \\
&= \frac{39}{15} \\
&= \frac{13}{5} \\
\end{flalign}
```

計算は途中経過を残しておくと何をやっているか分かりやすくなります。
コードに例えると…

```C#
int sales = 10000;             //売上高
int costOfSales = 5000;        //売上原価
int managementFee = 1000;      //管理費
int nonOperatingIncome = 300;  //営業外収益
int nonOperatingExpenses = 50; //営業外費用
int specialProfit = 550;       //特別利益
int extraordinaryLoss = 400;   //特別損失
int tax = 1600;                //税金
int netProfit;                 //純利益
//⇒純利益を計算する

// (1)1回で計算する
//純利益 = 売上高 - 売上原価 - 管理費 + 営業外収益 - 営業外費用 + 特別利益 - 特別損失 - 税金
netProfit = sales - costOfSales
          - managementFee
          + nonOperatingIncome - nonOperatingExpenses
          + specialProfit - extraordinaryLoss
          - tax

// (2)途中経過を残す
//売上総利益 = 売上高 - 売上原価
int grossProfit = sales - costOfSales;
//営業利益 = 売上総利益 - 管理費
int operatingProfit = grossProfit - managementFee;
//経常利益 = 営業利益 + (営業外収益 - 営業外費用)
int ordinaryProfit = operatingProfit + (nonOperatingIncome - nonOperatingExpenses);
//税引前利益 = 経常利益 + (特別利益 - 特別損失)
int profitBeforeTax = ordinaryProfit + (specialProfit - extraordinaryLoss);
//純利益 = 税引前利益 - 税金
netProfit = profitBeforeTax - tax;
```
のようになります。
途中経過を書くことで、間違いを見つけやすくもなりますし、保守性、拡張性も高まります。

因みに上記の計算には誤りがあり正解は「$\frac{1}{5}$」です。


# おわりに
「読みやすいコードとは」という問題は簡単に答えが出るものではありません。
これからも試行錯誤しながら少しでも良いコードが書けるよう精進いたします。