首页 >

面向对象编程的弊端是什么? – 网络|

没有管理员权限怎么办,3dsll怎么看自己的fc,电脑怎么建多一个盘w7面向对象编程的弊端是什么? - 网络|面向对象编程的弊端是什么

但,这并不是真的。

如果你经历过很多,就会发现“只要如何如何,就一定能如何如何”这个提法一旦出现,基本上就不靠谱,不管是编程还是别的什么事情。

在大量的场景中,可以偏执的认为“万物皆对象”(或者万物皆别的什么),但是哲学上的单纯并不一定能让现实中的工程变得更“好”。如果说非得有个“万物皆XX”,那么这个XX八成就是根据众多需求综合到一起的“折衷”。

简单从工程讲的话,如果程序(或者说工作)是一次性的,那么怎么写得快,能work就怎么来。这个相对好理解。但是,如果程序是要长期维护的,那么如何管理其复杂性是核心的问题。而管理复杂性的要点在于

  • 让事情本身变得简单。这说白了就是砍需求,研发和PM之间要经常沟通去避免nicetohave的需求变动带来的程序复杂性的剧烈变化(比如一个1对1的实体关系,需求变动一点就变成了麻烦的多的“有时1对1,有时1对多”的混合关系)。
  • 运用隔离的手段将复杂性拆解为互相影响很小的单元。一个单元对外只暴露一个简单的“接口”,隐藏内部复杂性。这就是“抽象”或者“封装“的力量。但是问题在于,这个抽象本身是否做的合适是由于问题决定的,而不是代码本身决定的。

即便是抽象,也有很多种做法。可以定义一组接口,这个接口是一组函数、一组服务的RPC还是一个class的publicmethod都可以根据实际情况商讨。面向对象只是这里面其中一种做法而已。一个想要把程序编好的人,需要注重的是理解问题,然后尝试做出几种不同的抽象,评估各自优缺点后得到一个当时可行解的能力。而现有的大环境、教育体系,没有那么多真实的、复杂的案例,只能用一些简单的samplecode来教授。并且在说明问题本身时,简化问题本身,而突出代码设计的“模式”。这就好像是在用视频教人游泳一样。学习者自己需要认识到这些培训只是个参考,玩真的还是要到项目里去体会。

即便是用面向对象做抽象也会有问题。很多时候,面向对象编程并不是一种好的“抽象”。如果抽象做得好,透过抽象出来的“接口”就可以轻易的使用这个系统。这时“大量的复杂性”被隐藏到接口后的实现里。这就像是你看电视从来都不需要拆开壳子看里面液晶屏幕和视频信号的转换,只需要知道【电源】、【调台】、【调音量】就能用。一个抽象做得好,往往要“deep”,隐藏足够的复杂度。而面向对象的文化/教育往往会鼓励程序员做很多无意义的,无性价比的抽象。看看有些代码里完全不知所云的adaptor,factory,builder等就是这种做法的产物。

此外,在大量使用继承作为设计方法时,也没有起到任何实质的隔离作用。如果你尝试扩展一个继承体系,往往需要了解整个继承体系才能写对代码——这时,复杂性并没有被隐藏起来。你也许只是代码写的少了而已。对于这种复杂度没有降低,编写代码只是写的少,但是要看懂还是得结合整个体系才能做到的方式,不是抽象,是“压缩”。压缩只能少写代码,却会让系统更难以理解了。

也许不太容易理解压缩在这里意思。比如在一段被压缩的数据中有3个bytes是“A”,“1”,“8”。但是他们的意思可能是A连续出现18次,也许是A1连续出现8次。至于到底是哪个意思,必须从头读所有的数据才能弄明白。编码也是这个道理。

