OOP的意义是什么?


126

据我所知,尽管在OOP教育,语言和工具上花费了数百万或数十亿美元,但OOP并没有提高开发人员的生产力或软件可靠性,也没有降低开发成本。很少有人严格地使用OOP(很少有人坚持或理解LSP等原则);人们对问题域进行建模的方法似乎几乎没有统一性或一致性。通常,该类仅用于其语法糖。它将记录类型的函数放入自己的小命名空间中。

我已经为各种应用程序编写了大量代码。尽管在某些情况下,真正的可替代子类型在应用程序中发挥了重要作用,但这些情况非常例外。通常,尽管提供了大量的口头禅来谈论“重用”,但现实是,除非一段代码能够完全按照您的意愿进行,否则几乎没有成本效益的“重用”。设计类以正确的方式进行扩展非常困难,因此扩展的成本通常很高,以至于“重用”根本就不值得。

在许多方面,这并不令我感到惊讶。现实世界不是“ OO”,OO中隐含的想法(我们可以用某种分类法对事物建模)在我看来从根本上来说是有缺陷的(我可以坐在桌子,树桩,汽车引擎盖上) ,某人的膝盖-但其中之一不是-椅子)。即使我们转向更抽象的领域,OO建模也常常是困难,违反直觉的,并最终无益(考虑圆形/椭圆形或正方形/矩形的经典示例)。

那我在这里想念什么?OOP的价值在哪里?为什么所有的时间和金钱都无法使软件变得更好?


11
您的类比对于您预期的“用例”而言太抽象了;桌子,树桩,引擎盖,某人的腿是分子,原子,质子,中子,电子的组成部分,形成了足够大的表面积,可以让您的臀部靠重力抵挡。
icelava

38
不管启动同一线程多少次,它总是会引起很多兴趣(尽管事实是这里通常不允许重复)。当然,选择的答案始终是与问询者的最初观点一致的答案。
TM。

4
OOP的问题在于无法将其放在上下文中。对于某些用途,而不是全部用途,它是极好的。这是一个很棒的工具。这是一个糟糕的福音。
Mike Dunlavey,

16
对不起,但是我无法撼动您从未使用任何一种语言进行编程的感觉。原因如下:OOP是所有现代环境(Java,.NET,Python,Ruby-仅举几例主流)中基本组件库的操作基础。所有这些基础库每天都会被重用,所以如果这不算数,我也不知道该怎么做。因此,请不要误解我的意思,但如果有事实的话,可以重复使用代码-这是一个非常普遍的事实!我不希望这听起来有任何冒犯-只是在这里提出一点。
Matthias Hryniszak,2009年

2
@George Jempty:在“微软如何失去API之战”(joelonsoftware.com/articles/APIWar.html)中的乔尔·斯波斯基(Joel Spolsky ),标题为“自动变速器赢得了胜利”。
GodsBoss

Answers:


24

没有经验证据表明面向对象是人们思考世界的更自然的方式。编程心理学领域的一些工作表明,OO在某种程度上并不比其他方法更合适。

面向对象的表示形式似乎并没有普遍使用或使用较少。

仅采用面向对象的方法并要求开发人员使用这种方法是不够的,因为这可能会对开发人员的生产率以及所开发系统的质量产生负面影响。

摘自2000年10月ACM通讯部的“关于OO表示的可用性”。文章主要将OO与面向过程的方法进行了比较。关于使用面向对象方法“思考”的人们的工作方式有很多研究(Int。J. Human-Computer Studies 2001年,第54期,或Human-Computer Interaction 1995,第10卷以面向对象研究为主题),从我的阅读中,没有什么可以表明OO方法的某种自然性,使其比传统的程序方法更适合。


18
它工作正常。它无法做的是迫使不良编码者编写好的代码。出于这个原因,它会定期出现色相和哭泣。
混乱

6
@melaos:摘要在中间。OOP是工具包中的一种工具,不是唯一的工具,并且不能替代培训,经验和判断。
Mike Dunlavey,

44
当有人发布“问题”以争辩一个观点然后接受支持他的观点的第一个答案时,我觉得这很有趣,即使存在更高的评价相反的问题。人性很酷。
Bill K

3
@melaos,(至少那些文章的摘要)没有什么表明OO是人们自然的思维方式,因此,它并不比任何其他人可能会构造程序的方式固有地优越。
斯文德(Svend)

6
@Bill K:这是少数被引用的答案之一,而不是挥舞和仅仅坚持OO“必须”更好。如果参考文献支持OO并没有任何特别的改进或好处,因此支持我的原始立场,那么我不确定为什么我应该忽略它。您可以提供与我的OP相符的类似参考吗?
DrPizza

