💬

Cursorを使って、既存のアプリケーションコードを変更するときに意識していること

に公開

生成AIを使ったコーディング、皆様うまく乗りこなせていますでしょうか?欲しかった機能やアプリケーションを数分で作ってくれることもあれば、時間をかければかけるほど明後日の方向に向かうコードばかり出力されてイライラすることもあるのではないかと思います。

今回は私が普段行っているCursorを使った既存プロジェクトの機能改修のワークフローについて紹介します。特にAPIレスポンスの変更など、既存コードの流れを追いながら修正していく際に役立つアプローチをご紹介します。

事前準備:修正対象の特定

機能改修を効率的に進めるためには、まず何を修正するのかを正確に特定することが重要です。今回はダッシュボードとAPIの2つがあるシステムにおいて、APIレスポンスに新しいデータを追加したり不要なデータを削除したりする作業を例に挙げてみましょう。

要件・タスクの確認

まずはこれから何をやろうとしているかを自分の中で整理しましょう。自分の中でイメージできていないものを他人やAIにやらせようとするのは、どうしても認識やゴール設定のズレからすれ違い・トラブルを生みやすくなります。

この時点で生成AIを利用してやりたいことを整理するのも1つです。できるだけ具体的に、「今からこのAPI / 画面を変更する。現状はXXで、変更後はYYという動きになるはずだ」のような形で整理しておくと理想的です。

ブラウザ開発者ツールでAPIを特定

