首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我们真的需要OO语言来管理软件的复杂性吗?

我们真的需要OO语言来管理软件的复杂性吗?
EN

Software Engineering用户
提问于 2017-03-20 10:13:40
回答 15查看 31.9K关注 0票数 215

这将是一个非常非技术性的软问题,我不确定这是否是正确的平台。但我是个初学的CS学生,所以我希望你们能容忍。

第一学期通过Java和UML向我们介绍了OOP的概念,如封装、数据隐藏、模块化、继承等。(Java是我的第一种编程语言)

据我所知,OOP是一种管理软件复杂性的方法。但它的原理并不是新的或独特的,它们在某种意义上是普遍适用于所有工程领域的。

例如,car是一个非常复杂的结构,其复杂性由具有良好定义的行为和接口的模块化和封装组件组成的层次结构来管理。

但我不明白引入新编程范式的原因。我认为所有用于管理复杂性的原则都可以通过过程编程语言来实现。例如,对于模块化,我们可以将程序划分为许多执行定义良好的任务的小程序,这些程序的代码包含在单独的文件中。这些程序将通过其定义良好的输入和输出相互作用。文件可能受到保护(加密?)以实现封装。对于代码重用,我们可以在新程序需要时调用这些文件。这不是捕捉了OOP是什么,还是我遗漏了一些非常明显的东西?

我不是想要一个证明OOP管理复杂性的证据。在我看来,的确如此。但我认为,所有用于管理复杂性的原则,如模块化、封装、数据隐藏等,都可以很容易地通过过程语言实现。那么,如果没有OOP,我们就能管理复杂性,那么为什么要真正面向对象呢?

EN

回答 15

Software Engineering用户

回答已采纳

发布于 2017-03-20 15:32:23

让我用一个很低的理论回答:)

您真正要问的是:为什么在可以使用过程语言设计和编写OO代码时,直接在语言中包括对面向对象( Object )的支持?

答案是:为在源代码中如何表示OO制定一个标准,这样您就不会为相同的抽象最终得到22个不同的实现。

例如,假设我创建了一个MagicButton和一个MagicSlider,可以在用户界面系统中使用。我需要一种方法来分组可以与MagicButton一起使用的方法,只能与MagicSlider一起使用的方法,以及两者都可以使用的方法。这些对象共享一些方法,因为它们都是Magic对象。

我可以通过用一种特殊的方式命名函数( MagicSlider_DoSomething ... )来进行分组,通过将这些方法包含在以特殊方式命名的特定文件( MagicSliderMethods.XXX )中,或者我可以找到其他一些特殊的方法来做同样的事情。如果在语言上没有标准的方法来做它,我将做它不同于你,也不同于其他任何人。这使得共享代码更加困难。

是的,延迟分派-- OO语言中的虚拟方法--可以用过程语言实现,但是实现它的方法有很多种。根据编写代码的人的不同,您将在同一个程序中得到不同的OO实现。

想想可怜的维护开发人员。这个人必须管理不同的对象抽象和调用虚拟方法的不同方式,这取决于编写原始代码的人。

此外:在语言中使用抽象允许高级代码编辑器(如Eclipse )对代码进行大量静态分析。例如,Eclipse可以提供可用于对象的所有方法的列表,以及空"TODO方法“的自动实现。Eclispe准确地知道您的类必须根据您扩展的类和实现的接口实现哪些方法。如果没有语言标准来执行OO,这几乎是不可能的。

票数 178
EN

Software Engineering用户

发布于 2017-03-20 15:29:37

但我认为,所有用于管理复杂性的原则,如模块化、封装、数据隐藏等,都可以很容易地通过过程语言实现。

当你说,“很容易”的时候,你是在大胆的陈述。我读到的方式是:“我看不出有什么困难,所以不能太大。”当用这种方式表达时,很明显,你不是在问“为什么我们需要面向对象”,而是在问“为什么其他编程范式所遇到的导致OO发明的困难对我来说不是显而易见的吗?”