119

现实世界不是“ OO”,而OO中隐含的想法(即我们可以使用某些类分类法对事物进行建模)在我看来非常有缺陷

尽管这是事实,并且已经被其他人观察到(例如STL的发明者Stepanov),但其余的都是胡说八道。OOP可能有缺陷,它当然不是灵丹妙药,但由于它是减少依赖关系的好方法,因此它使大规模应用程序变得简单得多。当然,这仅适用于“好的” OOP设计。马虎的设计不会带来任何优势。但是,好的分离设计可以使用OOP很好地建模,而不能使用其他技术很好地建模。

有更好,更通用的模型(可以想到Haskell的类型模型),但它们通常也更复杂和/或难以有效实施。OOP是极端情况之间的良好折衷。


10
我感到有趣的是,这比问题和批准的答案加起来所获得的赞成票还要多。
布拉德·吉尔伯特

15
我发现Haskell的类型系统比OO更直观。
axblount

4
@Konrad:“但是它使大规模应用程序变得简单得多”-嗯,我不确定那是真的。从某种意义上讲,选择一件事不应该破坏另一件事,而是更简单,从某种意义上讲,它使它们更易于维护。那真是令人难以忍受……
米奇·

2
@BradGilbert:当然,提问者选择的答案与他最初提出的问题完全一致。这就提出了一个问题,如果您已经决定答案,为什么还要问这个问题呢?
TM。

2
@Mitch:我什至宣称您(到目前为止)不能在没有某种面向对象的情况下编写大型应用程序。此处的规模大于1M LOC。
康拉德·鲁道夫

45

OOP与创建可重用类无关,而与创建可用类有关。


7
好一个!如此真实。
Toon Krijthe

1
很公平。但是这样就不能解决“重新发明轮子”的问题,这在软件开发中确实是一个严重的问题-而不是拥有一个拥有N对眼睛寻找缺陷的库,而让我们拥有N对眼睛来解决问题的库所以。在需要重新使用它们之前,您可以构建许多可用的类。从我的见识来看,OOP从根本上在该领域存在缺陷-代码重用。它隐藏数据并将其“嫁接到”方法中,从而有效地使这些数据不可访问或难以互操作。
2013年

42

通常,该类仅用于其语法糖。它将记录类型的函数放入自己的小命名空间中。

是的,我也觉得这太普遍了。这不是面向对象的编程。它是基于对象的编程和以数据为中心的编程。在使用面向对象语言的10年中,我看到人们主要在进行基于对象的编程。OBP很快就会崩溃,恕我直言,因为您本质上是两个词中最糟的:1)过程编程而不遵循成熟的结构化编程方法; 2)OOP没有遵循成熟的OOP方法。

正确的OOP是一件美丽的事情。它使非常困难的问题易于解决,并且对于那些刚起步的人(不要试图在那里吹牛),它几乎看起来像是魔术。也就是说,OOP只是编程方法论工具箱中的一种工具。它不是全部结束的方法。它恰好非常适合大型企业应用程序。

大多数使用OOP语言工作的开发人员都在利用在日常使用的框架和类型中正确完成的OOP示例,但他们并不了解。这里有一些非常简单的示例:ADO.NET,Hibernate / NHibernate,日志记录框架,各种语言集合类型,ASP.NET堆栈,JSP堆栈等...这些都是在其代码库中严重依赖OOP的东西。


32

重用不应该是OOP的目标-也不是其他任何形式。

重用是良好设计和适当抽象水平的副作用。代码通过做一些有用的事情来实现重用,但是这样做并不能使它变得不灵活。代码是否为OO无关紧要-我们重用了有效的方法,而不是琐碎的事。那是实用主义。

OO作为通过继承重用的新方法的思想从根本上是有缺陷的。如您所见,LSP违例比比皆是。取而代之的是,将OO正确地视为一种管理问题域复杂性的方法。目标是随着时间的推移系统的可维护性。实现此目的的主要工具是将公共接口与私有实现分离。这使我们拥有由编译器强制执行的诸如“仅应使用...修改此规则”之类的规则,而不是代码检查。

我相信您会同意使用此工具,使我们能够创建和维护非常复杂的系统。这样做有很多价值,在其他范式中不容易做到。


3
关于重用和面向对象是单独的关注点,这是正确的。
丹·罗森斯塔克

28

