概要
にわかに騒がれて久しいgptですが、やはりエンジニアの端くれとして「こいつにプログラミングやらせてみたらどうなるんだ?」という好奇心は尽きないものです。
今回は、その一端として「レビューとリファクタリング」をやらせてみた。という内容です。
やってみたこと
以前プライベートで公開したQiitaの記事の中でオープンにしているスクリプトに対して、レビューとリファクタリングをやってみました。
使用したスクリプトはこちら(2019年作成のものなのでかなり古めかしい…)
元のスクリプト
/**
* reply
* ユーザからのアクションに返信する
*/
function reply(data) {
// POST情報から必要データを抽出
var lineUserId = data.events[0].source.userId;
var postMsg = data.events[0].message.text;
var replyToken = data.events[0].replyToken;
var action = data.events[0].message.action;
// 記録用に検索語とuserIdを記録
// debug(postMsg, lineUserId);
debug(action, lineUserId);
// 検索語に対しての回答をSSから取得
var answers = findResponseArray(postMsg);
// 回答メッセージを作成
var replyText = '「' + postMsg + '」ですね。かしこまりました。以下、回答です。';
// 回答の有無に応じて分岐
if (answers.length === 0) {
// 「類似の検索キーワード」がないかチェック
var mayBeWord = findMaybe(postMsg);
if (typeof mayBeWord === "undefined") {
// 回答がない場合の定型文
sendMessage(replyToken, '答えが見つかりませんでした。別のキーワードで質問してみてください。');
} else {
sendMayBe(replyToken, mayBeWord);
}
} else {
// 回答がある場合のメッセージ生成
answers.forEach(function(answer) {
replyText = replyText + "\n\n=============\n\nQ:" + answer.key + "\n\nA:" + answer.value;
});
// 1000文字を超える場合は途中で切る
if (replyText.length > 1000) {
replyText = replyText.slice(0,1000) + "……\n\n=============\n\n回答文字数オーバーです。詳細に検索キーワードを絞ってください。";
}
// メッセージAPI送信
sendMessage(replyToken, replyText);
}
}
#やってみた
とりあえずレビューを依頼
1. コメントへの指摘
コメントの言語が英語と日本語が混在しているため、一貫性を保つために、すべてのコメントを同じ言語(英語または日本語)に統一することをお勧めします。
仰るとおりです、直します。
2. 関数定義の確認
GASスクリプトには、findResponseArray()、debug()、findMaybe()、およびsendMessage()関数が含まれていることが前提となっていますが、これらの関数が定義されていないため、その実装が適切であることを確認してください。
あーこれはですね、大丈夫です。このファイルの外に定義してありますので動作します。ありがとう。
3. 未使用の変数
以下の行に関して、action変数がdata.events[0].message.actionから取得されていますが、これはLINEのWebhookイベントオブジェクトから直接取得することはできません。action変数は使用されていないため、この行を削除しても問題ありません。
var action = data.events[0].message.action;
仰るとおりです。消します。
4. 仕様へのコメント
コードの一部が、特定の文字数を超えた場合にメッセージを切り取るための処理が含まれています。ただし、LINEのメッセージには最大文字数が制限されているため、代わりに複数のメッセージに分割して送信することを検討してください。
確かに。これは仕様検討します。
総評
以上の点を修正することで、コードの品質と可読性が向上すると考えられます。全体的に、良いスクリプトであると言えますが、いくつかの改善点があります。
押忍、あざす。
次に早期returnする修正を指示
修正内容
function reply(data) {
var lineUserId = data.events[0].source.userId;
var postMsg = data.events[0].message.text;
var replyToken = data.events[0].replyToken;
// 記録用に検索語とuserIdを記録
debug(lineUserId, postMsg);
var answers = findResponseArray(postMsg);
if (answers.length === 0) {
var mayBeWord = findMaybe(postMsg);
if (typeof mayBeWord === "undefined") {
sendMessage(replyToken, '答えが見つかりませんでした。別のキーワードで質問してみてください。');
return;
} else {
sendMayBe(replyToken, mayBeWord);
return;
}
}
var replyText = '「' + postMsg + '」ですね。かしこまりました。以下、回答です。';
answers.forEach(function(answer) {
replyText = replyText + "\n\n=============\n\nQ:" + answer.key + "\n\nA:" + answer.value;
});
if (replyText.length > 1000) {
replyText = replyText.slice(0,1000) + "……\n\n=============\n\n回答文字数オーバーです。詳細に検索キーワードを絞ってください。";
}
sendMessage(replyToken, replyText);
}
おおお、たしかに処理を修正するタイミングが見極められている。素晴らしい。
関数に切り出させてみた
さらに雑い感じで整理を依頼しました。果たして適切な関数に切り出しができるか。

