5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

個人開発を効率化!React & Gemini で自動コードレビューツールを開発

Posted at

はじめに

最近個人で開発をしていたのですが(参照記事)、自分が書いたコードをレビューしたりリファクタリングの案を出してくれる存在がいなかったので、以下の3つの機能を備えた自動リファクタリング&レビューツールを作ってみました。

リファクタリングの自動化: ユーザーが入力したコードを解析し、AIが自動的にリファクタリングしたコードを提示します。冗長な記述を簡潔にしたり、より効率的なアルゴリズムに置き換えたりすることで、コードの可読性や保守性、実行速度の向上が期待できます。

シニアエンジニア視点でのコードレビュー生成: リファクタリングの結果だけでなく、シニアエンジニアとしてレビューコメントを提供します。コードの良い点、改善すべき点を具体的に指摘し、なぜそのように修正すべきなのかを丁寧に説明します。

ユニットテスト自動生成機能: 選択した言語がjavascriptであればJest, PythonであればPytestのようにそれぞれの言語合わせたフレームワークを用いたテストコードを自動で生成します。テストは先に書け、というツッコミは一旦聞かなかったことにします

リポジトリ

基本的にはReact+Tailwind CSSでフロントエンドを作成してGeminiのAPIから返ってきたレスポンスを表示するだけの簡単なものです。
https://github.com/kouheiohmikawa/ai_reviewer
※動かすためにはこちらからAPIキーを発行する必要があります。

使い方

トップ画面はこんな感じです。まずは使用している言語を選択して自分が書いたコードをコピペで貼り付けてレビュー&リファクタリングボタンをクリックします。
スクリーンショット 2025-01-02 23.22.18.png

レスポンスが返ってくるまで少し時間がかかります
スクリーンショット 2025-01-02 23.23.34.png

画面左側にリファクタリングしたコードの結果、中央にレビューコメントが表示されます。

スクリーンショット 2025-01-02 23.24.26.png

次にユニットテスト作成ボタンをクリックすると、画面右側に様々なケースのテストコードが表示されます。
スクリーンショット 2025-01-02 23.25.42.png

入出力

入力


def calculate_sum_and_product(data_list):
    # 数値のリストを受け取って合計と積を計算し、出力する
    total = 0
    for num in data_list:
        total = total + num

    product = 1
    for num in data_list:
        product = product * num

    print("Sum:", total)
    print("Product:", product)

    # 平均値も計算する
    average = total / len(data_list)

    # 標準偏差を計算する
    squared_diffs = []
    for i in range(len(data_list)):
       squared_diffs.append((data_list[i] - average) ** 2)

    sum_of_squared_diffs = 0
    for x in squared_diffs:
        sum_of_squared_diffs += x

    variance = sum_of_squared_diffs / len(data_list)

    # 標準偏差を計算
    std_dev = 0
    temp = variance
    for _ in range(100):
        std_dev = 0.5 * (std_dev + temp / (std_dev + 1e-10)) # 0除算を避けるために微小な値を加算

    print("Standard Deviation:", std_dev)

    return total, product, average, std_dev


my_numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
sum_result, product_result, average, std_dev = calculate_sum_and_product(my_numbers)

出力(リファクタリング)

import statistics

def calculate_summary(data_list):
    """数値のリストを受け取って、合計、積、平均、標準偏差を計算し、出力する"""

    # リストからの数値の合計を計算する
    total = sum(data_list)

    # リストからの数値の積を計算する
    product = statistics.prod(data_list)

    # リストからの平均を計算する
    average = statistics.mean(data_list)

    # リストからの標準偏差を計算する
    std_dev = statistics.stdev(data_list)

    print("Sum:", total)
    print("Product:", product)
    print("Average:", average)
    print("Standard Deviation:", std_dev)

    return total, product, average, std_dev


my_numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
sum_result, product_result, average, std_dev = calculate_summary(my_numbers)


**リファクタリングの改善点:**

