【Claude vs ChatGPT】Power Appsアプリのリファクタリング箇所の提案

**Claude( 3.5 Sonnet Artifacts)とChatGPT(GPT-4o)でPower Appsで作成したアプリのリファクタリング(コードの修正改善)箇所の提案対決**をしてみました。  
[これまで](https://powerplatformnikki.com/tag/%e3%83%89%e3%82%ad%e3%83%a5%e3%83%a1%e3%83%b3%e3%83%88%e7%94%9f%e6%88%90/)ドキュメント作成においてはClaudeの圧勝でしたが、リファクタリングにおいてはどうでしょうか。

また**生成AIでリファクタリングをする際に注意すべき点**も紹介します。

ソースのアプリはこちら↓

https://powerplatformnikki.com/tetrapps

## プロンプト

プロンプトはシンプルに以下を入力します。

```
このYAMLファイルはPower Appsで作成したアプリのソースコードです。
このアプリのリファクタリングすべき箇所を提案してください。
```

以下のパワハラプロンプトを繰り返すことを試してみましたが、あまり良い結果は得られませんでした。パワハラダメ絶対。

```
この出力を60点とします。100点の出力にするために足りないものを列挙した上で、100点の出力はどのようなものか出力して
```

Power Appsはマイナーな言語であるため特に誤った出力をしやすく、パワハラプロンプトではその結果を誤った方向に増幅させてしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/b91e1b47-81ab-7f55-0db2-1114c543fe39.png)

そのため**出力結果を鵜呑みにせず正しいかどうかを確かめ、誤っている場合には別のプロンプトを投げる**などの工夫が必要です。  
生成AIを利用する上では当たり前ですね。

## 出力結果

ClaudeとChatGPTの出力結果をそれぞれ評価・比較しながら、どのような誤った結果を出力するのかを確認します。

### ChatGPT

#### 繰り返し使用される値の定義

提案された箇所はイマイチですが、「複数の場所で同じ値が使用されおり、定数として定義できそうな箇所を網羅的に探してください」のようなプロンプトを追加で投げるといいかもしれません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/a5d2bac4-3266-2471-0f31-4f26a196ae4a.png)


#### コメントの整理

サボりがちなコメントはChatGPTに投げてしまった方がいいかもしれませんね。  
そのうちCopilot in Power Platformで実装されると思います。知らんけど。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/15f07d09-56df-dbbf-35bd-9159ecd2d6cd.png)

#### コードの再利用

リファクタリングでやることとしては正しいですが、Power Appsでコードの再利用をする場合はこのような書き方はできないので、これは誤った回答です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/ad4965b5-3a97-5a09-4882-a05f255b0204.png)

[Power Appsでのコードの再利用方法はこちら](https://powerplatformnikki.com/udfcomponent)

#### ネーミングの一貫性

提案された箇所で何が間違っているのかよくわからないです。  
コントロール名の変更はサボりがちなので、ChatGPTで生成・変更したうえでYAMLをUnpackするのわんちゃんあるかも。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/be20f4b3-3402-320d-892e-c044bf1d6df3.png)

#### 無駄なプロパティの削除

Power Appsではプロパティを削除することはできないので、こちらも誤った出力です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/401489aa-20fe-277e-1bb9-5dc8dbeb40c7.png)

以下全文です。

```
YAMLファイルの読み込み中にエラーが発生しました。このエラーは、特定のYAMLタグがサポートされていないことを示しています。

YAMLファイルの構造を確認して、タグに関する問題を特定するため、ファイルの内容の一部を表示します。特に問題が発生している箇所に焦点を当てます。

まず、`Screen1.fx.yaml`ファイルの最初の数行を読み込み、どのタグが問題を引き起こしているかを確認します。

YAMLファイルの内容を見ると、Power Appsで使用されるカスタムタグや式が含まれているようです。このため、標準のYAMLパーサーでは読み取れない場合があります。

タグや式を処理するためのカスタムパーサーを作成するか、単純にプレーンテキストとして解析して内容を確認し、リファクタリングすべき箇所を見つける方法を取ることが考えられます。

ここでは、プレーンテキストとして解析し、問題箇所を手動で見つける方法を試みます。ファイルの全内容を読み込み、その中からリファクタリングの提案を行います。

以下は、Power AppsのYAMLファイルから見つけたリファクタリングの提案です：

### 1. 繰り返し使用される値の定義
複数の場所で同じ値が使用されている場合、定数として定義すると保守性が向上します。

```yaml
constants:
  - ImageBackgroundHeight: 768
  - ImageBackgroundWidth: 1366

