如何让自己的代码顺利通过代码审查?

news2024/11/27 10:34:09

最近很多同学,都去暑期实习了,实习就意味着要在公司项目是写代码了。

大多数同学,可能面试能力不错,但是实操还是弱了一些。之前有位同学,春招靠面试能力去了大厂,然后实习刚工作的时候,要写代码的时候,发现弱点了,现在在抓紧补代码能力。

之前自己做一些项目,肯定都是没什么代码规范的,都是讲究一个怎么方便怎么写的态度去做,因为项目就自己看,不需要照顾其他人的感受。

然而,到了工作,就不一样啦,你写的代码是需要给其他同事看的,所以代码规范的事情,要注意一下的。

每个公司都有自己的代码规范,但是大差不差。

我们开发完需求,提测前,一般都需要代码评审一般都有哪些军规嘛

这次,给大家带来代码评审的 18 个军规。

img

1. 添加必要的注释

其实,写代码的时候,没有必要写太多的注释,因为好的方法名、变量名,就是最好的注释。以下就是笔者总结的一些注释规范:

  • 所有的类都必须添加创建者和创建日期,以及简单的注释描述

  • 方法内部的复杂业务逻辑或者算法,需要添加清楚的注释

  • 一般情况下,注释描述类、方法、变量的作用

  • 任何需要提醒的警告或TODO,也要注释清楚

  • 如果是注释一行代码的,就用//;如果注释代码块或者接口方法的,有多行/* **/

  • 一块代码逻辑如果你站在一个陌生人的角度去看,第一遍看不懂的话,就需要添加注释了

img

以下就是一些添加注释的demo:

/**
 * @author 田螺
 * @date 2023/04/22 5:20 PM
 * @desc 田螺的实现类,捡田螺、卖田螺
 */
public class TianLuoClass {
 
    /**
     * 这是卖田螺的两法,它将两个田螺的价格整数相加并返回结果。
     * 
     * @param x 第一个整数
     * @param y 第二个整数
     * @return 两个整数的和
     */
    public int sellTianLuo(int x, int y) {
        return x + y;
    }
}

2.日志打印规范

日志是快速定位问题的好帮手,是撕逼和甩锅的利器!打印好日志非常重要。如果代码评审的时候,这些日志规范没遵守,就需要修改

  • 日志级别选择不对。常见的日志级别有error、warn、info、debug四种,不要反手就是info

  • 日志没打印出调用方法的入参和响应结果,尤其是跨系统调用的时候。

  • 业务日志没包含关键参数,如userId,bizSeq等等,不方便问题排查

  • 如果日志包含关键信息,比如手机号、身份证等,需要脱敏处理

  • 一些不符合预期的情况,如一些未知异常(数据库的数据异常等),又或者不符合业务预期的特殊场景,都需要打印相关的日志

3. 命名规范

Java代码的命名应该清晰、简洁和易于理解。我们代码评审的时候,要注意是否有命名不规范,不清晰的代码。下面是一些命名规范的建议:

  • 类和接口应该使用首字母大写的驼峰命名法

  • 方法和变量应该使用小写的驼峰命名法

  • 常量应该使用全大写字母和下划线

  • 开发者是不是选择易于理解的名称给变量、类和方法进行命名

4.参数校验

我们代码评审的时候,要注意参数是否都做了校验,如userId非空检查、金额范围检查、userName长度校验等等。一般我们在处理业务逻辑的时候,要遵循先检查、后处理的原则。

如果你的数据库字段userName设置为varchar(16),对方传了一个32位的字符串过来,你不校验参数,插入数据库直接异常了。

很多bug都是因为没做参数校验造成的,这一军规,是代码评审重点关注的哈

img

5. 判空处理

  • 获取对象的属性时,都要判空处理。要不然很多时候会出现空指针异常。

if(object!=null){
   String name = object.getName();
}

如果你要遍历列表,也需要判空

  if (CollectionUtils.isNotEmpty(tianLuolist)) {
        for (TianLuo temp : tianLuolist) {
            //do something
        }
    }

6. 异常处理规范

