【ChatGPT】4. エラー対応 > 可読性・保守性・再利用性について

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

- 対応内容

https://qiita.com/sgpl20337/private/61a67f1e47580cd44e90

## コンパイル時エラー対応

<details>

>### 2. 保守性の向上
>
>#### 2.1 リファクタリングメソッド
>
>- `setTotalNum`メソッドを別のファイルに分けて、計算ロジックを抽象化することで、保守性を向上させます。

この対応にて 'decimal.js-light' の宣言が import へ変更されたためコンパイル時エラーが発生

```javascript:旧：Calculator.vue
<script src="https://cdn.jsdelivr.net/npm/decimal.js-light@2.5.0/decimal.min.js"></script>
```
```javascript:新：calculator.js
import Decimal from 'decimal.js-light';
```

生成AIに対して対応方針を質問し回答を確認
1. **モジュールがインストールされていない** の手順を実施しエラー対応

#### ・プロンプト
:::note alert
ERROR  Failed to compile with 1 error 18:47:27

error  in ./src/utils/calculator.js

Module not found: Error: Can't resolve 'decimal.js-light' in 'C:\project\calculator\src\utils'

ERROR in ./src/utils/calculator.js 2:0-39
Module not found: Error: Can't resolve 'decimal.js-light' in 'C:\project\calculator\src\utils'
 @ ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Calculator.vue?vue&type=script&lang=js 2:0-47 43:15-24
 @ ./src/components/Calculator.vue?vue&type=script&lang=js 1:0-203 1:219-222 1:224-424 1:224-424
 @ ./src/components/Calculator.vue 2:0-61 3:0-56 3:0-56 10:2-8
 @ ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/App.vue?vue&type=script&lang=js 1:0-53 5:4-14
 @ ./src/App.vue?vue&type=script&lang=js 1:0-190 1:206-209 1:211-398 1:211-398
 @ ./src/App.vue 2:0-54 3:0-49 3:0-49 9:2-8
 @ ./src/main.js 2:0-28 5:17-20

webpack compiled with 1 error
:::
> 原因と解決策は？

#### ・回答内容

このエラーメッセージは、`decimal.js-light` モジュールが `src/utils/calculator.js` 内でインポートされているものの、そのモジュールが見つからないことを示しています。これにはいくつかの原因と解決策があります。

### 原因と解決策

1. **モジュールがインストールされていない**

   `decimal.js-light` がプロジェクトの `node_modules` フォルダに存在しない場合、このエラーが発生します。モジュールをインストールするには、以下のコマンドを実行します：

   ```bash:bash
   npm install decimal.js-light
   ```

   または、もし `yarn` を使用している場合は：

   ```bash:bash
   yarn add decimal.js-light
   ```

2. **依存関係の破損**

   依存関係が壊れている場合、`node_modules` フォルダを削除して再インストールすることが有効です。以下の手順で試してみてください：

   ```bash:bash
   rm -rf node_modules
   npm install
   ```

   または、`yarn` を使用している場合：

   ```bash:bash
   rm -rf node_modules
   yarn install
   ```

3. **パスの問題**

   `decimal.js-light` が正しくインストールされているのにエラーが発生する場合、パスが正しく指定されていない可能性があります。`src/utils/calculator.js` ファイルで、`decimal.js-light` のインポートが以下のようになっていることを確認してください：

   ```javascript:javascript
   import Decimal from 'decimal.js-light';
   ```

   モジュール名が正確であることを確認し、スペルミスがないか再確認してください。

4. **キャッシュの問題**

   キャッシュが原因で問題が発生している場合もあります。キャッシュをクリアしてから再ビルドしてみてください。以下のコマンドでキャッシュをクリアできます：

   ```bash:bash
   npm cache clean --force
   ```

   その後、再度依存関係をインストールしてビルドします：

   ```bash:bash
   npm install
   npm run build
   ```

   または、`yarn` を使用している場合：

   ```bash:bash
   yarn cache clean
   yarn install
   yarn build
   ```

5. **ファイルシステムの問題**

   特定の環境やファイルシステムの設定によっては、モジュールが正しく読み込まれないことがあります。その場合、プロジェクトを一度クリーンにしてから再ビルドを試みるのも一つの手です。

