软件在能够复用之前必须先能用 —— Ralph Johnson

详细设计任务

  1. 业务接口的定义
  2. 领域模型(实体类)的定义
  3. 数据持久化层的接口定义
  4. 数据库表的存储设计
  5. 关键业务设计模式的选用
  6. 关键业务模块的设计方案
  7. 关键方法的实现算法

详细设计的好处:

  • 对产品的好处 * 更快的产品迭代

    • 更好的用户体验
    • 更好的用户投诉
  • 对技术团队的好处: * 为构建高并发、高可用和高扩展性的应用打下良好基础

    • 产品迭代中越跑越快
    • 降低程序推倒重来的概率
    • 减少产品运行中的事故
  • 对开发者的好处 * 更加清晰、严谨的逻辑思维能力

    • 良好的面向对象设计能力
    • 有条理、高效的工作,提高成就感
    • 更加轻松的面对问题,自信带来愉悦

优秀的详细设计,是在业务场景、开发周期、技术架构等因素综合考虑的结果

优秀的详细设计需要具备的能力:

  • 成为一名优秀的程序员
  • 良好的面相对象思维
  • 懂得如何在设计思路、开发周期、业务需求间取舍
  • 熟悉产品技术架构模型
  • 深入了解产品行业,熟悉业务细节,并能洞察业务的未来

优秀的判断力来自于经验,但经验来自于错误的判断 —— Fred Brooks

表达设计的方式

  • UML
  • 文档
  • 白板(适合在详细设计之前,对大体方案进行讨论时使用)
  • 代码

敏捷开发中的详细设计,提倡设计即编码

详细设计的产物:

  • 设计实体类
  • 设计前后端调用方式及数据格式
  • 设计业务接口(接口的输入输出和实现方式)
  • 设计数据库访问层接口
  • 设计数据表结构

详细设计的命名规范

  • 基本命名规范 * 驼峰命名法

    • Java命名规范,使用Checkstyle工具检查
  • 有意义的命名 * 具有正确的业务含义

    • 避免误导
    • 避免使用复杂的单词
    • 借用类型表达含义
  • 基于约定的命名 * 数据库访问层命名规范:XXDao,insertXX,updateXX,findXX...

    • 业务层规范,如XXService
    • 控制层规范,如XXAction,XXController,XXActivity...
    • 核心业务领域名词
    • 特定用途类的名字,如XXVO,XXDTO
    • 复数表示法,如XXXs,XXList...
  • 基于技术含义的命名 * 抽象类,AbstractXX

    • 自定义异常类,XXException
    • 测试类,XXTest
    • 设计模式,XXFactory,XXVistory
    • 队列,XXQueue
    • 后台任务,XXTask,XXJob...
  • 命名技巧 * 类命名技巧 * 使用名词或名词组合 * 每隔概念对应一个词 * 具有共性的业务使用相同结尾或开头 * 具有对应关系的类使用相同开头

    • 业务接口层命名技巧 * 基于约定命名

      • 相同动作使用相同动词
      • 具有业务含义的接口方法名
      • 借用方法返回值、方法参数表达含义
    • 数据访问层接口命名技巧 * 基于约定命名

      • 使用固定的方法名开头:insert,update,delete,find

善用注释

  • 利用TODO 注释标记尚未完成的功能
  • 解决方法名过长的问题
  • 说明返回值中的空值情况
  • 更新代码时,记得更新注释

数据库表的设计原则

  • 关系型数据库设计范式 * 1NF对属性的原子性约束

    • 2NF对记录的唯一性约束
    • 3NF对字段冗余性的约束(更新不频繁的表不需要遵守3NF)
  • 关系型数据库的表设计原则 * 统一的命名规范(模块名_表名)

    • 混用范式化和反范式化(更新频繁的表使用范式化设计,查询为主的表使用反范式化设计)
    • 表的个数越少越好(体现在业务实体的抽象上)
    • 一个表的字段越少越好(实体划分越明确,字段越少)
    • 联合主键和联合索引个数越少越好
  • 关系型数据库表的字段设计 * 统一的命名规范

    • 有好的注释
    • 字段的顺序
    • 选择更小的数据类型
    • 尽量避免NULL
  • 主键设计:自增int vs GUID * GUID 比自增int占用更大空间

    • GUID进行主键物理排序时,影响IO效率
    • 自增int 不利于分库分表
    • 自增int不利于数据库迁移
  • 非关系型数据库表的设计(以MongoDB为例) * 适用于内嵌数据的情况 * 数据不经常更新 * 数据最终一致性 * 子文档较小 * 单个文档数据小幅增加 * 快读读取

    • 适用于引用数据的情况: * 数据更新频繁

      • 数据中间过程一致性
      • 子文档较大
      • 文档数据大幅增加
      • 快速写入
    • MondoDB文档设计原则 * 优先考虑内嵌

      • 需要单独访问的对象,不适合在内嵌对象中
      • 内嵌数组不能没有上限
      • 不要担心应用级别的join
      • 反范式设计时,需要考虑读写比重
      • 如何设计,取决于应用程序的业务逻辑