良好的异常处理可以确保代码的可靠性和可维护性。因此,异常处理也是代码评审的一项重要规范。以下是一些异常处理的建议:

  • 不要捕获通用的Exception异常,而应该尽可能捕获特定的异常

  • 在捕获异常时,应该记录异常信息以便于调试

  • 内部异常要确认最终的处理方式,避免未知异常当作失败处理

  • finally块中释放资源,或者使用try-with-resource

  • 不要使用e.printStackTrace(),而是使用log打印。

  • catch了异常,要打印出具体的exception,否则无法更好定位问题

  • 捕获异常与抛出异常必须是完全匹配,或者捕获异常是抛异常的父类

  • 捕获到的异常,不能忽略它,要打印相对应的日志

  • 注意异常对你的代码层次结构的侵染(早发现早处理)

  • 自定义封装异常,不要丢弃原始异常的信息Throwable cause

  • 注意异常匹配的顺序,优先捕获具体的异常

  • 对外提供APi时,要提供对应的错误码

  • 系统内部应该抛出有业务含义的自定义异常,而不是直接抛出RuntimeException,或者直接抛出Exception\Throwable

7. 模块化,可扩展性

代码评审的时候,关注一下,代码编写设计是否满足模块话,接口是否具有可扩展性

比如你的需求是酱紫:是用户添加或者修改员工时,需要刷脸。那你是反手提供一个员工管理的提交刷脸信息接口?还是先思考:提交刷脸是不是通用流程呢?比如转账或者一键贴现需要接入刷脸的话,你是否需要重新实现一个接口呢?还是当前按业务类型划分模块,复用这个接口就好,保留接口的可扩展性。

如果按模块划分的话,未来如果其他场景比如一键贴现接入刷脸的话,不用再搞一套新的接口,只需要新增枚举,然后复用刷脸通过流程接口,实现一键贴现刷脸的差异化即可。

img

8. 并发控制规范

  • 在使用并发集合时,应该注意它们的线程安全性和并发性能,如ConcurrentHashMap是线性安全的,HashMap就是非线性安全的

  • 乐观锁,悲观锁防止数据库并发.乐观锁一般用版本号version控制,悲观锁一般用select …for update

  • 如果是单实例的多线程并发处理,一般通过Java锁机制,比如sychronized ,reentrantlock

  • 如果是同一集群的多线程并发处理,可以用Redis分布式锁或者走zookeeper

  • 如果是跨集群的多线程并发处理,则考虑数据库实现的分布式锁。

  • 在使用分布式锁的时候,要注意有哪些坑,比如redis一些经典的坑.

9. 单元测试规范

  • 测试类的命名,一般以测试的类+Test,如:CalculatorTest.

  • 测试方法的命名,一般以test开头+ 测试的方法,如testAdd.

  • 单测行覆盖率一般要求大于75%.

  • 单测一般要求包含主流程用例、参数边界值等校验用例

  • 单测一般也要求包含中间件访问超时、返回空、等异常的用例,比如访问数据库或者Redis异常.

  • 单测用例要求包含并发、防重、幂等等用例.

10. 代码格式规范

良好的代码格式,可以使代码更容易阅读和理解。下面是一些常见的代码格式化建议:

  • 缩进使用四个空格

  • 代码块使用花括号分隔

  • 每行不超过80个字符

  • 每个方法应该按照特定的顺序排列,例如:类变量、实例变量、构造函数、公共方法、私有方法等。

11. 接口兼容性

代码评审的时候,要重点关注是否考虑到了接口的兼容性.因为很多bug都是因为修改了对外旧接口,但是却不做兼容导致的。关键这个问题多数是比较严重的,可能直接导致系统发版失败的。新手程序员很容易犯这个错误哦~

img

所以,如果你的需求是在原来接口上修改,尤其这个接口是对外提供服务的话,一定要考虑接口兼容。举个例子吧,比如dubbo接口,原本是只接收A,B参数,现在你加了一个参数C,就可以考虑这样处理:

//老接口
void oldService(A,B){
  //兼容新接口,传个null代替C
  newService(A,B,null);
}

//新接口,暂时不能删掉老接口,需要做兼容。
void newService(A,B,C){
  ...
}

12. 程序逻辑是否清晰,主次是否够分明