在宗教方面,我要说的是,您对现代OOP的状态描绘得过于残酷。我会说它实际上降低了成本,制作大型软件项目管理,等等。这并不意味着它已经解决了软件混乱的根本问题,也并不意味着普通的开发人员是OOP专家。但是,将功能模块化为对象组件确实减少了世界范围内的意大利面条代码。

我可以想到数十个库,这些库可以很好地重用,并且节省了无法计算的时间和金钱。

但就OOP浪费时间而言,我要说的是,由于缺乏程序员培训,再加上学习特定于语言的OOP映射的陡峭学习曲线,情况更加复杂。有些人“获得” OOP,而其他人则永远不会。


2
我只是给了你一个投票,使你的得分超过2000分-希望它能坚持下去。:P
Jason Bunting

5
很少看到OOP被有效地教授。
乔恩·W

当被问到是否合理时,您的答案听起来很像敏捷/敏捷培训者给出的答案:“如果做得对,这将非常有用;如果失败,那么您就必须做错了。” 容易抛出诸如“可重用”和“可维护”之类的单词,但是要量化实际代码中的这些品质既不容易,也没有一个食谱可以告诉您如何编写良好的OOP(尽管有成千上万的书试图这样做)。 。我们还养成了表面上忽略硬件的坏习惯,这导致在祭坛上避免避免过早优化的可怕性能。
汤姆(Tom)

21

我认为使用不透明的上下文对象(在Win32中为HANDLE,在C中为FILE * s,举两个著名的例子-地狱,HANDLE位于内核模式屏障的另一侧,但实际上并没有得到在过程代码中也发现了比封装更多的东西)。我正在努力查看这对OOP有何特殊之处。

HANDLEs(和WinAPI的其余部分) OOP!C不能很好地支持OOP,因此没有特殊的语法,但这并不意味着它不使用相同的概念。从任何意义上讲,WinAPI都是面向对象的框架。

瞧,这是涉及OOP或替代技术的每一次讨论的麻烦:没有人清楚定义,每个人都在谈论其他事情,因此无法达成共识。对我来说似乎是在浪费时间。


1
我正要发布类似的内容。
布拉德·吉尔伯特

我同意您可以使用不带特殊语法的OOP概念,但另一方面,我认为WinAPI并不是OOP概念的一个很好的例子。
Lena Schimmel

14

它是一种编程范例。旨在使我们这些凡人可以更轻松地将问题分解为更小巧,更可行的部分。

如果您不觉得它有用。.不要使用它,不要花钱训练并开心。

另一方面,我确实认为它很有用,所以我会:)


14

相对于直接过程编程,OOP的第一个基本原则是信息隐藏和封装的概念。这个想法导致了将接口与实现分开的的概念。这些都是非常重要的概念,是放置框架以其他方式(更好)思考程序设计的基础。您无法真正反对这些属性-没有权衡取舍,并且它始终是一种更干净的模块化方式。

OOP的其他方面(包括继承和多态性)也很重要,但是正如其他人所暗示的那样,这些方面经常被过度使用。即:有时人们使用继承和/或多态是因为他们可以,而不是因为他们应该拥有。它们是功能强大的概念并且非常有用,但是需要明智地使用它们,而不是OOP的自动取胜优势。

相对于重复使用。我同意重复使用已超出OOP的销售标准。这是定义良好的对象(通常是更多原始/通用类)的可能的副作用,并且是封装和信息隐藏概念的直接结果。重复使用可能更容易,因为定义良好的类的接口更简单,更易于记录。


1
对于软件开发人员而言,重用是一个难题,不是吗,无论他们使用哪种范式,无论是面向对象的还是功能的,还是其他什么?这与对软件不断变化的要求相冲突,问题似乎是使设计变得灵活的问题之一。
Geoglyph

“将接口与实现分开的类的概念” ---我认为接口是接口,而类是实现?也许我只是一个过于面向过程的思想家,但是我认为这是多态性,即使用中具有统一性的代码差异,这才是OOP的关键。我认为“一堆C函数”与“ java类”一样,将接口与实现分开。也许我都错了?
乔纳斯·科尔克(JonasKölker),2009年

2
@Jonas-对于您的“一堆C函数” ---我同意它们可以将接口与实现分开,到那时它开始是OOP。如果例如在继续定义的API运行在C结构,你已经基本上建立封装(尤其是如果API操作不透明的结构)...然后它确实是OOP在C
高大杰夫

12

OOP的问题在于它已被超卖。

正如艾伦·凯(Alan Kay)最初设想的那样,它是替代以往拥有原始数据和全全局例程的做法的绝佳选择。

然后,一些管理顾问类型将其锁定并作为软件的救世主出售,随后类似旅鼠,学术界和行业的暴跌。

