入职后初次写代码该注意什么
一、务必在正确的 Git 分支上开发
开始编码前,第一件事是确认你所在的分支。
切勿直接在默认主分支(如 main/master)上修改代码。
要问清楚:该在什么分支开发、是否需要新建分支、如果需要新建分支基于哪个分支新建。 如果不确认就写代码,后面可能要返工甚至造成代码冲突。
二、务必确保需求已经理解清楚
在动手写任何代码之前,确保你对需求的理解与产品、测试、导师的理解完全一致。
具体做法:
- 主动沟通不清楚的点:对模糊不清的需求点,立即提问。使用”确认一下…”的口吻,来复述你的理解,确认你的理解是没有问题的。
- 输出技术方案(可选但推荐):对于稍复杂的功能,在编码前用简短的文档或注释梳理核心逻辑、关键数据结构、接口设计及潜在风险点。这能极大地减少返工,并培养你的设计思维。
不要没搞清楚需求就开始写代码,这样很容易返工。
三、边写边测,不要一次性写完再去测试
如果一项功能需要开发 10 个接口,切忌全部写完再统一测试。
每完成一个接口,就立即进行自测(使用 Postman、Swagger 或单元测试)。这样可以把问题提前暴露出来,避免把问题带到后面的接口开发中。
一次性写完再测,如果出了问题,排查起来会非常痛苦。
四、推荐采用”自上而下”的编写顺序
建议从**接口层(Controller)开始写,明确接口的入参、出参。再到业务层(Service)编写逻辑,此时仅定义你真正需要的实体类和 DAO 方法。最后才到数据层(Mapper/DAO)**实现具体数据库操作。
这种方式能有效避免提前过度设计,确保每一行代码都服务于明确的业务需求。
如果从 DAO 层开始写,可能会定义很多没有用的方法和实体类,浪费过多的时间。
五、合理使用 AI,让它成为你的”副驾驶”而非”代驾”
对于刚入行的同学,在使用 AI 辅助编程时,需注意方法,避免过度依赖。
不要将完整的需求描述直接丢给 AI 并期望它生成最终代码,这容易导致生成的代码结构混乱、不符合业务上下文,且后期调试和修改会异常困难。
建议采用”分段提问,主动把控”的策略:
- 分解任务:先将复杂功能拆解成清晰的步骤和子问题,再针对具体环节(如”如何实现某个查询”、“这个异常该怎么处理”)进行提问。
- 理解而非照搬:对 AI 给出的代码,务必逐行理解其逻辑和意图,确保你知其所以然。
- 手动验证与调试:AI 生成的代码可能存在边界错误或性能隐患,关键部分一定要亲自测试、调试,并将其融入你整体的代码框架中。
**AI 是强大的辅助工具,而非替代你思考的”代驾”。**合理使用能提升效率,过度依赖则会阻碍你真正理解业务、积累解决问题的能力。保持主动思考,让 AI 为你的思路服务,而不是被它的输出牵着走。
六、编码常犯问题
以下列出入职新人最常犯的几个编码问题,一定要注意避免。
1、for 循环里面不要有数据库操作
for 循环里面进行数据库操作,循环次数越多,性能下降越严重,最终可能导致接口超时或拖垮数据库。
一般都是用空间换时间:
- 对于查询操作,提前把需要的数据查询出来
- 对于修改操作,可以批量进行修改
2、不要使用 System.out.println 打印日志
这种打印日志只适合本地调试的时候使用。
真正上线或者提交代码到远程仓库的时候,一定要把这种打印日志注释掉。因为它是同步输出到控制台,会阻塞主线程,并且无法按级别过滤、归档或收集到日志中心。
正式项目中应该使用日志框架(如 @Slf4j)来打印日志。
3、不要使用魔法数字/字符串
直接在代码中写数字或字符串,可读性会很差,修改的时候还需要全局搜索,很容易出错。
错误的写法:
// 7 和 "SUCCESS" 是什么,可读性和可维护性都比较差if (order.getStatus() == 7) { return "SUCCESS";}正确的写法:
// 定义枚举public enum OrderStatus { COMPLETED(7, "已完成"); // ...}if (order.getStatus() == OrderStatus.COMPLETED.getCode()) { return ResultEnum.SUCCESS.getMessage();}4、使用事务注解的方法里用 try-catch 把数据库操作包住了
Spring 事务注解的回滚是通过捕捉异常来回滚的,如果你使用了 try-catch 把异常捕捉掉了,就无法回滚了。
@Transactionalpublic void updateOrder(Order order) { try { orderMapper.update(order); // 数据库操作1 accountService.deductBalance(order.getAmount()); // 数据库操作2,可能抛异常 } catch (Exception e) { log.error("更新失败", e); // 异常被捕获,事务标记为成功,即使扣款失败,订单状态也已被更新! }}5、忽视空指针异常
对任何可能为 null 的对象(特别是方法参数、查询返回值)进行判空处理,否则很容易出现空指针异常。
public class OrderService { public OrderDTO getOrderDetail(Long orderId) { // 直接调用,查询结果可能为 null Order order = orderRepository.findById(orderId);
// 直接转换,可能 NPE OrderDTO dto = convertToDTO(order);
return dto; // 如果 order 为 null,convertToDTO 内部可能 NPE }
private OrderDTO convertToDTO(Order order) { OrderDTO dto = new OrderDTO(); dto.setOrderId(order.getId()); // 如果 order 为 null,这里 NPE dto.setAmount(order.getTotalAmount()); dto.setItems(order.getItems().stream() // 如果 getItems() 返回 null,这里 NPE .map(this::convertItem) .collect(Collectors.toList())); return dto; }}6、集合遍历删除元素方式不对,导致 ConcurrentModificationException
在对集合进行迭代时,如果直接修改集合(添加或删除元素),会抛出 ConcurrentModificationException。这在单线程环境下也可能发生。
错误的写法:
// 遍历时删除元素会抛出异常List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));for (String item : list) { if ("B".equals(item)) { list.remove(item); // 抛出 ConcurrentModificationException! }}正确的写法:
Iterator<String> iterator = list.iterator();while (iterator.hasNext()) { String item = iterator.next(); if ("B".equals(item)) { iterator.remove(); // 安全删除 }}支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!