* `statistics` モジュールを使用して、標準偏差などの統計情報を簡単に計算
* `for` ループのネストを削除してコードの可読性を向上
* 0除算の回避のための微小値の追加を削除(`statistics` モジュールはこれを内部的に処理)

出力(レビューコメント)

良い点:

関数は明確な名前で、その目的を明確に示しています。
関数は、入力リストから合計、積、平均、標準偏差を正しく計算します。
改善点:

コード重複:

合計と積を計算する2つのループがあります。これを1つのループに統合できます。
効率的な標準偏差の計算:

使用されている方法は、精度を大きく損なう可能性のある反復的な方法です。代わりに、以下のようなより効率的な方法を使用することをお勧めします。
import statistics

std_dev = statistics.stdev(data_list)
例外処理:

リストが空の場合、関数はエラーを出力しません。空のリストが渡された場合にエラーメッセージを出力するように例外処理を追加する必要があります。
マジックナンバー:

ループ内で魔法の数値 100 が使用されています。代わりに、標準偏差の許容誤差の基準を示す意味のある変数を使用してください。
命名規則:

変数名 temp はわかりにくいです。よりわかりやすい名前に変更してください。
最適化されたコード:

以下は、改善されたコードです。

import statistics

def calculate_sum_and_product(data_list):
    # 数値のリストを受け取って合計と積を計算し、出力する
    if not data_list:
        raise ValueError("空のリストが渡されました。")

    total = 0
    product = 1
    for num in data_list:
        total += num
        product *= num

    average = total / len(data_list)
    std_dev = statistics.stdev(data_list)

    print("Sum:", total)
    print("Product:", product)
    print("Average:", average)
    print("Standard Deviation:", std_dev)

    return total, product, average, std_dev

出力(テストコード)

import pytest

def test_calculate_sum_and_product_empty_list():
    # 空のリストの場合のテスト
    result = calculate_sum_and_product([])
    assert result == (0, 1, 0, 0)

def test_calculate_sum_and_product_positive_list():
    # 正の数のリストの場合のテスト
    my_numbers = [1, 2, 3, 4, 5]
    result = calculate_sum_and_product(my_numbers)
    assert result == (15, 120, 3, 1.5811388300841898)

def test_calculate_sum_and_product_negative_list():
    # 負の数のリストの場合のテスト
    my_numbers = [-1, -2, -3, -4, -5]
    result = calculate_sum_and_product(my_numbers)
    assert result == (-15, -120, -3, 1.5811388300841898)

def test_calculate_sum_and_product_zero_list():
    # ゼロを含んだリストの場合のテスト
    my_numbers = [0, 1, 2, 3, 4, 5]
    result = calculate_sum_and_product(my_numbers)
    assert result == (15, 0, 2, 1.7320508075688772)

def test_calculate_sum_and_product_float_list():
    # 浮動小数点を含むリストの場合のテスト
    my_numbers = [1.2, 2.3, 3.4, 4.5, 5.6]
    result = calculate_sum_and_product(my_numbers)
    assert result == (16.999999999999996, 403.2, 3.3999999999999995, 1.667183175891228)

def test_calculate_sum_and_product_string_in_list():
    # リストに文字列が含まれている場合のテスト
    with pytest.raises(TypeError):
        calculate_sum_and_product(['a', 1, 2, 3])

def test_calculate_sum_and_product_uneven_list_length():
    # リストの長さが偶数でない場合のテスト
    my_numbers = [1, 2, 3, 4, 5, 6, 7]
    result = calculate_sum_and_product(my_numbers)
    assert result == (28, 5040, 4, 2.041241452525556)

非常に簡単なアプリですが、私のような開発初心者にとってはそもそもテストコードの書き方も分からなかったりするので一応役には立ちます。

宣伝

記事の冒頭で触れた最近開発しているアプリですが、デモVer.2をリリースしたので覗いてみてください(全国の地域に対応しました!)
URL ➡ https://www.live-spot.com/

まだまだバグや不具合は多いと思いますが、これからも改善は続けていきます!

あと、情報発信用のXのアカウントも作成したのでフォローしていただけると嬉しいです!

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?