【ChatGPT】6. エラー対応 > 依存性管理・エラーハンドリング・設計の原則について

# 概要
ここでは、生成AIから提示されたリファクタリング結果とエラー対応について記載する
リファクタリングを実施し、エラーが発生した場合はその内容について生成AIに質問した

- 対応内容

https://qiita.com/y-k_20337/items/5b70778372d6f891a93d

## 計算結果表示エラー対応

<details>

#### ・プロンプト
>     // 計算結果を表示する
>     calculateResult() {
>       // 数字入力時 かつ current演算子有り かつ まだ=ボタンを押していないとき
>       // 入力された数字、演算子をリセットし、currentNumberにtotalメソッドで計算結果を返す
>       if (this.isInsertNumber && this.currentOperator && !this.isResult) {
>         this.numArray.push(Number(this.currentNumber));
>         this.currentOperator = "";
>         this.lastCalculation = this.total();
>         this.numArray = [];
>         this.opeArray = [];
>         this.isResult = true;
>      }
>     },
> 
> 計算結果が保持されていないため、後の計算が正しくない

#### ・回答内容

コードを拝見したところ、`calculateResult` メソッドで計算結果を保持するためのロジックがいくつか足りていない可能性があります。以下の点を確認し、改善することで、計算結果を保持し、後の計算が正しく行えるようになるかと思います。

### 問題点
1. **`lastCalculation` の使い方**: `lastCalculation` に計算結果を保存していますが、後の計算でこの値を使用していないようです。次の計算時にこの値を利用する必要があります。

2. **`numArray` と `opeArray` のリセット**: 現在のコードでは `numArray` と `opeArray` をリセットしていますが、これが意図した動作かどうか確認する必要があります。もし前の計算結果を次の計算に持ち越したい場合、これらの配列はリセットしない方が良いでしょう。

### 改善案
計算結果を保持し、次の計算に使うためには、`numArray` と `opeArray` に保存している値を活用する必要があります。また、`lastCalculation` を使って計算結果を保持し、それを次回の計算に利用できるようにしましょう。

以下は、これらの点を改善したコードの例です：

```javascript:javascript
calculateResult() {
  // 数字入力時 かつ current演算子有り かつ まだ=ボタンを押していないとき
  if (this.isInsertNumber && this.currentOperator && !this.isResult) {
    // 現在の数字を numArray に追加
    this.numArray.push(Number(this.currentNumber));
    
    // 計算結果を取得
    this.lastCalculation = this.total();

    // 次回の計算に備えて numArray と opeArray をリセット
    // ただし、計算結果を保持するためにはリセットしない場合もある
    // this.numArray = [];
    // this.opeArray = [];
    
    // 結果を currentNumber にセット（次の計算のために表示するなど）
    this.currentNumber = this.lastCalculation.toString();
    
    // フラグを更新
    this.isResult = true;
  }
}

// total メソッドが計算結果を返すと仮定
total() {
  // 例: 計算ロジックがここに実装されていると仮定
  // 例えば、numArray と opeArray を使って計算を行い、結果を返す
  let result = 0;
  
  // 計算ロジックの例
  if (this.numArray.length > 0 && this.opeArray.length > 0) {
    result = this.numArray[0];
    for (let i = 0; i < this.opeArray.length; i++) {
      switch (this.opeArray[i]) {
        case '+':
          result += this.numArray[i + 1];
          break;
        case '-':
          result -= this.numArray[i + 1];
          break;
        case '*':
          result *= this.numArray[i + 1];
          break;
        case '/':
          result /= this.numArray[i + 1];
          break;
        // 他の演算子処理があればここに追加
      }
    }
  }
  
  return result;
}
```

### 追加の注意点
- **`numArray` と `opeArray` の使用**: `numArray` と `opeArray` をリセットせず、前回の結果を利用する場合、リセットのタイミングや方法に注意が必要です。計算結果を次回の計算に利用するために、適切に管理してください。

- **エラーハンドリング**: `total` メソッド内でエラー処理（例: ゼロ除算など）を追加すると、計算がより堅牢になります。

これらの改善により、計算結果を保持し、次の計算が正しく行えるようになるはずです。

</details>

## 小数点計算エラー対応

<details>