现在,在其他好的想法(例如函数式编程)被卖空之后,它们就像翻滚一样翻滚。

那我会做些什么呢?很多,我为此写了一本书。(这是绝版的-我没有得到一分钱,但你仍然可以得到副本。)亚马逊

我有建设性的回答是,不要将编程视为现实世界中事物建模的一种方式,而是将其编码为需求的一种方式。

这是非常不同的,并且基于信息论(任何人都可以理解的水平)。它说,可以将编程视为定义语言的过程,而这样做的技巧对于良好的编程至关重要。

它提升了特定领域语言(DSL)的概念。它完全同意DRY(请勿重复)。它极大地支持了代码生成。与现代应用程序相比,它导致软件的数据结构大大减少。

它试图重新振兴前进的道路在于创造性,并且甚至应该接受公认的思想。


凉。由于这本书已经绝版,您不想提供PDF,是吗?亚马逊
缓慢地向

我怀疑在此过程的早期,一些优秀的编码人员对他们可以使用OOP进行了猛烈的抨击,有人听到了他们的声音,并认为这意味着每个人都可以并且也会这样做。
混乱

@Daniel:好建议。我将对此进行研究,看看是否可以将其附加到我的Blogspot。您会发现它有点过时,因为它是在94年,但是原理并没有改变。
Mike Dunlavey,2009年

1
@Mike Dunlavey亲爱的先生,我可以支持@yar的好奇心,想知道是否有机会(至少部分地)通过互联网阅读/获取您的书吗?似乎您提出/开发的有效软件[组件]规范/实施方式与我想学习或教导的[我最近认识到]的方式非常吻合(而不是很好地引入的“货运”方式(但痛苦的模棱两可的主流OO书)。在此先感谢[和俄罗斯的欢呼:)。
mlvljr 2010年

1
@mlvljr:好的。最快的方法可能只是扫描它并制成一个大pdf文件。我会在接下来的几天内解决问题。不要让我忘记[对莫斯科最近发生的事情表示诚挚的哀悼,并为马萨诸塞州潮湿的居民欢呼]。
Mike Dunlavey'4

11

句柄(以及WinAPI的其余部分)是OOP!

他们是吗?它们不是可继承的,它们当然不能被替代,它们缺少定义明确的类……我认为它们与“ OOP”还差得很远。

您是否曾经使用WinAPI创建过窗口?然后,您应该知道定义了一个类(RegisterClass),创建了它的实例(CreateWindow),调用了虚方法(WndProc)和基类方法(DefWindowProc)等等。WinAPI甚至采用SmallTalk OOP的命名法,将方法称为“消息”(“窗口消息”)。

句柄可能不是可继承的,但后来有了finalJava。他们不缺课,他们该课的占位符:这就是“句柄”一词的含义。查看像MFC或.NET WinForms这样的体系结构,很明显,除了语法之外,与WinAPI并没有什么不同。


WINAPI不是OOP。它仅显示了编写可扩展过程代码的方式。好的技术是好的,无论它们是否为OOP。我可以用C编写WINAPI程序,并在自己的代码中使用相同的技术,所以我猜C是OOP。
08年

3
可能不是Alan Kay想到的(用谷歌搜索!),但是仍然是OOP。
康拉德·鲁道夫

11

是的,OOP不能解决我们所有的问题,对此感到抱歉。但是,我们正在致力于解决所有这些问题的SOA。


4
没听到吗 SOA是过去。如今,云计算将成为我们的救星。
DrPizza

我真的很想知道您的答案是否具有讽刺意味。我喜欢讽刺,但是通常它会被投票否决,这让我感到奇怪...
Lena Schimmel

我认为这很具有讽刺意味,我不会予以否决。但是我也不会投票!:-)
Yarik

这个问题很夸张,所以这是一个有效的答案(也是最好的答案)。
杰夫·戴维斯

10

OOP非常适合对内部计算机结构进行编程,例如GUI“小部件”,例如SelectList和TextBox可以是Item的子类型,它具有诸如“ move”和“ resize”之类的通用方法。

问题是,我们90%的人都在业务领域中工作,我们在其中处理诸如发票,员工,工作,订单等业务概念。这些对象不太适合OOP,因为“对象”更模糊不清,可能会根据业务重组等情况进行更改。

最糟糕的情况是将OO狂热地应用于数据库,包括对SQL数据库的OO令人惊讶的OO增强-正确地忽略了OO,除非数据库新手认为它们必须是正确的处理方式,因为它们是新的。