代码评审的时候,要关注程序逻辑是否清晰。比如,你的一个注册接口,有参数校验、判断用户是否已经注册、插入用户记录、发送注册成功通知等功能。如果你把所有所有功能代码塞到一个方法里面,程序逻辑就不清晰,主次不够分明,反例如下:

 public Response registerUser(String userName, String password, String email) {

        if (userName == null || StringUtils.isEmpty(userName)) {
          log.info("用户名不能为空!");
            throw new BizException();
        }

        if (password == null || password.length() < 6) {
            log.info("密码长度不能少于6位!");
            throw new BizException();
        }

        if (email == null || StringUtils.isEmpty(email) || !email.contains("@")) {
            log.info("邮箱格式不正确!");
            throw new BizException();
        }

        Response response = new Response();
        UserInfo userInfo = userService.queryUserInfoByUsername();
        if (Objects.nonNull(userInfo)) {
            response.setCode(0);
            response.setMsg("注册成功");
            return response;
        }


        UserInfo addUserInfo = new UserInfo();
        addUserInfo.setUserName(userName);
        addUserInfo.setPassword(password);
        addUserInfo.setEmail(email);
        userService.addUserInfo(addUserInfo);

        MessageDo messageDo = new MessageDo();
        messageDo.setUserName(userName);
        messageDo.setEmail(email);
        messageDo.setContent("注册成功");
        messageService.sendMsg(messageDo);

        response.setCode(0);
        response.setMsg("注册成功");
        return response;
    }

其实,以上这块代码,主次不够分明的点:参数校验就占registerUser方法很大一部分。正例可以划分主次,抽一下小函数,如下:

    public Response registerUser(String userName, String password, String email) {

        //检查参数
        checkRegisterParam(userName, password, email);
        //检查用户是否已经存在
        if (checkUserInfoExist(userName)) {
            Response response = new Response();
            response.setCode(0);
            response.setMsg("注册成功");
            return response;
        }

        //插入用户
        addUser(userName, password, email);
        sendMsgOfRegister(userName, email);

        //构造注册成功报文
        Response response = new Response();
        response.setCode(0);
        response.setMsg("注册成功");
        return response;
    }

    private void sendMsgOfRegister(String userName, String email) {
        MessageDo messageDo = new MessageDo();
        messageDo.setUserName(userName);
        messageDo.setEmail(email);
        messageDo.setContent("注册成功");
        messageService.sendMsg(messageDo);
    }

    private void addUser(String userName, String password, String email) {
        UserInfo addUserInfo = new UserInfo();
        addUserInfo.setUserName(userName);
        addUserInfo.setPassword(password);
        addUserInfo.setEmail(email);
        userService.addUserInfo(addUserInfo);
    }

    private boolean checkUserInfoExist(String userName) {
        UserInfo userInfo = userService.queryUserInfoByUsername();
        if (Objects.nonNull(userInfo)) {
            return true;
        }
        return false;
    }

    private void checkRegisterParam(String userName, String password, String email) {
        if (userName == null || StringUtils.isEmpty(userName)) {
            log.info("用户名不能为空!");
            throw new BizException();
        }

        if (password == null || password.length() < 6) {
            log.info("密码长度不能少于6位!");
            throw new BizException();
        }

        if (email == null || StringUtils.isEmpty(email) || !email.contains("@")) {
            log.info("邮箱格式不正确!");
            throw new BizException();
        } 
    }

13. 安全规范

代码评审,也非常有必要评审代码是否存在安全性问题。比如:

  • 输入校验:应该始终对任何来自外部的输入数据进行校验,以确保它们符合预期并且不会对系统造成伤害。校验应该包括检查数据的类型、大小和格式。

  • 防范SQL注入攻击:在使用SQL查询时,应该始终使用参数化查询或预处理语句,以防止SQL注入攻击。

  • 防范跨站脚本攻击(XSS): 在Web应用程序中,应该始终对输入的HTML、JavaScript和CSS进行校验,并转义特殊字符,以防止XSS攻击。

  • 避免敏感信息泄露: 敏感信息(如密码、密钥、会话ID等)应该在传输和存储时进行加密,以防止被未经授权的人访问。同时,应该避免在日志、调试信息或错误消息中泄露敏感信息。

  • 防范跨站请求伪造(CSRF): 应该为所有敏感操作(如更改密码、删除数据等)添加CSRF令牌,以防止未经授权的人员执行这些操作。

  • 防范安全漏洞: 应该使用安全性高的算法和协议(如HTTPS、TLS)来保护敏感数据的传输和存储,并定期对系统进行漏洞扫描和安全性审计。

