关于UML 2.5.1中Namespace::getNamesOfMember()实现的逻辑疑问
UML 2.5.1规范中
getNamesOfMember()的逻辑问题分析 getNamesOfMember()操作定义在UML 2.5.1规范第93页的Namespace元素7.8.10.6"操作"章节,其作用是返回一个成员在命名空间中拥有的所有名称(包含导入带来的别名)。以下是带行号的OCL实现代码:
getNamesOfMember(element : NamedElement) : String [0..*] The query getNamesOfMember() gives a set of all of the names that a member would have in a Namespace, taking importing into account. In general a member can have multiple names in a Namespace if it is imported more than once with different aliases. body: 1 | if self.ownedMember ->includes(element) 2 | then Set{element.name} 3 | else 4 | let elementImports : Set(ElementImport) 5 | = self.elementImport->select(ei | ei.importedElement = element) 6 | in 7 | if elementImports->notEmpty() -- <== ??? 8 | then 9 | elementImports->collect(el | el.getName()) 10 | ->asSet() 11 | else 12 | self.packageImport->select( 13 | pi | pi.importedPackage.visibleMembers().oclAsType(NamedElement) 14 | ->includes(element)) 15 | -> collect(pi | pi.importedPackage.getNamesOfMember(element)) 16 | ->asSet() 17 | endif 18 | endif
问题描述
当前实现存在逻辑缺陷:当Namespace同时包含匹配目标元素的ElementImports和PackageImports时,来自PackageImports的对应元素名称无法被纳入输出——因为第7行开始的内层if...else分支会在elementImports非空时直接返回结果,完全跳过了PackageImports的处理逻辑。但根据UML规范,Namespace允许同时存在来自不同包的ElementImports和PackageImports,甚至可能出现命名冲突,这种情况下应该把所有来源的名称都返回。
请问这是否是代码中存在多余或缺失的括号导致的问题?
解答
这不是括号缺失或多余导致的问题,而是内层if...else的分支逻辑设计错误。
原代码的逻辑是:仅当没有匹配的ElementImports时,才去处理PackageImports。但按照规范要求,无论是否存在ElementImports,都需要检查PackageImports并收集对应的名称,最后合并所有来源的结果。
正确的逻辑应该是:
- 收集来自ElementImports的所有名称(如果有的话)
- 收集来自PackageImports的所有名称(如果有的话)
- 将这两部分结果合并为一个集合返回
修改后的核心逻辑大致如下:
let elementImports : Set(ElementImport) = self.elementImport->select(ei | ei.importedElement = element) in let elementImportNames = elementImports->collect(el | el.getName())->asSet() in let packageImportNames = self.packageImport->select( pi | pi.importedPackage.visibleMembers().oclAsType(NamedElement)->includes(element)) ->collect(pi | pi.importedPackage.getNamesOfMember(element))->asSet() in elementImportNames->union(packageImportNames)
这样就能同时包含来自ElementImports和PackageImports的所有名称,符合UML规范中对该操作的定义。
内容的提问来源于stack exchange,提问作者Robert Hairgrove
相关产品推荐
相关产品推荐

