【问题标题】:DoSomethingToThing(Thing n) vs Thing.DoSomething()DoSomethingToThing(Thing n) 与 Thing.DoSomething()
【发布时间】:2008-09-16 20:42:12
【问题描述】:

哪些因素决定了哪种方法更合适?

【问题讨论】:

标签: language-agnostic oop coding-style


【解决方案1】:

我认为两者都有自己的位置。

你不应该仅仅因为你认为“函数式编程很好”就使用DoSomethingToThing(Thing n)。同样,您不应该简单地使用Thing.DoSomething(),因为“面向对象编程很好”。

我认为这取决于您要传达的内容。停止将您的代码视为一系列指令,并开始将其视为故事的段落或句子。从手头任务的角度考虑哪些部分是最重要的。

例如,如果你想强调的“句子”部分是宾语,你应该使用OO风格。

例子:

fileHandle.close();

大多数时候,当您传递文件句柄时,您主要考虑的是跟踪它所代表的文件。

反例:

string x = "Hello World";
submitHttpRequest( x );

在这种情况下,提交 HTTP 请求远比作为正文的字符串重要,所以submitHttpRequst(x)x.submitViaHttp() 更可取

不用说,这些并不是相互排斥的。你可能真的有

networkConnection.submitHttpRequest(x)

你将它们混合在一起。重要的是您要考虑要强调哪些部分,以及您将向代码的未来读者传达什么。

