阿里巴巴|如何提高代码质量( 二 )


编码最高原则:
可读性
控制复杂度 self-document 可维护性
优雅
分层规范
合理的代码分层 , 能控制各层的复杂度 , 以分层的思路去设计 , 也能提高代码的复用性 。 对于分层 , 我认为熟悉的就是好的 , 能满足工作中的大部分情况就好 , 这里不谈六边形架构、清晰架构、DODAF等概念 , 自己驾驭不了 , 还不能拿出来吹 。 我推荐DDD最基础的4层分层架构 , 如下:
用户界面/接口层 ? 应用层 ? 领域层 ? 基础设施层 这里举个我实际项目中用到的例子:
-- bootstrap -- BeanConfig-- application -- pv -- ChannelPvApplicationService -- sns-- domain -- abtest -- AbtestService -- address -- coupon -- entity -- Coupon -- CouponStatus -- CategoryCouponTemplate -- category -- user -- UserRepository -- service -- OneIdService -- UserService -- item -- ItemRepostory -- live -- LiveStatus-- infrastructure -- concurrent -- ThreadPoolExecutorFactory -- MonitorableCallerRunsPolicy -- dal -- IGraphDal -- TuringDal -- DefaultUserRepository -- dao -- MybatisItemDao -- util -- DateUtil -- MoneyUtil -- UriUtil -- monitor -- Event -- Timing -- TimingAspect -- TimingEvent -- Monitors-- view -- atomicwidget -- BannerWidget -- CrazySubsidyWidget -- FeedItemsWidget -- NavigateBarWidget -- LiveWidget -- page -- HomeScreenPage -- CategoryFeedsPage -- SearchCardPage -- widget -- Widget -- DispatchableWidget -- Debuggable -- AbstractWidget -- AbstractDispatchableWidget -- WidgetDispatcher -- WidgetResult -- WidgetContextIncompatibleException 上述项目结构中 , 因为是导购项目 , view相当于用户界面层 , application是应用层 , domain是领域层 , infrastructure是基础设施层 。
再对包的划分说明一下:
领域对象、值对象、DTO、Service等定义都放在子域的包下 , 不要有大而全的entity、service、impl等包(这里的子域是一个内聚的逻辑概念 , 对应的是领域设计里的子域 , 如上例中的item在我们的导购里就是商品这个子域) 常量定义尽量跟着相关的类走 , 作为类的静态字段 , 不要有大而全的Constant类(Switch相关的除外 , 但也要按职责尽量拆分开关类) 代码规范
代码规范就推荐阿里经济体开发规约 , 很全面 , 也是阿里同学的基本要求 。 代码规范就推荐「阿里经济体开发规约」 , 很全面 , 也是阿里同学的基本要求 , 开源版本:阿里巴巴java开发手册 https://github.com/alibaba/p3c
结合自己的经验 , 重点说几点:
命名
命名不用泛称(反例:processData) 尽量用完整的单词描述清楚作用和意图 , 不要怕字多 对象后缀领域对象不带后缀DTO:RPC接口提供的对象以作为VO:跟前端交互的对象PO:跟数据库直接交互的对象 日志
所有后台都要有操作日志、数据变更日志 日志要配置异步写盘 线上仅保留WARN和ERROR级别日志 所有日志都要有traceId 异常日志要有堆栈、入参、能说清楚是什么错误的信息(可以出统一组件) 打印日志时 , 禁止直接用JSON工具将对象转换成String 异常
怎么抛:尽量使用非受检异常 , 提高代码可读性 怎么处理:统一异常用切面处理 , 或依赖SpringMvc的ControllerAdvice统一处理 异常catch范围尽量小 , 分清稳定代码和非稳定代码 禁止直接吞掉异常 时刻警惕NPE , 多用Optional处理 注释
注释只为了说明为什么这么做 , 不用来说明是在做什么 面向对象
遵循原则:SRP/OCP/LSP/ISP/DIP 尽量只暴露行为 , 不暴露数据 慎用继承 , 优先使用组合方式 其它规范
方法行数保持在一屏之内(30行以内) 代码提交commit message一定要讲清楚做了啥控制每次提交的代码量(一个功能一提交) 参数尽量用不可变对象(不对入参做修改 , 保持明确的入参和出参)尽量不用隐式入参(ThreadLocal) 数据结构无随机读取时 , 用LinkedList替代ArrayList 风格做好分层 , 同层用统一的风格(设计/编码) 安全生产