一名实习生的复盘:技术与规划的经验教训
这篇文章是对一名实习生在开发工作中经验教训的复盘总结(不是我本人的复盘,而是基于他/她的记录整理)。通过分析他在实习期间遇到的问题,结合代码示例,我尝试详细梳理技术细节和项目管理的经验,希望对其他开发者有所启发。
1. 年前开发年后CR,没提前看不熟悉
这位实习生在年前赶工开发功能,年后进行代码审查(CR)时,发现自己对代码逻辑已经模糊。原因是没有提前复习,导致CR时效率低下,甚至被指出一些低级错误。
教训
- 提前回顾:CR前至少提前一天重温代码,梳理关键逻辑。
- 文档支持:提交代码时附上简要说明,代码中写好注释。
示例
他之前写的代码:
java
public String processData(List<String> input) {
String result = "";
for (String s : input) {
result += s.split(",")[0];
}
return result;
}
改进后:
java
/**
* 处理输入列表,提取每个字符串逗号前的部分并拼接
* @param input 输入列表,格式如 "abc,def"
* @return 拼接结果,如 "abc"
*/
public String processData(List<String> input) {
StringBuilder result = new StringBuilder();
for (String s : input) {
result.append(s.split(",")[0]);
}
return result.toString();
}
改进后不仅逻辑清晰,还避免了字符串拼接的性能问题。
2. 如果不是主流程,try/catch不应该阻塞
这位实习生习惯对所有代码块都用try/catch
包裹,但后来发现,如果是非主流程的逻辑(如日志记录或次要功能),过度捕获异常可能会掩盖问题,甚至阻塞主流程的执行。
教训
- 明确主次:主流程要保证执行,非主流程的异常可以记录后继续运行。
- 精准捕获 :只处理特定异常,避免用
Exception
捕获所有问题。
详细解释
比如他在某个服务中既处理核心业务,又记录操作日志,结果日志失败导致整个服务中断。正确的做法是分开处理,让主流程独立运行。
示例
之前代码:
java
public void processOrder(Order order) {
try {
saveOrder(order); // 主流程:保存订单
logOperation(order); // 非主流程:记录日志
} catch (Exception e) {
log.error("Processing failed", e);
throw new RuntimeException("Order processing failed");
}
}
改进后:
java
public void processOrder(Order order) {
saveOrder(order); // 主流程直接执行
try {
logOperation(order); // 非主流程单独捕获
} catch (Exception e) {
log.warn("Failed to log operation, continuing", e); // 记录警告但不中断
}
}
private void saveOrder(Order order) { /* 保存订单 */ }
private void logOperation(Order order) { /* 记录日志 */ }
这样即使日志记录失败,订单保存也不会受影响。
3. join别用,干大数据联表习惯了回来被提醒
这位实习生之前参与过大数据项目,习惯用SQL的JOIN
操作处理表关联。回到业务开发后,他不自觉地在Java代码中用String.join
拼接字符串,结果被提醒这不是SQL场景,性能和适用性都不佳。
教训
- 区分场景 :SQL的
JOIN
适合数据库操作,Java中字符串拼接用StringBuilder
更高效。 - 调整思维:从大数据切换到业务开发时,要适应不同技术栈的习惯。
示例
他之前写的代码:
java
public String combineNames(List<String> names) {
return String.join(",", names); // 模仿SQL JOIN的思维
}
改进后:
java
public String combineNames(List<String> names) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < names.size(); i++) {
sb.append(names.get(i));
if (i < names.size() - 1) sb.append(",");
}
return sb.toString();
}
StringBuilder
在小数据量下更高效,且逻辑更直观,与SQL的JOIN
完全是不同场景。
4. 传参还是要VO/DTO
他在开发网关调用时没理解规范,跟着老代码用Map
做返回值,结果被指出不规范。应该用VO(View Object)或DTO(Data Transfer Object)定义明确的接口。
教训
- 结构化数据 :用VO/DTO替代
Map
,提高代码可读性和维护性。 - 理解而非模仿:不要盲目抄老代码,要弄清设计意图。
示例
之前代码:
java
public Map<String, Object> getUserInfo(String userId) {
Map<String, Object> result = new HashMap<>();
result.put("id", userId);
result.put("name", "John");
return result;
}
改进后:
java
public class UserVO {
private String id;
private String name;
// Getters and Setters
}
public UserVO getUserInfo(String userId) {
UserVO vo = new UserVO();
vo.setId(userId);
vo.setName("John");
return vo;
}
VO让接口字段一目了然,后续扩展也更方便。
5. 多考虑能不能用Lion配置
公司使用Lion配置中心管理参数,但他经常硬编码配置项,后来发现很多值可以用Lion动态调整。
教训
- 动态管理:优先用配置中心替代硬编码。
- 灵活性:减少代码修改,提高环境适应性。
示例
之前代码:
java
private static final String API_URL = "http://localhost:8080/api";
改进后:
java
@Value("${api.url}")
private String apiUrl; // 从Lion读取
通过Spring注解动态获取配置,环境切换更顺畅。
6. 不同环境配置要注意
他在开发中引用了SET(某种工具集)和中心服务的依赖,但没注意开发、测试、生产环境的配置差异,导致上线时依赖版本冲突或配置不生效。
教训
- 环境隔离:不同环境的依赖版本和配置要明确区分。
- 提前验证:上线前检查依赖和配置的兼容性。
详细解释
比如他在开发时用的是SET的本地版本,但生产环境依赖中心服务的远程版本,结果上线后报错。他后来意识到,应该在POM文件中通过属性控制版本,并在配置文件中区分环境。
示例
之前配置:
xml
<dependency>
<groupId>com.example</groupId>
<artifactId>center-service</artifactId>
<version>1.0.0</version>
</dependency>
改进后:
xml
<properties>
<center.service.version>1.0.0</center.service.version> <!-- 开发环境 -->
</properties>
<dependency>
<groupId>com.example</groupId>
<artifactId>center-service</artifactId>
<version>${center.service.version}</version>
</dependency>
同时在配置文件中区分环境:
yaml
# dev.yml
center:
service:
version: 1.0.0
# prod.yml
center:
service:
version: 2.0.0
通过Maven属性和配置文件动态管理,避免硬编码带来的问题。
7. ST/QA/Prod要注意相关域名和参数
他在ST(系统测试)、QA(质量保证)和Prod(生产)环境切换时,没仔细检查域名和参数,导致生产环境部分功能不可用。
教训
- 逐一核对:上线前检查每个环境的域名和参数。
- 自动化工具:用脚本验证配置一致性。
示例
之前代码:
java
private static final String DOMAIN = "qa.example.com";
改进后:
java
@Value("${app.domain}")
private String domain; // 从配置中心读取
配置文件:
yaml
# qa.yml
app:
domain: qa.example.com
# prod.yml
app:
domain: prod.example.com
通过配置中心管理域名,确保环境切换无误。
8. 时间上要早规划
他计划离职前三周备机上线,但因各种杂事拖延,最后三周都没和前端在备机验证,导致上线仓促。
教训
- 预留缓冲:重要节点要提前规划时间。
- 主动推进:尽早和相关方确认进度。
示例时间表
diff
- T-3周:完成开发,提交CR
- T-2周:备机部署,与前端联调
- T-1周:修复问题,上线验证
9. 做决定记得艾特主R
他和前端约好备机联调,但主R(负责人)后来觉得不合适,临时改到QA联调,导致进度混乱。
教训
- 提前确认:关键决定要@主R确认。
- 沟通留档:用IM或邮件记录,避免误解。
示例沟通
python
@主R:计划下周二在备机上与前端联调,涉及功能X,请确认是否可行?
总结
这位实习生的经历反映了从技术细节到项目管理的成长过程。代码上,他学会了规范和优化;规划上,他明白了提前准备和沟通的重要性。这些经验教训对任何开发者来说都值得借鉴。