没错,但是...也许,OOP可以简化应用程序中某些与业务无关的方面(例如UI实施),这正是开发人员(最终!)可以花更多时间从事业务的主要原因之一。相关方面?
2009年

10

根据我回顾过的代码和项目设计的经验,OOP的价值并未完全实现,因为许多开发人员尚未在他们脑海中正确地概念化面向对象的模型。因此,他们不使用OO设计进行编程,而是经常继续编写自顶向下的过程代码,从而使类相当平坦。设计。(如果您甚至可以首先将其称为“设计”)

观察到很少有同事知道什么是抽象类或接口,这真是令人恐惧,更不用说正确设计适合业务需求的继承层次结构了。

但是,当存在良好的OO设计时,仅是阅读代码并看到代码自然地融入到直观的组件/类中,这绝对是一件乐事。我一直认为系统体系结构和设计就像设计公司中各个部门和员工的工作一样,所有这些工作都可以在宏伟的事情中完成某些工作,并发挥推动组织/系统前进所需的协同作用。

当然,不幸的是,这种情况很少见。就像世界上设计精美的实体对象与设计糟糕的物理对象所占的比例一样,在软件工程和设计方面也可以说得差不多。拥有好的工具并不一定能带来好的做法和结果。


1
在阅读代码时,我从未达到程序上的纯粹喜悦阶段或OOP。:)
bruceatk

1
纯粹的喜悦,不,但是也许有些微笑?
丹·罗森斯塔克

9

也许引擎盖,膝上或一棵树不是椅子,但它们都是可坐的。


2
您从未没有接口的情况下就不必使用OO语言了吗?你真幸运
finnw

不,他们不是。它们不是为坐下而设计的,因此,我想以此类推,不应该编写它们来实现ISittable接口。它们来自第3方库,现在您正在编写一个包含包含坐席的域的项目,您将发现必须编写适配器对象以将它们包装起来使其成为ISittable。看到?不太像现实世界。
EricS 2014年

8

我认为那些现实世界的东西是对象

你做?

发票有什么方法?等一下。它无法付款,无法发送,无法与供应商实际交付的商品进行比较。它根本没有任何方法。它完全是惰性的,没有功能。它是一种记录类型(如果需要,可以是一个结构),而不是对象。

同样,您提到的其他内容。

仅仅因为某物是真实的,就不能使它成为OO这个词的对象。OO对象是状态和行为的特殊耦合,可以自行起作用。这在现实世界中并不丰富。


2
以任何机器,电子设备或生物为例,它们都是“状态与行为的耦合”。
TM。

1
我同意发票的Send()或Pay()之类的方法“不自然”。但是,例如,作为发票的派生但INHERENT属性的总额是多少?它不是OOP能够以一种非常“自然”的方式对完全惰性的现实实体进行建模的示例吗?本身并不是一个巨大的成就,但仍然...
Yarik

@Yarik:这些“惰性”实体导致了基于对象的设计。对我来说,唯一合适的面向对象是Simulation,在该对象中,对象“可以按照自己的意愿行动”,如答案所示。如果OO是完成某件事的唯一可行方法,那很好,但是否则我们不能坚持更简单,更喜欢解决问题的事情吗?

7

最近9年来,我一直在编写OO代码。除了使用消息传递之外,我很难想象其他方法。我看到的主要好处与CodingTheWheel所说的完全一致:模块化。OO自然地带我从具有清晰接口和明确职责(即,松散耦合,高度内聚的代码以及明确的关注点分离)的模块化组件构建应用程序。

我认为OO崩溃的地方是当人们创建深层嵌套的类继承关系时。这会导致复杂性。但是,将常见的功能性排除在基类之外,然后在其他子类中重用它是一件非常优雅的事情,恕我直言!


7

首先,观察结果有些草率。我没有关于软件生产率的任何数据,也没有充分的理由相信它没有增长。此外,由于有很多人滥用OO,即使OO是自花生酱以来最重要的事情,对OO的良好使用也不一定会提高生产率。毕竟,一个无能的脑外科医生可能比没有一个更糟糕,但是有能力的人可能是无价的。

就是说,OO是一种不同的安排方式,将过程代码附加到数据上而不是使过程代码对数据进行操作。就其本身而言,这至少应该是一个小小的胜利,因为在某些情况下,OO方法更为自然。毕竟,没有什么可以阻止任何人用C ++编写过程API,因此提供对象的选择反而使该语言更具通用性。

此外,OO有一些功能非常出色:它允许旧代码无需更改就可以自动调用新代码。如果我有程序管理的代码,并且添加了与以前的代码类似但又不同的新东西,则必须更改程序代码。在OO系统中,我继承了功能,更改了所需内容,由于多态性,新代码自动被使用。这增加了变化的局限性,这是一件好事。

