《代码精进之路 从码农到工匠》学习笔记目录
原书:《代码精进之路 从码农到工匠》 | 作者:张建飞
3.7 精简辅助代码
Java 中使用 Optional 优化判空,但 Optional 自身为 null 时也会报 NullPointerException
被嫌弃的代码
1
2
3
4
5
6
7
8
9
| if(user !=null){
Address address = user.getAddress();
if(address != null){
PhoneNumber phoneNumber = address.getPhoneNumber();
if(phoneNumber != null){
log.info("用户的电话号码={}", phoneNumber.getNumber());
}
}
}
|
消除 if 语句的代码:用户电话号码提取器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| import java.util.Optional;
public class PhoneNumberExtractor {
public final static Integer extract(User user) {
return Optional.ofNullable(user)
// address 为 null 时,可以返回默认值 0
.map(User::getAddress).orElse(Optional.empty())
// phoneNumber 为 null 时,抛出空指针异常
.flatMap(Address::getPhoneNumber)
.map(PhoneNumber::getNumber)
.orElse(0);
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| import java.util.Optional;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
class PhoneNumberExtractorTest {
@Test
void return_0_when_user_is_null() {
Integer phoneNumber = PhoneNumberExtractor.extract(null);
assertThat(phoneNumber).isEqualTo(0);
}
@Test
void return_0_when_address_is_null() {
Integer phoneNumber = PhoneNumberExtractor.extract(User.builder().address(null).build());
assertThat(phoneNumber).isEqualTo(0);
}
@Test
void throws_NullPointerException_when_phone_number_is_null() {
Optional<Address> address = Optional.of(Address.builder().phoneNumber(null).build());
User user = User.builder().address(address).build();
Assertions.assertThrows(NullPointerException.class, () -> PhoneNumberExtractor.extract(user));
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| import lombok.Builder;
import lombok.Getter;
import java.util.Optional;
@Builder
@Getter
public class User {
private Optional<Address> address;
}
@Builder
@Getter
public class Address {
private Optional<PhoneNumber> phoneNumber;
}
@Builder
@Getter
public class PhoneNumber {
private Integer number;
}
|
9.5.2 分层架构
目的
通过分离关注点来降低系统的复杂度,同时满足单一职责、高内聚、低耦合、提高可复用性和降低维护成本
使用建议
- 分层只知道直接的下层
- 或者可以宽松一些:分层可以访问它之下的任何分层
- Martin Fowler 的经验是在实际中使用这个方法会更好,因为它避免了在中间分层创建代码(或者完整的代理类)
10.1 不教条
软件的第一性原理是“控制软件复杂度”。
但凡能提高代码可读性、可扩展性和可维护性的方法,都是值得考虑的,并不一定要拘泥于某种特定的开发过程或者编程范式。
10.1.2 贫血还是充血
使用哪个,核心在于是否能有效的控制复杂度。
10.4 结构化思维
5W2H 分析法
- Why
- Who
- When
- Where
- What
- How
- How much
10.4.2 如何做晋升述职
提出问题 -> 定义问题 -> 分析问题 -> 解决问题 -> 最后展望未来
另一个思维 zoom in / zoom out
说事情时,先从宏观背景开始,让大家知道事情发生的背景,为什么这件事很重要?
然后讲到具体细节,怎么做成的?
解决了什么问题?
后端思考是什么?
最后,从细节回到整体,结果是什么?带来的客户价值是什么?你对未来的思考是什么?
11.3.4 团队特色
把攻克软件复杂度作为首要技术目标
12.2.2 CQRS
命令查询分离(Command Query Separation, CQS)
最早是 Betrand Meyer(Eiffel 语言之父,OCP 的提出者)提出的概念,其基本思想
在于任何一个对象的方法可以分为以下两类:
- 命令(Command):不返回任何结果,但会改变对象的状态
- 查询(Query):返回结果,但不会改变对象的状态,对系统没有副作用
命令查询职责分离模式(Command Query Responsibility Segregation, CQRS)
是对 CQS 模式的改进而成的一种简单架构模式。
该模式从业务上分离修改(增、删、改)和查询的行为,从而使逻辑更加清晰。
- 该模式是读写分离的,有利于优化读写操作
- 让代码更清晰简洁、更能体现出领域,易于维护
- 是封装、低耦合、高内聚、单一责任原则的体现
待学习
第 3 章 函数
- 3.7.2 优化缓存判断
- 3.7.3 优雅降级
- 3.8 组合函数模式(组合函数模式出自 Kent Beck 的《Smalltalk Best Practice Patterns》)
- 3.10 函数编程
- 减少冗余代码,让代码更简洁、可读性更好
- “无副作用”,都是线程安全的不可变对象
第 7 章 DDD 的精髓
- 领域实体
- 聚合根
- 领域服务
- 领域事件
- 四色建模法
- InfoQ 运用四色建模法进行领域分析
- Robert C. Martin 的《架构整洁之道》中作者提出:整洁的架构应该是“核心业务逻辑和技术细节相分离”的