《实现领域驱动设计》的译者其实没错?
Jasmine 2022-8-7 19:54
有一个地方想和您商榷,这张图上说对象树是译者的臆想,我觉得译者译成对象树也对,因为聚合根和其他对象是一对多关系,您觉得呢?
******
补充一下背景:
此图摘自我写的《DDD话语批评之一:评张逸的“状态和事件本质相同”》,图中内容是《实现领域驱动设计》(Vaughn Vernon 著,滕云 译,张逸 审,电子工业出版社)中某段内容的英文原文和中文译文对照,加了一些批注。
关于此图的更多评论,还可以参见我的另一篇文章《猴子掰玉米?比较不同版《领域驱动设计》说“不变式”和“聚合”》。
******
UMLChina潘加宇
(1)
“对象树”在某些情况下是对的。
如果组合(聚合)关联的整体一端的多重性上限为1,也就是说,部分对象在同一时间最多只属于一个整体对象,那么这个整体-部分的对象链接结构确实是一棵有向树。
例如,图1左侧的类图就可能得到右侧形状的对象图(树)。
图1
如果一个部分对象可以属于多个整体对象(实际上这时整体-部分的含义已经模糊),那就是一张有向无环图,如图2。
图2
这意味着组合(聚合)是非对称的:如果对象B是对象A的部分,那么对象A不能直接或间接成为对象B的部分。
“间接”背后的意思是:组合(聚合)是传递的,如果对象B是对象A的部分,对象C是对象B的部分,那么,对象C是对象A的部分。
像图3是不允许的。C是B的部分,B是A的部分,也就意味着C间接是A的部分,那就不允许A同时也是C的部分。
图3
(2)
“对象树”有道理是不是意味着“译者译成对象树也对”?这个倒要好好说一说。
原文用词是graph of … objects(对象图),是不是译者像您(提问者)这样,想到了这一点,站得高看得远,然后毅然出手纠正作者,把译文改为“对象树”呢?
我们把这段译文一句一句仔细看看就知道了,看看译者(以及审校者)的水平是不是有三四层楼那么高。
还可以参见我之前写的文章:
(3)
原文:
Is an Aggregate just a way to cluster a graph of closely related objects under a common parent?
中译本译文:
聚合只是将一些共享父类、密切关联的对象聚集成一个对象树吗?
大问题:
“共享父类的对象”的说法在概念上是错误的。
我的剖析:
原文只是说under a common parent,“共享”属于译者自由发挥。
译者可能搞混了类和对象,搞混了集合和个体,看到原文的parent,误以为是“父类”(其实是整体对象),从而臆想出“共享父类”、“一个(应为一棵)对象树”的译文。
说“共享父类的类”或“类的对象”或“共享父类的类的对象”都可以,但不应说“共享父类的对象”。
“共享父类的类”的类图(不考虑多继承)如图4左侧的树,但是这棵树是“类(集合)”的树,不是“对象(个体)”的树。对象关系是像图4右侧这样的。
图4
以人举例,“共享父类的类的对象”是由若干“中国男人”对象、“美国女人”对象、……组成的集合,它们的类的父类都是“人”。
读者可以自行体会"人有男有女"、"人有手有脚"、“人有车有房”、“人有高富帅有屌丝”的区别。
当然,作者此处用parent一词欠考虑,但还是尽量尊重原文,parent可译为“父对象”。
中问题:
related不是“关联”。
我的剖析:
“关联”一般指association,association一词在面向对象中有特定含义,组合(聚合)就是一种特殊的关联。
在问题所给图片中可以看到,在本句之后就有association出现,“can the associations be navigated……”,作者在这里用词还是很准确的。
related可以译成“相关”。
这个看起来像是个小问题,无非是译者用词比较随意,但并非如此。
Aggregate的各个部件之间只是相关(related),并不需要存在关联(association)。
以人举例,类图如图5:
图5
手、眼、心、肝这些部件和整体对象存在关联(组合关联),但它们之间并不需要存在关联,像图6这样:
图6
注意:我的用词是“不需要存在”。如果你要是执意要像图6这样做,也不是不可以,只不过是一个不良结构。
可能有的开发人员会想,图6可以呀,这些部件之间有“兄弟”或“同事”关联呀!其实这些“兄弟”或“同事”是从整体-部分关联推算出来的冗余概念,系统不需要维护。
部件之间说“相关(related)”可以。
怎么个相关?静态上,它们都是人的部件,动态上,它们在某个场景中由整体对象协调来完成任务,如图7:
图7
*注意:可能某些部件并不需要参与某个场景,也就是说,图5中某些类的对象不一定出现在图7中(当然,可能会出现在其他场景中)。这个知识点,评点后面几句译文时还会再提到。
建议译文:
聚合只是把在共同父对象之下紧密相关的对象图聚集在一起的一种方式吗?
(4)
原文:
If so, is there some practical limit to the number of objects that should be allowed to reside in the graph?
中译本译文:
如果是这样,对于存在于这个树中的对象有没有一个实用的数目限制?
我的剖析:
这句的问题,主要还是之前提到的graph译成“树”以及“这个树”,还有allowed的漏译。
建议译文:
如果是这样,对于允许驻留在该图上的对象数目,有没有一些实际的限制?
(5)
原文:
Since one Aggregate instance can reference other Aggregate instances, can the associations be navigated deeply, modifying various objects along the way?
中译本译文:
既然一个聚合可以引用另一个聚合,我们是否可以深度地递归遍历下去,并且在此过程中修改对象呢?
问题一:
“遍历”属于概念不清。
我的剖析:
首先,原文用词的是navigate,意思是“导航”,并没有使用traversal、traverse等词。
traversal、traverse等词在计算机科学的特定场景中可译为“遍历”,意思是访问所有结点。
可是,整体对象在履行责任时,并不一定涉及其所有直接或间接的部分对象。注意,是“不一定”,需要“访问所有结点”的责任当然可以有。
如图8的类图:
图8
某个时刻的对象图可能如图9:
图9
在发生某次责任分配时,有可能只涉及到图9中的某些对象,不存在“遍历”,如图10:
图10(红色箭头表示责任分配)
最简单的组合关联就是类和属性了,在某次操作执行期间,对象并不一定要“遍历”其所有属性的值嘛。
问题二:
“深度地递归”属于概念不清和编造。
我的剖析:
原文是“navigated deeply”,译者也可能是看到deeply之后,想起有“深度遍历”,于是把navigated误解成“遍历”,然后来了一个“深度地递归遍历”。
“深度遍历”属于不严谨用语,都遍历了,无所不至,还不够深吗,难道还有“浅度遍历”不成?严谨的用语应该是“使用深度优先搜索(算法)的遍历”。
不过,为了省几个字,现在不只是口头交流,很多正式出版的书和文章也堂而皇之写“深度遍历”,这是很无奈的事情。
译者特地在“深度”后面插入了一个“地”,似乎说的又不是“使用深度优先搜索(算法)的遍历”,而是说要遍历得很深——又回到前面说的了,都遍历了,无所不至,还不够深吗?
但是再往下看,译者又在“深度地”后面自作主张加了原文没有的“递归”二字,变成“深度地递归遍历”,似乎又转回来了,还是在说“使用深度优先搜索(算法)的遍历”。
可惜,加的“递归”二字又是另一个概念不清。
“深度遍历”不意味着要“递归”,也可以“非递归”啊!
进一步展开来说,各种“递归”都可以改成“非递归”啊!
可能是加上“递归”二字觉得比较有格调吧。
问题三:
漏译了instance
我的剖析:
原因同前,类和对象的概念混淆。
建议译文:
Since one Aggregate instance can reference other Aggregate instances, can the associations be navigated deeply, modifying various objects along the way?
既然一个聚合实例可以引用其他聚合实例,那么关联是否可以向深处导航,沿途修改各种对象呢?
以下是扩展:
Eric Evans在“Domain-Driven Design”一书中的很多地方提到关联时,使用了traversal一词,这带来了很多尴尬。
如图11的“Domain-Driven Design”原文:
图11
2005清华版中译本没有译成“遍历”,选择译成“导航”,如图12:
图12
2016人邮版中译本译为“遍历”,如图13:
图13
我现在的观点是,原文用traversal不能说不合适,这个词有很多用法,不能拿后来计算机科学的用法来绑架其它用法。
在翻译上,如果确实是计算机科学中“访问所有结点”的场景,就译成“遍历”,否则可以译成“游历”或其他词。
在这一点上,Vaughn Vernon要小心得多,他大量使用的是navigation,书中只有一个地方用到traversal——“traversal through deep object graphs”。