> *文章作者:Kris Schultz*
>
> *3D Specialist Solutions Architect, Amazon Web Services*
>
> *文章译者:郑予彬*
>
> *亚马逊云科技资深开发者布道师*
>
> *代码校验:阙铭飞*
>
> *亚马逊云科技大中华区解决方案研发中心 解决方案架构师*
[Amazon CodeWhisperer](https://aws.amazon.com/codewhisperer/?trk=cndc-detail) 是一款很赞的生成式人工智能编程工具。自从在工作中使用了 CodeWhisperer,我发现不仅代码编译的效率有所提高,应用开发的工作也变得快乐起来。然而,任何生成式 AI 工具的有效学习都需要初学者要有接受新工作方式的的心态和意愿。
作为一名早期的“探索者”,我发现了几个对我很有用的功能和可以提高生产效率的小技巧,将在这篇文章中和大家分享:
* 减少输入
* 函数生成
* 类的生成
* 算法的实现
* 单元测试的编写
* 创建示例数据
* 简化正则表达式
* 更快地学习第三方代码库
* 代码的文档化
## **CodeWhiperer 的安装部署**
使用 Codewhiperer,需要在你的集成式开发环境(IDE)中安装最新的 Amazon Toolkit。支持的 IDE 包括 Visual Studio(VS)Code 和 JetBrains IDE(IntelliJ、PyCharm、CLion、GoLand、WebStorm、Rider、PhpStorm、RubyMine 和 DataGrip)。另外,CodeWhisperer 被内置了 Amazon Cloud9 和 Amazon Lambda 控制台, 也可以在 JupyterLab、[Amazon SageMaker](https://aws.amazon.com/cn/sagemaker/?trk=cndc-detail) Studio、以及 Amazon Glue Studio Code 中通过加入 CodeWhisperer extension 进行使用。有关设置说明,请参阅:[CodeWhisperer “入门” 资源](https://aws.amazon.com/codewhisperer/resources/?trk=cndc-detail)。
CodeWhisperer 为输入需求自动提供建议。如果没有收到建议,可以随时使用 **Option + C (Mac)** 或 **Alt + C (Windows)** 快捷方式手动触发。
CodeWhisperer 有时还会向你提供多种建议以供选择。你可以按 → 和 ← 键循环浏览所有可用的建议。
CodeWhisperer 提供的建议是非确定性的,这意味着开发者收到的建议可能与本文中显示的建议略有不同。如果收到的建议不符合需求,可以尝试使用箭头键循环浏览所有可用的建议,或者尝试稍微改写任何代码注释提示。即使是标点符号的变化也可能产生新的建议。
本文中的示例是用 JavaScript 和 TypeScript 编写的。当然,演示操作同样适用于 CodeWhisperer 支持的其他编程语言。
## **减少输入**
对于常见的代码功能实现,CodeWhisperer 的作用在于功能完成自动化,这大大减少了编写**单行代码**或**代码块**时的键入次数。CodeWhisperer 在键入时自动提供建议。当建议有用时接受这些建议,当建议没有帮助时则忽略这些建议。根据我的经验,仅以这种方式使用 CodeWhisperer 可以使我的文字输入减少 **50%** 或更多。
## **函数生成**
### **根据函数名自动生成函数**
资深的程序员为其函数和参数提供清晰准确的描述性名称。如果你在自己的编程中遵循这种做法,**CodeWhisperer** 将拥有为你实现许多功能所需的所有上下文。
在输入下面的函数名后,**CodeWhisperer** 生成的函数体。
**用户输入 (JavaScript)**
```JavaScript
function standardDeviation(numbers)
```
**结果:**
```JavaScript
function standardDeviation(numbers) {
const avg = average(numbers);
const variance = numbers.map((x) => Math.pow(x - avg, 2)).reduce((a, b) => a + b, 0) / numbers.length;
return Math.sqrt(variance);
}
```
### **根据描述生成函数**
有时,仅凭一个好的函数签名不足以传达函数的预期行为。在这些情况下,可以使用详细的代码注释作为提示发给 CodeWhisperer。建议在选择这种方式时使用相应语言的文档注释分隔符。
**用户输入 (JavaScript)**
```JavaScript
/**
* Given a list that contains some numbers and strings, format them into a string
* in which the numbers are prepended with "#" and the strings are wrapped in
* double quotes.
*/
```
**结果:**
```JavaScript
/**
* Given a list that contains some numbers and strings, format them into a string
* in which the numbers are prepended with "#" and the strings are wrapped in
* double quotes.
*/
function formatList(list) {
return list
.map((item) => {
if (typeof item === "number") {
return `#\${item}`;
} else {
return `"\${item}"`;
}
})
.join(", ");
}
```
## **类的生成**
可以通过单个代码注释生成完整或部分的类实现。注释应描述该类的关键属性和行为。
**用户输入(TypeScript):**
```TypeScript
/**
* A folder has a name, children, and an optional parent. A child can't be added
* twice.
*/
```
**结果:**
在完成上面的函数块注释之后,CodeWhisperer 提供了多种建议,并附有每种方法的文档注释!
```TypeScript
/**
* A folder has a name, children, and an optional parent. A child can't be added
* twice.
*/
class Folder {
constructor(name, parent) {
this.name = name;
this.children = [];
this.parent = parent;
}
/**
* Add a child to the folder.
* @param child The child to add.
* @returns True if the child was added, false if it was already present.
*/
addChild(child) {
if (this.children.includes(child)) {
return false;
}
this.children.push(child);
return true;
}
/**
* Remove a child from the folder.
* @param child The child to remove.
* @returns True if the child was removed, false if it wasn't present.
*/
removeChild(child) {
if (!this.children.includes(child)) {
return false;
}
this.children.splice(this.children.indexOf(child), 1);
return true;
}
}
```
## **算法的实现**
CodeWhisperer 能够轻松实现**通用的算法**。只需告诉 CodeWhisperer 你想将哪种算法应用于特定的编码问题,它就会执行。
**用户输入 (JavaScript)**
```JavaScript
const actors = [ ... ];
// Sort the actors by age using the merge sort algorithm.
```
**结果:**
```JavaScript
const actors = [
{name: 'Tom Cruise', age: 56},
{name: 'Meryl Streep', age: 49},
{name: 'Jack Nicholson', age: 39},
{name: 'Christopher Walken', age: 53}
];
// Sort the actors by age using the merge sort algorithm.
function mergeSort(arr) {
if (arr.length <= 1) {
return arr;
}
const middle = Math.floor(arr.length / 2);
const left = arr.slice(0, middle);
const right = arr.slice(middle);
return merge(mergeSort(left), mergeSort(right));
}
function merge(left, right) {
const result = [];
while (left.length && right.length) {
if (left[0].age < right[0].age) {
result.push(left.shift());
} else {
result.push(right.shift());
}
}
while (left.length) {
result.push(left.shift());
}
while (right.length) {
result.push(right.shift());
}
return result;
}
```
## **单元测试的编写**
CodeWhisperer 加速了单元测试的实现。不仅能够实现我请求的大多数明确的单元测试的逻辑,而且经常为我甚至没有想到的边缘情况来建议单元测试。
当我想让 CodeWhisperer 实现一个单元测试时,我会像下面的例子一样,首先声明我正在测试的条件和预期的结果。
**用户输入 (JavaScript)**
```JavaScript
describe("Folder.addChild()", () => {
it("when adding an existing folder should not add duplicate"
```
**结果:**
```JavaScript
describe("Folder.addChild()", () => {
it("when adding an existing folder should not add duplicate", () => {
const folder = new Folder("root");
const child = new Folder("child");
expect(folder.addChild(child)).toBe(true);
expect(folder.addChild(child)).toBe(false);
});
it("when adding a new folder should add it", () => {
const folder = new Folder("root");
const child = new Folder("child");
expect(folder.addChild(child)).toBe(true);
});
it("when adding a new folder should add it to parent", () => {
const folder = new Folder("root");
const child = new Folder("child");
folder.addChild(child);
expect(child.parent).toBe(folder);
});
}
```
在完成一两个测试之后,即使没有明确的提示,CodeWhisperer 也会建议更多的测试。在后续的文章和视频里,我们将展示 CodeWhisperer 更多的测试建议。
**提示**:你会注意到我的测试描述包括:
1. 我正在测试的函数;
2. 我正在测试的条件;
3. 我期望的结果。
遵循这个由三部分组成的模式是确保 CodeWhisperer 拥有实现高质量测试逻辑所需的上下文的好方法。
## **创建示例数据**
我发现,CodeWhisperer 可以生成虚拟数据,或者实际的、具有可重复模式的代码。举例来说,在下面的列表中,我只输入了第一个 “用户” 对象作为示例,CodeWhisperer 就很好的延续了这个模式。
**用户输入 (JavaScript)**
```JavaScript
const fakeUsers = [
{ name: "User 1", id: "user1" },
```
**结果:**
```JavaScript
const fakeUsers = [
{ name: "User 1", id: "user1" },
{ name: "User 2", id: "user2" },
{ name: "User 3", id: "user3" },
{ name: "User 4", id: "user4" },
{ name: "User 5", id: "user5" },
{ name: "User 6", id: "user6" }
]
```
它甚至可以生成随机但看似合理的值,如下所示:
**用户输入 (JavaScript)**
```JavaScript
const fakeUsers = [
{ name: "Sally", id: "user1" },
```
**结果:**
```JavaScript
const fakeUsers = [
{ name: "Sally", id: "user1" },
{ name: "Bob", id: "user2" },
{ name: "Joe", id: "user3" },
{ name: "Jane", id: "user4" },
{ name: "Jill", id: "user5" },
{ name: "Jack", id: "user6" }
```
## **Regular Expression 简化正则表达式**
虽然 CodeWhisperer 还不能将自然语言自动转换为自定义 Regular Expression,但它确实知道很多常用的 Regular Expression,帮助开发者节省时间。每当你需要正则表达式时,它们随手可得。
让我们来看一个相对复杂但常见的 Regular Expression。
**用户输入 (JavaScript)**
```JavaScript
/**
* Function that validates whether a string is a valid email address.
*/
```
**结果:**
```JavaScript
/**
* Function that validates whether a string is a valid email address.
*/
export function isValidEmail(email) {
return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+\$/.test(email);
}
```
## **快速学习第三方代码库**
当使用不熟悉的库、模块或框架时,CodeWhisperer 有助于加快自学习速度。
在下面的示例中,我需要编写一个实用函数,该函数将获取来自 API 的 gzip 压缩值并将其转换成其余代码可以理解的值。我知道 “pako” 库会帮助到我,但我不知道如何使用。于是我给 CodeWhisperer 提示:一条导入声明和一条描述我目的的描述。
```JavaScript
import pako from "pako";
/**
* Accepts a base64-encoded, gzip-compressed JSON string and returns
* a parsed JSON object.
*/
```
**结果:**
```JavaScript
import pako from "pako";
/**
* Accepts a base64-encoded, gzip-compressed JSON string and returns
* a parsed JSON object.
*/
export default function decompress(str) {
const buffer = pako.inflate(atob(str));
const json = buffer.toString();
return JSON.parse(json);
}
```
## **代码的文档化**
CodeWhisperer 能为生成的代码和现有的代码生成文档和注释。
例如,假设我想要 CodeWhisperer 帮我为 **FavoritesFilter** TypeScript 类的 matches() 方法生成文档注释。
```TypeScript
class FavoritesFilter implements IAssetFilter {
...
matches(asset: Asset): boolean {
...
}
}
```
我们知需要在方法名称的正上方键入文档注释分隔符(/** */),CodeWhisperer 就会为我生成文档注释的正文。
**注意**:当 CodeWhisperer 用于这个场景时,我们需要使用 **Option + C (Mac)** 或 **Alt + C (Windows)** 手动触发建议。
## **结论**
希望上面的分享能激发你开始尝试使用 CodeWhisperer 这样智能的代码工具的想法。立即[安装 CodeWhisperer](https://aws.amazon.com/codewhisperer/resources/?trk=cndc-detail),并开始在自己的项目中使用这些节省时间的方法和技巧。当然,这些建议和技巧只是 CodeWhisper 的部分功能。随着更多有开发者开始将 CodeWhisperer 应用到他们的日常工作流程中,我相信更多的技巧、经验和最佳实践还将持续出现。如果你也有心得体验,请发表评论让我们知道。你的分享会对更多的人有所帮助。
## **参考资料**
* [10 ways to build applications faster with Amazon CodeWhisperer](https://aws.amazon.com/cn/blogs/devops/10-ways-to-build-applications-faster-with-amazon-codewhisperer/?trk=cndc-detail)
* [Amazon CodeWhisperer Startup](https://aws.amazon.com/cn/codewhisperer/resources/?trk=cndc-detail)
* [Amazon CodeWhisperer User Guide](https://docs.aws.amazon.com/codewhisperer/latest/userguide/sagemaker-setup.html?trk=cndc-detail)
![Build on cloud.gif](https://dev-media.amazoncloud.cn/fb5a04aa37e349f6b8905ca492e10071_Build%20on%20cloud.gif "Build on cloud.gif")