您认为面向对象的编程是解决复杂性的解决方案吗?为什么?这个话题可能有些争议,但我打算知道这里的专家的答案!

有帮助吗?

解决方案

没有解决复杂性的方法。

在“神话人月”中,弗雷德·布鲁克斯(Fred Brooks)讨论了编程意外复杂性和基本复杂性之间的差异。意外复杂性是由我们的工具和方法引起的,例如必须用语言编写和测试其他代码,因为我们无法直接表达我们的想法以及类似的内容。新方法和技术可以降低意外复杂性。我可以比二十五年前更快,更好地编写程序,因为我有更好的语言和工具。

基本的复杂性来自以下事实:我们尝试使用编程的工作本质上是复杂的,并且存在不可还原的复杂性。在这种情况下,“必不可少的”是指“与事物的本质有关”而不是“非常必要的”。

因此,他声称不会有银弹,写作软件将继续很困难。

我强烈建议您阅读他的书:具体来说,我推荐“银周年版”,并提供另一篇“无银弹”的文章。在此,他回顾了提出的复杂性解决方案,并考虑了它们的影响。 (他发现最有效的是收缩包装软件 - 曾经写一些复杂的东西,并出售数千或数百万的副本。)

现在,以对象为导向的编程在正确完成时可以通过创建抽象和隐藏复杂性来帮助您。类的对象具有一定的定义行为,我们可以从中推荐这种行为,而不必关心实施的复杂性。正确编写的课程彼此之间的耦合较低,如果您可以摆脱它,则分裂和互动是应对复杂性的绝佳方法。它们也具有很高的凝聚力,因为它们是一组彼此非常紧密相关的功能和数据。

其他提示

我希望您很快会得到一些更好的答案,但这是一个简单的答案:

OOP通过以更接近我们建模世界上所有其他所有内容的方式来建模软件来帮助*对*进行复杂性。通常,图像与墙体对象相互作用的球对象要比想象一系列的例程和数据结构来执行相同的事情要容易得多,因为它更接近我们与现实世界的交互方式。

*因为没有什么可以“解决”复杂性

我认为当前对OOP的主流定义不是管理复杂性的好解决方案。

如果您回到它的根源,我相信艾伦·凯(Alan Kay)受到“ LISP”的影响很大。

由于LISP并未被主流采用所破坏,因此它可能设法保留了其核心价值。因此,我认为看LISP如何解决这个复杂性问题可能会给我们一些见识,我们可以将其用作判断在处理复杂性方面有多么有用的基础。

如果您查看“ 3A讲座:亨德森·埃舍尔的示例”的结尾。 SICP, ,Hal Abelson建议不是通过将任务分解为较小的子任务而是通过创建抽象层来管理复杂性。在最高级别,您就较低的抽象级别的解决方案来表达对复杂问题的解决方案。

我认为OOP最初是为了创建这些抽象层的机制。

不幸的是,如今,OOP(AB)用于编写意大利面条代码/结构。

我将构成一个例子:FPS多玩家游戏。

在最高级别上,游戏可以通过一堆玩家在地图上跑来跑去,并使用武器互相射击。

在下一个较低层,我们必须谈论地图,武器和玩家。也许我们可以将它们作为在游戏世界中相互作用的物理对象谈论。

在下一个较低级别,我们可以讨论对象如何进行物理相互作用(运动,碰撞等)。

等等等等。