14. 事务控制规范

  • 一般推荐使用编程式事务,而不是一个注解 @Transactional的声明式事务。因为 @Transactional有很多场景,可能导致事务不生效。

  • 事务范围要明确,数据库操作必须在事务作用范围内,如果是非数据库操作,尽量不要包含在事务内。

  • 不要在事务内进行远程调用(可能导致数据不一致,比如本地成功了,但是远程方法失败了,这时候需要用分布式事务解决方案)

  • 事务中避免处理太多数据,一些查询相关的操作,尽量放到事务之外(避免大事务问题)

15. 幂等处理规范

什么是幂等?

计算机科学中,幂等表示一次和多次请求某一个资源应该具有同样的副作用,或者说,多次请求所产生的影响与一次请求执行的影响效果相同。

代码评审的时候,要关注接口是否考虑幂等。比如开户接口,多次请求过来的时候,需要先查一下该客户是否已经开过户,如果已经开户成功,直接返回开户成功的报文。如果还没开户,就先开户,再返回开户成功的报文。这就是幂等处理。

一般情况有这几种幂等处理方案:

  • select+insert+主键/唯一索引冲突

  • 直接insert + 主键/唯一索引冲突

  • 状态机幂等

  • 抽取防重表

  • token令牌

  • 悲观锁

  • 乐观锁

  • 分布式锁

幂等要求有个唯一标记,比如数据库防重表的一个业务唯一键。同时强调多次请求和一次请求所产生影响是一样的。

img

16. 中间件注意事项 (数据库,redis)

代码评审的时候,如果用数据库、Redis、RocketMq等的中间件时,我们需要关注这些中间件的一些注意事项哈。

比如数据库

  • 关注数据库连接池参数设置、超时参数设置是否合理

  • 避免循环调用数据库操作

  • 如果不分页,查询SQL时,如果条数不明确,是否加了limit限制限制

  • 数据库的返回是否判空处理

  • 数据库慢SQL是否有监控

  • 表结构更新是否做兼容,存量表数据是否涉及兼容问题考虑

  • 索引添加是否合理

  • 是否连表过多等等

比如Redis:

  • Redis的key使用是否规范

  • Redis 异常捕获以及处理逻辑是否合理

  • Redis连接池、超时参数设置是否合理

  • Redis 是否使用了有坑的那些命令,如hgetall、smember

  • 是否可能会存在缓存穿透、缓存雪奔、缓存击穿等问题。

17. 注意代码坏味道问题

理解几个常见的代码坏味道,大家代码评审的时候,需要关注一些哈:

  • 大量重复代码(抽公用方法,设计模式)

  • 方法参数过多(可封装成一个DTO对象)

  • 方法过长(抽小函数)

  • 判断条件太多(优化if...else)

  • 不处理没用的代码(没用的import)

  • 避免过度设计

18. 远程调用

远程调用是代码评审重点关注的一栏,比如:

  • 不要把超时当作失败处理: 远程调用可能会失败,比如网络中断、超时等等。开发者需要注意远程调用返回的错误码,除非是明确的失败,如果仅仅是超时等问题,不能当作失败处理!而是应该发起查询,确认是否成功,再做处理。

  • 异常处理:远程调用可能会抛出异常,例如由于服务端错误或请求格式不正确等。因此,开发人员需要确保能够捕获和处理这些异常,以避免系统崩溃或数据丢失。

  • 网络安全:由于远程调用涉及网络通信,因此开发人员需要考虑网络安全的问题,例如数据加密、认证、访问控制等。尽可能使用安全的协议,例如HTTPS 或 SSL/TLS

  • 服务质量:远程调用可能会影响系统的性能和可用性。因此,开发人员需要确保服务的质量,例如避免过度使用远程调用、优化数据传输、实现负载均衡等。

  • 版本兼容:由于远程调用涉及不同的进程或计算机之间的通信,因此开发人员需要注意服务端和客户端之间的版本兼容性。尽可能使用相同的接口和数据格式,避免出现不兼容的情况。

  • 尽量避免for循环远程调用: 尽量避免for循环远程调用,而应该考虑实现了批量功能的接口。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/647045.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java30天拿下-----第二天(运算符,标识符,Scanner,进制转换)

