我们何时真正使用面向对象的编程?[关闭]


35

我正在用Python编写一个程序,该程序基本上可以操作字符串,而我想知道是否应该使用OOP原理来执行它。客户确实告诉我他不在乎代码,他只是想把事情做好

我知道,面向对象的代码从定义上讲不是更干净,相反,非OO代码从定义上讲并不是很糟糕。我要提出的问题或多或少是基于意见的,但可能有一些我不知道的规则。

有关要执行的操作的更多信息:

  • 解析.csv文件并根据配置文件处理数据(列可能不同,例如列数或它们保存的数据)
  • 使用以上处理的数据创建新的自定义格式的数据(或基于上述某些值的多个文件)
  • 使用最后格式化的数据来创建XML文件。
  • 根据XML文件XML的内容将XML文件拆分为多个
  • 该应用程序应基于CLI
  • 当然还有其他事情,例如:记录一些事件,解析CLI参数等等。

现在,这根本不是一个很大的应用程序,也几乎完成了,但是在整个开发过程中,我一直在问自己是否应该使用OOP来完成。

所以,我的问题是:你们如何知道/决定何时在应用程序中使用OOP


12
关于,“客户……不关心代码,他只是想把事情做好。” 好,那就去做 但是这东西有多复杂?如何好,你会真正理解需求?客户稍后再要求您更改事物的可能性有多大?有时,您只需要快速而又肮脏的技巧,但是您将花费更多的时间和精力,解决问题的某种结构化方法(例如,OO设计)就越有可能使您受益。
所罗门慢

5
不要在您的帖子中使用“编辑”或其他类似的绰号。每个Stack Exchange帖子都有详细的编辑历史记录,任何人都可以查看。无论如何,在评论中使用“我没问过OOP是什么”之类的信息更合适,而不是您的问题。
罗伯特·哈维

@RobertHarvey好的,知道了。下次我会做。
Grajdeanu Alex。

Answers:


60

Python是一种多范式语言,这意味着您可以选择最适合该任务的范式。诸如Java之类的某些语言是单一范例OO,这意味着如果您尝试使用任何其他范例都会感到头痛。说“总是使用OO”的海报可能来自这种语言的背景。但幸运的是您可以选择!

我注意到您的程序是一个CLI应用程序,可以读取一些输入(csv和配置文件)并生成一些输出(xml文件),但是它不是交互式的,因此没有状态GUI或API。这样的程序自然地表示为从输入到输出的功能,该功能委托给其他用于子任务的功能。

另一方面,OO与封装可变状态有关,因此更适合于交互式应用程序,GUI和API的可变状态公开。OO是与第一个GUI并行开发的,这并非巧合。

OO的另一个优点是,多态性使您的架构松散得多,可以轻松替换同一接口的不同实现。与依赖项注入结合使用,可以允许基于配置的依赖项和其他有趣内容的加载。不过,这最适合于非常大的应用程序。对于您所描述的大小的程序,几乎没有太多好处,而且开销很大。

除了实际读取和写入文件的功能之外,您的大部分逻辑都可以编写为无副作用的函数,这些函数需要一些输入并返回其他输出。这非常容易测试,比测试OO单元要简单得多,因为在OO单元中,您需要模拟依赖关系等等。

底线:我建议将一堆函数拆分为用于组织的模块,但不要包含对象。


8
最终,一个平衡的答案不仅赞扬了OOP :-)
cmaster

1
这就是我所期望的答案。可以扩大您的答案吗?到目前为止看起来很棒。
Grajdeanu Alex。

3
@ Dex'ter:谢谢。您还需要什么其他信息?
JacquesB '16

3
我还要补充一点,函数式编程可能是继续阅读的范例。
安德鲁说,请恢复莫妮卡(Monica)

1
@Bergi:是的,这是多范式语言的好处。您可以使用OO库,而不必以OO风格编写自己的程序。
JacquesB '16

15

考虑GUI上的按钮。它具有状态(大小,颜色,位置,标签等)。事情可能会发生(单击它,需要重绘等)。在这种情况下,将其建模为对象是有意义的。作为对象,它可以包含其状态,可以在其上执行的一组操作(方法),并且可以通过触发事件来通知应用程序的其他部分事情已经发生了。

OOP是用于处理GUI以及系统某些部分处于易失状态的其他情况的绝佳工具。

其他情况(例如您描述的情况)是通过不同的方法很好地处理的:从源读取数据,将数据处理并写到目的地:声明式(或函数式)编程。与OOP解决方案相比,用于数据处理的声明性代码往往更易于阅读且更短。

正如正确使用锤子和锯子一样,它们都是强大的工具一样,面向对象和声明性编程技术也是如此。您可能会用锯子把钉子钉在一块木头上。同样,您可以用锤子将一块木头切成两半。同样,您可以创建仅具有功能的GUI并使用对象处理数据。但是,如果正确使用工具,结果将更干净,更简单。

