【问题标题】:What's a good name for a method that gets or creates an object?获取或创建对象的方法的好名字是什么?
【发布时间】:2022-03-08 23:27:15
【问题描述】:

假设您有一个缓存,以及一个可以执行以下操作的方法:

if (wanted Foo is not in cache)
    cache.Add(new Foo())
Return Foo from cache

你会怎么称呼这个方法? GetFoo()GetOrCreateFoo() 或其他(更好)?或者这真的应该分为两种方法吗?

【问题讨论】:

  • 为什么不选择 AddFoo 或 CreateFoo?此方法将创建一个新的 Foo(除非它已经存在)。

标签: naming-conventions


【解决方案1】:

在大多数情况下,一个简单的GetFoo 就足够了,因为调用者不需要知道您正在创建和缓存它。这就是封装的全部意义所在。

但是,在某些情况下,创建是一项昂贵的操作,因此了解您可能正在按需创建某些内容并且在某些情况下会很慢是很有用的。在这种情况下,不同的命名约定使调用者更清楚。 GetOrCreate()Get(Options.CreateIfMissing) 对调用者来说是一个很好的提示。

(当然应该在文档中注明该行为,但最好使用方法名称来提醒人们在阅读代码时会产生副作用,而无需他们打开并阅读每个方法的文档被称为)

我发现这种情况最常发生的情况是(例如)在查找树节点时(例如在 XML 文档中),您可能有 CreateNode(创建节点而不将其添加到树中)和AddNode(将现有节点添加到树中)。在这种情况下,“如果节点不存在则添加节点”需要具有不同的描述性名称,因此我将使用 EnsureNodeExists 之类的名称来区分它并明确目的。

【讨论】:

  • 您通常会为get 提供某种唯一键。在这种情况下,您可能不是在寻找特定的键,而是在寻找特定的列值,因此 getFooByWhatever 可能是合适的(显然实际上并未使用 whatever)。
  • 我喜欢CreateIfMissing 的措辞。不错!
【解决方案2】:

我知道我在这个问题上已经很晚了,但是我可以建议 GrabFoo() 作为 get-or-create-if-missing 的约定来区分它与 GetFoo() 吗?

查看synonyms of Get,我看到了几个合适的动词,其中一些已经常用作方法动词。例如,Fetch 已经意味着从外部系统获取某些东西。 (例如数据库或网络)

Grab 似乎很少使用,并且可能带有 I want you to get-or-create it, no matter what. 的(尽管很弱)语义

【讨论】:

  • “grab”一词的意思是“get”,它与“create”没有任何含义。
【解决方案3】:

Getsert 怎么样?来自getinsert,因为updateinsertUpsert

虽然我没有看到任何流行的框架使用这个术语,但这符合@Jason Williams 指出的想法,即:

  • 用户应该清楚,它不会只是做一个普通的get
  • 您无需查看文档即可查看其功能
  • 易于上手且直观? (我不确定)

【讨论】:

  • 我认为 GetFoo() 不清楚,因为如果对象不存在,它不会让调用者知道他们是否会得到空结果。所以Getsert会更清楚。
  • 我喜欢 portmanteau 的想法,但 Getsert 让我想到了 get + assert,它有不同的含义。
【解决方案4】:

obtainacquire 这两个词似乎很合适。特别是obtain

拥有;获得、取得或获得,如通过 努力或请求:获得许可;以获得更好的 收入。

可以说,在你的情况下,方法的调用者获得了 foo。