对这个问题的一个答案是,这些困难中的许多并不存在于你所从事的项目中。你没有被要求更新40年前的意大利面代码。您并不打算为操作系统编写新的显示管理器。您不是在调试多线程分布式应用程序。

对于我们CS学生负责编写的许多玩具程序,我们可以像用Java或Python一样用BASIC或程序集编写它们。这是因为任务的固有复杂性是如此之低,只有一个开发人员,没有遗留的互操作性问题,性能并不重要,而且代码很可能只在一台机器上运行几次。

想象一下,带一个学生司机,让他们在繁忙的街道上合并在高峰时间,在手动变速器,没有同步网格,走向陡峭的山。灾难。为什么?他们无法管理同时遵循任务所需的所有规则所需的复杂程度。

现在想象一下同一个学生,同一辆车,在一个空旷的停车场里以步行的速度行驶。他们很好,因为他们的技能水平足以完成这项任务。没有压力,风险很小,他们可以一次一次地承担起、掌握、转移、加速、驾驶这些单独的子任务。

那个学生可能会问为什么我们有自动变速器,如果一个熟练的司机可以同时完成所有这些事情?答案是,在最佳条件下,熟练的司机不需要自动驾驶。但我们并不都是处于巅峰状态的专业司机,我们通常想让汽车设计师为我们处理所有这些复杂的问题。

一个熟练、有纪律的程序员确实可以在C或程序集中创建一个高复杂度的系统。但我们并不都是莱纳斯·托瓦尔兹。我们也不应该这样做,去创造有用的软件。

我个人对重新发明现代语言的所有特性没有兴趣,甚至在我能够解决眼前的问题之前。如果我能利用一种包括已经解决的问题的解决方案的语言,为什么我不能呢?

所以我将把你的问题转过来问你,如果语言提供了像封装和多态这样方便的特性,我们为什么不使用它们呢?

票数 66
EN

Software Engineering用户

发布于 2017-03-20 05:54:39

您所描述的不是OOP,而是抽象。抽象在所有现代设计模型中都存在,甚至那些不是OOP的模型也是如此。OOP是一种非常特殊的抽象。

首先,值得注意的是,OOP没有单一的定义,因此可能有人不同意我所描述的OOP。

其次,重要的是要记住,OOP是受传统设计模型的启发,因此与汽车设计的相似之处并不是巧合。

然而,以下是OOP比您所说的更微妙的一些方法:

  • 封装:这不仅仅是为了拥有一个模块的集合接口(即抽象),而是要禁止这个接口之外的访问。在Java中,访问私有变量是编译错误,而在您的car设计中,您可以(在某些情况下)使用与预期接口不同的方式。
  • 继承:这确实是使OOP独一无二的原因。一旦定义了接口,就可以实现多个接口,并且可以以继承的方式完成这个任务,在继承之前的所有部分的同时,还可以更改其实现的特定部分,从而极大地减少代码重复。如果你认为汽车的封装组件,没有一个真正的等价于此。对于我来说,没有办法通过使用不同的设备并更改其实现的一个特定部分来制造一个齿轮。(至少我不这么认为,我对汽车知之甚少)。
  • 多态性:一旦定义了接口,从可用操作的角度来看,使用该接口的任何操作都应该是不可区分的,您不需要知道使用什么实现来使用接口。这就是子类型和Liskov代换原理变得重要的地方。
  • 耦合: OOP的一个关键方面是,我们将事物与相同的操作紧密地联系在一起,并将它们可能具有的不同形式分散开来。数据与对该数据的操作捆绑在一起。这意味着很容易添加新形式的数据(新的实现),但是很难向接口添加新的操作(因为您必须更新实现接口的每个类)。这与函数式语言中的代数数据类型形成了对比,后者很容易添加一个新操作(您只需要编写一个处理所有情况的函数),但是很难添加一个新的变体(因为您需要向所有函数添加一个新的大小写)。
票数 22
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/344522

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档