我使用的一般经验法则是,如果我有很多状态,或者需要用户交互,那么我会使用对象。否则,我将使用(可能的话,使用纯和高阶)函数。


6

面向对象编程为您的武器库增加了四个新工具

  1. 封装形式
  2. 抽象化
  3. 遗产
  4. 多态性

当OOP变得足够大且复杂到足以从这些工具中受益时,您将在应用程序中使用OOP。


18
抽象和多态是编程的许多“方向”提供的工具。与继承相比,OOP实际上提供了一种较弱的封装形式,因为继承会鼓励泄漏的抽象设计。OOP真正添加到工具包中的唯一一件事就是继承,这被普遍认为是一件坏事。
大卫·阿诺

4
@DavidArno:您基本上是在说“从不使用OOP”。
罗伯特·哈维

6
这是在花大量精力研究其他人的代码之后的一天,程序的直接过程实现通常比对OO设计的理解不好的实现更好。OO体系结构可能非常强大,但应像烹饪中的香料一样使用,并且具有专业知识和适量的知识。误用面向对象的设计与在糟糕的餐厅中要求番茄酱一样普遍。
2016年

6
四种工具(封装,抽象,继承,多态)都不是OOP专用的。也许您应该解释OOP在这些方面与其他范式有何不同。
Giorgio

4
@gardenhead,您奇怪的优越感对您的职位无济于事。也许您应该提出一个标题为“为什么最常用的语言经常是OO?”的问题。更好的是,按Ctrl + F并键入'GUI'。
Gusdor

1

这个问题对我来说有点困惑。如果您是用Python编写的,那么您肯定会使用对象。当您打开文件时,它返回一个对象。当产生结果时,它返回一个迭代器对象。您创建的每个函数都是一个对象。至少可以这样质疑OO在Python应用程序中的价值。

根据这里的评论,是的,Python支持功能范例,但主要基于对象。语言本身和内置库围绕对象。是的,它支持lambda(Java和任何其他通常描述为OO的语言都支持lambda),但是与真正的功能语言相比,它是故意简化的。

围绕OO设计和功能设计的这些区别也许已经过时了。如果我在OO设计的Object *上创建一个多态函数,然后将指向该函数的指针作为参数传递给功能样式化的函数*,那么该OO还是具有功能?我认为这既是解决问题的一种也是非常有效的方法。

我认为真正的问题是“什么时候应该开始设计自己的类而不是仅创建具有功能的模块?” 我认为正确的答案是:何时可以简化解决方案。对于任何面向对象的语言,我都会给出相同的基本答案。

*冗余是有意的:我不想在这里被指责为对象是OO或函数是有功能的。


5
是的,对象不等于OOP。在拥有对象与围绕对象及其交互来构建体系结构之间存在区别。有点像如果您创建一个并不意味着您正在执行函数编程的函数。
2016年

您可以很容易地将Python / JavaScript对象视为Record,这很实用。功能语言具有对象。关键是第二个单词:定向。OOP语言完全围绕使用对象来定位,而其他一些语言只是将它们视为工具箱的另一部分。
Dan Pantry

0

面向对象编程的最大优点之一是,您无需推理程序流,而可以开始推理状态。

很多时候我看到对象,我看到方法,但是我也看到的是,代码背后的驱动思想是流动而不是状态。

一旦确定了状态,就可以轻松地构建良好的OOP代码,因为一旦代码变得太复杂,您就会发现您不再能够确定状态并知道需要重构。

考虑您的示例:您想解析一个csv文件。它来自哪里:磁盘上的文件。您将其加载并放入内存中并进行解析。现在您的客户端来了:嘿,我也想从网络上解析文件。因此,您很高兴,因为您为加载文件提供了一个不错的界面,而只需制作从Web上获取文件的代码,而程序的其余部分则保持不变。

令人高兴的是:您可以对此进行测试。


3
您从磁盘读取文件与从Web读取文件的示例也可以通过不同的功能来实现。您不需要OO。
JacquesB '16

0

用外行的话来说:

  • 您可以在所需的任何类型的项目中使用OOP或非OOP。
  • OOP不是万能药,但它有助于管理复杂性。
  • 它超越了模块化,它涉及到分区。想一想,如果船体受损,则船舶可用于保持浮力的不同隔室。
  • OOP是一种管理依赖关系的方法,因此,由于程序的不同组件只能通过一组定义的方式来与其他组件进行通信,因此可以更轻松地查找错误。
  • 在程序中,有很多事情在起作用:变量,常量,方法,文件,参数,函数,模块等。它们之间的交互作用有时是不可预测的。OOP是一组原则,可减少事物之间相互交互的方式。您不会被迫使用OOP来做到这一点,但这会有所帮助。