まず、ブラウザの開発者ツールを開いてダッシュボードを操作します。このとき、APIを変更する場合は、Networkタブで通信を監視しましょう。このタブでアプリケーションが呼び出しているAPIリクエストをチェックし、修正が必要なAPIを特定します。特定ができたら、対象のAPIのパスとメソッドをコピーしましょう。(例: GET https://example.com/latest/billing/subscriptions)。

この情報を利用して、どのコードを修正すればよいのかをCursorにて特定していきます。

Cursorでコード調査を効率化する

1. APIが定義されているファイルを特定する

Cursorでは、Agentモードを積極的に使っています。これは複数のファイルを横断した調査などを自律的に行わせることで、変更が必要な場所の特定を効率的に行わせることが目的です。今回の例では、Agentモードで以下のような指示を出しました。

GET /latest/billing/subscriptions のAPIについて作業を行いたい。このAPIが定義されているコントローラーを特定して。

このような指示を出すと、Cursorは対象のAPIを探し出し、関連するファイルを教えてくれます。今回の例ではNestJSを使ったアプリケーションなので、「コントローラーを探せ」と指示しています。もしプロジェクトがRemixでできているならば、routesディレクトリを調べると指示する必要があります。このようにフレームワークに応じた指示を出すことが重要です。

数分も経たずに調査結果が出てきます。ファイル名やメソッド名などが調査結果として出力されますので、そのファイルをエディタ側で開いておきましょう。

検索結果から、GET /latest/billing/subscriptions のAPIは src/api/billings/billings.controller.ts ファイルの BillingsController クラスで定義されていることがわかります。APIメソッドは XXXX で定義されていました。

このファイルが調査・実装・テストのスタート地点となります。ある程度プロジェクトやアプリケーションコードに慣れている方であれば、この時点で「あぁ、じゃあこのメソッドを変更すればいいね」とすぐに自分で作業を開始できるかもしれません。

2. 実装内容の詳細把握

次のステップでは、特定したAPIの実装内容を詳しく調査します。Cursorではファイルやディレクトリをコンテキストとして渡すことができます。先ほど開いたファイルを @でコンテキストとして渡し、調査の開始地点として指定しましょう。

ありがとう。@billings.controller.ts の該当APIについて、処理内容を可能な限り詳しく調査して。

ファイルパスを指定することで、Cursorはそのファイルを中心に関連するコードまで調査してくれます。調査結果から以下のような情報が得られます。

  • APIのエンドポイント定義
  • 認証方法
  • 使用しているサービス
  • 処理の流れ
  • 返却されるデータの形式や内容

この情報を元に、どのコードをどのように修正すべきかの計画を立てることができます。

機能改修の方針決定

実装内容の大まかな把握がCursor Agentによってできました。次に必要なのは実装計画です。この時点で実装方針がすでに頭の中に出来上がっている場合は、直接Cursorへ指示したり、自分で編集してしまうことも可能です。もし方針が定まっていない場合は、次のように要望や修正リクエストの内容をCursor Agentに相談しましょう。

ありがとう。変更したいコードを見つけました。
以下の要望があるのですが、どのように実装すべきでしょうか?

基本情報 (使ってる
id: サブスクリプションID
current_period_start: 課金期間開始日
current_period_end: 課金期間終了日
customer: 顧客ID
status: サブスクリプションのステータス

...以下省略

今回のケースでは、APIレスポンスを現在使用している項目と不要な項目を整理する必要がありました。Cursorに相談すると、いくつかの実装案を提示してくれるので、その中から最適なものを選びます。

実装方針の確定

提案された実装案から最適なものを選び、具体的な実装方針を決定します。ここで実装に関する細かい要望があれば、それも伝えておきましょう。今回はクラス内にprivateメソッドを追加しようとしていましたので、クラスの外に実装してユニットテストも追加するように依頼しました。

1番でいきましょう。ただしtransformSubscriptionは@subscription.service.tsではなく @subscription.utils.ts に実装します。その上でユニットテストを@subscription.service.spec.ts へ追加しましょう。テストコードについては、型定義は厳密ではなくて良いです。asを使ってテストコードが冗長にならないようにしてください。

このように、実装案を選択しつつ、ファイル構成やコーディングスタイルに関する具体的な指示を追加することで、より自分の意図に沿った実装を得ることができます。

コード実装とレビュー

Cursorによって生成されたコードを確認し、必要に応じて修正します。例えば、冗長な型定義が見つかった場合は、より簡潔な形に改善することができます。

改善前:

// ホスティングサブスクリプション検索用の最小限の型
interface SubscriptionListLike {
  data: Array<{
    id: string;
    items: {
      data: Array<{
        price?: {
          id?: string;
          nickname?: string;
        };
      }>;
    };
    metadata?: {
      server_id?: string;
    };
    status?: string;
  }>;
}

interface SubscriptionLike {
  id: string;
  items: {
    data: Array<{
      id: string;
      price?: {
        id?: string;
        nickname?: string;
        lookup_key?: string;
      };
    }>;
  };
  metadata?: Record<string, string>;
  automatic_tax: {
    enabled: boolean;
  };
  default_tax_rates?: Array<string | { id: string }>;
  status?: string;
}

この型定義はよくよく見ると、SubscriptionListLikeを2重に定義していることがわかります。Cursorに修正指示を出してもいいのですが、これくらいは手でやることが多いです。日本語を書くより、コピーアンドペーストで変更する方がはやいですしね。

interface SubscriptionListLike {
  data: Array<SubscriptionLike>;
}

interface SubscriptionLike {
  id: string;
  items: {
    data: Array<{
      id: string;
      price?: {
        id?: string;
        nickname?: string;
        lookup_key?: string;
      };
    }>;
  };
  metadata?: Record<string, string>;
  automatic_tax: {
    enabled: boolean;
  };
  default_tax_rates?: Array<string | { id: string }>;
  status?: string;
}

テストと動作確認

最後のステップでは、以下の確認を行います:

  1. ユニットテストの実行

    • 新しく追加したテストが正常に動作するか確認
    • 既存のテストが壊れていないか確認
  2. 型定義の整合性チェック

    • リファクタリングした型定義に問題がないか確認
    • 依存しているコードに影響がないか確認
  3. 実際のAPIの動作確認

    • ブラウザ開発者ツールで修正したAPIを呼び出し
    • 期待どおりのレスポンスが返ってくるか確認
    • ダッシュボード側の表示が正常か確認

まとめ

Cursorを使った機能改修のワークフローを紹介しました。AIアシスタントを活用することで、特に以下のような効果が得られます:

  1. コードの調査時間を大幅に短縮
  2. 複雑なAPIの流れを素早く理解
  3. 複数の実装案から最適なものを選択
  4. 型定義やテストの整合性を効率的にチェック

特に大規模なコードベースで作業する場合や、自分が詳しくないコードに手を入れる場合に、このアプローチは非常に効果的です。Cursorの強力なAI機能を活用して、より効率的かつ正確なコード改修を行ってみてください。

以上、Cursorを使った既存プロジェクトの機能改修のステップについて、自分の取り組み方を紹介しました。皆さんのプロジェクトでも参考になれば幸いです。

デジタルキューブ

Discussion