これらの解決策を試しても問題が解決しない場合は、プロジェクトの構成や依存関係に関する詳細な情報が必要かもしれません。その場合は、さらに詳細なエラーメッセージやプロジェクトの設定情報を提供していただけると、より具体的なアドバイスができるかもしれません。

</details>

## リファクタリングメソッドエラー対応

<details>

>### 2. 保守性の向上
>
>#### 2.1 リファクタリングメソッド
>
> - コンポーネント内で使用する際には、次のようにインポートします。
>
> ```javascript:javascript
> import { calculate } from '@/utils/calculator';
> 
> methods: {
>   total() {
>     return this.numArray.reduce((prev, next, index) => {
>       return calculate(prev, next, this.opeArray[index]);
>     });
>   }
> }
> ```

この対応にて意図しない動作が確認されたため手動で修正対応
this.opeArray に対する index 番号が誤っていたため [index - 1] に修正

```javascript:旧：Calculator.vue
methods: {
    // reduceメソッドを使い、全ての計算結果を出す
    total() {
      return this.numArray.reduce((prev, next, index) => {
        return this.setTotalNum(prev, next, index - 1);
      });
    },
```
```javascript:新：Calculator.vue
import { calculate } from '@/utils/calculator';

methods: {
  total() {
    return this.numArray.reduce((prev, next, index) => {
      return calculate(prev, next, this.opeArray[index - 1]);
    });
  }
}
```

</details>

## コンポーネントの分割エラー対応

<details>

>### 3. 再利用性の向上
>
>#### 3.1 コンポーネントの分割
>
>- 電卓の各部分をコンポーネントに分割することで再利用性が向上します。

この対応にて 'CalculatorButton' の import 宣言が不足しているため読み込みエラーが発生

生成AIに対して対応方針を質問し回答を確認
1. **コンポーネントの登録が不足している** の手順を実施しエラー対応

#### ・プロンプト
:::note alert
main.js:8 [Vue warn]: Unknown custom element: <CalculatorButton> - did you register the component correctly? For recursive components, make sure to provide the "name" option.

found in

---> <Calculator> at src/components/Calculator.vue
       <App> at src/App.vue
         <Root>
:::
> 原因と解決策は？

#### ・回答内容

この警告は、`<CalculatorButton>` というカスタムコンポーネントが `<Calculator>` コンポーネント内で使われているが、Vue にそのコンポーネントが正しく登録されていないことを示しています。これにはいくつかの原因が考えられ、それぞれに対する解決策があります。

### 原因と解決策

1. **コンポーネントの登録が不足している**

   `<CalculatorButton>` コンポーネントがローカルに登録されていないか、正しく登録されていない場合があります。`Calculator.vue` ファイルでコンポーネントを正しくインポートし、登録しているか確認してください。

   例えば、`Calculator.vue` ファイル内で次のようにインポートし、`components` オプションで登録する必要があります：

   ```javascript:javascript
   <template>
     <div>
       <CalculatorButton />
     </div>
   </template>

   <script>
   import CalculatorButton from './CalculatorButton.vue'; // パスは実際の位置に合わせて変更してください

   export default {
     components: {
       CalculatorButton
     }
   };
   </script>
   ```

2. **コンポーネントのファイル名とパスの誤り**

   コンポーネントファイル名やパスが間違っている可能性があります。`CalculatorButton.vue` が `src/components/` フォルダ内に正しく存在し、ファイル名が正確であるか確認してください。また、インポートのパスが間違っていないかもチェックしてください。

3. **コンポーネントの名前設定が不足している**

   コンポーネントが再帰的に使われている場合や、他の理由でコンポーネントの名前が必要な場合があります。`CalculatorButton.vue` ファイル内で `name` オプションが設定されているか確認してください：

   ```javascript:javascript
   <template>
     <button>Click me</button>
   </template>

   <script>
   export default {
     name: 'CalculatorButton'
   };
   </script>
   ```

4. **グローバルコンポーネントの登録ミス**

   グローバルにコンポーネントを登録する場合、`main.js` で正しく登録されているか確認してください。例えば、以下のようにグローバルコンポーネントを登録することができます：

   ```javascript:javascript
   import Vue from 'vue';
   import App from './App.vue';
   import CalculatorButton from './components/CalculatorButton.vue';

   Vue.component('CalculatorButton', CalculatorButton);

   new Vue({
     render: h => h(App)
   }).$mount('#app');
   ```