やりよった

修正後のスクリプト
function reply(data) {
var lineUserId = data.events[0].source.userId;
var postMsg = data.events[0].message.text;
var replyToken = data.events[0].replyToken;
// 記録用に検索語とuserIdを記録
debug(lineUserId, postMsg);
var answers = findResponseArray(postMsg);
sendResponse(replyToken, postMsg, answers);
}
function sendResponse(replyToken, postMsg, answers) {
if (answers.length === 0) {
var mayBeWord = findMaybe(postMsg);
if (typeof mayBeWord === "undefined") {
sendMessage(replyToken, '答えが見つかりませんでした。別のキーワードで質問してみてください。');
} else {
sendMayBe(replyToken, mayBeWord);
}
return;
}
var replyText = buildReplyText(postMsg, answers);
sendMessage(replyToken, replyText);
}
function buildReplyText(postMsg, answers) {
var replyText = '「' + postMsg + '」ですね。かしこまりました。以下、回答です。';
answers.forEach(function(answer) {
replyText = replyText + "\n\n=============\n\nQ:" + answer.key + "\n\nA:" + answer.value;
});
if (replyText.length > 1000) {
replyText = replyText.slice(0,1000) + "……\n\n=============\n\n回答文字数オーバーです。詳細に検索キーワードを絞ってください。";
}
return replyText;
}
やりよる…命名も悪くない(気がする)。
終わりに。
ソースコド丸投げは多分業務上しばらくできない気もしますが、普段貰わない人からレビューを受けている間隔でとても新鮮でした。ご参考までに。
おまけ
Class作らせてみたりもしましたが、これは如何に(まだ未判断)
class ReplyHandler {
constructor(data) {
this.lineUserId = data.events[0].source.userId;
this.userMessage = data.events[0].message.text;
this.replyToken = data.events[0].replyToken;
}
processReply() {
// 記録用に検索語とuserIdを記録
debug(this.lineUserId, this.userMessage);
const answers = findResponseArray(this.userMessage);
this.sendResponse(this.userMessage, answers);
}
sendResponse(userMessage, answers) {
if (answers.length === 0) {
const mayBeWord = findMaybe(userMessage);
if (typeof mayBeWord === "undefined") {
sendMessage(this.replyToken, '答えが見つかりませんでした。別のキーワードで質問してみてください。');
} else {
sendMayBe(this.replyToken, mayBeWord);
}
return;
}
const replyText = this.buildReplyText(userMessage, answers);
sendMessage(this.replyToken, replyText);
}
buildReplyText(userMessage, answers) {
let replyText = '「' + userMessage + '」ですね。かしこまりました。以下、回答です。';
answers.forEach(function(answer) {
replyText = replyText + "\n\n=============\n\nQ:" + answer.key + "\n\nA:" + answer.value;
});
if (replyText.length > 1000) {
replyText = replyText.slice(0,1000) + "……\n\n=============\n\n回答文字数オーバーです。詳細に検索キーワードを絞ってください。";
}
return replyText;
}
}
function reply(data) {
const replyHandler = new ReplyHandler(data);
replyHandler.processReply();
}