ImageBackGround As image:
    Height: =ImageBackgroundHeight
    Width: =ImageBackgroundWidth

### 2. コメントの整理
コメントがコード内に散在している場合、コメントを整理して見やすくしましょう。

```yaml
GalleryBoard As gallery.galleryVertical:
    # フィルター済み
    '#CopilotOverlayLabel': ="フィルター済み"
    BorderColor: =Index(ColBlocks, 5).Color
    BorderThickness: =1
    DelayItemLoading: =true
    Fill: =RGBA(240, 240, 240, .9)
    Height: =700
    Items: =Filter(ColBoard, Row >= 1)
    Layout: =Layout.Vertical
    LoadingSpinner: =LoadingSpinner.Data

### 3. コードの再利用
同じロジックが複数箇所に存在する場合、それを関数やメソッドとして定義します。

```yaml
functions:
  - function getBoardItems():
      return Filter(ColBoard, Row >= 1)

GalleryBoard As gallery.galleryVertical:
    Items: =getBoardItems()

### 4. ネーミングの一貫性
変数や関数の名前を一貫性のあるものに変更します。

```yaml
constants:
  - BackgroundImageHeight: 768
  - BackgroundImageWidth: 1366

ImageBackGround As image:
    Height: =BackgroundImageHeight
    Width: =BackgroundImageWidth

### 5. 無駄なプロパティの削除
使用されていないプロパティが存在する場合、それらを削除してコードを簡潔にします。
```

また現状ChatGPTではyamlファイルを正しく読み込めないようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/55b41402-4e7d-320c-5201-6cf37e164891.png)

### Claude

Claudeの方が提案された修正点の数は多いです。

#### コードの分割と再利用

正しい記述ではないですが、ChatGPTよりも正確度の高い回答が得られました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/51d1b6ea-1930-69ba-5602-9043f081d8d2.png)

#### 定数の使用

ChatGPTの「繰り返し使用される値の定義」と同じ修正点を挙げていますが、内容の正確度はClaudeの方が高いです。  
実際テトリス風ゲームの作成時、ボードのサイズを変数に格納していなかったために少し修正に時間がかかってしまいました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/56baeb50-d915-ec11-4382-421375e757b4.png)

#### エラーハンドリングの改善

このアプリでは

エラーハンドリングは必要ないですが、普通の業務アプリでは必要なのでそこを正しく指摘できています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/99593894-9833-5f68-71f5-e74d64915acc.png)

#### 命名規則の統一

ChatGPTと同様の出力ですが、例が少ないのでより詳細に出力してもらう必要がありそうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/e0265a47-6b81-f849-cbe7-ea50228281ea.png)

#### コメントとドキュメンテーション

こちらもChatGPTと同様ですが、コメントの量も質もClaudeの方が優れています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/33fc34f9-d541-4294-5824-01e165b7274c.png)

#### パフォーマンスの最適化

リファクタリングの作業としては正しいですが、キャッシュするには名前付き計算式ではなく変数やコレクションに格納必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/12afdc44-cd53-d7b4-b534-0d157d2c0743.png)

#### UI/UXの改善

レスポンシブデザインに対応させようとしています。  
対応させるつもりがないなら他の方向性で提案をしてもらった方がいいかもしれません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/6ea9184d-24c4-38c6-e5b7-d54856e108ed.png)

以下全文です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618051/b1af1c7c-a22a-470c-6ac4-240ce47f1227.png)

