当前位置: 首页 > news >正文

Java 与 PHP 开发核心良好习惯笔记(含通用+语言特有)

良好的开发习惯不仅能提升代码可读性、可维护性,还能减少 Bug 产生、降低协作成本。结合通用开发规范与 Java/PHP 语言特性,在已有习惯基础上,补充核心习惯,形成完整的开发规范体系。

一、通用开发习惯(Java/PHP 均适用)

1. 代码格式规范统一,拒绝“随心所欲”

  • 缩进与换行:统一使用 4 个空格缩进(禁止 Tab 缩进,避免不同编辑器显示异常);每个代码块(类、方法、循环、条件)前后空 1 行;运算符前后、逗号后加空格(如 int a = 1 + 2; List<String> list = Arrays.asList("a", "b");)。
  • 命名规范:遵循“见名知意”原则,拒绝拼音、缩写(通用缩写如 UserDTO 除外):
    • 类名:帕斯卡命名法(首字母大写,如 UserService OrderController);
    • 方法名/变量名:驼峰命名法(首字母小写,如 getUserInfo() orderId);
    • 常量:全大写+下划线分隔(如 MAX_RETRY_COUNT REDIS_KEY_PREFIX);
    • 数据库相关:表名小写+下划线(如 user_info),字段名与变量名对应(避免表字段 u_id 对应变量 userId 不一致)。
  • 文件与目录结构:按功能/模块划分目录,避免所有文件堆在同一目录:
    • 例:Java 项目 com.company.module.controller/service/dao/model;PHP 项目 app/controller/service/dao/model,确保“不同职责的代码在不同目录”。
  • 开发思维:增量开发
    • 在构思、开发功能时,代码要易拓展、易维护,保证后续增加新功能时,只做增量开发,而不是代码重构。

