代码功底
代码功底是架构师的基础能力,直接影响系统的质量和稳定性。优秀的代码功底体现在代码质量、异常处理、可读性和抽象能力等多个方面。
📋 目录结构
💻 一、代码质量
代码质量是架构师代码功底的核心体现,直接影响系统的稳定性和可维护性。
1.1 编码规范
编码规范是保证代码质量的基础,统一的编码规范能够让团队协作更高效。
1.1.1 命名规范
变量命名原则:
- 使用有意义的变量名,避免使用
a、b、x等无意义的名字 - 遵循驼峰命名或下划线命名,保持风格统一
- 布尔变量使用
is、has、can等前缀 - 常量使用全大写下划线分隔
好的命名示例:
java
// ✅ 好的命名
String userName = "admin";
boolean isActive = true;
boolean hasPermission = false;
int maxRetryCount = 3;
static final int MAX_CONNECTION_POOL_SIZE = 100;
// ❌ 不好的命名
String n = "admin"; // 无意义
boolean flag = true; // 不清楚含义
int num = 3; // 不明确函数命名原则:
- 使用动词开头,清晰表达函数功能
- 查询函数使用
get、find、query等前缀 - 修改函数使用
set、update、delete等前缀 - 布尔返回使用
is、has、can等前缀
好的函数命名示例:
java
// ✅ 好的命名
public User findUserById(Long id) { }
public void updateUser(User user) { }
public boolean isUserActive(Long userId) { }
public List<User> queryUsersByRole(String role) { }
// ❌ 不好的命名
public User user(Long id) { } // 不清楚是查询还是创建
public void process(User user) { } // 不明确处理什么1.1.2 代码格式
缩进和空格:
- 使用统一的缩进(2 空格或 4 空格)
- 运算符前后留空格
- 方法参数之间留空格
- 大括号位置统一
代码格式示例:
java
// ✅ 好的格式
public class UserService {
public User findUserById(Long id) {
if (id == null || id <= 0) {
throw new IllegalArgumentException("Invalid user id");
}
return userRepository.findById(id);
}
}
// ❌ 不好的格式
public class UserService{
public User findUserById(Long id){
if(id==null||id<=0){
throw new IllegalArgumentException("Invalid user id");}
return userRepository.findById(id);}}行长度控制:
- 每行代码不超过 120 个字符
- 长表达式拆分为多行
- 方法参数过多时,每个参数占一行
1.1.3 代码组织
类组织原则:
- 类应该只有一个职责
- 类的成员变量应该在顶部
- 构造函数应该在成员变量之后
- 方法应该按功能分组,公共方法在前
包组织原则:
- 按功能模块组织包结构
- 使用清晰的包命名
- 避免循环依赖
包结构示例:
com.example.project
├── controller # 控制器层
├── service # 服务层
│ ├── impl # 服务实现
│ └── dto # 数据传输对象
├── repository # 数据访问层
├── model # 数据模型
└── util # 工具类1.2 测试覆盖
完善的测试覆盖是保证代码质量的重要手段。
1.2.1 单元测试
单元测试原则:
- 测试覆盖率应该达到 80% 以上
- 每个公共方法都应该有对应的测试
- 测试应该独立,不依赖其他测试
- 测试应该快速执行
单元测试示例:
java
// 被测试的类
public class Calculator {
public int add(int a, int b) {
if (a < 0 || b < 0) {
throw new IllegalArgumentException("Numbers must be positive");
}
return a + b;
}
public int divide(int a, int b) {
if (b == 0) {
throw new ArithmeticException("Cannot divide by zero");
}
return a / b;
}
}
// 单元测试
@RunWith(JUnit4.class)
public class CalculatorTest {
private Calculator calculator;
@Before
public void setUp() {
calculator = new Calculator();
}
@Test
public void testAdd_PositiveNumbers_ReturnsSum() {
// Given
int a = 5;
int b = 3;
// When
int result = calculator.add(a, b);
// Then
assertEquals(8, result);
}
@Test(expected = IllegalArgumentException.class)
public void testAdd_NegativeNumber_ThrowsException() {
// Given
int a = -5;
int b = 3;
// When
calculator.add(a, b);
// Then - 应该抛出异常
}
@Test
public void testDivide_ValidNumbers_ReturnsQuotient() {
// Given
int a = 10;
int b = 2;
// When
int result = calculator.divide(a, b);
// Then
assertEquals(5, result);
}
@Test(expected = ArithmeticException.class)
public void testDivide_ByZero_ThrowsException() {
// Given
int a = 10;
int b = 0;
// When
calculator.divide(a, b);
// Then - 应该抛出异常
}
}1.2.2 集成测试
集成测试原则:
- 测试系统各模块之间的集成
- 测试与外部系统的交互
- 使用测试数据库,避免影响生产数据
- 测试后清理测试数据
集成测试示例:
java
@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class UserServiceIntegrationTest {
@Autowired
private UserService userService;
@Autowired
private UserRepository userRepository;
@Test
public void testCreateUser_Success() {
// Given
UserDTO userDTO = new UserDTO();
userDTO.setName("John");
userDTO.setEmail("john@example.com");
// When
User createdUser = userService.createUser(userDTO);
// Then
assertNotNull(createdUser.getId());
assertEquals("John", createdUser.getName());
assertEquals("john@example.com", createdUser.getEmail());
// 验证数据库中的数据
User dbUser = userRepository.findById(createdUser.getId()).orElse(null);
assertNotNull(dbUser);
assertEquals("John", dbUser.getName());
}
}1.2.3 测试覆盖率
覆盖率指标:
- 行覆盖率(Line Coverage):执行的代码行数 / 总代码行数
- 分支覆盖率(Branch Coverage):执行的分支数 / 总分支数
- 方法覆盖率(Method Coverage):执行的方法数 / 总方法数
覆盖率目标:
- 核心业务代码:覆盖率应该达到 90% 以上
- 工具类和辅助代码:覆盖率应该达到 80% 以上
- 整体代码:覆盖率应该达到 80% 以上
1.3 代码审查
代码审查是保证代码质量的重要环节。
1.3.1 审查要点
功能正确性:
- 代码是否实现了需求
- 边界条件是否处理正确
- 异常情况是否处理
代码质量:
- 代码是否符合编码规范
- 是否有重复代码
- 是否有明显的性能问题
可维护性:
- 代码是否易于理解
- 是否有充分的注释
- 是否有适当的文档
1.3.2 审查流程
🛡️ 二、异常处理
完善的异常处理机制是保证系统稳定性的关键。
2.1 异常场景
系统运行过程中会遇到各种异常场景,需要妥善处理。
2.1.1 常见异常类型
运行时异常:
NullPointerException:空指针异常IllegalArgumentException:非法参数异常IndexOutOfBoundsException:数组越界异常ArithmeticException:算术异常
检查异常:
IOException:IO 异常SQLException:SQL 异常ClassNotFoundException:类未找到异常
自定义异常:
- 业务异常:如
UserNotFoundException、InsufficientBalanceException - 系统异常:如
SystemException、ServiceException
2.1.2 异常处理策略
异常处理层次:
异常处理示例:
java
// 业务异常定义
public class BusinessException extends RuntimeException {
private String code;
private String message;
public BusinessException(String code, String message) {
super(message);
this.code = code;
this.message = message;
}
public String getCode() {
return code;
}
}
// 业务层异常处理
@Service
public class UserService {
public User findUserById(Long id) {
if (id == null || id <= 0) {
throw new BusinessException("INVALID_USER_ID", "Invalid user id");
}
User user = userRepository.findById(id);
if (user == null) {
throw new BusinessException("USER_NOT_FOUND", "User not found");
}
return user;
}
}
// 全局异常处理
@ControllerAdvice
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler(BusinessException.class)
@ResponseBody
public Result handleBusinessException(BusinessException e) {
logger.warn("Business exception: {}", e.getMessage());
return Result.failure(e.getCode(), e.getMessage());
}
@ExceptionHandler(Exception.class)
@ResponseBody
public Result handleException(Exception e) {
logger.error("System exception: ", e);
return Result.failure("SYSTEM_ERROR", "System error, please try again later");
}
}2.2 资源管理
系统使用的资源(内存、连接、文件等)需要妥善管理,避免资源泄漏。
2.2.1 内存管理
内存泄漏防范:
- 及时释放不再使用的对象
- 避免循环引用
- 使用对象池复用对象
- 监控内存使用情况
内存管理示例:
java
// ❌ 不好的做法 - 可能导致内存泄漏
public class BadResourceManager {
private List<Object> cache = new ArrayList<>();
public void addToCache(Object obj) {
cache.add(obj); // 没有限制,可能无限增长
}
}
// ✅ 好的做法 - 限制缓存大小
public class GoodResourceManager {
private static final int MAX_CACHE_SIZE = 1000;
private List<Object> cache = new ArrayList<>();
public synchronized void addToCache(Object obj) {
if (cache.size() >= MAX_CACHE_SIZE) {
cache.remove(0); // 移除最旧的元素
}
cache.add(obj);
}
public synchronized void clearCache() {
cache.clear();
}
}2.2.2 连接管理
数据库连接管理:
- 使用连接池管理数据库连接
- 及时关闭连接,避免连接泄漏
- 设置连接超时时间
连接管理示例:
java
// ✅ 使用 try-with-resources 自动关闭连接
public class UserDao {
@Autowired
private DataSource dataSource;
public User findById(Long id) {
String sql = "SELECT * FROM users WHERE id = ?";
try (Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setLong(1, id);
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
return mapRow(rs);
}
}
} catch (SQLException e) {
logger.error("Error finding user by id: {}", id, e);
throw new DataAccessException("Error finding user", e);
}
return null;
}
}HTTP 连接管理:
java
// ✅ 使用连接池管理 HTTP 连接
@Configuration
public class HttpClientConfig {
@Bean
public CloseableHttpClient httpClient() {
PoolingHttpClientConnectionManager connectionManager =
new PoolingHttpClientConnectionManager();
// 设置最大连接数
connectionManager.setMaxTotal(200);
// 设置每个路由的最大连接数
connectionManager.setDefaultMaxPerRoute(20);
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(5000) // 连接超时 5 秒
.setSocketTimeout(10000) // 读取超时 10 秒
.setConnectionRequestTimeout(3000) // 从连接池获取连接超时 3 秒
.build();
return HttpClients.custom()
.setConnectionManager(connectionManager)
.setDefaultRequestConfig(requestConfig)
.build();
}
}2.3 超时控制
合理的超时设置能够防止系统被长时间阻塞。
2.3.1 超时场景
常见超时场景:
- 数据库查询超时
- HTTP 请求超时
- RPC 调用超时
- 文件读取超时
2.3.2 超时设置
超时设置原则:
- 根据业务特点设置合理的超时时间
- 区分不同类型操作的超时时间
- 提供超时后的降级方案
超时设置示例:
java
// 数据库查询超时
@Configuration
public class DatabaseConfig {
@Bean
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/test");
config.setUsername("root");
config.setPassword("password");
// 连接超时时间 30 秒
config.setConnectionTimeout(30000);
// 连接最大生命周期 30 分钟
config.setMaxLifetime(1800000);
// 空闲连接最大存活时间 10 分钟
config.setIdleTimeout(600000);
// 查询超时时间 10 秒
config.addDataSourceProperty("socketTimeout", "10000");
return new HikariDataSource(config);
}
}
// HTTP 请求超时
@Service
public class HttpService {
@Autowired
private RestTemplate restTemplate;
public String callExternalApi(String url) {
try {
HttpHeaders headers = new HttpHeaders();
HttpEntity<String> entity = new HttpEntity<>(headers);
ResponseEntity<String> response = restTemplate.exchange(
url,
HttpMethod.GET,
entity,
String.class
);
return response.getBody();
} catch (ResourceAccessException e) {
// 超时异常处理
logger.error("Request timeout: {}", url, e);
return getDefaultValue(); // 返回默认值
}
}
}📖 三、代码可读性
可读性强的代码能够降低维护成本,提升开发效率。
3.1 命名规范
良好的命名能够让代码自我解释。
3.1.1 变量命名
命名原则:
- 使用有意义的名称
- 避免使用缩写
- 保持命名一致性
- 遵循团队命名规范
3.1.2 函数命名
函数命名原则:
- 使用动词开头
- 清晰表达函数功能
- 避免使用过长的名称
3.2 代码注释
适当的注释能够帮助理解代码意图。
3.2.1 注释原则
何时需要注释:
- 复杂的业务逻辑
- 算法实现
- API 接口说明
- 不明显的设计决策
注释示例:
java
/**
* 计算用户积分
*
* 积分规则:
* 1. 基础积分:消费金额 * 0.01
* 2. VIP 用户额外奖励:基础积分 * 0.2
* 3. 活动期间双倍积分
*
* @param amount 消费金额
* @param isVip 是否为 VIP 用户
* @param isActivityPeriod 是否在活动期间
* @return 用户积分
*/
public int calculatePoints(BigDecimal amount, boolean isVip, boolean isActivityPeriod) {
// 基础积分计算
int basePoints = amount.multiply(new BigDecimal("0.01")).intValue();
// VIP 用户额外奖励
if (isVip) {
basePoints = (int) (basePoints * 1.2);
}
// 活动期间双倍积分
if (isActivityPeriod) {
basePoints = basePoints * 2;
}
return basePoints;
}3.3 文档同步
代码文档应该与代码保持同步。
文档同步原则:
- 代码变更时同步更新文档
- 定期检查文档准确性
- 使用自动化工具生成文档
🎯 四、抽象能力
优秀的抽象能力是设计高质量架构的关键。
4.1 抽象设计
良好的抽象能够隐藏实现细节,提供清晰的接口。
4.1.1 抽象层次
抽象层次划分:
4.1.2 抽象示例
抽象设计示例:
java
// 抽象接口定义
public interface PaymentService {
/**
* 支付接口
*
* @param order 订单信息
* @return 支付结果
*/
PaymentResult pay(Order order);
/**
* 退款接口
*
* @param orderId 订单ID
* @return 退款结果
*/
RefundResult refund(String orderId);
}
// 支付宝实现
@Service("alipayPaymentService")
public class AlipayPaymentService implements PaymentService {
@Override
public PaymentResult pay(Order order) {
// 支付宝支付实现
// ...
}
@Override
public RefundResult refund(String orderId) {
// 支付宝退款实现
// ...
}
}
// 微信支付实现
@Service("wechatPaymentService")
public class WechatPaymentService implements PaymentService {
@Override
public PaymentResult pay(Order order) {
// 微信支付实现
// ...
}
@Override
public RefundResult refund(String orderId) {
// 微信退款实现
// ...
}
}
// 使用抽象接口,不依赖具体实现
@Service
public class OrderService {
@Autowired
@Qualifier("alipayPaymentService")
private PaymentService paymentService;
public void processOrder(Order order) {
// 使用抽象接口,可以轻松切换支付方式
PaymentResult result = paymentService.pay(order);
// ...
}
}4.2 接口设计
良好的接口设计应该遵循 SOLID 原则。
4.2.1 接口隔离原则
接口隔离示例:
java
// ❌ 不好的设计 - 接口太大
public interface UserService {
void createUser(User user);
void updateUser(User user);
void deleteUser(Long id);
User findUserById(Long id);
List<User> findUsersByRole(String role);
void sendEmail(User user, String content);
void generateReport(User user);
}
// ✅ 好的设计 - 接口隔离
public interface UserRepository {
void create(User user);
void update(User user);
void delete(Long id);
User findById(Long id);
List<User> findByRole(String role);
}
public interface UserNotificationService {
void sendEmail(User user, String content);
}
public interface UserReportService {
void generateReport(User user);
}4.3 架构稳定
稳定的架构应该能够应对需求变化。
4.3.1 扩展点设计
扩展点设计示例:
java
// 策略接口 - 可扩展的扩展点
public interface DiscountStrategy {
BigDecimal calculateDiscount(Order order);
}
// 普通折扣策略
@Component("normalDiscount")
public class NormalDiscountStrategy implements DiscountStrategy {
@Override
public BigDecimal calculateDiscount(Order order) {
return order.getAmount().multiply(new BigDecimal("0.05"));
}
}
// VIP 折扣策略
@Component("vipDiscount")
public class VipDiscountStrategy implements DiscountStrategy {
@Override
public BigDecimal calculateDiscount(Order order) {
return order.getAmount().multiply(new BigDecimal("0.15"));
}
}
// 使用策略模式,便于扩展新的折扣策略
@Service
public class DiscountService {
private Map<String, DiscountStrategy> strategies;
@Autowired
public DiscountService(List<DiscountStrategy> strategyList) {
strategies = strategyList.stream()
.collect(Collectors.toMap(
s -> s.getClass().getAnnotation(Component.class).value(),
s -> s
));
}
public BigDecimal calculateDiscount(Order order, String strategyType) {
DiscountStrategy strategy = strategies.get(strategyType);
if (strategy == null) {
throw new IllegalArgumentException("Unknown discount strategy: " + strategyType);
}
return strategy.calculateDiscount(order);
}
}📝 总结
代码功底是架构师的基础能力,需要通过持续的学习和实践不断提升。
能力提升路径
- 初级阶段:掌握编码规范和基本实践
- 中级阶段:提升代码质量和可维护性
- 高级阶段:设计优秀的抽象和架构
实践建议
- 编写代码时始终考虑代码质量
- 充分测试,保证测试覆盖率
- 参与代码审查,学习优秀代码
- 持续重构,提升代码质量