随着最近ChatGPT、AutoGPT的诞生,如何利用AI提效赋能成为了大家关注的焦点。然而,OpenAI较高的实用门槛(科学上网),使得大部分程序猿只能望洋兴叹,空有渴望AI的能力,却无使用AI的途径。
而最近,一款名为Bito AI的插件横空出世。通过这款工具,可以让AI轻松编写代码、解析语意、编写单测、检查安全性等等功能。可以说是给编程人员带来了不少的福利。更重要的是,这款工具是免费的!且其支持VS Code、Chrome插件以及Jetbrains的全系列IDE,如:IDEA、PyCharm、Clion、GoLand等,几乎可以说是覆盖了大部分开发同学。
今天,我就将这款工具分享给你。
作者编程的工具主要是IDEA,因此我主要介绍IDEA工具下的Bito AI使用教程。通过Settings => Plugins,在插件市场中搜索"bito"就可以搜索到对应的插件。点击安装后并重启IDEA,就可以在右侧边栏找到插件啦~
在插件的右下角,介绍了目前插件支持的功能,从左到右依次是:代码解释、生成注释、性能检测、安全检测、风格测试、提高可读性、代码整洁、生成单元测试。
这里我主要挑代码解释、安全检查、生成单元测试这三个我个人觉得最有用的功能做个简单的介绍。
对于一些好奇心旺盛的程序员来说,知其然也要知其所以然。为了探究实现的原理,往往离不开查看源码的过程。以我最近在研究的HashMap为例子,他的hash方法让我一直疑惑不解:
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
代码本身并不复杂,但是一个右移16位做异或的操作却让我难以理解。为啥要做异或运算?为啥又是右移了16位再做异或运算?我翻遍了百度、知乎,也才笼统的得到一个答案:可能是为了解决哈希冲突。
但是当我向AI请求这段代码的含义时,简简单单就获得了一个清晰易懂的答案。(通过选中你关注的代码,右键就可以打开Bito AI插件,选择explain this code,就可以获取到AI对于这段代码的理解。)
看到答案的我也不由的惊呼起来,有这等工具加持,我还会怕冗长的Spring框架看不懂吗?我还会害怕自己理解不了繁琐的源码原理吗?
显然,有了这样的工具,对于程序员理解框架、理解内在的实现含义,必然是一大助力。
在日常业务代码中,我们难免会遇到一些【可能出现异常的情况】,最常见的比如空指针异常。那么是否可以借助于AI的能力,尽可能的避免空指针,避免成为团队的"Null-King/Queue"呢?答案是肯定的。
同上述操作类型,我们可以通过选中代码后,右键点击进行安全检查,AI就会自动为你的代码做安全检测。
点击之后,AI就会为你分析当前的代码的问题所在,并自动为你生成一份“它”认为的安全的代码:(通过强调一下”使用中文“,可以让AI翻译成一下成你能简单理解的内容。)
在AI生成完代码后,Bito插件还会为你自动生成Diff View,供你判断当前AI到底改动了什么。方便你对代码进行合并。
从生成的代码中我们不难看到,除了对于空指针的判断以为,AI还“自顾自的”为你创建了几种它认为需要检查的情况。如:要校验商品当前是否有效、是否正在使用中等等。通过对自己的代码反复的分析,无疑可以提高编程的质量、减少犯错的概率。
在写完了一段代码以后,为了保证自己逻辑的完整性、可行性,免不了需要写一些单元测试的代码。对于这一点,BitoAI也能够支持。只是遗憾的是,目前BitoAI还做不到像上面一样,通过选中一段代码,并右键点击"Generate Unit Test",BitoAI就能针对你所选择的代码生成一段单元测试。
目前只能通过手动将代码粘贴到右侧的对话框中,让AI自动生成。
原始代码:
@SneakyThrows
public Boolean deductProduct(ProductPO productPO) {
log.info("distribuiteLock:" + JSON.toJSONString(productPO));
//首先获取分布式的锁
RLock lock = redissonClient.getLock("deductProduct");
try {
LOGGER.info("分布式锁加锁!");
//尝试对redis的分布式锁进行加锁
boolean success = lock.tryLock(30, TimeUnit.SECONDS);
if (!success) {
//加锁失败,直接返回
return false;
}
LOGGER.info("查找商品的数据为 :" + JSON.toJSONString(productPO));
Example example = new Example(ProductPO.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("skuId", productPO.getSkuId());
List<ProductPO> productPOS = productMapper.selectByExample(example);
if (CollectionUtils.isEmpty(productPOS)) {
throw new RuntimeException("当前商品不存在");
}
for (ProductPO selectProductPO : productPOS) {
//对对应的sku进行数量扣减
Integer number = selectProductPO.getNumber();
LOGGER.info("当前商品的数量为:" + number);
if (number <= 0) {
//小于等于0时,不进行扣减
continue;
}
selectProductPO.setNumber(number - productPO.getNumber());
productMapper.updateByPrimaryKey(selectProductPO);
}
} finally {
//最后一定记得释放锁资源
LOGGER.info("分布式锁释放!");
lock.unlock();
}
return true;
}
AI生成的单元测试代码:
import org.junit.jupiter.api.Test;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
public class DeductProductTest {
@Mock
private RedissonClient redissonClient;
@Mock
private ProductMapper productMapper;
@InjectMocks
private MyClass myClass;
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testDeductProduct() {
// set up test data
ProductPO productPO = new ProductPO();
productPO.setSkuId("123");
productPO.setNumber(1);
ProductPO existingProductPO = new ProductPO();
existingProductPO.setNumber(10);
// mock RedissonClient.getLock() method
RLock lock = mock(RLock.class);
when(redissonClient.getLock("deductProduct")).thenReturn(lock);
// mock RLock.tryLock() method
when(lock.tryLock(30, TimeUnit.SECONDS)).thenReturn(true);
// mock ProductMapper.selectByExample() method
Example example = new Example(ProductPO.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("skuId", productPO.getSkuId());
when(productMapper.selectByExample(example)).thenReturn(Collections.singletonList(existingProductPO));
// call the method to be tested
boolean result = myClass.deductProduct(productPO);
// assert the result
assertTrue(result);
// verify RedissonClient.getLock() method is called once with the correct parameter
verify(redissonClient, times(1)).getLock("deductProduct");
// verify RLock.tryLock() method is called once with the correct parameters
verify(lock, times(1)).tryLock(30, TimeUnit.SECONDS);
// verify ProductMapper.selectByExample() method is called once with the correct parameter
verify(productMapper, times(1)).selectByExample(example);
// verify ProductMapper.updateByPrimaryKey() method is called once with the correct parameter
verify(productMapper, times(1)).updateByPrimaryKey(existingProductPO);
}
}
尽管生成出来的代码实际上并不能很好的运行起来(mock数据有问题、且类上没有写启动的方法),但是实际上简单的修改修改,基本的一个单测样例就出来了。实际上还是很大的节省了开发的代码内容的。
理性中立客观的来说,虽然当前的BitoAI提供的功能还存在着一定的缺陷。比如部分生成的代码质量不高、解释的语言也更像是一些没用的话术。但是产品本身设计出来的功能和预期实现的目标确实是很诱人。试想一下,如果未来在编写代码的时候,能有一个无所不知的AI协助你,那么你的开发效率是不是可以得到几何倍数的提升呢?
更多干货内容,欢迎关注wx公众号【笑傲菌】~
有哪些好用的 AI 神器推荐?