这意味着什么,(我是从SICP引用的。重新试图解决。因此,如果问题的描述发生了很小的变化,则可能只需要较小的解决方案。

因此,使用OOP的明智方法是在每个抽象的每个级别上创建抽象层,您可以使用从下面的级别使用“对象”来解决手头的问题。

这是我从演讲中引用的一点: http://www.youtube.com/watch?v=cytrfncmqhq

像往常一样,我不同意所有人。 OOP并没有为您提供管理复杂性的工具,而是创造了大量的复杂性,因为它是一种不足和数学上的虚假范式。它使程序员无休止地混淆了,尝试用无法用OOP建模的OOP建模事物。

在我看来,这里的开创性工作是迈耶面向对象的软件构建。它详细介绍了一组要求,包括我认为至关重要的一组:开放式原则。这说明必须开放延期,但同时封闭了供使用。

迈耶(Meyer)从埃菲尔(Eiffel)体现的这些要求中得出从这些要求中得出的方向。封装提供了封闭,继承开放性,所提到的“事物”是类。

我认为这项工作是很好的科学,因为迈耶显然是错误的,而且由于他的工作质量,可以将错误指向错误并解决问题,这是可能的。

错误是使类或类型的模块化单元。那是错误的,事实证明是错误的。甚至迈耶都认识到这个问题(称为协方差问题),OOP无法处理高于一个高于一个的Arity的关系(也就是说,OOP适用于属性,但在二进制关系上失败了)。在艾菲尔(Eiffel)中,这个问题导致类型系统中的一个不合适!

解决方案很清楚。模块化单位必须大于一种类型。它必须由几种类型组成,以及与它们相关的方法。

这种抽象模型得到了抽象的数学理论的支持,即类别理论:类型是类别的对象,方法(函数)是箭头,这不足为奇。

有了这个模型, 一些 一组功能已知。表示形式是对公众隐藏的,因此这是封装,但是我们使用模块而不是类。

标准元语言(SML)和OCAML直接基于此模型。 OCAML还具有类:OOP:这不是没有用的,因为OOP可以让您派遣属性(又称动态绑定)。但是,大多数现实世界中的问题都涉及关系,而OCAML中的类别并不多。

在C ++标准模板库中,几乎没有使用毫不奇怪的继承。

一个简单的事实是,OOP并不能为您提供正确的工具来处理复杂性,甚至没有为您提供处理真正简单问题的工具,而是误导了两代程序员。 OOP远非帮助,这是自C,Fortran和Cobol开始疲倦以来的最邪恶和坏事。

面向对象的编程的根源可以追溯到1960年代。随着硬件和软件变得越来越复杂,可管理性通常成为一个问题。研究人员研究了维持软件质量并开发面向对象的编程的方法,部分原因是通过强烈强调来解决常见问题 编程逻辑的离散,可重复使用的单元。

因此,面向对象的程序可以被视为相互作用对象的集合,而不是传统模型,在该模型中,程序被视为要执行的任务列表(子例程)。在OOP中,每个对象都能接收消息,处理数据并将消息发送到其他对象。每个对象都可以看作是具有独特角色或责任的独立“机器”。这些对象上的操作(或“方法”)是 与对象本身紧密相关。

http://en.wikipedia.org/wiki/object-oriented_programming

这种关注的分离以及对象取向的其他特征,例如多态性,继承,消息传递,解耦和封装,提供了一个合乎逻辑和概念的框架,可以通过这种框架以高效的方式管理大型程序的复杂性。

软件开发有许多复杂性。在编程级别,OOP试图通过使用对象和类对问题域进行建模来解决复杂性。著名的宗师说解决问题只是代表了问题,因此解决方案是表示本身。因此,通过使用类抽象,使用访问修饰符和方法封装,继承了用于指定关系和重复使用的继承,建立关系和类之间的关系的组成,多态性作为简化确定相似对象中不同行为的手段,可以管理复杂性。

还有其他方法可以管理软件复杂性,例如逻辑(Prolog)和功能(Haskell)编程。

在比编程高的水平上,我们需要设计模式和原理来指导OOP。因此,OOP正在以低(编码)水平管理复杂性,而这些方法(例如设计模式和原理)将解决方案的设计以较高(系统和应用程序)级别指导解决方案的设计,并使软件开发和处理复杂性更易于管理。

为了回答您的问题,是的,OOP只是解决许多其他解决方案中复杂性的方法。它是低水平的解决方案。我们需要设计模式和原理来指导OOP更高级别。

面向对象的编程 管理 必不可少的和可选的复杂性,但也不会减少。

我更喜欢Eric Steven Raymond提供的定义 UNIX编程的艺术, ,因为它在必要,可选和意外复杂性之间描述。http://www.faqs.org/docs/artu/ch13s01.html#id2964646

OOP对基本或可选的复杂性无能为力,它们是该计划要求的函数。它可能会影响意外复杂性,因为您有时可以用OOP创建更优雅的设计。但是,有时候,使用OOP时的设计更糟。

复杂的问题不能通过技术更简单,它们只能是 管理 通过技术。

OOP是一种技术,一种概念,也是解决问题的方法。

OOP为您提供了强制执行的工具 设计 这可以使管理复杂性更容易,但是您可以轻松地拥有不良设计,从而提高您的复杂性。换句话说,如果不正确使用,您的问题可能会产生技术引起的复杂性。

请记住,还有许多其他方面可以决定您的项目的成功程度(即项目管理风格,问题定义,变更管理等)。您使用的技术仅与它对您有所帮助 管理 问题。

到底, 面向对象的编程不能是 解决方案 复杂性;这只是管理它的工具。 (如果正确使用)

在许多情况下,对象取向(常规使用)是有用的工具,但它不足以解决复杂性。

特别是,它通常会增加很多“偶然的复杂性“示例是围绕实施继承的复杂性,需要提供大量“标准功能”作为等值()和哈希库德()等。简单并不容易"

大多数语言中的对象也倾向于封装很多 可变状态 - 在一个并发世界中,越来越开始看起来像是一个糟糕的设计决定。再次有趣 Rich Hickey的视频 查看对象身份和状态之间的区别,以及将两者混合在一起可能是错误的。

面向对象的编程是表示问题的一种方式,仅此而已。它本身并不比任何其他编程范式都不那么复杂。设计良好的OOP系统可以管理和降低复杂性,但是设计一个比必要的要复杂得多的系统也很容易。

正如C ++所说的那样,OOP给您足够的绳子可以悬挂自己。

我认为 是的, ,仅仅是因为它使您可以将复杂性切成隐藏细节的小型自我的“构建块”,然后使用它们来创建所需的功能,一步一步地逐层。

分裂和征服。

OOP是一种尝试解决方案。

管理复杂性的最佳方法是创建抽象。如果我可以将数据变成有用的集合,并具有可识别的功能,这些功能可以在这些集合上运行,那么我可以开始将这些集合视为离散的“事物”。这是课程和方法的基础。在这方面,设计正确的OOP可以帮助管理复杂性。

一路上的某个地方,有人决定我们可以使用OOP来帮助解决代码恢复问题。我的意思是,为什么要重新发明轮子?如果其他人为解决这个问题做了很多工作,请利用他们所做的工作,请添加您的特定项目所需的调整和瞧!您创建了一个功能强大,复杂的应用程序,您的工作相对较少。 OO程序员可以是非常有生产力的程序员。

最终的结果是,现代的OO程序员最终成为“巫师的学徒”,在那里他们将一堆大而笨拙的库与几行“胶”绑在一起,并得到一些有效的东西。 sorta。有点。大多数时候。与该库一起使用此库有潜在的副作用吗?也许。但是,谁有时间真正挖掘这些库中包含的代码?特别是当图书馆不断发展时。结果是我们最终得到了肿的应用程序,在该应用程序中,程序员需要该库中的少数类和方法,但是该应用程序必须承担他们不需要的所有其他内容的重量。

最终结果是您最终的复杂性比您需要的要复杂得多。

要处理要分离功能的复杂性的另一种机制。您希望所有数据访问功能在一个地方。您希望在一个地方所有用户界面功能。您希望所有控制器都在一个地方。因此,您创建了管理功能不同部分的不同类。到目前为止,一切都很好。这在一定程度上缩放了;熟练数据访问的开发人员可以编写这些类,您的用户界面人员可以编写用户界面类,等等。一切都很好。

直到您必须维护其他人写的东西。

是的,很高兴知道所有数据访问功能都位于此处。但是什么叫他们?

该方法在该类上调用该方法。但是,当我查看类定义时,该名称没有任何方法。哦,这是从继承链中的其他一两层继承的。等一下;该类实现了接口?该接口有多少个不同的类?而且,我们正在使用一些复杂的运行时系统(我正在看着您,春季)来在运行时“连接”课程吗?在哪里可以使用实现该接口的任何类?

您最终得到了许多精确的东西的小型离散方法。但是这个人在另一堂课中称之为一个。在另一个班级中称之为一个。在另一个类中称之为一个。在另外一堂课中称之为一个。返回特定类型的结果。您必须在其上调用一种做某件事的方法。返回另一种类型的结果。等等。

有一个术语:意大利面条代码。

您最终只需要一个非常复杂的系统才能撰写代码。因此,视觉工作室,Eclipse和Netbeans等视野。所有这些都有很大的学习曲线。确实,其中许多人能够封装/汇总由不同组开发的多个工具,每个工具都有自己的学习曲线。

这是管理复杂性吗?

调试代码是编写它的两倍。祝您好运,调试其中一些东西。特别是如果使用多个库,则使用某种依赖性注入系统在运行时“连接”。

总而言之:OOP提供了看起来像是有前途的工具来帮助管理复杂性。现实情况是生成的代码往往会肿,因为您不能仅从所有这些链接的库中提取所需的作品),并且您需要复杂的工具来浏览代码。它很快成为一场维护噩梦。