2. 异常处理:不吞异常、不裸抛异常

  • 禁止“沉默异常”避免 try-catch 后不处理(如 catch (Exception e) {},至少打印异常日志(Java 用 log.error("异常描述", e),PHP 用 error_log("异常描述: " . $e->getMessage())),便于问题追溯。
  • 精准捕获异常:不直接捕获 Exception 父类,优先捕获具体异常(如 Java SQLException NullPointerException,PHP PDOException InvalidArgumentException),减少异常范围。
  • 自定义业务异常:复杂业务场景下,定义业务异常类(如 BusinessException),搭配错误码(如 ERROR_USER_NOT_FOUND = 1001),统一异常返回格式(如 {"code":1001, "msg":"用户不存在", "data":{}}),避免接口返回格式混乱。

3. 输入校验:前端校验是辅助,后端校验是底线

  • 所有接口入参必须在后端做校验(前端校验可被绕过,不能依赖):
    • Java:使用 javax.validation 注解(如 @NotNull @Min(1) @Pattern(regexp = "^1[3-9]\\d{9}$")),配合全局异常处理器返回校验结果;
    • PHP:使用框架校验器(如 ThinkPHP validate() 方法、Laravel $request->validate())或自定义校验逻辑,避免直接使用 $_GET/$_POST 数据。
  • 校验场景:必填项、数据类型(如 id 必须是正整数)、格式(手机号、邮箱、日期)、业务规则(如“下单时库存需大于 0”)。

4. 复用代码:拒绝复制粘贴,提取公共逻辑(兼顾实用性)

  • 重复出现 2 次以上的代码,优先提取为公共方法/工具类:
    • 例:日期格式化、字符串处理、加密解密、HTTP 请求等通用逻辑,封装为 DateUtil StringUtil HttpUtil
    • 业务层面重复逻辑(如“用户权限校验”“订单状态判断”),提取为服务层公共方法(如 UserService::checkPermission())。
  • 提取公共方法的“边界原则”:若提取后代码量大于原本代码量、或需要额外传递多个参数才能复用(导致逻辑更复杂),则无需提取——复用的核心是“简化代码、提升可维护性”,而非“为了提取而提取”。
  • 避免“超大方法”:单个方法代码行数控制在 50 行以内,超过则拆分(如一个“下单接口”拆分为 checkStock() createOrder() notifyPay() 等子方法),提升可读性。

5. 版本控制:规范 Git 操作,便于协作与回滚

  • 分支管理:遵循“主分支+开发分支”规范:
    • master/main:生产环境分支,仅存放稳定代码,禁止直接提交;
    • dev:开发分支,所有功能开发在 dev 或基于 dev 创建的特性分支(如 feature/user-login);
    • 修复生产 Bug 用 hotfix 分支(如 hotfix/order-payment-error),修复后合并到 master 和 dev
  • 提交规范:提交信息按“类型: 描述”格式编写(如 feat: 新增用户登录接口 fix: 修复订单列表分页异常 refactor: 优化用户服务代码结构),避免“修改代码”“fix bug”等模糊描述。
  • 提交前检查:提交前执行代码格式化、本地测试,避免提交语法错误、未完成代码;多人协作时,提交前先 git pull 拉取最新代码,解决冲突后再提交。

6. 数据库操作:安全、高效、可维护

  • 避免 SQL 注入:禁止拼接 SQL 字符串(如 String sql = "select * from user where username = '" + username + "'"),必须使用参数绑定:
    • Java:用 PreparedStatement 或 MyBatis 占位符(#{username});
    • PHP:用 PDO 预处理($stmt->execute([$username]))或框架 ORM 自带参数绑定。
  • 优化 SQL 性能
    • 复杂查询先在 DBeaver/Navicat 中测试执行计划(EXPLAIN),确保走索引(避免 full table scan);
    • 分页查询必加 limit,禁止查询全表(如 select * from order 无限制);
    • 批量操作使用批量插入/更新(如 Java MyBatis BatchExecutor,PHP PDO::exec() 批量 SQL),避免循环单条操作数据库。
  • 事务管理:涉及多表操作(如“下单减库存”),必须加事务,确保原子性:
    • Java:用 @Transactional 注解(指定异常回滚条件);
    • PHP:用 try { $pdo->beginTransaction(); ... $pdo->commit(); } catch (Exception $e) { $pdo->rollBack(); }

7. 注释规范:注释是“代码说明书”,不是冗余描述

  • 必须加注释的场景
    • 类/接口:说明核心职责、作者、创建日期(如 /** 订单服务,处理订单创建、支付、取消等业务 @author 用户名 @date 2025-01-01 */);
    • 方法:说明入参含义、返回值格式、异常情况(如 /** 获取用户信息 @param userId 用户ID @return UserDTO 用户信息DTO @throws BusinessException 1001-用户不存在 */);
    • 复杂逻辑:核心业务逻辑(如“折扣计算规则”“状态流转逻辑”)加行注释,说明设计思路(避免后续维护者看不懂“为什么这么写”)。
  • 禁止冗余注释:避免注释与代码重复(如 // 定义用户ID int userId;),注释应补充代码未表达的信息(如 // 兼容旧系统,用户ID允许为字符串格式)。

二、Java 开发特有良好习惯

1. 面向对象:遵循设计原则,拒绝“面条代码”

  • 单一职责:一个类/方法只做一件事(如 UserController 只处理用户相关接口,不包含订单逻辑);
  • 依赖注入(DI):使用 Spring 依赖注入(@Autowired @Resource),避免手动 new 对象(如 UserService userService = new UserService();),降低代码耦合;
  • 接口编程:复杂业务场景下,优先定义接口(如 UserService),再实现类(UserServiceImpl),便于后续扩展(如新增 UserServiceV2Impl 兼容新需求);
  • 避免过度封装:封装是为了简化使用,不是“越复杂越好”(如一个简单的字符串判断,无需封装为多层类)。

2. 异常处理强化:抛出必处理,不裸抛无追溯

  • 抛出异常必须有处理链路:方法声明 throws Exception(或具体异常)后,调用该方法的所有上游链路(如 Controller → Service → Dao)中,必须有一处进行 try-catch 处理(打印日志、返回错误响应等),禁止“裸抛异常”导致程序崩溃。
    • 示例:Service 层方法 public UserDTO getUserById(Long userId) throws BusinessExceptionController 层调用时必须捕获:
      @GetMapping("/user/{id}")
      public Result<UserDTO> getUser(@PathVariable Long id) {try {UserDTO user = userService.getUserById(id);return Result.success(user);} catch (BusinessException e) {log.error("获取用户失败,用户ID:{}", id, e);return Result.error(e.getCode(), e.getMessage());}
      }
      
  • 禁止方法抛出 Exception 父类:方法声明抛出异常时,优先抛出具体业务异常(如 BusinessException)或框架特定异常(如 SQLException),让调用方清晰知道需要处理的异常类型,避免“一刀切”捕获所有异常。

3. 空值处理:拒绝返回 null,强制判空防 NPE

  • 方法返回值避免 null:接口或工具方法返回集合、对象时,优先返回默认值而非 null
    • 集合:返回空集合(Collections.emptyList() new ArrayList<>()),而非 null
    • 对象:简单场景返回空对象(如 new EmptyUserDTO()),复杂场景用 Optional 包装(Java 8+),明确告知调用方“可能无数据”;
    • 基本类型:返回默认值(如 int 返回 0boolean 返回 false)。
  • 强制判空校验:所有入参、方法返回值、对象属性使用前,必须做判空处理:
    • 简单判空:if (userId == null) { throw new IllegalArgumentException("用户ID不能为空"); }
    • 链式判空:用 Optional 简化(如 Optional.ofNullable(user).map(User::getAddress).map(Address::getCity).orElse("默认城市")),避免多层 if (obj != null) 嵌套;
    • 集合判空:if (CollectionUtils.isEmpty(list)) { return Result.success(Collections.emptyList()); }(使用 org.springframework.util.CollectionUtils 工具类)。

4. 内存与资源:避免泄露,及时释放

  • 关闭资源:数据库连接、IO 流、Redis 连接等资源,必须在 finally 中关闭或使用 try-with-resources(Java 7+):
    // 推荐 try-with-resources(自动关闭资源)
    try (InputStream is = new FileInputStream("file.txt");OutputStream os = new FileOutputStream("output.txt")) {// 操作流
    } catch (IOException e) {log.error("IO 异常", e);
    }
    
  • 慎用静态变量:静态变量生命周期与应用一致,避免存储大量数据(如 static List<User> allUsers),容易导致内存溢出;
  • 集合操作
    • 初始化集合时指定容量(如 List<String> list = new ArrayList<>(10);),避免频繁扩容;
    • 遍历集合时禁止修改(如 for (User user : list) { list.remove(user); }),用迭代器(Iterator)或 stream 操作;
    • 避免 null 集合返回,用空集合替代(如 return Collections.emptyList();),减少 NullPointerException

5. 框架使用:遵循框架规范,不“反骨”

  • Spring Boot 规范
    • 控制器(@Controller @RestController)只负责接收请求、返回响应,不包含业务逻辑(业务逻辑放在 @Service 层);
    • 数据访问(@Repository)只负责数据库操作,不包含业务规则判断;
    • 配置文件(application.yml)中区分环境(dev/test/prod),敏感信息(数据库密码、密钥)用配置中心(如 Nacos)或环境变量,禁止硬编码。
  • MyBatis 规范
    • Mapper 接口与 XML 文件同名同目录,SQL 语句写在 XML 中(复杂 SQL)或用注解(简单 SQL,如 @Select("select * from user where id = #{id}"));
    • 避免在 XML 中写复杂逻辑(如多层 if-else),复杂逻辑放在服务层处理;
    • 分页查询使用 PageHelper 等工具,统一分页参数(如 pageNum pageSize)。
    • MyBatis-Plus 核心规范

      实体类与表映射
      使用 @TableName 注解明确实体类与数据库表名映射,字段与列名通过 @TableField 注解配置。若遵循驼峰转下划线命名约定,可省略部分注解。

      Mapper 接口规范
      继承 BaseMapper<T> 获得基础 CRUD 方法,无需编写 XML。自定义方法需通过注解(如 @Select)或 XML 实现,XML 文件建议放在 resources/mapper 目录下。

      Service 层规范
      Service 接口继承 IService<T>,实现类继承 ServiceImpl<M, T> 并实现接口。复杂业务逻辑在 Service 层处理,避免在 Mapper 层编写。

      1.SQL 编写与注解

      简单查询
      优先使用 MyBatis-Plus 内置方法(如 selectById)。条件构造器 QueryWrapperLambdaQueryWrapper 构建动态查询:

      LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
      wrapper.eq(User::getName, "张三").gt(User::getAge, 18);
      

      2.复杂 SQL
      XML 中编写多表关联或复杂聚合查询,但需避免 Java 逻辑(如循环判断)。注解方式适用于简单 SQL:

      @Select("SELECT * FROM user WHERE status = #{status}")
      List<User> selectByStatus(@Param("status") Integer status);
      

      3.分页与性能优化

      分页实现
      配置分页插件后,直接使用 Page 对象:

      Page<User> page = new Page<>(pageNum, pageSize);
      userMapper.selectPage(page, wrapper);
      

      4.性能建议

    • 避免 select *,明确查询字段
    • 大数据量查询使用流式处理或分页
    • 索引字段需在 Wrapper 中优先作为条件

6. 调试与测试:提升问题定位效率

  • 单元测试:核心服务层方法编写 JUnit 测试(如 UserServiceTest),覆盖正常场景、异常场景(如“用户不存在”“参数为空”),确保修改代码后不影响原有功能;
  • 日志分级:按场景使用不同日志级别(debug 调试信息、info 业务日志、warn 警告信息、error 错误信息),生产环境关闭 debug 日志,避免日志泛滥;
  • 远程调试:生产环境无法本地调试时,开启远程调试(JVM 参数 -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005),配合 IDEA 远程连接定位问题(注意生产环境开启后及时关闭,避免安全风险)。

三、PHP 开发特有良好习惯

1. 环境与配置:统一环境,避免“本地能跑,线上报错”

  • PHP 版本统一:团队成员使用相同 PHP 版本(如 7.4+),避免因版本差异导致语法不兼容(如 PHP 7+ 新增的类型声明、箭头函数);
  • 配置文件分离:区分开发/测试/生产配置(如 config/dev.php config/prod.php),通过环境变量($_ENV['APP_ENV'])切换,敏感信息(数据库密码)放在环境变量或 .env 文件(禁止提交到 Git);
  • 开启错误提示:开发环境开启 error_reporting(E_ALL) display_errors=On,及时发现语法错误;生产环境关闭 display_errors=Off,开启 log_errors=On,错误日志写入文件(避免暴露敏感信息给用户)。

2. 语法与性能:避免“低效语法”“危险语法”

  • 避免全局变量/函数:全局变量($GLOBALS)、全局函数容易导致变量污染,优先用类/命名空间封装;
  • 数组操作
    • 用 isset($arr['key']) 或 array_key_exists('key', $arr) 判断数组键是否存在,避免 $arr['key'] 不存在时报错;
    • 遍历数组优先用 foreach(如 foreach ($list as $item) {}),避免 for 循环(需获取数组长度,效率较低);
    • 数组初始化用短语法($arr = ['a', 'b']),替代 array('a', 'b')
  • 字符串拼接:短字符串用 . 拼接(如 $name = $user['name'] . '先生'),长字符串用 heredoc(<<<EOD ... EOD;),避免频繁拼接导致性能损耗;
  • 避免 eval() 函数eval() 执行字符串代码,存在安全风险(如注入恶意代码),尽量用其他方式替代。

3. 框架使用:遵循框架约定,提升开发效率

  • ThinkPHP/Laravel 规范
    • 控制器(app/controller)方法返回统一格式(如 return json(['code'=>200, 'msg'=>'success', 'data'=>$data]));
    • 模型(app/model)定义表名、字段映射(如 ThinkPHP protected $table = 'user_info'; protected $schema = ['id'=>'int', 'name'=>'string'];),避免硬编码表名;
    • 中间件(app/middleware)处理通用逻辑(如登录校验、日志记录),避免在控制器中重复编写。
  • ORM 操作:优先使用框架 ORM 封装的方法(如 User::where('id', $id)->find()),复杂 SQL 用查询构造器(如 DB::table('user')->where('age', '>', 18)->select()),避免直接拼接 SQL。

4. 调试与日志:快速定位问题

  • 日志查看:除了 runtime/logs 中的 SQL 日志,还需关注错误日志(runtime/logs/error-xxx.log),日志中记录请求参数、响应结果、异常堆栈(便于复现问题);
  • 调试工具:开发环境使用 dump() dd()(Laravel)或 var_dump() 打印变量,但提交前必须删除(避免泄露敏感信息);
  • XDebug 调试:配置 XDebug 配合 PhpStorm,支持断点调试、变量查看,替代“打印变量”的低效调试方式。

四、总结:习惯的核心是“降低成本”

良好的开发习惯本质是“降低个人维护成本、团队协作成本、问题定位成本”:

  • 代码格式、命名、注释规范:让自己和他人“一眼看懂代码”;
  • 异常处理、输入校验、事务管理:减少 Bug 产生,降低线上故障风险;
  • 复用代码、版本控制、框架规范:提升开发效率,便于协作与迭代;
  • Java 特有的“异常链路处理”“空值防护”“公共方法提取边界”:针对性解决 Java 语言高频问题(NPE、异常崩溃、代码冗余)。

以上习惯需在日常开发中刻意练习(如提交代码前自查格式、写完接口加校验、复杂逻辑写注释、返回值避免 null),形成肌肉记忆后,既能提升代码质量,也能让自己成为“更靠谱的开发者”。

http://www.dtcms.com/a/609202.html

相关文章:

  • AI 电影制作迈入新阶段:谷歌云Veo 3.1模型发布,实现音频全覆盖与精细化创意剪辑
  • C++函数式策略模式中配置修改
  • [MCP][]快速入门MCP开发
  • 为食堂写个网站建设免费毕业设计的网站建设
  • 云原生数据平台(cloudeon)--核心服务组件扩展
  • 字典或者列表常用方法介绍
  • 计算机网络中的地址体系全解析(包含 A/B/C 类地址 + 私有地址 + CIDR)
  • SpringBoot教程(三十四)| SpringBoot集成本地缓存Caffeine
  • 专业摄影网站推荐专业做卖菜的网站
  • Hadess V1.2.5版本发布,新增推送规则、制品扫描等,有效保障制品质量与安全
  • 华清远见25072班单片机高级学习day1
  • Apache Flink运行环境搭建
  • Node.js(v16.13.2版本)安装及环境配置教程
  • Flutter 每日库: device_info_plus获取设备详细信息
  • 小马网站建设网站备案好
  • 做某网站的设计与实现网页设计代码案例
  • 生产级 Rust Web 应用架构:使用 Axum 实现模块化设计与健壮的错误处理
  • 大模型三阶段训练:预训练、SFT、RLHF解决的核心问题
  • 记/基准] RELIABLE AND DIVERSE EVALUATION OF LLM MEDICAL KNOWLEDGE MASTERY
  • TensorFlow深度学习实战(9)——卷积神经网络应用
  • LeetCode 分类刷题:203. 移除链表元素
  • 【Qt开发】Qt窗口(一) -> 菜单栏
  • Python的json模块和jsonpath模块
  • Crawl4ai 框架的学习与使用
  • hadoop节点扩容和缩容操作流程
  • RDF 与 RDFS:知识图谱推理的基石
  • 最新轻量版域名防红跳转源码 带后台 支持随机跳转有效放屏蔽
  • linux: udp服务器与客户端 CS 基于ipv4的地址结构体
  • 做食品网站需要什么条件手机靓号网站建设
  • 运筹说145期:从快递到自动驾驶:启发式算法的智慧幕后