【讨论】:

    【解决方案5】:

    我的首选是GetFoo(),因为从调用者的角度来看,该操作正在获取,而缓存更多的是实现细节。

    【讨论】:

      【解决方案6】:

      我将其称为 GetFoo,因为 调用者 并不关心它是否会被赋予一个新的或已经创建的 Foo - 它只是想GetFoo

      【讨论】:

        【解决方案7】:

        如果您是引用透明或对象是单例,则另一个有意义的选项。

        有时getOrCreate() 调用确实是延迟初始化。因此,您想创建一个对象,如果它已经创建,则返回对它的引用。在这种情况下,我将调用 lazyGet 方法,该方法也用于其他库,如 javaslang's lazy

        MyObject lazyGet() {
        }
        

        这对呼叫站点有一个好处。如果您的调用在创建上下文中代价高昂,您的被调用者知道,那么可以使用急切初始化将调用成本转移到程序的非关键部分。

        P.S.:这也用于记忆,这是一种优化技术,您可以返回不可变数据结构的缓存对象。

        【讨论】:

          【解决方案8】:

          我使用Take 而不是Get。原因:

          • take 听起来也有点像make
          • to take 与给定上下文中的get 具有相同的含义
          • take 听起来比 get 更有说服力,所以如果我不能 get 它,我就 take

          【讨论】:

            【解决方案9】:

            我建议使用obtain。我们已经在我们的团队中制定了这个约定,我们对此感到很自在。

            来自Cambridge 的定义:

            得到:得到某物,尤其是通过索取、购买、为之工作或从其他东西中生产出来。

            而这正是我们所需要的。

            【讨论】:

              【解决方案10】:

              对于缓存,我会简单地称之为GetFoo()。缓存旨在充当数据源后面的外观,以便调用者可以轻松访问项目,而不必担心它们是如何被加载的。

              我将其称为GetFoo,但如果请求的对象不在缓存中,缓存将加载它(以及可能具有的所有潜在性能影响)。

              【讨论】:

                【解决方案11】:

                就像大多数人在这里提到的那样,我只会选择GetFoo()

                原因是 - 该方法负责返回对象实例。这是它的首要责任。如果没有创建对象,则创建对象将其放入缓存中,然后将其返回。外部调用者,不需要打扰内部返回对象的方法,调用者将在需要时简单地调用 GetFoo()。 GetFoo() 方法封装并隐藏了创建和缓存对象背后的复杂性。因此GetFoo()

                【讨论】:

                  【解决方案12】:

                  我知道这个话题有 6 年。但是...我认为最好的名字是

                  getInstanceFoo()
                  

                  getFooInstance()
                  

                  在单例类中。

                  【讨论】:

                    【解决方案13】:

                    几个似乎合适的定义:

                    • 导致存在或发生;生产
                    • 引起或创造

                    这个词也分解成你问题中的两个想法。

                    获取创建一个方法的好名字是什么? 对象?”

                    Be = 创建

                    得到=得到

                    加上它真的很短。


                    另一种选择是解决

                    我从 Autofac 借用这个词,它使用 Resolve 方法为您获取一个对象的实例,或者在必要时创建它。

                    【讨论】:

                      【解决方案14】:

                      这取决于什么样的对象对用户有意义。

                      如果创建对用户来说不重要,那就是GetFoo;否则,将其命名为 createOrGetFoo。

                      如果需要区分概念,可以使用 GetFoo、CreateFoo 和 createOrGetFoo 等方法。

                      根据您提供的信息,我更愿意将其命名为 GetFoo。

                      【讨论】:

                        【解决方案15】:

                        假设此方法在 cacheManager 上,则 fetch(wanted) [或 get(wanted) 取决于您的个人偏好] 就足够了 - API 文档表明如果该项目不存在则创建该项目。

                        需要相应地输入 - 所以方法名称中不需要 Foo。

                        【讨论】:

                          【解决方案16】:

                          upsert(更新和插入),getsert 如在获取或插入和返回中。

                          或者发挥创意:

                          • greate 在 get 或 create 中

                          • gadd 在 get 或 add 中

                          【讨论】:

                          • 良好的命名有助于理解代码——但“upsert”、“greate”、“gadd”不容易理解。
                          【解决方案17】:

                          1.查找同义词(不好)

                          您可以尝试找到“get”的同义词。但是,您可能会认为不使用“get”的 getter 可能意味着其他东西,但您不知道它的确切作用。我会避免使用这种方法,因为最终理解它的作用永远不会干净。

                          2。使用副词作为后缀(不好)

                          您可以通过确保您执行某项操作来添加指定 get-Method 的副词。像“getCreated”、“getSafe”、“getAssured”、“getEnsured”、“getInit”、“getInitialized”。这样就可以清楚地理解它是一个吸气剂,但也告诉你它会发生其他事情。但是,您可能不知道名称是属性的一部分还是 get 的一部分。像“getSecureUrl”。所以我会避免使用 get 的后缀。

                          3.使用副词作为前缀(不好)

                          您也可以添加副词作为前缀,以说明您在做什么。像“secureGet”,“safeGet”,“initGet”,......虽然这不会干扰属性,但您不知道它是否是一个吸气剂或者其他什么东西在吸气剂之前做了一些事情而没有实际得到一些东西。所以返回值可能是出乎意料的。我也会避免这种方法。

                          4.使用描述你实际所做的事情的词语(也许)

                          与其说这是一个get-Method,你也可以说我有一个初始化值的方法。它还返回一个值对它来说是一个好处。比如:

                          function initNameid($name) { ... }
                          

                          这样你就知道你也可以初始化一些东西,而不仅仅是得到一些东西。这样一来,您就可以保持吸气剂的清洁和简单,而无需混合它。但是,就好像您正在搜索您必须考虑的更标准的东西一样,如果他们正在搜索吸气剂,人们可能找不到它。所以它可能也不是最好的。

                          5.使用其他属性增强 getter (好)

                          您可以添加额外的属性来告诉用户 getter 做了更多的事情:

                          function getName($id, $create = false) { ... }
                          

                          这样你就可以为 get 函数提供信息,如果布尔值为真,它应该尝试强制它的值。如果您使用适当的 IDE,它还会向您展示该争论的关键是“强制”、“创建”或类似的东西,因此您将始终知道它的作用。就预期而言,它可能会采用最简洁的方法。

                          6.将初始化和 getter 组合起来,而不用组合它们(好)

                          扪心自问,为什么还要把它结合起来?当然,这是一条线,但是……你需要吗?简单的一个接一个怎么样:

                          initName($name);
                          getNameId($name);
                          

                          有时最好不要仅仅因为只有一行而混合一些东西。

                          7.你真的创造了东西还是简单地存储它?(好)

                          如果你只是存储一些类似的东西:

                          public static $name;
                          public static getName() {
                          if (!self::$name) $name = ...
                            return self::$name;
                          }
                          

                          如果一个 getter 也只是缓存了一些东西,那么就没有必要改变它的名字。它来了,完全没有问题。所以你不需要解决一个不存在的问题。

                          8.为什么你需要在一个动词中结合两种不同的含义?(好)

                          如果你用一个函数来获取或创建一些东西……这样命名真的很糟糕吗? “getCreate”或“getOrCreate”等并不像听起来那么糟糕。很清楚它的作用。当然,它不是一个单一的动词,但是你做A或B然后A。那么如果你能留在AB并且每个人都知道它的意思,你为什么还要尝试找到C呢?问有没有东西也不错,但既然是两种不同的东西,没必要去想新词。

                          【讨论】:

                            【解决方案18】:

                            我称之为“GetOrDefault()”。 在不匹配的情况下:返回在相同方法中建立的构造实例,但不物理保存实例。 稍后可以进一步编辑实例属性,所以我会调用 Upsert() 来保存。

                            【讨论】:

                              【解决方案19】:

                              如果这种设计在您的应用程序中合乎逻辑,那么我认为GetOrCreateFoo 是一个合适的名称。

                              另一种明确传达其目的的方法是

                              GetFoo(bool createIfNotExists)
                              

                              当然,如果我们真的在谈论缓存,实施方可能并不关心项目是否刚刚创建。以上适用于调用者确实需要知道Foo的可能创建及其含义的情况(例如从文件系统或数据库检索时,也许?)

                              【讨论】:

                              • GetOrCreateFoo :我不同意这里。方法只是获取 foo 的对象,如果没有创建,则创建该对象,放入缓存并返回该对象。创建和缓存在方法之前过于内部,因此不必是GetOrCreateFoo
                              • @this。 __curious_geek:在缓存的特定情况下,我可以同意这一点,但问题是“获取或创建对象的方法的好名称是什么”,在更一般的情况下,调用者很可能会这样做想要控制这个(考虑在System.IO.File.Open 中非常有用的FileMode.OpenOrCreate
                              • 向 getter 添加布尔参数以添加此功能不会提高可读性,除非您使用的是带有命名参数的编程语言。
                              【解决方案20】:

                              我也将其称为“getFoo()”,并在您的 cmets 中添加如果 Foo 不存在该函数的作用。

                              【讨论】:

                              • -1 名称应该传达方法的作用,您不需要注释。另外,我不希望“获取”函数会产生副作用,例如创建某些东西。
                              猜你喜欢
                              • 2017-03-23
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 2021-08-18
                              • 2011-05-29
                              • 2017-04-13
                              • 2012-09-02
                              相关资源
                              最近更新 更多