0%

对象是过程的抽象,线程是调度的抽象

  1. 并发是一种架构设计:并发不是简单的 “用 Thread 跑个任务”。它是一种宏观的设计决策,应该在架构设计早期就考虑,而不是事后添加。它可以将“做什么”和“何时做”解耦。

  2. 并发与性能不是等价的

    • 并发结构性问题。旨在让程序在同一时间做多件事(更清晰的设计)。

    • 并行性能问题。旨在让程序在更短的时间内做一件事(提高速度)。

    • 并发可以带来并行,从而提升性能,但这不是唯一目的。并发只有在多个线程或处理器之间能分享大量等待时间的时候管用

  3. 并发编写的核心难点对共享数据的正确访问。不同执行线程对同一数据资源的竞争和协作是万恶之源。

  4. 并发防御原则

    • 单一权责原则 (SRP):并发相关的代码应该有自己独立的开发、修改和调优的生命周期。不要将并发代码与其他业务代码混在一起。

    • 限制数据作用域:共享数据是危险的。严格限制哪些数据可以被共享,并通过精细的同步机制来保护它们。

    • 使用数据副本:尽可能避免共享,使用数据的副本进行处理。

    • 线程应尽可能独立:让每个线程在自己的世界中运行,不与其他线程共享数据。例如,使用 ThreadLocal 变量。

阅读全文 »

通过迭进设计达到整洁目的

简单设计 4 规则:

  1. 运行所有测试 Run all the tests

  2. 不可重复 Contains no duplication

  3. 表达了程序员的意图 Expresses the intent of the programmer

  4. 尽可能减少类和方法的数量 Minimizes the number of classes and methods

阅读全文 »

在阅读本章时,不是太明白,遂借助 deepseek 理解本章:

核心思想:构造与使用分离

这是本章最根本、最重要的理念。作者认为,系统混乱的主要根源在于:

构造(Construction) 和 使用(Use) 这两件事被混在了一起。

  • 构造:创建对象、定义依赖关系、组装应用程序结构的过程。(如何将零件组装成引擎

  • 使用:系统运行时,对象之间协作执行业务逻辑的过程。(如何踩油门让汽车跑起来

将这两者混杂,会导致代码职责不清、难以测试和维护。一个整洁的系统架构应该将这两者清晰地分离开。

阅读全文 »

类的组织 Class Organization

公共函数调用的私有函数,紧跟公共函数后,这符合自上向下原则,让程序读起来像一篇报纸文章

封装 Encapsulation

有时为了测试,会把 private 的变量或函数变成 protected 或 Internal 的

首先想办法隐藏,保有隐私,发送封装总是下策

阅读全文 »

TDD 三定律 The Three Laws of TDD

  • 在编写不能通过的单元测试前,不可编写生产代码

  • 只可编写刚好无法通过的单元测试,不能编译也算不通过

  • 只可编写刚好足以通过当前失败测试的生产代码

保持测试整洁 Keep Tests Clean

脏测试等同于没测试

测试不干净 -> 改动代码能力受到限制 -> 失去改进代码结构的能力 -> 代码腐化

阅读全文 »

使用第三方代码 Using Third-Party Code

在接口提供者和使用者之间存在与生俱来的矛盾

  1. 第三方程序包或框架提供者追求普适性,能在多种环境中工作,从而吸引广泛的用户

  2. 使用者想要得到集中满足特定需求的接口

因此,应该对第三方代码进行适当的封装

阅读全文 »

错误处理很重要,但是如果它搞乱了代码逻辑,就是错误的做法

使用异常而非返回码 Use Exceptions Rather Than Return Codes

  • 将逻辑和错误处理隔离

先写 try-catch-finally 语句 Write Your Try-Catch-Finally Statement First

异常的妙处在于:它们在程序中定义了范围,执行 try-catch-finally 语句中 try 部分的代码时,你是在表明可随时取消执行,并在 catch 语句中接续

在某种意义上,try 代码块就像是 事务

  • 最好先写出 try-catch-finally 代码块,能帮你定义该代码的用户 应该期待什么

尝试编写强行抛出异常的测试,再往处理器中添加行为,使之满足测试要求

阅读全文 »

数据抽象 Data Abstraction

隐藏实现 并非 只是在变量之间放上一个函数层那么简单,隐藏实现 关乎 抽象

类不能简单地通过 Setter 和 Getter 把变量暴露出去,而应该暴露抽象接口,以便用户无需了解数据的的实现就能操作数据本体

如果把变量设为 private,然后通过 Setter 和 Getter 暴露,这跟设为 public 有什么区别

举两个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Point {
public double x;
public double y;
}


public interface Point {
double getX();
double getY();
void setCartesian(double x, double y);
double getR();
double getTheta();
void setPolar(double r, double theta);
}
阅读全文 »

  • 代码格式关乎沟通,而沟通是专业开发者的头等大事

  • 每个空白行都是一条线索,表示出新的独立概念

  • 关系密切的概念应该互相靠近

  • 变量声明:应尽可能靠近其使用位置

  • 实体变量:应在类的顶部声明(Java)或 底部声明(C++, 剪刀原则),团队遵循相同规范即可

阅读全文 »

生活不止眼前的苟且,还有诗和远方

转眼,为期一周的旅游就结束了,此时那一幕幕还在眼前浮现,何不记录一番

与 2023 年(桐庐)不同,这次我和老婆一下去了两个海滨城市:烟台 和 威海

阅读全文 »