Free-View Version

Live Version

<Scan the QR code>

<to view the slide in your phone>

软件编程的

「定义」与「边界」

Created By

ADoyle

前提

长期的,功能繁多易变,趋于复杂的项目工程

短期的,功能有限或稳定,简单的项目工程

¯\_()_/¯

问题

你是否遇到过这些情况:

  1. 实现某个功能,代码即可以放在这个文件/类,也可以放另一个文件/类,并且两种方案没有明显的优劣?
     
  2. 接触一个陌生的项目,发现要实现一个功能得改很多很多文件的代码
     
  3. 认为给函数、变量、类取名是件难事

定义

Definition

范围

Scope

命名

Naming

认知表述

We're better at doing it than knowing what we're doing.

--《What is an abstraction?》 Eric Normand

循序渐进的过程

命名

名正则言順,言順则事成

命名即认知

命名为指名

There are only two hard things in Computer Science:

cache invalidation and naming things.

-- Phil Karlton

容器

组件

行为的定义

查询

1. find_a_record(id)

2. find_a_record_or_throw_error_if_null(id)

3. find_a_record_or_null_if_null(id)

上下文

Contexts

有一千个读者,就有一千个哈姆雷特

命名总是上下文相关的

路由

Code is read much more often than it is written.

-- Raymond Chen - MSFT

保持一致性

Consistency

命名一致性

  • 名词
  • 动词
    • 增: add/create
    • 删: remove/delete
    • 改: update
    • 查: get/query
  • 形容词
    • 表状态: is_xxx
  • 关系
    • 条件: xxx_by_yyy
    • 数量:
      • 全部: zzz_all
      • 部分: zzz_some
    • 逻辑
      • and
      • or
  • 主动: xxx
  • 被动:
  • 时态
    • 过去: did_xxx
    • 现在: xxx
    • 将来: will_xxx

抽象与具体

Twitter

Twitter_Logo_Blue

抽象

具象

底层(机制)

高层(业务)

易变

稳定

需求

沟通

Communication

定义

总结

  • 命名即认知
    • 如何命名某样事物反应出你当时的理解
  • 分层定义 hierarchical
    • 越具体的越接近上层(易变的)
    • 越宽泛的越接近底层(不变的)
  • 尽可能详细地定义
    • 因为每个人阅读同一个单词会有不一样的理解
    • code is read much more often than it is written.
  • ......

软件编程的

定义边界

明确定义是为了明确边界

边界

Boundary

Created with Sketch.
Created with Sketch.

Created with Sketch.

Model

View

Controller

Created with Sketch.

一般

设定边界

边界,意味着约定/约束

(强)约束

  • 文档约定
  • 函数签名注释
  • 分离关注点
  • 防御式编程 (assert)
  • 运行时校验层
  • 职能划分
  • 强类型语言静态检查

(弱)约定

为什么要设定边界?

如何划分边界?

  • 如果没有理由,就不要主动设定边界
  • 如果不能理解,就按已有的约束来做,如果没有约束,就随便做

 

  • 命名的边界
  • 业务的边界
  • 代码的边界
  • 数据的边界
  • 逻辑的边界
  • 测试的边界
  • 职能的边界

边界 - 示例

识别边界 - 命名

如何避免重名?

识别边界 - 业务

  • 业务操作 与 原子性操作
    • RESTful API
    • 增删改查
      • 权限判断
  • 业务语义的定义
    • 如何区分业务逻辑?
      • 多参数
      • 上下文分离
  • 代码与配置
  • DSL 与代码
    • 内部 DSL
    • 外部 DSL

识别边界 - 代码

代码的边界·尾递归优化

int factorial(int n, int acc) {
    if (n == 0) return acc;
    return factorial(n - 1, acc * n);
}
int factorial(int n, int acc) {
    while (true)
    {
        if (n == 0) return acc;

        acc *= n;
        n--;
    }
}

识别边界 - 代码

编译与执行

  • 静态与动态
  • 尾调用优化

识别边界 - 代码

函数、模块、框架、系统

  • 单一职责原则
  • 模块化、插件化
  • OOP
  • FP

 

  • 数据与代码
    • 数据完整性校验
  • 数据与行为

识别边界 - 数据

识别边界 - 数据

识别边界 - 数据

识别边界 - 数据

When persistence logic leaks to domain logic

  • Case #1: Dealing with object’s persistent state in a domain entity
  • Case #2: Dealing with Ids
  • Case #3: Segregating domain entity properties

When domain logic leaks into persistence logic

  • Case #1: Cascade deletion
  • Case #2: Stored procedures
  • Case #3: Default database values

识别边界 - 数据

Most of the leaks come from thinking not in terms of the domain, but in terms of data. Many developers perceive the application they develop just like that. For them, entities are just a storage for data they transfer from the database to UI, and ORM is just a helper that allows them not to copy this data from SQL queries to C# objects manually.

识别边界 - 数据

状态是对数据的抽象
数据多半不能直接被用户看到(比如你不能直接返回一个timestamp给用户),而状态则更贴近业务;
数据需要是原子的(数据库第一、二范式),而状态一般涉及一条以上的数据;
数据稳定性高,状态变数多:需求变化了,不应该去操作全量数据,而是修改状态控制;
数据适合放在有持久化的地方,而状态根据数据动态算出,适合放在内存中(当然,系统大到出现集群的概念以后,状态也可能需要持久化)。

数据库存储状态,即数据

应用操作并维护状态

业务逻辑 Business logic

应用逻辑 Application logic

数据逻辑 Data logic (暂未考虑)

识别边界 - 逻辑

识别边界 - 测试

  • 黑盒测试
  • 单元测试 与 集成测试
  • Dev 与 Ops
  • Full-Stack Developer
  • 设计 与 开发

尝试跨越职能的边界,站在新的角度看问题

识别边界 - 职能

Summary

  1. 认知自己所做的,没有歧义地表达
  2. 有层次,多维度地看待事物

跨越边界

突破原有的限制,开阔思路

Boundary Crossing

~ The End~

颜色

#74aaff

#94dc6f

#ff9900

Style

软件编程的「定义」与「边界」

By ADoyle

软件编程的「定义」与「边界」

Keep updating

  • 3,024