命名 class 以避免与解释语言中的本机数据结构相关联

Naming a class to avoid association with native data structures in an interpreted language

简介

这个问题涉及在解释语言中命名 class 以避免与本机数据结构关联的细微差别,在本例中为 Python。

背景

我目前正在重构现有的基础设施。我们有一个 class ComplexList,它的命名让我从本质上将它与一个可变的 Python list 联系起来。然而,它的底层实现和使用更为复杂(如下所述)。

它实际上是什么:一个准不可变 "master" dict 映射到压缩二进制结构中的地址位置,包括用于了解位向量中标志位位置的元数据。

在 class 中有一个 list 键映射回主 dict。这就是它被称为 ComplexList 的原因:因为作为输入,它需要一个键列表,这些键可用于从 master dict.

检索项目

通过将其定义存储在受保护的方法 _create_master_dict() 中,主 dict 映射几乎不可变。

此方法用于在任何时候将新条目添加到 ComplexList 时重新生成主控 dict,这意味着即使库用户手动操作存储主控的受保护变量 dict, 他们的更改最终会被覆盖。

然后我们使用继承来允许子 classes 使用他们自己的附加映射来扩展父 _create_master_dict()

因此我说 "quasi-immutable":当然它不是真正不可变的,但是通过实现,它不应该被修改。

问题

这样的 class 可以起什么好名字,以避免与本机 Python 数据结构和方法关联?

想法

我已经考虑过:ComplexMapComplexListToDict,这些方面的事情,但是当然,map() 又是一种本机 Python 方法,并且使用 [= class 名称中的 12=] 和 dict 可能会更加混乱。

我也考虑过像 ComplexData 这样完全抽象的东西,但这似乎有点 晦涩难懂。

答案首选项

我不反对改用我上面提到的任何想法。我也可以保持原样!这完全有可能是我想多了。

想要的答案

这个库一旦被采用,将会被很多人使用。我正在寻找简洁且直观的想法。这可能意味着答案与我自己的直觉不符,因此欢迎所有反馈!

参考文献

作为参考,我查看了 PEP 8, Google Python style guide 和许多其他 Whosebug 文章,但我还没有偶然发现一个问题完全按照这些思路讨论任何内容。

许多 Whosebug 文章仅限于变量命名约定或避免在命名中使用匈牙利符号。似乎没有太多文献讨论好的命名方式 classes.

希望我的解释不要太冗长,有助于说明情况。任何想法和意见将不胜感激!

标准名称

这太主观了,但是当 aggregates/collections 与标准集合接口有很大差异时,我更喜欢将名称设为复数。如果我们有一个 Control 的集合,其界面非常不寻常,完全不像标准容器,那么我可能会将其命名为 Controls.

这可以防止 temptation/confusion 将它与标准库中的任何现有接口相关联,并且可以在某种程度上抵挡那些可能试图使其符合标准接口以某种方式概括它的狂热者对于如此狭窄且经过充分测试的用例,成本很高,但收益很小。

标准名称 = 标准期望

一个实际的认识是,如果一个接口不符合与名称相关的规范约定,它可能会减少混淆和诱惑,并引起开发人员更多的注意来检查实际的接口,而不是假设简单地以一种首先避免此类标准名称的方式命名它。我认为以相当标准的方式命名某物的主要好处是传达它符合标准期望。如果不能,那么也许有一些不太主观的论点可以完全避免使用标准名称,因为这实际上有损于首先使用标准名称的主要好处,如果它是 "overloaded" 对于不符合相关预期的情况。

实际上,我能想到的唯一好处是,如果我根据接口的性质和底层数据结构将其命名为 ControlListControlDictControlMap而不是 Controls,那么人们可能会想提出这些类型的问题,说明为什么它不符合具有相似名称的标准接口(答案很简单,但我宁愿不要在全部)。

例如,公制命名约定的全部意义在于它们符合标准预期。当我们说某个东西是七 "meters" 时,很明显会发生什么。目前尚不清楚我们是否重载了 "meters" 有时可能意味着 "feet" 或 "yards" 在某些情况下没有进一步说明的名称,如果我们再次使用,我们实际上会稀释和混淆整个公制系统约定像 "meters" 这样的名字在不同的上下文中,相同的标准名称承载着截然不同的期望。

复数名称的论证(实用时)

因此,名称的复数形式是一个非常基本的选项,您可能会探索,也可能不会。实际上,我认为任何 class,尤其是那些以偏离标准的 UpperCamelCase 约定命名的,都不应该让人们认为它的行为类似于标准容器中的接口,它们共享一个子集名字。在我看来这是相当没有实际意义的。但是,当我们与开发人员合作时,他们的整个生计和信念都建立在对与错的基础上,并且需要相信自己来激励自己去做他们所做的事情,那里有各种模糊的想法,"moot" 不是总是 "moot".

有时您会遇到开发人员,他们看到 ListDictMap 或类似的东西作为某些名称的前缀或后缀,并希望它与界面完全一致以及标准库中的行为,这可能会绊倒人们,有时会让他们长篇大论。我是一个怪异的开发者,关心 "human factors" 和这样的心理是好是坏(更关心的是广泛的人如何倾向于对代码做出反应,而不是代码是如何以非个人的方式编写的sense),并且我已经与范围广泛的开发人员打交道(包括一些非常极端和有趣但才华横溢、固执己见且难以相处的角色),以朝着我喜欢的那种约定工作,有时在某种尝试中强加给团队导致 "minimal fuss".

因此,除非接口符合相同的要求,否则避免使用此类名称可能会有一些小好处。当它偏离标准期望时,我只是倾向于支持复数名称,如 Controls 而不是 ControlListControlSequenceControlMap 或任何此类名称,因为它不需要这样想了很多,并没有提出那么多问题。我还必须承认,有时这些接口确实会面临意想不到的设计更改(具有 key/value 对的类地图接口可能会变成类序列接口),并且这种非常基本的复数命名约定避免了诱惑继续重命名 class 并在那些接口和潜在的底层数据结构仍在进行中的次优场景中进行不必要的代码更改。

在我的行业(电影和游戏的视觉效果等)中,面对这些次优场景是很常见的,在这些场景中,界面可能需要随着底层实现的巨大方面而改变,因为昨天流行的数据结构和考虑到最先进的计算机图形技术行业变化的速度有多快,算法随时可能会过时,您必须非常幸运或使用非常高级的代码才能避免任何更改接口的需要在那时候。支持甚至不传达底层数据结构的多元聚合约定对于减少在这种极端情况下导致比最低要求更多的代码更改的诱惑特别有益。

我比较喜欢的风格是,当我们需要把Foo聚合成一些非标准的(在界面设计上)collection/container作为"primary aggregate",然后调用它Foos。如果我需要一些辅助的、不常用的容器,比如 FooBar 的映射,那么考虑在这些情况下尽可能只使用标准容器,而不创建新的 class/type。如果不是,那么我可能会调用不常用的辅助容器,如 FooMap 或类似的东西,在这种情况下,我会寻求尽可能符合标准 map/dictionary 接口除非它不切实际,此时我耸耸肩并仍然称它为 FooMap 并尝试解决文档中的任何歧义和混淆。我至少可以证明,偏爱这种风格并强加它已经导致开发人员之间似乎不那么大惊小怪了,包括我曾经合作过的一些最教条的类型(有趣的是,我合作过的一些最多产的开发人员也是最教条的,不要太惹恼他们是有帮助的)。显然,这是非常轶事,作为免责声明,我建议对这里的任何答案持保留态度。