```
# Power Apps Application Refactoring Suggestions

## 1. コードの分割と再利用

### 問題点
現在、多くのロジックが直接コントロールのプロパティに埋め込まれています。これは可読性を低下させ、コードの再利用を困難にします。

### 提案
- 共通のロジックを関数として抽出し、App.Formulasセクションに配置します。
- 複雑な条件文や計算を別の変数や関数に分離します。

### 例
App As appinfo:
    Formulas: |
        Set(
            fnRotateBlock,
            (direction, block) => // 回転ロジックをここに記述
        );

## 2. 定数の使用

### 問題点
マジックナンバーや文字列リテラルが多用されています。

### 提案
- 頻繁に使用される値を定数として定義します。
- App.Formulasセクションで定数を宣言します。

### 例
App As appinfo:
    Formulas: |
        Set(
            BOARD_WIDTH,
            9
        );
        Set(
            BOARD_HEIGHT,
            24
        );

## 3. エラーハンドリングの改善

### 問題点
現在、OnErrorプロパティが単純に`false`に設定されています。

### 提案
- より堅牢なエラーハンドリングを実装します。
- エラーメッセージを表示するか、ログに記録するロジックを追加します。

### 例
App As appinfo:
    OnError: |
        Notify(
            "エラーが発生しました: " & Error.Message,
            NotificationType.Error
        );
        Trace(
            "Error: " & Error.Message,
            Error.Formula,
            Trace.Error
        );

## 4. 命名規則の統一

### 問題点
変数や関数の命名規則が一貫していません。

### 提案
- 一貫した命名規則を採用します（例：キャメルケースまたはスネークケース）。
- 意味のある名前を使用し、略語を避けます。

### 例
- `ColBlocks` → `CollectionBlocks`
- `fnRotateBlock` → `RotateBlockFunction`

## 5. コメントとドキュメンテーション

### 問題点
コードにコメントが少なく、複雑なロジックの理解が困難です。

### 提案
- 複雑なロジックには説明的なコメントを追加します。
- 関数の目的、パラメータ、戻り値を文書化します。

### 例
// ブロックを回転させる関数
// direction: 回転方向 (1: 時計回り, -1: 反時計回り)
// block: 回転させるブロックのデータ
// 戻り値: 回転後のブロックデータ
Set(
    fnRotateBlock,
    (direction, block) => // 回転ロジックをここに記述
);

## 6. パフォーマンスの最適化

### 問題点
一部のコレクションや計算が頻繁に実行されている可能性があります。

### 提案
- 頻繁に使用される計算結果をキャッシュします。
- 大きなコレクションに対する操作を最適化します。

### 例
App As appinfo:
    Formulas: |
        Set(
            CachedMovingMino,
            Filter(ColBoard, "Moving" in MinoStatus.Status)
        );

## 7. UI/UXの改善

### 問題点
一部のUI要素の配置やサイズが固定値で設定されています。

### 提案
- 相対的な配置やサイズを使用して、異なる画面サイズに対応します。
- アクセシビリティを考慮したデザインを採用します。

### 例
X: =Parent.Width/2 - Self.Width/2
Y: =Parent.Height/2 - Self.Height/2

これらの提案を実装することで、コードの可読性、保守性、パフォーマンスが向上し、より堅牢なアプリケーションになると考えられます。
```


## まとめ

総合的にClaudeの方がリファクタリングの提案においては量・質ともに優れていました。  
一定間違った回答を出力しますが、**どこから手を付けていいかわからないという状態**からは抜け出せそうです。

Geminiも試してみたいけどお金がないです。[欲しいものリスト](https://www.amazon.co.jp/hz/wishlist/ls/2W3O0OXW2ONUH?ref_=wl_share)や[Amazonのアソシエイトリンク(PR)](https://amzn.to/3zH1SYT)で支援していただければGeminiの結果も追記するかもしれません。

## 元記事

https://powerplatformnikki.com/refactoringgenai/