#### ・プロンプト
>     // 数字ボタンが押されたときの処理
>     handleNumberInput(num) {
>       try {
>         if (isNaN(num)) throw new Error("Invalid number input");
> 
>         if (this.validateNumberInput(num)) {
>           // 正負を逆にする
>           if (num === "+/-") {
>             if (!this.isInsertNumber) return;
>             this.currentNumber = -1 * this.currentNumber;
>             return;
>           }
>           // = を押した直後、一度数字をリセットして次の計算をする
>           if (this.isResult) {
>             this.currentNumber = "0";
>             this.isResult = false;
>           }
>           // 数字以外が入力された場合は演算子の配列に今の演算子をpushして数字0にし、次の数字を入力できるようにする
>           if (!this.isInsertNumber) {
>             this.opeArray.push(this.currentOperator);
>             this.currentNumber = "0";
>             this.isInsertNumber = true;
>           }
>           // 小数点は１つまでしか入力できない
>           if (num === "." && this.currentNumber.indexOf(".") > -1) {
>             return;
>           }
>           this.currentNumber += num;
>         }
>       } catch (error) {
>         console.error("An error occurred:", error);
>         alert("Invalid number input. Please enter a valid number.");
>       }
>     },
> 
> 小数点を押したときに数字と判定されてエラーになってしまう

#### ・回答内容

小数点 (`.`) を押したときにエラーが発生する問題の原因は、`isNaN(num)` を使って小数点を含む数値を検証しようとしているためです。`isNaN` は数値以外の入力を検出するのには適していますが、入力が文字列の場合（例えば `"."` など）には適していません。

`handleNumberInput` メソッドで小数点を含む数値も正しく処理できるようにするためには、以下の点を修正する必要があります。

### 修正案

1. **小数点の検証を分ける**: 小数点の検証は、数値の検証とは別に処理する必要があります。小数点が含まれている場合、その前の部分が有効な数値であるかどうかを確認し、数字入力として適切に処理します。

2. **`validateNumberInput` の役割を修正**: `validateNumberInput` メソッドは、数値として有効かどうかを検証するため、直接小数点の検証を行うべきではありません。

### 修正コード例

以下のコードでは、`handleNumberInput` メソッドの修正と、`validateNumberInput` メソッドの修正を示しています。

```javascript:javascript
// 数字入力を検証するメソッド
validateNumberInput(num) {
  // 数値として有効かどうかを検証
  // numが数値かつ NaN でないことを確認
  const parsedNum = Number(num);
  return !isNaN(parsedNum) || num === ".";  // 小数点も許可する
}

// 数字ボタンが押されたときの処理
handleNumberInput(num) {
  try {
    // 小数点を含む場合の特殊な処理を追加
    if (num === ".") {
      // 現在の数字に小数点が含まれていない場合のみ小数点を追加
      if (this.currentNumber.indexOf(".") === -1) {
        this.currentNumber += num;
      }
      return;
    }

    if (!this.validateNumberInput(num)) {
      throw new Error("Invalid number input");
    }

    // 正負を逆にする
    if (num === "+/-") {
      if (!this.isInsertNumber) return;
      this.currentNumber = (-1 * parseFloat(this.currentNumber)).toString();
      return;
    }

    // = を押した直後、一度数字をリセットして次の計算をする
    if (this.isResult) {
      this.currentNumber = "0";
      this.isResult = false;
    }

    // 数字以外が入力された場合は演算子の配列に今の演算子を push して数字0にし、次の数字を入力できるようにする
    if (!this.isInsertNumber) {
      this.opeArray.push(this.currentOperator);
      this.currentNumber = "0";
      this.isInsertNumber = true;
    }

    // 数字の入力
    this.currentNumber += num;
  } catch (error) {
    console.error("An error occurred:", error);
    alert("Invalid number input. Please enter a valid number.");
  }
}
```

### 変更点と説明
1. **`validateNumberInput`**:
   \- 数値または小数点（`.`）が有効な入力として受け入れられるように修正。
   
2. **`handleNumberInput`**:
   \- 小数点が入力されたときの処理を追加し、すでに小数点が含まれている場合は追加しないようにしています。
   \- 正負変換の処理を修正し、`parseFloat` を使って数値に変換してから計算するようにしました。

これにより、小数点を含む数値も正しく処理できるようになります。また、エラーが発生しないようにするためのエラーハンドリングも改善されています。

</details>