一、概述
cola架构作为整洁面向对象的分层架构,从战略设计到业务设计,都提供了不错的方法论,并提供了可以落地的领域驱动设计方案。
在学习与使用cola架构的过程中,对cola架构中的Gateway层腐败问题做出问题的发现、分析、解决、总结.
cola架构:https://github.com/alibaba/COLA
二、问题描述
在提出问题之前,先引用自cola源码中的一段代码
public List<SubMetric> listByTechInfluence(String userId){
List<MetricDO> metricDOList = metricMapper.listByMainMetric(userId, MainMetricType.TECH_INFLUENCE.getMetricCode());
ATAMetric ataMetric = new ATAMetric();
SharingMetric sharingMetric = new SharingMetric();
PatentMetric patentMetric = new PatentMetric();
PaperMetric paperMetric = new PaperMetric();
List<SubMetric> subMetricList = new ArrayList<>();
subMetricList.add(ataMetric);
subMetricList.add(sharingMetric);
subMetricList.add(patentMetric);
subMetricList.add(paperMetric);
metricDOList.forEach(metricDO -> {
String json = metricDO.getMetricItem();
switch (SubMetricType.valueOf(metricDO.getSubMetric())){
case ATA:
ataMetric.addMetricItem(ATAMetricItem.valueOf(json));
break;
case Sharing:
sharingMetric.addMetricItem(SharingMetricItem.valueOf(json));
break;
case Patent:
patentMetric.addMetricItem(PatentMetricItem.valueOf(json));
break;
case Paper:
paperMetric.addMetricItem(PaperMetricItem.valueOf(json));
default:
log.error("illegal SubMetric type: " + metricDO.getSubMetric());
}
});
return subMetricList;
}
上面是MetricGatewayImpl 类中的listByTechInfluence方法
针对这段代码,我们提出假设:
1.SubMetricType 中的文章类型,出现了需要增加的情况,是否意味着,此方法是否需要继续膨胀?
2.SubMetricType是用户文章的一种属性,那么,当文章属性变多时,比如,增加属性“文章字数、文档版本、文章点赞数、分享数、收藏数、是否在国家期刊发表”等,根据不同属性计算出的分数不同。 按领域对象设计,需要针对属性进行建模,那么,按照原有设计,都需要在gateway层将持久化对象转换为领域对象,那么gateway层将不堪重负。
基于以上两个假设,提出问题:
- 如何实现领域对象的持久化?并在实施的过程中解决基础设施层腐败问题?
- Gateway层的职责应如何设计?
三、问题分析
1.引用《领域驱动设计》这本书中的部分观点:
上述文字中,提到,整个AGGREGATE通常由一个独立的FACTORY来创建,FACTORY负责把对根的引用传递出去,并确保创建出的AGGREGATE满足固定规则。
按照上述观点,聚合根通常由工厂来创建,那么在cola架构中,领域对象的创建实在Gateway层中实现的。
那么如果说,将领域对象的创建工作有对象工厂实现,那么需要解决另一个问题,持久化对象与对象工厂之间如何建立关系?
2.引用《领域驱动设计》这本书中的部分观点
按照上述观点,使用值对象来优化数据库,那么,如果为聚合根,创建一个值对象,用于与计算机底层进行交互,那么,Gateway层的问题就迎刃而解。
四、解决方案
概述:做厚领域对象层,做薄Gateway层
1.在领域对象层使用值对象和对象工厂,做厚领域对象层
值对象valueObject职责:用于所有能够存储聚合根值的信息
对象工厂factory职责:用于值对象和聚合根之间的桥梁,用于使用值对象创建聚合根或者由聚合根创建值对象。
在领域层创建聚合根的值对象,使用工厂对象作为聚合更与值对象之间的桥梁,将聚合根与值对象之间的转换关系沉淀于工厂对象中。
在此逻辑中,工厂对象可以在进行拆分更细粒度的工厂对象,那么如上述cola中,文章的属性扩展引发Gateway层膨胀的问题迎刃而解。
2.做薄Gateway层
由于对象的创建逻辑交给了对象工厂,那么Gateway层职责就变得简单了。
Gateway职责: 负责操作持久化层,并将持久化对象转换为领域对象中的值对象,
在java中,对象之间的拷贝,有mapstruct、Apache.BeanUtils.copyProperties()、SpringFrameWork下的BeanUtils.copyProperties()等诸多方案。如上述框架任然不能满足需求,那么在项目中考虑单独引入converter层作为持久层对象po与值对象之间的转换关系。
五、总结
按照以上方法,既保留了领域对象的扩展能力,同时解决了基础设施层的腐败问题。