这些编程范例之间有什么区别,它们是否更适合于特定问题,或者任何用例都优先于其他问题?
架构示例赞赏!
答案 0 :(得分:118)
他们所有人都以自己的方式表现出色 - 他们只是解决同样问题的不同方法。
在纯粹的程序化风格中,数据往往与操作它的函数高度分离。
在面向对象的风格中,数据往往带有一系列功能。
在功能样式中,数据和函数倾向于彼此具有更多共同点(如在Lisp和Scheme中),同时在实际使用函数方面提供更多灵活性。算法也倾向于用递归和组合来定义,而不是循环和迭代。
当然,语言本身只会影响首选的风格。即使在像Haskell这样的纯函数式语言中,你也可以用程序风格编写(虽然这是非常气馁的),甚至在像C这样的过程语言中,你也可以用面向对象的方式编程(比如在GTK +和EFL API)。
需要明确的是,每种范例的“优势”仅仅是对算法和数据结构的建模。例如,如果您的算法涉及列表和树,则功能算法可能是最明智的。或者,例如,如果您的数据是高度结构化的,那么将其组合为对象可能更有意义,如果这是您的语言的本机范例 - 或者,它可以很容易地被编写为monad的功能抽象,是Haskell或ML等语言的原生范例。
您使用的选择只是对您的项目和您的语言支持的抽象更有意义的。
答案 1 :(得分:22)
我认为现有的图书馆,工具,示例和社区完全胜过范式。例如,ML(或其他)可能是最终的通用编程语言,但如果你无法获得任何好的库,那么你就会被搞砸。
例如,如果您正在制作视频游戏,那么C ++中有更多优秀的代码示例和SDK,因此您可能会更好。对于小型Web应用程序,有一些很棒的Python,PHP和Ruby框架可以让您快速启动并运行。由于编译时检查以及企业库和平台,Java是大型项目的绝佳选择。
以前的情况是,不同语言的标准库非常小并且很容易复制 - C,C ++,汇编程序,ML,LISP等。随附基础知识,但是当它涉及到时,它往往会被淘汰标准化网络通信,加密,图形,数据文件格式(包括XML),甚至基本的数据结构,如平衡树和哈希表都被排除在外!
Python,PHP,Ruby和Java等现代语言现在提供了更加体面的标准库,并且可以轻松使用许多优秀的第三方库,这在很大程度上要归功于它们采用命名空间来防止库与库发生冲突彼此和垃圾收集,以标准化库的内存管理方案。
答案 2 :(得分:20)
这些范例不必相互排斥。如果你看一下python,它支持函数和类,但同时,一切都是一个对象,包括函数。您可以在一段代码中混合和匹配功能/ oop /程序样式。
我的意思是,在函数式语言中(至少在Haskell中,我学过的唯一一个)没有语句!函数只允许在其中有一个表达式!!但是,功能是一等公民,你可以传递它们作为参数,以及一堆其他的能力。他们可以用很少的代码来做强大的事情。
虽然在像C这样的过程语言中,你可以传递函数的唯一方法是使用函数指针,而这一点并不能启用许多强大的任务。
在python中,函数是一等公民,但它可以包含任意数量的语句。所以你可以拥有一个包含过程代码的函数,但你可以像函数式语言一样传递它。
OOP也是如此。像Java这样的语言不允许您在类之外编写过程/函数。传递函数的唯一方法是将它包装在实现该函数的对象中,然后传递该对象。
在Python中,您没有此限制。
答案 3 :(得分:13)
对于GUI,我会说面向对象的范例非常适合。 Window是一个Object,Textboxes是Objects,而Okay-Button也是一个。另一方面,字符串处理之类的东西可以用更少的开销完成,因此使用简单的程序范例更简单。
我认为这也不是语言问题。您可以使用几乎任何流行的语言编写功能,程序或面向对象,尽管在某些语言中可能需要额外的努力。
答案 4 :(得分:6)
为了回答你的问题,我们需要两个要素:
Wikipeida上的software architecture article上显示了软件架构样式/模式列表。你可以在网上轻松研究它们。
简而言之,Procedural适用于遵循程序的模型,OOP适用于设计,而Functional适用于高级编程。
我认为你应该尝试阅读每个范例的历史,看看为什么人们创造它并且你可以轻松地理解它们。
在理解了它们之后,您可以将架构样式/模式的项目链接到编程范例。
答案 5 :(得分:2)
我认为他们通常不是“对抗”,但你可以将它们结合起来。我也认为,你提到的词语常常只是流行语。实际上很少有人知道“面向对象”意味着什么,即使他们是最虔诚的传播者。
答案 6 :(得分:1)
我的一位朋友正在使用NVIDIA CUDA编写图形应用。应用程序非常适合OOP范例,问题可以整齐地分解为模块。但是,要使用CUDA,您需要使用不支持inheritance的C.因此,你需要聪明。
a)你设计了一个聪明的系统,它将在一定程度上模拟继承。它可以做到!
i)你可以使用hook system,它要求父P的每个子C对函数F都有一定的覆盖。你可以让孩子注册他们的覆盖,这些覆盖将在需要时被存储和调用。 / p>
ii)您可以使用struct memory alignment功能将孩子投射到父母身上。
这可能很整洁,但要想出面向未来的可靠解决方案并不容易。您将花费大量时间设计系统,并且无法保证您不会在项目中途遇到问题。实施multiple inheritance甚至更难,即使不是几乎不可能。
b)您可以使用一致的命名策略并使用divide and conquer方法来创建程序。它不会有任何继承,但因为你的功能很小,易于理解并且格式一致,所以你不需要它。您需要编写的代码量会增加,很难保持专注并且不会屈服于简单的解决方案(黑客)。然而,这种忍者编码方式是C编码方式。在低级别自由和编写好的代码之间保持平衡。实现这一目标的好方法是使用函数式语言编写原型。例如,Haskell非常适合原型算法。
我倾向于接近b。我使用方法a编写了一个可能的解决方案,我会说实话,使用该代码感觉非常不自然。