也就是说,还需要考虑其他因素:

  • 您的程序员是否精通OOP / OOD?
  • 您的程序员是否精通OOP语言?
  • 您认为该软件会随着时间的推移变得复杂吗?
  • 您打算将来扩展或重用代码吗?
  • 您认为您的“设计”可以成为资产吗?即您是否能够利用它来发展或作为未来项目的基础?

不要误会我的意思:无需使用OOP就可以实现所有目标,但是使用OOP会更容易。

但...

如果您的团队不擅长OOP / OOD并且在该领域没有专业知识,请利用您拥有的资源。


-2

所以,我的问题是:你们如何知道/决定何时在应用程序中使用OOP?

始终使用它。一旦习惯了使用它,就可以将其用于所有内容。这是确保功能及其使用之间良好抽象的好方法,这对维护有很大好处。例如,我们将其用于

  • 小型数据结构对象,因为它们通常是多态的,例如,解析某些数据后的中间数据结构通常具有多个小实体,这些小实体具有共同的行为,但也具有特殊性。对于具有特定实现和行为(即类层次结构(多态性))的通用基类或接口,这是一个很好的用例。

  • 例如,日志记录,因为它可以轻松替代其他记录器

  • 大型程序结构,因为您会想到多个并发的程序,并且可能会利用多cpu处理器。例如,由于对象的原因,Web服务器可以琐碎地使用多个并发请求处理程序。

正如我所提到的,它使重构和重用更加容易,鼓励了良好的抽象,所有这些都简化了维护。OOP应该一直被接受和使用。好的OOP编程应避免使用静态方法和/或静态数据,并使用对象进行所有操作。


6
我没有投票(即使我很接近),但我认为这就是您投票否决的原因:“总是使用它,因为它很棒”很少是一个很好的建议。总是有例外。没有工具有缺点,OOP也不例外。告诉人们这是一件好事,告诉人们它有什么好处,告诉人们它为什么有好处,告诉人们如果可以的话,避免选择替代品,但是永远不要告诉人们不要考虑替代品。
cmaster

@cmaster,我可以接受人们的不赞成,这是他们的选择,我也做到了。在主题上,我仍然认为这是提出问题的人的正确答案;恕我直言,OP需要一路跳起来并使用OOP,而不是试图决定何时使用OOP,并偶尔选择创建类,而是编写过程代码。
埃里克·艾德

2
@cmaster我很感谢Erik的建议。面对“取决于情况”的答案,通常可能是政治上正确的方法,让我们面对现实的人们,OO几乎已经成为支持它的编程环境的基准。因此,不要自欺欺人,OO几乎不会出错。所描述的脚本虽然是线性的,但足够复杂,对象可以为您带来一些好处。
马丁·马特

2
@ErikEidt“ OP需要完全进入并使用OOP”,您可以这样解释:“ OP需要停止思考解决客户问题的最佳方法,而要遵循开诚布公的真实道路。” 可悲的是,我不得不处理很多所谓的计算机专业人士谁的遵循软件设计方法。强制性的迪尔伯特漫画:dilbert.com/strip/1996-02-27
alephzero

1
就像把它作为“又一个无意识的OOP狂热者”挥舞一样容易,我认为有一点要说,实际上是100%投入某种东西来真正内部化和吸收它。不是,您可以在余生中每天使用它,但是您实际上是在学习长处和短处,而不仅仅是阅读它们。我建议几乎任何人都花几个月的时间来进行硬核OOP和几个月的硬核FP(ála haskell)以及几个月的程序C等等。只是进入那里,弄脏它。
萨拉

-2

面向对象编程提供了创建框架的工具。这些工具是封装,抽象,继承和多态。这些想法将帮助您将程序分为两个部分。

如何使用-这是代码的框架部分,您在其中创建某种抽象,确定您的块一般如何工作以及如何与其他块交互。

要做什么-这部分是块本身进行实际工作的地方。在这里,该类派生自“ How to section”中创建的基类。

一个可以从OOPS中大大受益

  1. 如果您可以重用现有框架,而只需要在“要做的事情”部分中实现特定的细节。
  2. 当前项目正在实现的功能是通用/常用的一个,其他项目/未来项目可以从当前项目开发过程中创建的框架中受益。
  3. 将大型项目分解为众所周知的模式以解决大问题。
  4. 即使是很小的项目,也要使用OOPS来养成使用它的习惯,并在出现1-3种类型的问题时做好准备

因此,您基本上是在说,无论您要解决的实际任务是什么,都应始终使用OOP?
JacquesB '16

不:),那里有许多程序脚本,有些脚本比其他脚本更好地解决了一个特殊问题。OOPS绝不是所有人的最佳解决方案,但是OOPS却很受欢迎。在OOPS中建立良好的类和结构需要花费时间和实践,因此,如果您想有效地使用OOPS,最好从较小的项目开始。一旦掌握了它,它完全取决于您。我将OOPS概念视为主要用于构建框架的工具。
拉胡尔·梅农
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.