据我了解,OOP 是大型项目最常用的范例。我还知道大系统的一些较小的子集使用其他范例(例如SQL,它是声明性的),而且我还意识到,在较低级别的计算中,OOP 并不真正可行。但在我看来,通常高层解决方案的各个部分几乎总是以 OOP 方式组合在一起。

是否有任何场景,真正的非 OOP 范式实际上是 更好的 选择大规模解决方案?或者说这在当今是闻所未闻的?

自从我开始学习CS以来我就一直想知道这个问题;人们很容易感觉到 OOP 是一种永远无法被超越的编程必杀技。

有帮助吗?

解决方案

在我看来,OOP的原因是使用如此广泛是没有这么多,它是工作的工具。我认为它更是一个可以解决的方式,他们理解来描述客户。

一个CAR是具有发动机的车辆。这是编程和现实世界都在一个!

这是很难理解任何可以这么优雅适合编程和真实的世界。

其他提示

Linux是一个大型项目这是非常不OOP。而且它不会有很多从它要么获得。

我认为OOP具有良好的环到它,因为它已与像封装,数据隐藏,代码复用,模块化et.c.良好的编程相关联的做法本身但是,这些优点是决不是唯一的,以OOP。

您可以看看二郎,由乔·阿姆斯特朗撰写。

百科:

  

“Erlang是通用   并行编程语言和   运行系统。顺序子集   的Erlang是一个功能性的语言,   严格的评估,单   分配和动态类型。“

乔阿姆斯特朗:

  

“由于问题   面向对象的语言是他们已经   把所有这种隐含的环境,   他们随身携带他们。您   想要一个香蕉,但你得到的是一个   大猩猩拿着香蕉和   整个丛林“。

OOP的承诺是代码重用和更简单的维护。我不知道它传递。我看到的东西,如点网为大致相同,我们用来获取各种来回厂商的C库。如果你愿意,你可以调用代码重用。至于保养不好的代码是错误代码。 OOP没有帮助。

我是OOP的忠实粉丝,我每天练习OOP。 这是写代码的最自然的方式,因为它与真实的生活。