Java30天拿下-----第二天 一 运算符算术运算符赋值运算符关系运算符逻辑运算符三元运算符运算符的优先级 二 标识符关键字保留字 三 控制台接收键盘输入&#xff1a;Scanner四 进制进制的转换&#xff08;基本功&#xff09;其他进制转为十进制十进制转为其他进制二进制转为其他…

《当我谈跑步时,我谈些什么》痛楚难以避免,而磨难可以选择

《当我谈跑步时&#xff0c;我谈些什么》痛楚难以避免&#xff0c;而磨难可以选择 村上春树&#xff0c;日本当代小说家&#xff0c;情感类类型作家。主要作品有《且听风吟》《挪威的森林》《海边的卡夫卡》《奇鸟行状录》《1Q84》等。 施小炜 译 来自百度百科的一条&#xff1…

存储快速入门——【2】数据复制与容灾、云存储、大数据概念

存储快速入门——【2】数据复制与容灾、云存储、大数据概念 一、数据复制与容灾 1 恢复时间目标&#xff08;RTO&#xff09;和恢复点目标&#xff08;RPO&#xff09; 对于信息系统而言&#xff0c;容灾就是使信息系统具有应对一定的灾难袭击&#xff0c;保持系统或间断运行…

2023年软件测试工程师,初级到高级进阶路线指南,测试之路...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 提到软件测试工程…

一、JavaScript函数this指向

1 this的绑定规则 2 apply/call/bind 3 this绑定优先级 4 绑定之外的情况 5 箭头函数的使用 6 this面试题分 <script>// 定义函数function foo(name) {console.log("foo函数:", this)}// 1.方式一: 直接调用 这里的this指向window// foo()// 2.方式二: 通…

Java网络编程知识

目录 1.网络编程概述 1.网络编程的目的 2.网络编程的三个问题 1.如何准确定位网络上的主机&#xff1f; 2.如何定位主机上的特定应用&#xff1f; 3.找到主机后如何可靠高效的进行数据传输&#xff1f; 2.通信要素一:IP和端口号 1.IP地址 2.端口号 3.套接字 4.通信要…

基于Yolov8的纸箱破损检测系统

目录 1.Yolov8介绍 2.纸箱破损数据集介绍 2.1数据集划分 2.2 通过voc_label.py得到适合yolov8训练需要的 2.3生成内容如下 3.训练结果分析 4. 纸张破损检测系统设计 4.1 PySide6介绍 4.2 安装PySide6 4.3 纸张破损检测系统设计 1.Yolov8介绍 Ultralytics YOLOv8是Ultral…

SpringBoot动态加载jar包中的bean

一、业务场景 在有些业务场景下&#xff0c;需要SpringBoot来动态加载jar中的class文件&#xff0c;自动往spring容器中添加新的bean&#xff1b;如物联网设备上传的信息用物模型来解析&#xff0c;用java来解析物模型&#xff0c;但用户的设备千差万别&#xff0c;解析设备的…

系统移植 搭建nfs服务器,启动盘,内核安装和加载

目录 1. nfs 服务器网络环境搭建 1.1. 查看是否安装了 nfs 服务器 1.2. 修改nfs配置文件 1.3. 创建nfs工作目录 1.4. 重启nfs服务 1.5. 开始测试是否成功 2. SD 卡启动盘 2.1. 方法1&#xff1a;从0扇区开始烧写 2.2. 方法2&#xff1a;直接部署 3. Linux 内核的安装…

SpringBoot编程---Day 01

目录 一、springboot介绍 &#xff08;一&#xff09;Spring Boot 特性 &#xff08;二&#xff09;了解自动配置原理 &#xff08;三&#xff09;springboot 入口功能详解 &#xff08;四&#xff09;自定义banner &#xff08;五&#xff09;容器功能 (六)配置文件 二…