缺点是好的OO不是免费的:需要时间和精力来正确学习它。由于这是一个主要的流行语,因此有很多人和产品都为做到这一点而做得不好。设计一个好的类接口要比一个好的过程API容易得多,并且存在各种容易犯的错误(例如深层的类层次结构)。

可以将其视为另一种工具,通常不一定更好。例如,除螺丝刀外还有锤子。也许我们最终会摆脱软件工程的实践,因为知道使用哪种扳手来敲入螺钉。


我最喜欢你的最后一段。
Mike Dunlavey,

6

@西恩

但是,将常见的功能性排除在基类之外,然后在其他子类中重用它是一件非常优雅的事情,恕我直言!

但是“程序性”开发人员已经这样做了数十年。语法和术语可能有所不同,但是效果是相同的。OOP不仅具有“在基类中重用通用功能”的功能,而且我什至可以说很难将其描述为OOP。从不同的代码位调用相同的函数是一种与子过程本身一样古老的技术。


6

@康拉德

OOP可能有缺陷,它当然不是灵丹妙药,但是它使大规模应用程序变得简单得多,因为它是减少依赖关系的好方法

那是教条。我没有看到什么使OOP在这方面比旧的过程编程好得多。每当我进行过程调用时,我都会使自己脱离实现的细节。


6

对我来说,OOP语法本身具有很多价值。与尝试使用一堆不同的flat(或“ floating”)函数来对相同数据执行相同操作相比,使用试图表示真实事物或数据结构的对象通常要有用得多。具有良好OOP的事物具有一定的自然“流动性”,这对于长期读取,写入和维护更加有意义。

发票实际上不是具有可以执行功能的“对象”并不一定要紧-对象实例可以存在只是为了对数据执行功能,而不必知道实际存在的数据类型。可以成功调用函数“ invoice.toJson()”,而无需知道“发票”是哪种数据-结果将是Json,无论它来自数据库,XML,CSV还是其他JSON对象。使用过程函数,您突然需要更多地了解您的数据,并最终获得诸如“ xmlToJson()”,“ csvToJson()”,“ dbToJson()”之类的函数。如果您更改了基础数据类型,将会非常头痛。

OOP的要点是通过将其抽象化来隐藏实际的实现。为了实现该目标,您必须创建一个公共接口。为了在创建该公共接口并使工作保持干燥的同时简化工作,您必须使用诸如抽象类,继承,多态和设计模式之类的概念。

所以对我来说,OOP的真正首要目标是使将来的代码维护和更改变得更容易。但是即使如此,如果正确地以程序代码无法做到的方式正确完成,它确实可以大大简化事情。它是否与“现实世界”不匹配无关紧要-使用代码进行编程始终不会与现实世界对象进行交互。OOP只是使我的工作更轻松,更快捷的工具-我会每天都去。


5

@CodingTheWheel

但就OOP浪费时间而言,我要说的是,由于缺乏程序员培训,再加上学习特定于语言的OOP映射的陡峭学习曲线,情况更加复杂。有些人“获得” OOP,而其他人则永远不会。

不过,我不知道这是否真的令人惊讶。我认为技术上合理的方法(LSP很明显)很难使用,但是如果我们不使用这种方法,无论如何它会使代码变得脆弱且不可扩展(因为我们无法再对此进行推理了)。而且我认为OOP导致我们产生的违反直觉的结果使得人们不去接受它就不足为奇了。

更重要的是,由于从根本上说软件对于普通人来说已经太难了,以至于无法可靠,准确地编写代码,我们是否真的应该赞颂一贯教学不佳且难以学习的技术?如果收益是显而易见的,那么尽管有困难,还是值得坚持不懈的,但是事实并非如此。


如今,“适当的培训”必须非常长,抽象且复杂。我知道:我教编程。几十年前,许多人可以学习进行某种编程。我认为这不再是事实。

5

@杰夫

相对于直接的过程编程,OOP的第一个基本原则是信息隐藏和封装的概念。这个想法导致了将接口与实现分开的类的概念。

哪个具有更隐藏的实现:C ++的iostream或C的FILE * s?

我认为使用不透明的上下文对象(在Win32中为HANDLE,在C中为FILE * s,举两个著名的例子-地狱,HANDLE位于内核模式屏障的另一侧,但实际上并没有得到在过程代码中也发现了比封装更多的东西)。我正在努力查看这对OOP有何特殊之处。