再说说类型本身。一些面向对象编码对类型的定义要求的比较严格。其本质假设是“如果一个Object的类型是XXXX”,则其行为模式必然是“YYYY”。但现实当中,一个Object的行为模式不光与他的类型有关,还与这个Object“如何被使用”有关。比方说,一个User的Object,如果是用户自己看自己,就可以登陆、登出,修改昵称;如果是其他普通用户看,就只能看看看昵称和头像;如果是管理员来操作,可以reset密码、注销或者踢出登陆。这时就得界定一个Scope,来说明现在的User到底是哪个scope的User。DDD的一些理念就源自于此——找到某个上下文的某个实体概念,不能有歧义。但是即便不用DDD,也必须用各种变通的手段,把“如何用”的信息与类型信息结合到一起来实现逻辑。很郁闷的是,这个“如何用”完全没有章法,可能是“iOSApp登陆“,也可能是“第一次下单时”,或者是“系统处于降级状态”时。你永远也猜不到下一次可能会有个什么条件是要纳入到上下文的。大家都知道大量用if不好,容易让代码变成麻花,无法维护。但面向对象编程本身没解决这个问题。很多文章提出面向对象某个模式可以少写if,让代码容易维护。但是这其实是建立在那个问题的上下文已经明确的基础之上。上下文易变的问题没有解决,换一个上下文,招数便不灵了,到时还得处理一坨“模式代码”,非常恶心。

最后,面向对象会倾向于将不同的代码抽象为不同相互作用的Object,但是有一些现实因素会让这么面向对象得到非常不理想的效果:

  • 安全-如果你的代码要求非常安全,那么所有的Object都要耦合安全控制的代码;要不就是在一层对外的接口之前拦截一道处理安全问题,内部Object都无视安全问题。这也就相当于放弃了一部分的安全性。
  • 性能-如果强调性能的话,是要尽量减少隔离的层次的。无论抽象如何做,只要隔离发生,就要经历一次转换以及相应的性能损耗。比如早期的Hibernate不支持“bulkinsert”和“bulkupdate”,只能逼着程序员做forloopIO;而native的sql却可以轻易办到。在每多一次IO都很伤的场景下,这种隔离只能把事情做的更糟。
  • 数据为中心-很多业务场景都是以数据为中心。也就是说DB里的那坨数据是唯一的truth。在代码层面做的只是为处理数据更加方便。这时做的很多抽象意义不大。比如你可以在ORM层强制声明读取出来的一个数据少了某个字段是invalid的。但是你没法阻止你的第三方数据提供商源给你invalid的数据。对Invalid数据的处理远不是一个Annotation就能搞定的,必须引入复杂的业务流程。
  • 灵活性和成本-每次做某种抽象都意味着对一个系统“要做某种变化的能力做出优化”,但是同时,也就意味着或多或少对其他种变化适应性做“劣化“。如果系统变化的方向和预期的不一致,那么浪费掉的工作不说,为了再次调整设计方向的代价也会相当的大。这种情况比比皆是。

总结下,偶希望所有的程序员都要理解自己的工作的最终目的是干什么的,并且活用自己所能用到的一切工具来达成自己的目标。不要在各种编程范式里迷了路。如果是初学编程的人,偶衷心的希望你的编程课程讲授的是解决一些实际的问题,多了解业务,多尝试对业务的变动作出合理和准确的预。不要过早的接触高层的思想和哲学层面的问题——一个小孩看《红楼梦》又能真的看懂多少呢。


面向对象编程的弊端是什么? - 网络|
  • c语言转换函数怎么写? - 网络|
  • c语言转换函数怎么写? - 网络| | c语言转换函数怎么写? - 网络| ...

    面向对象编程的弊端是什么? - 网络|
  • 马来西亚的“蒙古国模特诈尸案”震惊世界,事件的主因是什么呢? - 网络|
  • 马来西亚的“蒙古国模特诈尸案”震惊世界,事件的主因是什么呢? - 网络| | 马来西亚的“蒙古国模特诈尸案”震惊世界,事件的主因是什么呢? - 网络| ...

    面向对象编程的弊端是什么? - 网络|
  • 说起德国手表,你最先想到哪个品牌? - 网络|
  • 说起德国手表,你最先想到哪个品牌? - 网络| | 说起德国手表,你最先想到哪个品牌? - 网络| ...