不过,我认识到面向对象的虚拟化可能会导致性能问题。 当然,这取决于你的设计语言和您选择的平台(写在基于垃圾收集语言如Java或C#可能执行比写在C ++例如系统更糟系统)。

我想在实时系统中,过程编程可能更合适。

请注意,并非所有声称是OOP的所有项目实际上OOP。有时,大多数代码是程序性的,或数据模型是贫血时,等等。 ..

ZYX,你写道:“大多数系统使用关系数据库......”

恐怕没有这样的事情。关系模型将是40岁的明年仍然从未实施。我想你的意思是,“SQL数据库”。你应该通过法比安·帕斯卡尔读什么要了解一个关系数据库管理系统和SQL数据库管理系统之间的区别。

“...关系模型通常选择由于它的普及,”

真,这是受欢迎的。

“...的工具的可用性,”

唉没有必要的主要工具:关系模型的实现

“载体”

是啊,关系模型精细的支持,我敢肯定,但它是由数据库管理系统实现完全不支持。

“和事实,即关系模型实际上是一个数学概念,”

是的,这是一个数学概念,但是,没有得到执行,它在很大程度上局限于象牙塔。弦理论也是一个数学概念,但我不会实现与它的系统。

在事实上,尽管它是一个methematical的概念,它肯定不是一门科学(如计算机科学),因为它没有任何科学的第一个要求:这是证伪:有没有一个关系数据库管理系统的实施对我们可以检查它的权利要求中。

这是纯蛇油。

“......违背OOP。”

和违背OOP,关系模型从未实现。

购买一本关于SQL并获得成效。

保留关系模型非生产性理论家。

. 。显然,您可以将 C# 与五种不同的编程范例一起使用,将 C++ 与三种不同的编程范例一起使用,等等。

软件构建与基础物理学不同。物理学致力于使用可能受到新实验数据和/或理论挑战的范式来描述现实。物理学是一门寻找“真理”的科学,而软件构造则不然。

软件建设是一个 商业. 。你需要成为 富有成效的, , IE。实现一些有人愿意花钱的目标。使用范式是因为它们对于 有效地生产软件. 。你不需要每个人都同意。如果我做 OOP 并且它对我来说效果很好,我不在乎“新”范式是否可能对我有用 20%,如果我有时间和金钱来学习它,然后重新思考整个软件结构我'我正在从头开始工作并重新设计它。

另外,你可能使用另一种范式,我仍然会很高兴,就像我可以经营一家日本餐馆赚钱,你可以通过隔壁的墨西哥餐馆赚钱一样。我不需要和你讨论日本菜是否比墨西哥菜更好。

我怀疑 OOP 会很快消失,它太适合我们的问题和思维模式了。

我们开始看到的是多范式方法,声明性和功能性的想法被纳入面向对象的设计中。大多数较新的 JVM 语言(JavaFX、Scala、Clojure 等)以及 .net 平台上的 LINQ 和 F# 都是一个很好的例子。

需要注意的是,我在这里并不是在谈论取代 OO,而是在谈论对其的补充。

  • JavaFX 已经表明,声明式 解决方案超越了 SQL 和 XSLT, 也可用于装订 视觉对象之间的属性和事件 GUI 中的组件

  • 具有容错性和高 并发系统,功能正常 编程是一个 非常 良好的拟合性, 正如爱立信所证明的那样 AXD301(使用 Erlang 编程)

所以...随着并发性变得越来越重要并且 FP 变得越来越流行,我想不支持这种范式的语言将会受到影响。这包括许多当前流行的语言,例如 C++、Java 和 Ruby,不过 JavaScript 应该可以很好地应对。

使用OOP使代码更易于管理(如在修改/更新/添加新的功能)和理解。这是更大的项目尤其如此。因为模块/对象封装该数据的数据和操作更容易理解的功能性和大画面。

OOP的好处是,它是更易于讨论(与其他开发者/管理/顾客)一个LogManager的或的OrderManager,其中的每一个包括特定功能,则描述“的一组中的文件转储数据的方法”和'是守的订单细节轨道的方法。

所以我想OOP是特别大的项目有用的,但总有一些新的概念转向了所以要在未来寻找新的东西,评估和保持什么是有用的。

人们喜欢把各种东西的“对象”,并把它们归类,所以毫无疑问,OOP是如此受欢迎。然而,有些情况下OOP还没有得到更大的普及一些区域。大多数系统使用关系数据库,而不是目标。即使第二的一些拥有一些显着的记录,这对于某些类型的任务更好,关系模型unsually选择,因为它的普及,工具,支持可用性和事实关系模型实际上是一个数学概念,相反, OOP。

其中I从未见过OOP另一个区域是软件构建过程。所有的配置,使脚本程序,部分原因是缺乏壳语言的OOP支持的,部分原因是因为OOP是这样的任务太复杂了。

我的观点略有争议,但我不认为 OOP(至少是现在广泛应用的一种)是 有助于制作我的特定领域中最大规模的软件(VFX,在场景组织和应用程序状态方面与游戏有些相似)。我发现它对于中小型规模非常有用。我在这里必须要小心一点,因为我过去邀请过一些小怪,但我应该限定这是我在特定类型领域的狭隘经验。

我经常发现的困难是,如果你有所有这些封装数据的小具体对象,那么它们现在都想互相交谈。它们之间的交互可能变得极其复杂,就像这样(除了在跨越数千个对象的真实应用程序中更加复杂之外):

enter image description here

这与其说是与耦合直接相关的依赖图,不如说是“交互图”。可能存在抽象来将这些具体对象彼此解耦。 Foo 可能不会说话 Bar 直接地。它可能会通过以下方式与之对话 IBar 或类似的东西。该图仍然会连接 FooBar 因为,尽管已解耦,但它们仍然可以互相交谈。

构成自己小生态系统的中小型对象之间的所有这些通信,如果应用于我的领域中大型代码库的整个规模,可能会变得极其难以维护。而且它变得非常难以维护,因为很难推理对象之间的所有这些交互会发生什么,比如副作用。

相反,我发现有用的是将整个代码库组织成完全独立的、访问中央“数据库”的庞大子系统。然后每个子系统输入和输出数据。其他一些子系统可能会访问相同的数据,但没有任何一个系统直接相互通信。

enter image description here

...或这个:

enter image description here

...每个单独的系统不再尝试封装状态。它并不试图成为自己的生态系统。相反,它在中央数据库中读取和写入数据。

当然在每个子系统的实现中,他们可能会使用一些对象来帮助实现它们。这就是我发现 OOP 在这些子系统的实现中非常有用的地方。但这些子系统中的每一个都构成了一个相对中小型的项目,不是太大,而正是在中小型项目中,我发现 OOP 非常有用。

最少知识的“流水线编程”

这使得每个子系统都可以只专注于做自己的事情,而几乎不知道外界正在发生什么。专注于物理的开发人员只需坐下来研究物理子系统,对软件的工作原理知之甚少,除了有一个中央数据库,他可以从中检索运动组件(仅数据)等内容,并通过将物理应用于该数据来转换它们。这使得他的工作变得非常简单,并且使得他可以用最少的关于其他事情如何运作的知识来完成他最擅长的事情。输入中心数据和输出中心数据:这就是每个子系统必须正确执行才能使其他所有功能正常工作的全部内容。这是我在我的领域中发现的最接近“装配线编程”的东西,每个开发人员都可以用最少的关于整个系统如何工作的知识来完成自己的事情。

由于每个子系统的关注范围较窄,测试仍然相当简单。我们不再通过依赖注入来模拟具体对象,而是生成与特定系统相关的最少量的数据,并测试特定系统是否为给定的输入提供正确的输出。由于需要测试的系统很少(只需几十个就可以组成一个复杂的软件),因此还大大减少了所需的测试数量。

打破封装

然后,系统变成一个相当扁平的管道,通过几乎不知道彼此存在的独立子系统来转换中央应用程序状态。有时可能会将一个中心事件推送到另一个系统处理的数据库,但另一个系统仍然不知道该事件来自哪里。我发现这是至少在我的领域解决复杂性的关键,并且它是通过实体组件系统有效实现的。

然而,它类似于更广泛的过程或函数式编程,以解耦所有这些子系统,并让它们在对外部世界了解最少的情况下工作,因为我们正在打破封装以实现这一目标并避免要求系统与每个子系统进行对话其他。当您放大时,您可能会发现您所共享的对象被用于实现这些子系统中的任何一个,但从最广泛的范围来看,这些系统类似于 OOP 以外的东西。

全球数据

我必须承认,一开始我对于将 ECS 应用到我的领域中的架构设计非常犹豫,因为首先,据我所知,流行的商业竞争对手(3DS Max、SoftImage 等)以前从未这样做过,其次,它看起来像是一大堆全球可访问的数据。

然而,我发现这并不是一个大问题。我们仍然可以非常有效地维护不变量,甚至可能比以前更好。原因在于 ECS 将所有内容组织成系统和组件的方式。您可以放心,音频系统不会尝试改变运动组件,例如,即使在最黑客的情况下也不会。即使团队协调不力,ECS 也不太可能降级为您无法再推断哪些系统访问哪个组件的情况,因为这在纸面上相当明显,并且实际上没有任何理由让某个系统访问不合适的组件。

相反,它常常消除了许多以前对数据完全开放的黑客事物的诱惑,因为在我们以前的代码库中,在松散的协调和关键时间下所做的许多黑客行为都是在匆忙尝试X射线抽象并试图访问物体生态系统的内部。由于人们匆忙地试图获取他们想要访问的数据并用他们想要访问的数据做事,抽象开始变得漏洞百出。他们基本上是在尝试只访问数据,这导致界面设计迅速退化。

由于系统的组织方式,仍然存在一些隐约类似于封装的东西,因为通常只有一个系统修改特定类型的组件(在某些特殊情况下有两个系统)。但他们不拥有该数据,也不提供检索该数据的功能。系统之间不相互通信。它们都通过中央 ECS 数据库进行操作(这是必须注入所有这些系统的唯一依赖项)。

灵活性和可扩展性

这在关于实体组件系统的外部资源中已经得到了广泛的讨论,但它们在适应全新的设计理念方面非常灵活 事后看来,即使是突破性的概念,比如对哺乳动物、昆虫和植物的生物的建议,它们在阳光下同时发芽。

原因之一是没有需要打破的中心抽象。如果您需要更多数据,或者只是创建一个将植物、哺乳动物和昆虫所需的组件串在一起的实体,则可以引入一些新组件。设计用于处理昆虫、哺乳动物和植物组件的系统然后会自动拾取它,除了添加一行代码以使用新的组件组合实例化实体之外,您可能会获得所需的行为,而无需进行任何更改。当您需要全新的功能时,您只需添加一个新系统或修改现有系统即可。

我在其他地方没有发现太多讨论的是,即使在没有我们未能预料到的突破性设计更改的情况下,这也能在多大程度上简化维护。即使忽略 ECS 的灵活性,当您的代码库达到一定规模时,它也确实可以简化事情。

将对象转化为数据

在之前的 OOP 密集型代码库中,我发现维护接近上面第一张图的代码库非常困难,所需的代码量呈爆炸式增长,因为类比 Car 在此图中:

enter image description here

...必须构建为实现多个接口的完全独立的子类型(类)。所以我们系统中的对象数量呈爆炸性增长:点光源与方向光的单独对象、鱼眼相机与其他相机的单独对象等。我们有数千个对象以无限的组合实现了几十个抽象接口。

当我将它与 ECS 进行比较时,只需要数百个,并且我们能够在使用一小部分代码之前做完全相同的事情,因为这转变了类比 Car 实体变成不再需要其类的东西。它变成了一个简单的组件数据集合,作为一个组件数据的通用实例 Entity 类型。

面向对象编程的替代方案

因此,在某些情况下,在设计的最广泛层面上过度应用 OOP 可能会开始真正降低可维护性。从最广泛的鸟瞰系统的角度来看,它可以帮助将其扁平化,而不是尝试将其建模得如此“深入”,即对象与对象之间的交互,无论多么抽象。

比较我过去和现在开发的两个系统,新的系统功能更多,但需要数十万的 LOC。前者需要超过 2000 万个 LOC。当然,这不是最公平的比较,因为前一个系统有巨大的遗产,但如果你从两个系统中提取一部分,它们在功能上相当相同,没有遗留的包袱(至少与我们可能得到的接近相同), ECS 只需要一小部分代码即可完成相同的操作,部分原因是它通过将系统中的类转换为原始数据(组件)的集合(实体),并由大型系统来处理它们,从而显着减少了系统中的类数量一船小/中型物体。

有没有一种真正的非 OOP 范式实际上是 大型解决方案的更好选择?或者这是闻所未闻的 日?

这绝非闻所未闻。例如,我上面描述的系统广泛用于游戏中。这在我的领域中相当罕见(我的领域中的大多数架构都是类似 COM 的纯接口,这就是我过去研究过的架构类型),但我发现凝视游戏玩家在做什么时设计一个架构会带来很大的不同,因为它能够创造出在不断发展的过程中仍然非常容易理解的东西。

也就是说,有些人认为 ECS 本身就是一种面向对象编程。如果是这样,它就不像我们大多数人想象的那种 OOP,因为数据(组件和组成它们的实体)和功能(系统)是分离的。它需要放弃广泛系统级别的封装,这通常被认为是 OOP 最基本的方面之一。

高级编码

但在我看来,通常是更高层次的解决方案 几乎总是以 OOP 方式放在一起。

如果您可以将一个应用程序与非常高级的代码拼凑在一起,那么就您的团队必须维护的代码而言,它的规模往往相当小或中等,并且可能可以使用 OOP 非常有效地组装。

在我的视觉特效领域,我们经常要做一些相对较低级别的事情,如光线追踪、图像处理、网格处理、流体动力学等,并且不能只是将第三方产品拼凑在一起,因为我们实际上是在竞争更多的是我们在底层可以做的事情(用户对尖端的、有竞争力的生产渲染改进比更好的 GUI 更感兴趣)。因此,可能有很多很多代码,从非常低级的位和字节重组到脚本编写者通过嵌入式脚本语言编写的非常高级的代码。

通讯网络

但是,任何类型的应用程序(高级或低级或组合)都会有一个足够大的规模,它围绕着一个非常复杂的中央应用程序状态,我发现尝试封装所有内容不再有用。成物体。这样做往往会增加复杂性,并且由于事物之间发生的交互量成倍增加而难以推理正在发生的事情。如果没有足够大的规模的断点,我们停止将每个事物建模为必须相互交谈的封装生态系统,那么推理数千个生态系统相互交谈就不再那么容易了。即使每个单独都很简单,但将所有内容作为一个整体考虑时可能会开始超出我们的头脑,并且如果您尝试仅围绕 OOP 原则来设计整个大型系统。它可以帮助至少在某些领域打破某种规模的封装。

到那时,让物理系统封装自己的数据就不一定那么有用了(否则很多东西可能想要与它交谈并检索该数据以及使用适当的输入数据对其进行初始化),这就是我发现通过 ECS 的这种替代方案非常有用,因为它将类比物理系统和所有此类大型系统转变为“中央数据库转换器”或“输出新内容的中央数据库读取器”,现在它们可以相互忽略。然后,每个系统开始更像是扁平管道中的进程,而不是形成非常复杂的通信图中的节点的对象。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top