5. **ビルドキャッシュの問題**

   コンポーネントが正しく登録されているにも関わらずエラーが発生する場合、ビルドキャッシュが問題を引き起こしている可能性があります。キャッシュをクリアしてからビルドし直してみてください。

   ```bash:bash
   npm cache clean --force
   npm run build
   ```

   または、`yarn` を使用している場合：

   ```bash:bash
   yarn cache clean
   yarn build
   ```

6. **Vue コンポーネントの構文エラー**

   コンポーネントファイル内に構文エラーや不正なコードが含まれていると、Vue がコンポーネントを正しく認識できないことがあります。コンポーネントファイル内にエラーがないか確認してください。

これらの確認を行うことで、問題が解決することが多いです。それでも解決しない場合は、具体的なコードや設定に関する追加情報を提供していただけると、さらに詳細なアドバイスが可能です。

</details>

## コンポーネントの使用エラー対応

<details>

>### 3. 再利用性の向上
>
>#### 3.1 コンポーネントの分割
>
>- `CalculatorButton` コンポーネントを使用することで、ボタンの種類に応じたクラスやラベルを動的に設定できます。
>```html:html
><!-- Calculator.vue -->
><template>
>  <div>
>    <CalculatorButton v-for="num in buttons.num" :key="num" :label="num" buttonClass="is-dark" >@click="handleNumberInput(num)" />
>    <CalculatorButton v-for="operator in buttons.operator" :key="operator" :label="operator" >buttonClass="is-primary" @click="handleOperatorInput(operator)" />
>    <CalculatorButton label="=" buttonClass="is-success" @click="calculateResult" />
>    <CalculatorButton label="C" buttonClass="is-danger" @click="clearCurrentNumber" />
>    <CalculatorButton label="AC" buttonClass="is-danger" @click="resetCalculator" />
>  </div>
></template>
>```

この対応にて意図しない動作が確認されたため手動で修正対応
表示順の修正や必要なスタイルの class 宣言を追加

```html:旧：Calculator.vue
<template>
  <div class="calc">
    <h1 class="title">calculator</h1>
    <div class="result box" style="text-align: right">
      {{ showNum }}
    </div>
    <div class="clear">
      <button @click="clearCurrent" class="button is-danger is-medium">C</button>
      <button @click="clearAll" class="button is-danger is-medium">AC</button>
    </div>
    <div class="buttons columns">
      <div class="number-buttons colum is-one-third">
        <button v-for="num in buttons.num" :key="num" class="button is-dark" @click="selectNumber(num)">{{ num }}</button>
      </div>
      <div class="column">
        <button v-for="operator in buttons.operator" :key="operator" class="button is-primary is-medium" @click="selectOparator(operator)">{{ operator }}</button>
      </div>
    </div>
    <div class="">
      <button @click="showResult" class="button is-success is-medium equal-button">=</button>
    </div>
  </div>
</template>
```
```html:新：Calculator.vue
<template>
  <div class="calc">
    <h1 class="title">calculator</h1>
    <div class="result box" style="text-align: right">
      {{ showNum }}
    </div>
    <div class="clear">
      <CalculatorButton label="C" buttonClass="is-danger is-medium" @click="clearCurrentNumber"/>
      <CalculatorButton label="AC" buttonClass="is-danger is-medium" @click="resetCalculator"/>
    </div>
    <div class="buttons columns">
      <div class="number-button-container colum is-one-third">
        <CalculatorButton v-for="num in buttons.num" :key="num" :label="num" buttonClass="is-dark" @click="handleNumberInput(num)"/>
      </div>
      <div class="column">
        <CalculatorButton v-for="operator in buttons.operator" :key="operator" :label="operator" buttonClass="is-primary is-medium" @click="handleOperatorInput(operator)"/>
      </div>
    </div>
    <div class="">
      <CalculatorButton label="=" buttonClass="is-success is-medium equal-button" @click="calculateResult"/>
    </div>
  </div>
</template>
```

</details>