我想这可能就是我努力查看好处的部分原因:显然良好的部分并非特定于OOP,而特定于OOP的部分显然并不好!(这并不是说它们一定是不好的,而是我没有看到证据表明它们广泛适用并且始终如一)。


5

在我读过的唯一一个开发博客中,那个由Joel-On-Software-Found-of-SO所提供的东西,很久以前,我读到OO不会导致生产率提高。自动内存管理。凉。谁可以拒绝数据?

我仍然相信面向对象非面向对象的编程与具有内联编程的所有功能。

(而且我应该知道,就像我从GWBasic开始的那样。)当您重构代码以使用函数时,variable2654将成为variable3您所使用的方法。或者,更好的是,它有一个您可以理解的名称,并且该函数是否简短,它被称为value 足以完全理解。

当没有功能的代码变成带有方法的代码时,您将删除大量的代码。

当你重构代码是真正的面向对象,bcq,和Z成为thisthisthisthis。而且由于我不相信使用this关键字,因此您可以删除大量的代码。实际上,即使您使用也可以做到这一点this



我不认为OO是自然的隐喻。

我也不认为语言是自然的隐喻,也不认为Fowler的“气味”比说“这段代码的味道不好”更好。就是说,我认为面向对象不是关于自然的隐喻,而那些认为对象只是突然出现在您面前的人根本就没注意这一点。您定义了对象Universe,更好的对象Universe将导致代码更短,更易于理解,更好地工作,或者所有这些(以及我遗忘的某些标准)。我认为使用客户/域的自然对象作为编程对象的人会失去重新定义Universe的能力。

例如,当您使用航空公司预订系统时,所谓的预订可能根本不符合法律/商务预订。



一些基本概念是很酷的工具

我认为大多数人都夸大了“当您有锤子时,他们都是钉子”的事情。我认为硬币/镜子的另一面也是如此:当您拥有多态性/继承性之类的小工具时,您会发现适合手套/袜子/隐形眼镜的用途。OO的工具非常强大。我认为,单一继承是绝对不可让人迷失的必要,而我自己的多重继承软件则无法承受。



OOP的意义是什么?

我认为这是处理绝对大量代码库的好方法。我认为它可以让您组织和重新组织代码,并提供一种语言来执行此操作(除了您正在使用的编程语言之外),并以一种非常自然且易于理解的方式对代码进行模块化。

OOP注定会被大多数开发人员误解

这是因为这是一个像人生一样令人大开眼界的过程:您越来越从经验中了解OO,并开始避免某些模式,并在变得更聪明时采用其他模式。最好的例子之一是您停止对不控制的类使用继承,而改用Facade模式。



关于您的小文章/问题

我确实想提到你是对的。在很大程度上,可重用性是一个梦想。这是来自安德斯·赫伊尔斯贝格(Anders Hejilsberg)的引述,内容来自此处

如果您要求刚开始的程序员编写日历控件,他们经常会自言自语:“哦,我要编写世界上最好的日历控件!就日历类型而言,它将是多态的。它将具有显示器,以及那个,那个,另一个。他们需要在两个月内交付日历应用程序。他们将所有这些基础结构都放置在控件中,然后花了两天时间在其之上编写一个糟糕的日历应用程序。他们会认为:“在该应用程序的下一版本中,我将做更多的事情。”

一旦他们开始考虑如何实际实现抽象设计的所有其他具体化,那么事实证明他们的设计是完全错误的。现在他们把自己画在了一个角落,他们不得不把整个东西扔掉。我一遍又一遍地看到。我坚信简约。除非您实际上要解决一般问题,否则不要尝试建立解决特定问题的框架,因为您不知道该框架的外观。


4

您是否曾经使用WinAPI创建过窗口?

比我想念的要多得多。

然后,您应该知道定义了一个类(RegisterClass),创建了它的实例(CreateWindow),调用了虚方法(WndProc)和基类方法(DefWindowProc)等。WinAPI甚至采用SmallTalk OOP的命名法,将方法称为“消息”(“窗口消息”)。

然后,您还将知道它不会自行发送消息,这是一个很大的空白。它还具有糟糕的子类化。

句柄可能不是可继承的,但是Java中有final。他们不缺课,他们是该课的占位符:这就是“句柄”一词的含义。查看像MFC或.NET WinForms这样的体系结构,很明显,除了语法之外,与WinAPI并没有什么不同。

它们无论在接口还是实现上都是不可继承的,可替换性最低,并且与程序编码器自从永远以来所做的事情没有本质区别。

真的吗 OOP的最好方面只是...传统过程代码? 那很重要吗?


