自从踏上AI辅助开发这条不归路,就回不了头,只能勇往直前!就算是简单的智能提示、补充代码、自动多语言补全等功能,就已经让你离不开它,更何况强大的代码生成成功。如果还没有开始使用AI辅助开发,那么赶快为自己的开发工具安装一个免费的AI助手,基本上目前流行的开发工具都会有对应的免费的辅助AI插件。
对于第一次使用AI辅助开发的开发者,记住一点:给出的问题,也就是需求,越详细,AI给的代码就越完整,功能也完善。本文将通过一个实例来探讨如何让AI助手生成满意的代码。
本文的开发环境为vs code
,AI助手将使用Fitten Code
扩展。安装完Fitten Code
后,会在主侧边栏显示一个Fitten Code
的图标,切换到Fitten Code
,在底部会有一个输入框,输入想要的问题就能生成所需的代码。
现在,在输入框输入“使用Typescript创建一个仓储用来获取远程数据”并按回车发送,将会看到以下返回信息:
从生成的Repository
类可以看到,已经生成了getAll
和getById
方法,并建议添加create
、update
和delete
等方法。当然,你应该不会满足于此,获取数据时,分页、过滤和高级过滤等等功能还没添加,建议的三个方法也生成,这时候,就需要列一个详细的需求给它,让它生成更完整的代码。
下面在输入框输入以下需求:
使用Typescript创建一个仓储类用来获取远程数据并具有以下功能:
* 获取传递给构造函数的配置项pageSizes的第一数据作为当前的pageSize,并添加setPageSize方法来设置设置当前的pageSize,要验证设置的pageSize是否在pageSizes中,pageSize改变后,重新加载数据。添加getPageSize方法来获取当前的pageSize。
* 添加setPage方法来设置当前页,当前页改变后,重新加载数据。添加getPage方法来获取当前页,
* 添加filter方法来执行数据过滤
* 添加sort方法来对数据进行排序
* 添加search方法来对数据进行高级过滤
* 添加getTotal方法来获取记录总数
* 添加getPages方法来获取总页数
* 添加load方法来获取远程数据,在执行远程加载前,如果在构造函数中传入了beforeLoad函数,则先执行beforeLoad,如果返回false,则不执行数据加载。如果可以加载数据,则先调用getParams方法整合分页、过滤、高级过滤等数据,为加载数据提供参数。在数据加载后,如果从构造函数中传入了afterLoad函数,则执行afterLoad函数,然后触发laod事件。
* 添加create方法用来保存新记录
* 添加update方法用来更新记录
* 添加delete方法用来删除记录
* 添加一个方法用来获取单一数据
等待一会就会得到以下代码:
import axios, { AxiosResponse } from 'axios';interface RemoteData {id: number;name: string;// 其他字段...
}interface RepositoryConfig {baseUrl: string;pageSizes: number[];beforeLoad?: () => boolean;afterLoad?: (data: RemoteData[]) => void;
}class AdvancedRepository {private baseUrl: string;private pageSizes: number[];private pageSize: number;private page: number;private total: number;private data: RemoteData[];private beforeLoad?: () => boolean;private afterLoad?: (data: RemoteData[]) => void;constructor(config: RepositoryConfig) {this.baseUrl = config.baseUrl;this.pageSizes = config.pageSizes;this.pageSize = config.pageSizes[0];this.page = 1;this.total = 0;this.data = [];this.beforeLoad = config.beforeLoad;this.afterLoad = config.afterLoad;}public setPageSize(size: number): void {if (!this.pageSizes.includes(size)) {throw new Error('Invalid page size');}this.pageSize = size;this.load();}public getPageSize(): number {return this.pageSize;}public setPage(page: number): void {this.page = page;this.load();}public getPage(): number {return this.page;}public filter(filterFn: (item: RemoteData) => boolean): void {this.data = this.data.filter(filterFn);}public sort(sortFn: (a: RemoteData, b: RemoteData) => number): void {this.data.sort(sortFn);}public search(searchFn: (item: RemoteData) => boolean): void {this.data = this.data.filter(searchFn);}public getTotal(): number {return this.total;}public getPages(): number {return Math.ceil(this.total / this.pageSize);}public async load(): Promise<void> {if (this.beforeLoad && !this.beforeLoad()) {return;}const params = this.getParams();try {const response: AxiosResponse<{ data: RemoteData[]; total: number }> = await axios.get(`${this.baseUrl}/data`, { params });this.data = response.data.data;this.total = response.data.total;if (this.afterLoad) {this.afterLoad(this.data);}// 触发load事件} catch (error) {console.error('Error fetching data:', error);throw error;}}private getParams(): any {return {page: this.page,pageSize: this.pageSize,// 其他参数...};}public async create(data: RemoteData): Promise<RemoteData> {try {const response: AxiosResponse<RemoteData> = await axios.post(`${this.baseUrl}/data`, data);this.load();return response.data;} catch (error) {console.error('Error creating data:', error);throw error;}}public async update(id: number, data: RemoteData): Promise<RemoteData> {try {const response: AxiosResponse<RemoteData> = await axios.put(`${this.baseUrl}/data/${id}`, data);this.load();return response.data;} catch (error) {console.error('Error updating data:', error);throw error;}}public async delete(id: number): Promise<void> {try {await axios.delete(`${this.baseUrl}/data/${id}`);this.load();} catch (error) {console.error('Error deleting data:', error);throw error;}}public async getById(id: number): Promise<RemoteData> {try {const response: AxiosResponse<RemoteData> = await axios.get(`${this.baseUrl}/data/${id}`);return response.data;} catch (error) {console.error(`Error fetching data with id ${id}:`, error);throw error;}}
}// 使用示例
const repo = new AdvancedRepository({baseUrl: 'https://api.example.com',pageSizes: [10, 20, 50],beforeLoad: () => {// 执行一些预加载逻辑return true;},afterLoad: (data) => {console.log('Data loaded:', data);}
});repo.load().then(() => {console.log('Data loaded');
}).catch(error => {console.error('Error:', error);
});
虽然代码不尽人意,但起码已具雏形。这时候你的选择可以是重新组织需求,再次生成,或者选择全部代码,在选择代码上单击鼠标右键,在右键菜单中选择Fitten Code - 开始聊天
,然后在输入框中输入:
在filter方法中,用filter属性记录当前过滤值,然后重新调用load方法。sort和search方法与fitler方法类似。在数据加载后,从data中获取记录, 如果有afterLoad函数,则将afterLoad函数返回值作为data属性的值,在更新total后,根据pageSize重新计算pages。
以下是返回的代码:
import axios, { AxiosResponse } from 'axios';interface RemoteData {id: number;name: string;// 其他字段...
}interface RepositoryConfig {baseUrl: string;pageSizes: number[];beforeLoad?: () => boolean;afterLoad?: (data: RemoteData[]) => void;
}class Repository {private baseUrl: string;private pageSizes: number[];private pageSize: number;private page: number;private total: number;private data: RemoteData[];private beforeLoad?: () => boolean;private afterLoad?: (data: RemoteData[]) => void;private filterFn?: (item: RemoteData) => boolean;private sortFn?: (a: RemoteData, b: RemoteData) => number;private searchFn?: (item: RemoteData) => boolean;constructor(config: RepositoryConfig) {this.baseUrl = config.baseUrl;this.pageSizes = config.pageSizes;this.pageSize = config.pageSizes[0];this.page = 1;this.total = 0;this.data = [];this.beforeLoad = config.beforeLoad;this.afterLoad = config.afterLoad;}public setPageSize(size: number): void {if (!this.pageSizes.includes(size)) {throw new Error('Invalid page size');}this.pageSize = size;this.load();}public getPageSize(): number {return this.pageSize;}public setPage(page: number): void {this.page = page;this.load();}public getPage(): number {return this.page;}public filter(filterFn: (item: RemoteData) => boolean): void {this.filterFn = filterFn;this.load();}public sort(sortFn: (a: RemoteData, b: RemoteData) => number): void {this.sortFn = sortFn;this.load();}public search(searchFn: (item: RemoteData) => boolean): void {this.searchFn = searchFn;this.load();}public getTotal(): number {return this.total;}public getPages(): number {return Math.ceil(this.total / this.pageSize);}public async load(): Promise<void> {if (this.beforeLoad && !this.beforeLoad()) {return;}const params = this.getParams();try {const response: AxiosResponse<{ data: RemoteData[]; total: number }> = await axios.get(`${this.baseUrl}/data`, { params });let data = response.data.data;if (this.filterFn) {data = data.filter(this.filterFn);}if (this.sortFn) {data.sort(this.sortFn);}if (this.searchFn) {data = data.filter(this.searchFn);}this.data = data;this.total = response.data.total;if (this.afterLoad) {this.data = this.afterLoad(this.data);}} catch (error) {console.error('Error fetching data:', error);throw error;}}private getParams(): any {return {page: this.page,pageSize: this.pageSize,// 其他参数...};}public async create(data: RemoteData): Promise<RemoteData> {try {const response: AxiosResponse<RemoteData> = await axios.post(`${this.baseUrl}/data`, data);this.load();return response.data;} catch (error) {console.error('Error creating data:', error);throw error;}}public async update(id: number, data: RemoteData): Promise<RemoteData> {try {const response: AxiosResponse<RemoteData> = await axios.put(`${this.baseUrl}/data/${id}`, data);this.load();return response.data;} catch (error) {console.error('Error updating data:', error);throw error;}}public async delete(id: number): Promise<void> {try {await axios.delete(`${this.baseUrl}/data/${id}`);this.load();} catch (error) {console.error('Error deleting data:', error);throw error;}}public async getById(id: number): Promise<RemoteData> {try {const response: AxiosResponse<RemoteData> = await axios.get(`${this.baseUrl}/data/${id}`);return response.data;} catch (error) {console.error(`Error fetching data with id ${id}:`, error);throw error;}}
}
从返回的代码可以看到,AI还是没完全领会,filter等是作为远程参数去获取数据,还是只做了本地过滤,这也只能怪自己没把需求说清楚。重复选择代码,开始聊天的操作并输入:
在getParams中整合filter、sort、search等信息作为远程查询的参数,而不是对返回的数据执行过滤和排序
以下是更新好的代码:
import axios, { AxiosResponse } from 'axios';interface RemoteData {id: number;name: string;// 其他字段...
}interface RepositoryConfig {baseUrl: string;pageSizes: number[];beforeLoad?: () => boolean;afterLoad?: (data: RemoteData[]) => void;
}class Repository {private baseUrl: string;private pageSizes: number[];private pageSize: number;private page: number;private total: number;private data: RemoteData[];private beforeLoad?: () => boolean;private afterLoad?: (data: RemoteData[]) => void;private filterParams?: any;private sortParams?: any;private searchParams?: any;constructor(config: RepositoryConfig) {this.baseUrl = config.baseUrl;this.pageSizes = config.pageSizes;this.pageSize = config.pageSizes[0];this.page = 1;this.total = 0;this.data = [];this.beforeLoad = config.beforeLoad;this.afterLoad = config.afterLoad;}public setPageSize(size: number): void {if (!this.pageSizes.includes(size)) {throw new Error('Invalid page size');}this.pageSize = size;this.load();}public getPageSize(): number {return this.pageSize;}public setPage(page: number): void {this.page = page;this.load();}public getPage(): number {return this.page;}public filter(filterParams: any): void {this.filterParams = filterParams;this.load();}public sort(sortParams: any): void {this.sortParams = sortParams;this.load();}public search(searchParams: any): void {this.searchParams = searchParams;this.load();}public getTotal(): number {return this.total;}public getPages(): number {return Math.ceil(this.total / this.pageSize);}public async load(): Promise<void> {if (this.beforeLoad && !this.beforeLoad()) {return;}const params = this.getParams();try {const response: AxiosResponse<{ data: RemoteData[]; total: number }> = await axios.get(`${this.baseUrl}/data`, { params });this.data = response.data.data;this.total = response.data.total;if (this.afterLoad) {this.data = this.afterLoad(this.data);}} catch (error) {console.error('Error fetching data:', error);throw error;}}private getParams(): any {const params: any = {page: this.page,pageSize: this.pageSize,// 其他参数...};if (this.filterParams) {Object.assign(params, this.filterParams);}if (this.sortParams) {Object.assign(params, this.sortParams);}if (this.searchParams) {Object.assign(params, this.searchParams);}return params;}public async create(data: RemoteData): Promise<RemoteData> {try {const response: AxiosResponse<RemoteData> = await axios.post(`${this.baseUrl}/data`, data);this.load();return response.data;} catch (error) {console.error('Error creating data:', error);throw error;}}public async update(id: number, data: RemoteData): Promise<RemoteData> {try {const response: AxiosResponse<RemoteData> = await axios.put(`${this.baseUrl}/data/${id}`, data);this.load();return response.data;} catch (error) {console.error('Error updating data:', error);throw error;}}public async delete(id: number): Promise<void> {try {await axios.delete(`${this.baseUrl}/data/${id}`);this.load();} catch (error) {console.error('Error deleting data:', error);throw error;}}public async getById(id: number): Promise<RemoteData> {try {const response: AxiosResponse<RemoteData> = await axios.get(`${this.baseUrl}/data/${id}`);return response.data;} catch (error) {console.error(`Error fetching data with id ${id}:`, error);throw error;}}
}
如果觉得代码还是不太满意,可以继续重复以下操作更改代码直到满意,还可以选择代码后,在选择代码上单击鼠标右键选择Fitter Code - 优化代码
,让它自己去优化代码,返回结果如下:
import axios, { AxiosResponse } from 'axios';interface RemoteData {id: number;name: string;// 其他字段...
}interface RepositoryConfig {baseUrl: string;pageSizes: number[];beforeLoad?: () => boolean;afterLoad?: (data: RemoteData[]) => void;
}class Repository {private baseUrl: string;private pageSizes: number[];private pageSize: number;private page: number;private total: number;private data: RemoteData[];private beforeLoad?: () => boolean;private afterLoad?: (data: RemoteData[]) => void;private filterParams?: any;private sortParams?: any;private searchParams?: any;constructor(config: RepositoryConfig) {this.baseUrl = config.baseUrl;this.pageSizes = config.pageSizes;this.pageSize = config.pageSizes[0];this.page = 1;this.total = 0;this.data = [];this.beforeLoad = config.beforeLoad;this.afterLoad = config.afterLoad;}public setPageSize(size: number): void {if (!this.pageSizes.includes(size)) {throw new Error('Invalid page size');}this.pageSize = size;this.load();}public getPageSize(): number {return this.pageSize;}public setPage(page: number): void {this.page = page;this.load();}public getPage(): number {return this.page;}public filter(filterParams: any): void {this.filterParams = filterParams;this.load();}public sort(sortParams: any): void {this.sortParams = sortParams;this.load();}public search(searchParams: any): void {this.searchParams = searchParams;this.load();}public getTotal(): number {return this.total;}public getPages(): number {return Math.ceil(this.total / this.pageSize);}public async load(): Promise<void> {if (this.beforeLoad && !this.beforeLoad()) {return;}const params = this.getParams();try {const response: AxiosResponse<{ data: RemoteData[]; total: number }> = await axios.get(`${this.baseUrl}/data`, { params });this.data = response.data.data;this.total = response.data.total;if (this.afterLoad) {this.data = this.afterLoad(this.data);}} catch (error) {console.error('Error fetching data:', error);throw error;}}private getParams(): any {const params: any = {page: this.page,pageSize: this.pageSize,// 其他参数...};if (this.filterParams) {Object.assign(params, this.filterParams);}if (this.sortParams) {Object.assign(params, this.sortParams);}if (this.searchParams) {Object.assign(params, this.searchParams);}return params;}public async create(data: RemoteData): Promise<RemoteData> {try {const response: AxiosResponse<RemoteData> = await axios.post(`${this.baseUrl}/data`, data);this.load();return response.data;} catch (error) {console.error('Error creating data:', error);throw error;}}public async update(id: number, data: RemoteData): Promise<RemoteData> {try {const response: AxiosResponse<RemoteData> = await axios.put(`${this.baseUrl}/data/${id}`, data);this.load();return response.data;} catch (error) {console.error('Error updating data:', error);throw error;}}public async delete(id: number): Promise<void> {try {await axios.delete(`${this.baseUrl}/data/${id}`);this.load();} catch (error) {console.error('Error deleting data:', error);throw error;}}public async getById(id: number): Promise<RemoteData> {try {const response: AxiosResponse<RemoteData> = await axios.get(`${this.baseUrl}/data/${id}`);return response.data;} catch (error) {console.error(`Error fetching data with id ${id}:`, error);throw error;}}
}
在通过手动和互动等方法完成代码后,就可以让AI帮忙生成完整的单元测试代码,获得最终的代码了。
从以上的探讨过程可以看到,AI还不能做到尽善尽美,但已经可以大大提高开发效率了。不过要注意的是,有时候AI会陷入死循环,譬如说A这样会导致问题B,然后它去改,问题B解决了,但会出现A的问题没有解决,然后它就进入死循环,A和B来回切换,这时候,就要换个思路了,不要和它继续纠缠下去,不然会很累。可行的办法有换个解决问题的思路,或者找其他免费的AI辅助,如千义通问等等,这些AI各具特色,有自己擅长的东西,多问几个,会获得更精准的解决方案。笔者觉得更重要的是,提高自己的设计能力和需求讲述能力,将可大大释放AI的能力。