OO编程的好处是什么?它会帮助我编写更好的代码吗?
我是PHPer,并且没有编写面向对象的代码。
OO相对于过程代码的优点是什么?在哪里可以学到如何将这些思想应用于PHP?
解决方案
对象有助于使代码在不同的部分之间保持隔离,因此,如果我们需要更改一个部分,则可以确信它不会影响其他部分:松散耦合。
然后,一段时间后,我们会发现为一个应用程序创建的对象在其他应用程序中也很有用,并且开始获得更好的代码重用性。因此,新应用程序已经完成了部分工作,并使用了经过时间考验的代码:软件构建速度更快,错误更少。
人们会从各种角度告诉我们有关OOP的各种信息。但是,如果我们想发表自己的意见,而不是接受别人的意见,那么我建议阅读Bertrand Meyer的"面向对象的软件构造"。
本质上,他采用了非OOP编程技术,并分析了它们的基本缺陷。然后,他得出了解决这些缺陷的替代技术。换句话说,他从第一原理得出OOP。这是一项了不起的工作,而且非常令人信服。
阅读它,我们将了解为什么,何时何地以推理的方式进行备份的方式。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
是的,如果我们真的知道。
它可以可视化大型系统的各个部分之间如何进行交互。在设计级别上非常有用。
如果仅编写几行代码,我们将获得的唯一好处是,使用分解成精心设计的对象的库通常比使用函数要容易一些。
要充分利用它,我们还需要遵循可靠的OO设计实践。始终使用许多小型类封装所有数据,而永远不要使用大型"包罗万象"类。让班级为我们完成工作,而不是要求其提供数据并在班级外进行工作,等等。
它可能不会在一段时间内对我们有很大帮助,并且如果我们始终在做小型网站(我不能肯定地说,我不是真的在做php),可能永远也不会帮到我们,但是随着时间的推移,在大型项目上,它可以是无价的。
曾经有一段时间,当我第一次开始编程时,我编写了面向用户的代码。效果很好,但是很难维护。
然后,我学习了面向对象(OO),我编写的代码变得更易于维护,更易于在项目之间共享,而且生活非常美好……除用户外,其他每个人都受益匪浅。
现在,我知道了计算机编程的真正灵丹妙药。我写OO代码,但首先我要使我的用户客观化。起初将人当作对象看似不礼貌,但是这会使我们编写所有软件以使用明确定义的界面工作时变得更加优雅,并且当用户发送意外消息时,我们只能忽略它,或者标记有表示足够重要性的标志,然后对它们进行例外处理。
OO的生活是美好的...
大型系统(如Wordpress,Drupal或者XOOPS)使用OOP概念。我们可以在那里看到使用它们的好处。代码重用,模块化,可维护性和可扩展性。
我们可以修改对象的某些部分,并且会影响整个应用程序。无需搜索替换我们执行某些操作的每个位置(并且可能会丢失它)。
我们可以在各处重复使用对象,从而节省了大量的复制和粘贴操作。修补错误需要修补一个对象,而不是全部执行相同操作的16页代码。
当我们封装逻辑并"隐藏"实现时,使用对象更容易,从现在起六个月内,我们已经忘记了为什么做某事,并且对于使用代码的嵌套人员或者gal也是如此。例如,我们要遍历Wordpress中的帖子所要做的就是调用一个函数。我不需要知道它是如何工作的,我只需要知道如何调用它即可。
OOP实际上是包装在对象方法/函数中的过程代码。我们仍然需要知道如何编写体面的线性代码才能实现对象的方法和功能。它只是使重用,扩展,修复,调试和维护东西变得容易得多。
http://www.onlamp.com/pub/a/php/2005/07/28/oo_php.html
它不会自动为我们提供帮助。我们可以编写比结构程序更糟糕的" OO"程序,反之亦然。 OOP是允许我们创建更强大的抽象的工具。
- 与每个强大的工具一样,我们必须正确使用它。
- 与每个强大的工具一样,需要花费一些时间来学习如何正确使用它。
- 与所有强大的工具一样,我们会犯错误。
- 与每个强大的工具一样,我们将需要进行大量练习。
- 与每个强大的工具一样,我们应该阅读很多有关它的内容,并阅读其他人的想法。向他人学习。
- 但是,就像所有强大的工具一样,有些人滥用它。学会不向他们学习不良做法。这很难。
我会这样说:如果我们编写任何复杂的东西,都应该对所考虑的概念进行编码,而不是尝试考虑所使用语言本身所固有的概念。这样,我们可以减少错误。这些概念的形式化称为设计。
函数式编程可让我们定义与动词相关的概念,因为每个函数本质上都是一个动词(例如,print())。另一方面,OO编程还允许我们定义与名词相关的概念。
对象有助于封装复杂性。对于大多数PHP编程,不可能为任何相当复杂的应用程序编写良好,简洁的代码。编写OO PHP可以将代码放入单独的框中,将其与其他所有内容隔离开来。这有几个好处。
- 只要对象具有明确定义的输入和输出,该对象执行其操作的方式就无关紧要-存储/检索数据可能从平面文件到XML再到内存缓存再到MySQL再到Oracle,只有我们必须只关注一个对象。
- 只要对象具有明确定义的输入和输出,就可以将其完全替换为另一个具有相同输入/输出的对象。在运行时确定是否要向印度尼西亚的粗略服务器发送MySQL,Postgres,memcached或者HTTP POST / GET请求。
- OO使单元测试更加容易。如果我们可以定义特定对象应该执行的操作(即,对于给定的输入它应该给我们带来什么结果),那么我们可以轻松编写代码以针对该代码测试数千个值并检查结果,并且我们会立即知道是否有某些事情休息。
- 我们"隐藏"在对象中的代码越多,使用该功能时所需要看到的代码就越少。我曾经用PHP编写过一个轮询应用程序,该应用程序处理了轮询的所有方面-数据库交互,轮询生成,投票,排名,排序和显示-并且我的网站上只需要一行代码(
Poll :: Display()
)。 )来实现应用程序可以执行的全部操作-这使得维护我的首页变得更加容易。
请记住,与Python或者Ruby之类的语言相比,PHP(甚至PHP5)中的OO并不是很好的OO。 Python中的一切都是对象模型,这使我对OO编程真正感到满意,而作为一名前PHP程序员(和双重认证的Zend工程师),如果我们想了解OO是什么,我强烈建议我们探索Python的OO。所有关于。至少,它将编写更好的PHP代码。
没有人提到的一件事是,OO代码有助于编写可读代码:
sherry.changePhoneNumber(); phoneCompany.assignNewPhoneNumberTo(sherry); sherry.receive(new PhoneNumber().withAreaCode("555").withNumber("194-2677"));
这样的美学使我感到奇怪的满足。
我是一个长期的过程PHP程序员,偶尔涉足面向对象的PHP。乔尔的上述回答很好地总结了这些好处。我认为,一个次要的好处是,它迫使我们从一开始就更好地定义需求。我们必须了解对象与将要作用于它们的方法之间的关系。
彼得·拉文(Peter Lavin)的"面向对象的PHP"是一本帮助过渡的好书。
替代文字http:// object取向php.com/images/oop_cover.jpg
要学习PHP中的OO,我建议尝试使用一些好的书面OO PHP框架。
我们可能要看一下Zend Framework。
我会说有两个主要好处:
- 封装:不应隐藏不应从库外部调用的库中的代码,从而防止滥用并在保留外部接口的同时简化对库内部结构的更改。在良好的OO设计中,代码完成后,更改将更容易引入。
- 抽象:我们不是在处理数组,而是在与员工,部门等打交道。这意味着我们可以专注于业务逻辑,而只需编写更少的代码行。更少的行意味着更少的错误。
重用我不会严格地将其视为OO的好处,因为在纯过程模型中,智能库组织还可以让我们重用代码。
另一方面,与过程模型相比,在PHP中使用大量对象往往会降低性能,因为每个请求的对象构造开销都很大。必须在程序样式代码和oo样式代码之间找到良好的平衡。
我也是PHP的人,尽管我确实有很强的OOP背景知识,但是我想说,与PHP一起使用OOP的最好的书应该是PHP 5 Objects Patterns and Practice。
对我而言,最大的胜利就是继承,或者使一个对象的行为几乎与另一个对象完全一样,但有一些区别。这是我办公室的一个真实示例:
我们需要代码来处理客户发送给我们的TIFF文件,将它们转换为标准格式,将有关该文件的一些信息插入数据库,然后发送结果电子邮件。我在一组类中编写了此代码(在Python中,但想法是相同的)。 " fetcher"类从POP3邮箱中获取电子邮件,然后将其交给"容器"类,该类知道如何从电子邮件中读取附件。该类将每个图像交给"文件对象"类,该类进行了必要的处理。
好吧,有一天,我们有一位想要发送PDF文件的客户。我对" TIFF文件对象"类进行了子类化,并重写了"规范化"功能,改为将PDF用作输入,但是其他所有代码都保持不变。它第一次起作用,我感到非常高兴。
对我们的邮件服务器的更改意味着我需要通过IMAP来获取电子邮件。同样,我将" POP3提取程序"分类为子类,以便它可以说IMAP。问题解决了。
另一个客户希望通过CD邮寄给我们,因此我将"电子邮件容器"类归为"文件系统目录"类。瞧,做完了。
在每种情况下,新代码与旧代码的相似度为95%。例如," TIFF文件对象"类具有大约15种方法。 " PDF文件对象"类仅定义一种:将特定格式的文件转换为我们的标准的方法。它从其父类获得的所有其他信息。
现在,我们绝对可以在程序上执行相同的工作,例如通过编写:
if fileobjecttype == 'TIFF': data = <snip 30 lines of code to read and convert a TIFF file> elif fileobjecttype == 'PDF': data = <another 45 lines to read a PDF> elif fileobjecttype == 'PNG': data = <yep, another one>
最大的不同是,我相信我们可以使OOP看起来更整洁,更有条理。我的PDF类如下所示:
class PDFReader(GenericImageReader): def normalize(self): data = <45 lines to read a PDF>
就是这样。我们可以一目了然地看出,它所做的一件事情与它所继承的类所做的都不一样。它还迫使我们或者至少强烈鼓励我们在应用程序的各层之间建立干净的接口。在我的示例中,PDFReader毫无头绪,也不在乎其图像是来自POP3邮箱还是CD-ROM。 POP3提取程序对附件一无所知,因为它的工作仅仅是获取电子邮件并将它们传递出去。实际上,这使我们可以用最少的编码或者重新设计量来做一些非常令人惊奇的事情。
OOP不是魔术,但它是使代码井井有条的绝妙方法。即使我们没有在所有地方使用它,它仍然是我们真正应该开发的一项技能。
为了详细说明Joeri的答案:
国际标准化组织将封装定义为:"对象中包含的信息只能通过对象所支持的接口处的交互来访问的属性。"
因此,由于某些信息可通过这些接口访问,因此某些信息必须在对象内隐藏且不可访问。此类信息展示的属性称为信息隐藏,Parnas辩称,模块应设计为隐藏困难的决策和可能更改的决策,从而定义了该属性。
注意那个词:变化。信息隐藏涉及潜在事件,例如将来更改困难的设计决策。
考虑具有两个方法的类:方法a()是隐藏在该类中的信息,方法b()是公共的,因此可以被其他类直接访问。
将来对方法a()的更改很有可能需要对其他类中的方法进行更改。还有一种可能,就是将来对方法b()的更改将需要对其他类中的方法进行更改。但是,仅由于方法b()可能受更多类的依赖,方法a()发生此类波动变化的可能性通常会低于方法b()的可能性。
降低纹波影响的可能性是封装的主要优势。
考虑任何程序中最大的潜在源代码依赖项数量(MPE,缩写是图论)。从上面的定义可以推断,给定两个程序向用户提供相同的功能,则MPE最低的程序将得到更好的封装,而统计上封装得更好的程序将更便宜地维护和开发,因为成本最大电位变化的最大值将小于封装不太完善的系统的最大电位变化。
此外,考虑一种仅具有方法而没有类的语言,因此也就没有方法彼此隐藏信息的方法。假设我们的程序有1000个方法。该程序的MPE是多少?
封装理论告诉我们,给定一个由n个公共节点组成的系统,该系统的MPE为n(n-1)。因此,我们的1000种公开方法的MPE为999,000。
现在让我们将该系统分为两个类,每个类有500个方法。现在有了类,我们可以选择将某些方法设为公共方法,将某些方法设为私有方法。除非每种方法实际上都依赖于其他所有方法(这不太可能),否则情况将会如此。假设每个类中有50个方法是公共的。系统的MPE是什么?
封装理论告诉我们:n((n / r)-1 +(r-1)p)其中r是类的数目,p是每个类的公共方法的数目。这将使我们的两级系统的MPE为499,000。因此,在这种两类系统中进行更改的最大潜在成本已经大大低于未封装系统的成本。
假设我们将系统分为3个类,每个类有333个类(嗯,一个类将有334个类),每个类又有50个公共方法。什么是MPE?再次使用以上公式,MPE将约为482,000。
如果将系统分为4类,每类250种方法,则MPE将为449,000。
似乎增加我们系统中的类数量总是会减少其MPE,但事实并非如此。封装理论表明,应将系统分解为最小化MPE的类数为:r = sqrt(n / p),对于我们的系统而言,实际上为4. 例如,具有6个类的系统将具有MPE 465,666.
负担原则有两种形式。
强形式表示,转换实体集合的负担是转换的实体数量的函数。弱形式表示,转换实体集合的最大潜在负担是所转换实体的最大潜在数目的函数。
更详细地说,创建或者修改任何软件系统的负担取决于创建或者修改的程序单元数量。
依赖于特定的,经过修改的程序单元的程序单元与不依赖于经过修改的程序单元的程序单元相比,受到影响的可能性更高。
修改后的程序单元可能施加的最大潜在负担是依赖于它的所有程序单元的影响。
因此,减少对修改后的程序单元的依赖关系可以减少其更新将影响其他程序单元的可能性,从而减少该程序单元可能施加的最大潜在负担。
因此,减少系统中所有程序单元之间的最大潜在依赖关系数量会减少对特定程序单元的影响会导致对其他程序单元进行更新的可能性,从而减少所有更新的最大潜在负担。
因此,封装是面向对象的基础,封装有助于我们减少所有程序单元之间的最大潜在依赖关系数量,并减轻"负担原则"的弱形式。
我认为OOP适合那些考虑"对象"的人,在这些对象中,对象由数据以及对数据进行操作的功能组成。
- 如果我们倾向于将函数及其所操作的数据视为独立的事物,那么我们就是程序程序员。
- 如果我们倾向于将功能及其所操作的数据视为已连接,那么我们就是一个面向对象的程序员。
我警告不要出去学习模式。为了出色地进行面向对象的编程,我们需要教自己像面向对象的程序员那样思考。我们需要了解并指出以下优点:
- 封装形式
- 类与实例/对象
- 继承与多态
仅在程序员了解的编程风格越多,解决问题和编写精美代码的能力范围大的意义上,它才有助于我们成为一名更好的程序员。我们不能先编写所有面向对象的代码并自动获得好的代码,但是如果我们真的了解OOP的工作原理,并且不仅是复制粘贴当今流行的一些设计模式,那么我们可以编写一些漂亮的代码好的代码,尤其是在编写大型应用程序时。
似乎每个人都从字面上回答了问题,即OO的特定好处/缺点。
我们应该学习面向对象,但不是因为面向对象具有我们需要的任何特定魔术。
更一般的形式是:
- 问:"我应该学习(OO,FP,并发,基于逻辑,事件驱动等)编程吗?"
- 答:是的,即使我们不是每天都不直接使用它,学习一个新的范例总是很有用的。"
我在PHP中使用OOP所做的最好的事情之一是类生成器。
在任何给定的表中,它将涉及几乎相同的SQL操作:
- 插入
- 更新
- 选择
- 删除
- 存在(检查是否存在行)
- 搜索
- 列表
现在,除了特殊情况外,我不再需要编写所有这些SQL语句。在执行上述操作的过程中,不仅将编码减少了1分钟,而且还节省了调试代码的时间。
因此,只要表结构发生更改,我就只需重新生成类。
可能我们应该尝试对我有用的产品,并且让我的客户喜欢!