Lenshood

Software Developer @ThoughtWorks

0%

依赖倒置就是每一个实现都要抽一个接口出来吗?

本文的标题实际上来自于一次与项目上同事中午吃饭时的讨论:

A: 我觉得我们现在的抽象有点多,infra 层里面每一个类都抽取了接口,这些被调用的类多半只有一个实现, 我们是不是做的太细了?

B: 从依赖倒置的角度讲,domain 层和 service 层并不应该直接调用 infra 层的实现,因此我们确实是需要每一个实现都抽一个接口出来。

A: 那依赖倒置就是每一个实现都要抽一个接口出来吗?

B: 这个...

看来小伙伴 A 不经意间触碰到了 S.O.L.I.D. 的深水区...

相比于单一职责、开闭、接口隔离等原则,依赖倒置与里氏替换类似,属于更偏向操作指导的一类原则,比如从依赖倒置的定义来看:

依赖倒置:高层模块不应直接依赖低层模块,他们都应该依赖于彼此间的抽象。

以开发的角度理解:高层不要直接调用低层,而是调用抽取出来的接口。

那这么说,依赖倒置就是每一个实现都要抽一个接口出来吗?

为了解释这个问题,我们尝试来提出一个新的问题:为啥要依赖倒置?

Read more »

Caches

举例

1
2
3
4
5
6
7
8
9
10
11
LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.removalListener(MY_LISTENER)
.build(
new CacheLoader<Key, Graph>() {
@Override
public Graph load(Key key) throws AnyException {
return createExpensiveGraph(key);
}
});
Read more »

集合工具类

任何体验过 JDK 集合框架的人都了解且喜爱java.util.Collections中的工具。 Guava 在这方面提供了更多工具:应用于所有集合的静态方法。 而且这些是 Guava 最流行也最成熟的部分。

与特定 interface 相关联的方法以相对直观的规则来分组:

Interface JDK or Guava? Corresponding Guava utility class
Collection JDK Collections2
List JDK Lists
Set JDK Sets
SortedSet JDK Sets
Map JDK Maps
SortedMap JDK Maps
Queue JDK Queues
Multiset Guava Multisets
Multimap Guava Multimaps
BiMap Guava Maps
Table Guava Tables

在寻找变换、过滤等工具吗? 它们在我们的功能性语法下的 functional 文章里.

Read more »

新集合类型

Guava 引入了许多 JDK 未包含但我们却广泛使用的的新集合类型。他们全都设计为可以和 JDK 的集合框架友好的共存, 而不是硬塞入 JDK 的集合类抽象中。

一般来说,Guava 的集合会精确地按照 JDK interface 所定义的契约来实现。

Read more »

分布式锁

在传统单体应用中,我们用锁来保证非幂等操作在并发调用时不会产生意外的结果。最常见的应用场景应该就是 MySQL 用锁保证写表时不会重复写入或读表时读到脏数据。

进入微服务时代,整个业务系统可能是由数十个不同的服务节点组成,每个服务节点还包括多个实例确保高可用。在这样的环境下,一个写请求可能会由于负载均衡通过不同的服务实例操作数据,大多 NoSQL 实现为了并发性而牺牲了事务,则可能导致数据的正确性被破坏。这时如果有一个全局锁来对不同服务的操作进行限制,那么会一定程度解决上述问题。(对于复杂场景还需要采用分布式事务来处理回滚等等。)

与本地锁类似,分布式锁也是独立的对象,只不过存储在独立的节点上。最朴素的方法是在数据库中存储一段数据,以此为锁对象,存在则表示锁已被其他服务获取,不存在则表示可获取。当然此方案完全没考虑过死锁、可重入性等问题,而且如果是用关系型数据库来实现,则无法支撑高并发的场景。因此通常我们会采用 Redis、ZooKeeper 等方案来实现,并对锁代码进行一定设计,增加超时、重试等等功能。

Read more »

不可变集合

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static final ImmutableSet<String> COLOR_NAMES = ImmutableSet.of(
"red",
"orange",
"yellow",
"green",
"blue",
"purple");

class Foo {
final ImmutableSet<Bar> bars;
Foo(Set<Bar> bars) {
this.bars = ImmutableSet.copyOf(bars); // defensive copy!
}
}
Read more »

排序

示例

1
assertTrue(byLengthOrdering.reverse().isOrdered(list));

简述

Ordering是 Guava 的“流式”Comparator类。它能够用于构建复杂的比较器,并且能应用于集合对象上。

一个Ordering实例的核心仅仅是一个特殊的Comparator实例。Ordering简单的取用一些依赖Comparator的静态方法(例如 Collections.max)将之改造为实例方法。此外,Ordering类还提供了链式方法来改进、增强现有的比较器。

Read more »