【讨论】:

    【解决方案2】:

    要面向对象,告诉,不要问:http://www.pragmaticprogrammer.com/articles/tell-dont-ask

    所以,Thing.DoSomething() 而不是 DoSomethingToThing(Thing n)。

    【讨论】:

    • “告诉不要问”我喜欢这样!!好心!!
    • 这是一句老生常谈的小谚语 :)
    【解决方案3】:

    如果您正在处理事物的内部状态,Thing.DoSomething() 会更有意义,因为即使您更改事物的内部表示形式或它的工作方式,与之对话的代码也不必改变。如果您正在处理事物的集合,或者编写一些实用方法,那么过程式的 DoSomethingToThing() 可能更有意义或更直接;但是,通常可以表示为表示该集合的对象上的方法:例如

    GetTotalPriceofThings();
    

    Cart.getTotal();
    

    这真的取决于你的代码是如何面向对象的。

    【讨论】:

      【解决方案4】:
      1. Thing.DoSomething 如果 Thing 是您句子的主语,则适用。
        • DoSomethingToThing(Thing n) 如果 Thing 是句子的宾语,则适用。
        • ThingA.DoSomethingToThingB(ThingB m) 是不可避免的组合,因为在我能想到的所有语言中,函数属于一个类而不是相互拥有的。但这是有道理的,因为你可以有一个主题和一个对象。

      主动语态比被动语态更直接,因此请确保您的句子的主语不仅仅是“计算机”。也就是说,经常使用表格1和表格3,很少使用表格2。

      为了清楚起见:

      // Form 1:  "File handle, close."
      fileHandle.close(); 
      
      // Form 2:  "(Computer,) close the file handle."
      close(fileHandle);
      
      // Form 3:  "File handle, write the contents of another file handle."
      fileHandle.writeContentsOf(anotherFileHandle);
      

      【讨论】:

        【解决方案5】:

        我同意 Orion,但我将重新表述决策过程。

        你有一个名词和一个动词/一个宾语和一个动作。

        • 如果这种类型的许多对象都会使用此操作,请尝试将操作作为对象的一部分。
        • 否则,请尝试将操作单独分组,但包含相关操作。

        我喜欢文件/字符串示例。有许多字符串操作,例如“SendAsHTTPReply”,对于您的普通字符串不会发生,但在特定设置中经常发生。但是,您基本上总是会关闭一个文件(希望如此),因此将 Close 操作放在类界面中是非常有意义的。

        另一种理解方式是购买娱乐系统的一部分。将电视遥控器与电视捆绑在一起很有意义,因为您总是将它们一起使用。但是将特定录像机的电源线与电视捆绑在一起会很奇怪,因为许多客户永远不会使用它。关键思想是在此对象上多久执行一次此操作

        【讨论】:

          【解决方案6】:

          这里没有足够的信息。这取决于您的语言是否支持“Thing.something”或等效结构(即它是一种面向对象的语言)。如果是这样,那就更合适了,因为那是 OO 范式(成员应该与他们所作用的对象相关联)。当然,在程序风格中,DoSomethingtoThing() 是您唯一的选择……或者 ThingDoSomething()

          【讨论】:

            【解决方案7】:

            DoSomethingToThing(Thing n) 更像是一种函数式方法,而 Thing.DoSomething() 更像是一种面向对象的方法。

            【讨论】:

              【解决方案8】:

              这是面向对象与过程编程的选择:)

              我认为有据可查的 OO 优势适用于 Thing.DoSomething()

              【讨论】:

                【解决方案9】:
                【解决方案10】:

                这里有几个需要考虑的因素:

                • 能否修改或扩展Thing 类。如果没有,请使用前者
                • 可以实例化Thing。如果没有,请使用后者作为静态方法
                • 如果Thing 实际被修改(即具有更改的属性),则更喜欢后者。如果Thing 未修改,则后者同样可以接受。
                • 否则,由于对象要映射到现实世界的对象,请选择看起来更符合现实的方法。

                【讨论】:

                  【解决方案11】:

                  即使您不是在使用 OO 语言工作,也可以使用 Thing.DoSomething(),以提高代码的整体可读性,具有一组函数,例如:

                  ThingDoSomething() ThingDoAnotherTask() ThingWeDoSomethingElse()

                  然后

                  AnotherThingDoSomething()

                  等等就更好了。

                  适用于“事物”的所有代码都在一个位置。当然,“DoSomething”和其他任务的命名应该一致——所以你有一个 ThingOneRead()、一个 ThingTwoRead()... 现在你应该明白了。当您在 12 个月后重新开始编写代码时,您会很高兴花时间让事情变得合乎逻辑。

                  【讨论】:

                    【解决方案12】:

                    一般来说,如果“某事”是“事物”自然知道怎么做的动作,那么你应该使用 thing.doSomething()。这是很好的 OO 封装,否则 DoSomethingToThing(thing) 将不得不访问“事物”的潜在内部信息。

                    例如 invoice.getTotal()

                    如果“某物”自然不是“事物”域模型的一部分,那么一种选择是使用辅助方法。

                    例如:Logger.log(invoice)

                    【讨论】:

                      【解决方案13】:

                      如果对一个对象执行某项操作可能会在另一种情况下产生不同的结果,那么我建议您使用 oneThing.DoSomethingToThing(anotherThing)。

                      例如,您可能有两个在程序中保存东西,因此您可能采用 DatabaseObject.Save(thing) SessionObject.Save(thing) 会比 thing.Save() 或 thing.SaveToDatabase 或 thing 更有利。 SaveToSession()。

                      我很少不向类传递参数,除非我正在检索公共属性。

                      【讨论】:

                        【解决方案14】:

                        要添加到 Aeon 的答案,这取决于事情以及您想对它做什么。因此,如果您正在编写 Thing,并且 DoSomething 改变了 Thing 的内部状态,那么最好的方法是 Thing.DoSomething。但是,如果动作不仅仅改变内部状态,那么 DoSomething(Thing) 更有意义。例如:

                        Collection.Add(Thing)
                        

                        优于

                        Thing.AddSelfToCollection(Collection)
                        

                        如果你没有写 Thing,并且不能创建派生类,那么你别无选择,只能做 DoSomething(Thing)

                        【讨论】:

                          【解决方案15】:

                          即使在面向对象的编程中,使用函数调用而不是方法(或者就此而言调用对象的方法而不是我们调用它的方法)可能很有用。想象一个简单的数据库持久性框架,您只想在一个对象上调用 save()。您可以创建一个接口定义 save(Class1)、save(Class2 ) 等及其实施。然后您实际上会调用 databaseSaver.save(class1) 并将所有内容放在一个地方。

                          【讨论】:

                            【解决方案16】:

                            我必须同意Kevin Conner

                            还要记住这两种形式中的任何一种的调用者。调用者可能是其他对象的一个​​方法,它肯定会对你的事物做一些事情:)

                            【讨论】:

                              猜你喜欢
                              • 1970-01-01
                              • 2021-10-27
                              • 2019-05-27
                              • 2021-02-28
                              • 2010-12-14
                              • 1970-01-01
                              • 1970-01-01
                              • 2019-01-21
                              • 1970-01-01
                              相关资源
                              最近更新 更多