(九)枚举器和迭代器(1)

一、枚举器和可枚举类型 复习完了数组之后&#xff0c;由于数组遍历的这个行为&#xff0c;跟枚举器有很大的相关性&#xff0c;所以接下来继续要学习与枚举器相关的内容。 1、使用 foreach 语句 int[] arr1 { 10, 11, 12, 13 };foreach (int item in arr1)//枚举元素Consol…

尚硅谷大数据Flink1.17实战教程-笔记01【Flink概述、Flink快速上手】

尚硅谷大数据技术-教程-学习路线-笔记汇总表【课程资料下载】视频地址&#xff1a;尚硅谷大数据Flink1.17实战教程从入门到精通_哔哩哔哩_bilibili 尚硅谷大数据Flink1.17实战教程-笔记01【Flink概述、Flink快速上手】尚硅谷大数据Flink1.17实战教程-笔记02【Flink部署】尚硅谷…

【JVM 监控工具】性能诊断--JProfiler的使用

文章目录 背景一、Java 性能诊断工具简介二、简单命令行工具三、图形化综合诊断工具JVisualvmJProfiler 四、分布式应用性能诊断五、IDEA中设置JProfilerJProfiler是什么功能安装使用生成快照配置VM运行程序 背景 性能诊断是软件工程师在日常工作中需要经常面对和解决的问题&a…

公司新来的阿里p8,看了我做的APP和接口测试,甩给了我这份文档

移动应用App已经渗透到每个人的生活、娱乐、学习、工作当中&#xff0c;令人激动、兴奋且具有创造性的各种App犹如雨后春笋般交付到用户手中。各类智能终端也在快速发布&#xff0c;而开发者对于全球移动设备的质量和性能却掌握甚少&#xff0c;App与设备的兼容性问题常常导致用…

【状态估计】基于卡尔曼滤波器的传感器直流电机驱动研究(Matlab代码、Simulink实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Navicat 受邀出席 PostgreSQL 技术峰会,欢迎莅临我们的展台了解 Navicat 工具包如何提升你的工作效能

Navicat 受邀出席 PostgreSQL 技术峰会成都站&#xff0c;欢迎童鞋们莅临我们的展台。你有机会与我们的专家面对面交流&#xff0c;并了解实用的 Navicat 工具包如何帮助PostgreSQL用户&#xff08;应用开发人员、DBA、运维人员以及数据分析师&#xff09;有效地提升日常的工作…

串口控制小车(二次开发)

0.资料 项目工程文件夹 分文件原理 之前的代码 1.L9110S电机驱动模块demo 2.串口通信&#xff08;习题4&#xff1a;PC发送字符串指令给单片机&#xff09; 3.wifi模块&#xff08;串口中断代码优化&#xff09; 3.蓝牙模块 1.串口指令控制小车_分文件 1、和单片机的接…

MVC、MVP、MVVM:详解2

概述 MVC、MVP、MVVM 都是在 Android 开发中经常用到的架构思想&#xff0c;它们都是为了更好地分离代码、提高代码可复用性、方便维护等目的而设计的。下面对这三种架构思想进行简单的介绍和比较。 MVC MVC 架构是最早被使用的一种架构&#xff0c;它把程序分成了三个部分&…

CVPR 2023 首届视觉异常检测(Visual Anomaly and Novelty Detection,VAND)挑战赛 Zero-shot 赛道冠军

这篇文章主要介绍一下我们在 CVPR 2023 VAND Workshop 的挑战赛中所采用的模型和方案。在 Zero-shot 赛道中我们获得了冠军&#xff08;Winner&#xff09;&#xff0c;在 Few-shot 赛道中&#xff0c;我们获得了第四名&#xff08;Honorable Mentions&#xff09;。 题目&…

怎么安装anaconda?anaconda安装详解!

Anaconda Navigator 是 Anaconda 的图形化管理界面&#xff0c;点击它即可进入 Anaconda 的图像化管理界面。许多小伙伴可能被朋友或者小编安利过Anaconda而跃跃欲试&#xff0c;今天小编就将Anaconda安装详解分享给大家。心动的小伙伴们赶紧安装起来吧&#xff01; 下载 官方…