您必须记住Win32接口基本上是Win16的重新实现。它是二十多年前设计的。
布拉德·吉尔伯特

当我在大学学习编程时,大多使用C语言,但也使用其他一些语言,我们被教导了一些基本概念,并接触了一些平台,但据了解,提出设计,框架,最佳做法,等将取决于我们在工作场所。我们学习的是技术,而不是世界观。使用OO,您必须先学习宗教,然后才能做任何有用的事情,它完全决定了您如何看待解决方案。我认为那不是真的。

4

我完全同意InSciTek Jeff的回答,我将添加以下改进:

  • 信息隐藏和封装:对于任何可维护的代码而言至关重要。可以通过谨慎使用任何编程语言来完成,不需要OO功能,但是这样做会使您的代码有点像OO。
  • 继承:在一个重要的应用程序域中,所有那些OO 类型包含关系都非常适合:图形用户界面。如果您尝试在不提供OO语言支持的情况下构建GUI,则无论如何都将最终构建类似OO的功能,而在没有语言支持的情况下,这样做将更加困难且容易出错。例如Glade(最近)和X11 Xt(历史上)。

在没有意义的情况下使用OO功能(尤其是深度嵌套的抽象层次结构)毫无意义。但是对于某些应用程序领域,确实有一点。


是的,我认为您应该对对象使用OOP,对函数使用函数编程...
Svante

4

我相信OOP最有益的品质是数据隐藏/管理。但是,有很多例子误用了OOP,我认为这是造成混淆的地方。

仅仅因为您可以将某些东西变成对象并不意味着您应该这样做。但是,如果这样做会使您的代码更有条理/更易于阅读,那么您绝对应该这样做。

OOP非常有用的一个很好的实际例子是使用“产品”类和我在我们的网站上使用的对象。由于每个页面都是一个产品,并且每个产品都引用了其他产品,因此您所引用的数据可能会使您感到困惑。这个“ strURL”变量是指向当前页面,主页还是统计页面的链接吗?当然,您可以使各种不同的变量引用相同的信息,但是proCurrentPage-> strURL易于理解(对于开发人员而言)。

此外,将功能附加到这些页面上会更加简洁。我可以做proCurrentPage-> CleanCache(); 随后是proDisplayItem-> RenderPromo(); 如果我只是调用这些函数并假设当前数据可用,谁会知道会发生哪种情况。另外,如果必须将正确的变量传递给这些函数,那么我又回到了为不同产品放置各种变量的问题。

相反,使用对象,我所有的产品数据和功能都很好,干净而且易于理解。

然而。OOP的最大问题是,当有人认为一切都应该是OOP时。这就产生了很多问题。我的数据库中有88个表。我只有大约6个课,也许我应该大约有10个课。我绝对不需要88个课。在我使用它的情况下,大多数时候直接访问这些表是完全可以理解的,并且OOP实际上会使获取正在发生的事情的核心功能更加困难/乏味。

我认为,有用的对象和实用的过程的混合模型是最有效的编码方法。所有这些宗教战争中,人们主张使用一种方法却以牺牲其他方法为代价,这真是令人遗憾。他们俩都是好人,都有自己的位置。在大多数情况下,每个大型项目都同时使用这两种方法(在某些小型项目中,可能只需要一个对象或几个过程即可)。


3

对于可读性,我不太关心重用。后者意味着您的代码更容易更改。在构建软件的过程中,仅此一项就值得黄金。

OO是使程序可读的非常有效的方法。重用或不重用。


2

“现实世界不是“ OO”,”

真?我的世界充满了对象。我现在正在用一个。我认为让软件“对象”为真实对象建模可能不是一件坏事。

面向概念性事物(例如Windows,不是现实世界的窗口,而是计算机显示器上的显示面板)的OO设计经常有很多不足之处。但是对于诸如发票,运输单,保险索赔之类的现实世界而言,我认为这些现实世界都是物体。我的桌子上有一堆书,所以它们一定是真实的。


2

OOP的目的是为程序员提供另一种方式来向机器和人员描述和传达代码问题的解决方案。其中最重要的部分是与人沟通。OOP允许程序员通过以OO语言执行的规则来声明它们在代码中的含义。

与该主题的许多论证相反,OOP和OO概念在所有代码中普遍存在,包括非OOP语言(例如C)中的代码。许多高级的非OO程序员甚至会使用非OO语言来近似对象的功能。

将OO内置到语言中只会给程序员提供另一种表达方式。

编写代码的最大部分不是与机器进行通信,这很容易,最大的部分是与人类程序员进行通信。

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.