恕我直言,这是净损失;它增加了比消除的复杂性更复杂。如果没有它,它确实使您可以做极其困难的事情,甚至可能是不可能的。但是,任何大型项目都会迅速演变成无与伦比的混乱。

如果您已经知道它是如何工作的,并且您可以记住这一点,那么您可能有机会维护它。

请记住要应用Eagleson的定律:您自己的任何代码(您六个月都没有看过)也可能由其他人撰写。

在某种程度上...

为什么?因为它促进了非常合乎逻辑的模块化。至少与程序编程相比,它太诱人了,只写了大量的意大利面条代码。

面向对象的编程似乎有助于我们处理复杂性的原因是因为它迫使我们以特定的方式编写代码,而不是多种方式。面向任务的编程更加直观,这就是为什么编程开始的原因。对象取向需要培训和实践来有效理解和使用,但是通过将编程限制为一定路径,它允许受过培训的人有效地维护所编写的代码。

它不比任何其他方法更合乎逻辑或现实世界,而是一种通过类似镜头来解决问题的方式。许多技术专业都使用非直觉刚性方法的范式来处理其任务的复杂性。

处理复杂性的第三种方法将是功能编程,并且将来可能还会有其他新方法。

我认为这更多的是可维护性的解决方案,因为作为程序员,您应该在拥有数据的地方放置方法,从而创建应用程序的对象模型。

是的,这也是通过为您以自然方式“看到”代码的模型来解决复杂性的方法,作为具有属性和可能动作的对象

许可以下: CC-BY-SA归因
scroll top