难度等级:地阶中级
行列转化是我用的最多的编程技巧之一,不论是对领域建模还是表结构设计都大有裨益。适用于实体向聚合的转化阶段。我将通过一系列用户故事来描述其作用。
背景
小明是某NB公司的后端开发工程师,最近NB公司发展十分迅猛,日活大涨,高层决定搞活动拉新。最后落地下来就决定以抽奖发红包的形式来搞。
Story-1
PD:抽奖咋们也没搞过,只要满足XXPay实名认证就可以抽奖吧。
小明:这简单,给我一天。
于是乎就诞生了如下代码:
1 | class Lottery { |
小明直接把XXXPay验证逻辑写道了抽奖流程中,作为前置流程。
Story-2
PD:上次活动效果很好,拉新的目的达到了。我们要给高消费能力的人群再发红包,就再上次规则上加上积分大于1000的限制吧。
小明:好吧,你说什么就是什么咯。
1 | class Lottery { |
Story-3
PD:不好,上次活动引来了大批羊毛党,下次活动要接一下风控系统。
小明:WTF,搞个活动真麻烦。
1 | class Lottery { |
Story-4
PD: 老板们决定把抽奖做成常态工具,需要经常搞,你看看怎么弄。前置条件就那三个,但不一定都有。
小明:我就知道没啥好事。
小明认值考虑了下,这三个都是验证条件,返回结果只有true/false,我可以抽象一下提取成一个前置条件(Rule),得到如下代码。
1 | class Rule { |
Lottery实体加了3个属性,
1 | class Lottery { |
表结构也修改为:
id | name | rule_1 | rule_2 | rule_3 |
---|---|---|---|---|
1 | XXX拉新活动 | XXXPayRule | RiskRule | NULL |
经过这么一修改,小明十分满意,内心OS:还有谁!现在抽奖可自由配置规则,根据需要加载,比以前灵活度高了很多。
几个月内PD再没找过小明,小明也过了几天舒服日子。
Story-5
PD:现在发展太快了,很多子产品都用我们的抽奖工具,他们的验证规则太多了。什么注册满7天,只能中一次,XXX等等。
小明:这…让我想想。
看到这么多人用小明的抽奖系统,他内心很开心,但是这么多规则不知道如何承接。
这个时候其实就要用到 行列转换 这个技巧了。小明已经有意识的将规则抽象成了一个独立的类Rule
,但是却没有建立专门的表。对于不确定数量的规则,可以在Lottery
中加入规则的聚合List<Rule> rules
来表示独立的规则,而每个Rule
对于规则表中的一行记录。这样就把Lottery
表中的列rule_123
转化为了rule
表中的一行记录。
受到启发后,小明最终做出了如下修改:
1 | class Lottery { |
这样一来,Lottery
的代码也清爽了许多,最后一丝坏味道也去除了。
回过头来看行列转化,本质上是实体(Lottery)演变成了一个聚合(Lottery)。总结一下该技巧的使用条件:
列转行
适用时机:实体演变成聚合
关键点:抽象聚合子类,建立独立表存储。
行转列
适用时机:聚合蜕变成实体
关键点:与上述过程相反
就我个人的开发经验来看,大部分情况下都是列转行
,这样代表你的业务在进一步发展,很少遇到行转列
。行列转化
这其中有个阈值,个人觉得一般超过3个比较合适。