こんにちは、CX事業本部 Delivery部の若槻です。
前回のエントリではGitHub CopilotをVisual Studio Codeに導入するところまでやってみました。
今回は実践編として、GitHub Copilotに頼りながらDynamoDBテーブル上のデータをSDKで操作する関数(TypeScript)を作成してみました。
やってみた
SDKのインポート
まずAWS SDK for JavaScript v3をインポートする記述です。
script.ts
// DynamoDBテーブルをクエリする
// AWS SDK for JavaScript v3をインポート
import { DynamoDBClient, QueryCommand } from '@aws-sdk/client-dynamodb';
ポイント
- 冒頭でDynamoDBテーブルをクエリする旨を宣言することにより、次行以降でクエリに必要なモジュールのみがインポートされる。
- AWS SDK for JavaScript v3をインポートしたいことを明示的に記述しなければv2のインポート文がサジェストされてしまう。
DynamoDBクライアント作成
次にインポートしたSDKを使用してDynamoDBクライアントを作成します。
script.ts
// DynamoDBテーブルをクエリする
// AWS SDK for JavaScript v3をインポート
import { DynamoDBClient, QueryCommand } from '@aws-sdk/client-dynamodb';
// DynamoDBクライアントを作成
const client = new DynamoDBClient({ region: 'ap-northeast-1' });
ポイント
- コメント行で改行後にコードのサジェストがされない場合は、想定されるコードの書き出しを記述してあげることにより候補が出るようになる。
ユーザー型の定義
テーブル上に保管されるユーザーデータの型を定義します。
script.ts
// DynamoDBテーブルをクエリする
// AWS SDK for JavaScript v3をインポート
import { DynamoDBClient, QueryCommand } from '@aws-sdk/client-dynamodb';
// DynamoDBクライアントを作成
const client = new DynamoDBClient({ region: 'ap-northeast-1' });
// ユーザー型を定義
type User = {
id: string;
name: string;
age: number;
};
ポイント
- 型名をもとにそれらしい内容の型を自動で生成してくれるので、必要に応じて修正する。
クエリ実行する関数の作成
最後に、DynamoDBテーブルをクエリする処理を記述します。
script.ts
// DynamoDBテーブルをクエリする
// AWS SDK for JavaScript v3をインポート
import { DynamoDBClient, QueryCommand } from '@aws-sdk/client-dynamodb';
// DynamoDBクライアントを作成
const client = new DynamoDBClient({ region: 'ap-northeast-1' });
// ユーザー型を定義
type User = {
id: string;
name: string;
age: number;
};
// ユーザーをクエリしてユーザーリストを返す
export const queryUsers = async (): Promise<User[]> => {
const params = {
TableName: 'Users',
KeyConditionExpression: 'id = :id',
ExpressionAttributeValues: {
':id': { S: '1' },
},
};
const command = new QueryCommand(params);
const data = await client.send(command);
// プロパティ値がundefinedの場合は空文字列に置き換える
const users = data.Items?.map((item) => ({
id: item.id.S ?? '',
name: item.name.S ?? '',
age: item.age.N ? parseInt(item.age.N) : 0,
}));
// ユーザーリストを返す
return users ?? [];
};
ポイント
ユーザーをクエリする
というコメントだけだと単一のユーザーデータを返す関数を作ろうとするため、ユーザーをクエリしてユーザーリストを返す
まで記述してあげる必要があった。- 関数の中身は一気にサジェストして記述してくれますが、戻り値のデータでロパティ値がundefinedの場合が考慮されていないためタイプエラーとなった。エラーとなっている記述を消して明示的に
プロパティ値がundefinedの場合は空文字列に置き換える
という記述をしたら対応するコードをサジェストしてくれた。
引数としてクエリキーを受け取るようにする
引数としてクエリキーとなるidを受け取るようにし、クエリで使用するように修正します。
script.ts
// DynamoDBテーブルをクエリする
// AWS SDK for JavaScript v3をインポート
import { DynamoDBClient, QueryCommand } from '@aws-sdk/client-dynamodb';
// DynamoDBクライアントを作成
const client = new DynamoDBClient({ region: 'ap-northeast-1' });
// ユーザー型を定義
type User = {
id: string;
name: string;
age: number;
};
// ユーザーをクエリしてユーザーリストを返す
// 引数としてユーザーIDを受け取る
export const queryUser = async (id: string): Promise<User[]> => {
// DynamoDBクエリを作成
const command = new QueryCommand({
TableName: 'users',
KeyConditionExpression: 'id = :id',
ExpressionAttributeValues: {
':id': { S: id },
},
});
// DynamoDBクエリを実行
const result = await client.send(command);
// ユーザーリストを作成
const users: User[] = [];
// レスポンスからユーザーを抽出
// レスポンスのItemsはundefinedかItemの配列
// Type 'string | undefined' is not assignable to type 'string'. を考慮
if (result.Items) {
for (const item of result.Items) {
const user: User = {
id: item.id.S || '',
name: item.name.S || '',
age: item.age.N ? parseInt(item.age.N) : 0,
};
users.push(user);
}
}
return users;
};
引数としてユーザーIDを受け取る
のようにコメントを追加すれば、その通りに関数を作ってくれた。- クエリキーを関数の引数として受け取るように変更しようとしただけですが、再度全体のコードをサジェストしてもらっためクエリ結果をパースする処理がかなり変わってしまった。
- サジェストされたコードでエラーが発生している場合はそのエラーメッセージをコメントを記述すれば、考慮したコードを再度サジェストしてくれる。
おわりに
GitHub Copilotに頼りながらDynamoDBテーブル上のデータをSDKで操作する関数(TypeScript)を作成してみました。
コメントで要求を書くとコードをサジェストしてくれる体験はすごく面白いですが、サジェストのされ方に癖があったり試行毎にサジェスト内容が変わるため、欲しいコードを引き出すために若干のコツが必要だという印象を受けました。
今回は単一のモジュール上でのCopilotの動作を試しましたが、次回は複数のモジュールにまたがる場合の動作を試してみたいと思います。
以上