更多
2017年08月22日 11点56分 叶飞 修改

一起帮里有人问“面向对象”的问题。但我创建“一起帮”的目的是帮人解决“具体的”“实务性的”问题,“面向对象”太过于抽象,所以没批准发布。后来在QQ群里讨论,看他们七嘴八舌闹得慌,突然有一种“多情应笑我,早生华发”的萧瑟之感。

一转眼,我学编程都已经十年了。

十年之前,“面向对象”火得一塌糊涂。

十年之后,“面向对象”,没想到,还是这样云里雾里……

 

回头想想,之所以云里雾里,我认为一个很大的原因:我们把“面向对象”神话了

我今天,就想损一点儿,来把“面向对象”拉下神坛吧。O(∩_∩)O~

 

我现在都还记得,那时候炫耀自己的项目,“纯面向对象开发”……一个“纯”字,顿时逼格满满。现在想来,那时候说话确实不走脑子。“纯面向对象”,还有“不纯”的么?“不纯”的是什么?是杂质,是渣滓?是那些if...else...,是不是应该被剔除?问题是,你剔除了if...else ...,你项目里还能剩下些什么?

不知道大家以前有没有想过这个问题?

我觉得这是一个好问题。“纯面向对象”这种说法背后折射出来的,就是把“面向对象”和“面向过程”对立化,从而把“面向对象”人为拔高人为神话。

 

因为最近动了做培训来推广一起帮的念头,我会这样来思考这个问题:假如我是老师,我会怎么和同学们讲解“面向对象”?“继承”“封装”……No,No,No,那是以后的事。事实上,很长一段时间,我就是被这些东西搞晕了,而没能触及到“面向对象”的本质。

 

我觉得,一步一步由浅入深的理解“面向对象”,正确的姿势应该是这样的:

首先,同学们已经理解了方法/函数,明白为了代码的重用,我们需要一个又一个的函数。

那么,假设我们有一个项目,十万行代码(这其实就是微型项目),按一个函数平均50行计算,就会有2000个函数!好,问题来了,2000个函数啊,别说你记住了,你先想想,你咋命名?呵呵。

所以,一定得想办法,把他们“归类”(大家注意这个“”字):这50个函数,都是干这事儿的;那50个函数,都是干那事儿的……分门别类之后,2000个函数,50个类,这样,是不是有条理得多,清晰得多了呢?然后,调用一个方法的时候,先找到类,再找这个类下面的函数,是不是更流畅一些?比如:Blog.Publish(),Comment.Publish(),Blog.Agree(),Comment.Agree()……你看,也不用担心“重名”了。

这才是对“类”最基本最入门的理解——然而,很多同学,恰恰是缺乏这种最基本的理解,或者理解得不够深入,就直接奔那些“高大上”的概念去了。从而,在开发过程中整出很多莫名其妙的“幺蛾子”来。

可能有些同学不服气,“我怎么就理解得不够深入啦”,“这还需要这么深入理解”?或者,还有一些同学,要教育教育我,“你这个理解太初浅了”,“引入‘面向对象’,是为了‘重用’‘抽象’”,“来来来,我给你讲讲‘设计模式’,高级货!”……

这就是问题所在!有些同学,用了一堆的“高级货”,把本来复杂的程序搞得“更复杂”了。于是,有了所谓“滥用”,“滥用继承”“滥用设计模式”“滥用……”我想,有过一定开发经验的同学一定听说过甚至见识过这种“滥用”的,够酸爽吧?哈哈。那么,怎么才算“滥用”,怎么才能避免“滥用”?

其核心就在于理解一点:面向对象(其实包括所有针对“企业级应用”开发的思路策略),核心目的都是“降低系统的复杂度”,注意:降低,降低,降低,而不是“增加”系统的复杂度。业务需求本身已经够复杂了,就不要再给代码里“添乱”了。

请注意,这里的“复杂”,通常指的是“繁多”“杂乱”“无序”,人脑难以应付。怎么解决这个问题呢?无它,归类而已。

 

好了,回到“面向对象”,我们已经把函数进行了归类,感觉上舒服多了。然而,当代码量进一步膨胀,达到100万级的时候,就是类,也有500个了,我们的脑子还是不够用了。这时候,我们就会问:可不可以把这些类再进一步的归类呢?

当然可以,于是就有了“继承”;在“继承”的基础上,又有了“多态”;有了“多态”,就有了“设计模式”……

这些东西这篇博客我都不想讲,一篇博客也讲不了——太庞大了。

那我想讲的是什么?

是顺序,是目的

 

是先有方法函数,然后才有类;是有了类,然后才有了继承……

或者,更准确的说:是先有了一堆一堆多得让人抓狂的方法函数,才有了类;是先有了一堆一堆多得让人抓狂的类,才有了继承……

更本质的说法:是先有了问题,然后才有解决方案

而我们使用各种工具方法的目的,是为了解决问题。

 

这十年的编程生涯,我其实走得比较顺。(比TM的搞家装强太多了!)如果一定要说“走了什么弯路”,也就是在“面向对象”(以及衍生出来的种种,譬如“设计模式”)上面。

我想,最大的问题就在于:一开始,“面向对象”这玩意儿就是被“灌”进脑子里的,而且你还被不停的灌输它好很好灰常好——但究竟怎么个好法,却很少有人能说得清楚。所以一直晕乎晕乎的,不明觉厉。而且你会自然而然的产生一种心理:面向对象好,没有面向对象就是不好的。

这当然是不对的。

你可以把“面向对象”当做机关枪,机关枪火力猛射程远,但这并不是说机关枪就是最好的,手枪步枪狙击枪都是渣,而是各有各的用途。

这本来很好理解,然后,当你手里有了一把机关枪,而你又狂热的喜欢这把机关枪的时候,事情就变味了。你会说,机关枪一样可以干手枪的活,

  • 我用机关枪比你用手枪还好使,
  • 你觉得不好用,那是你不会用,
  • 不信你看着……

这就走上邪路了。

 

机关枪这个例子,如果现实生活中真有这样的人,你一定觉得他是疯子。

但在IT圈里,其实到处都是这种疯子。隔三差五的各种语言撕逼、框架撕逼、阵营撕逼,本质上,不就这么回事么?

 

矫枉过正的说,“面向对象”,或者“面向对象粉”们,确实有走上邪路的倾向。

如果说你确实能把“机关枪”玩出“狙击枪”的效果,那邪也邪得有个性,溜得飞起!问题是绝大多数人,没有这种本事,邯郸学步,就有些尴尬了。

 

我举一个例子:

现在有两个类,一个用户类(User),一个博客类(Blog),现在有一个发布博客的方法(Publish)。

那么,“发布博客”这个方法,究竟是应该放在用户的类里面,还是博客的类里面?即:究竟是User.Publish(Blog)呢,还是Blog.Publish()?

以下为思考时间:

滴答……

滴答,滴答……

滴答,滴答,滴答……

如果按照“万物皆对象”,“对象映射实体”,“方法就是对象的行为”……之类的格言来套的话,当然应该是User.Publish(Blog),你看,用户发布 博客,一一对应啊!美滴很~~就像我们老师教的那样,名词做对象,动词做方法……

但有过一定开发经验的同学,就知道应该是Blog.Publish(),但为什么呢?这看起来好像不对啊?博客怎么会发布呢?博客自己发布自己?什么鬼?不通啊!

 

确实不通,不过是你自己没“通”;或者,一开始就错了。

要理解这个问题,就得回到面向对象的“起点”,明白“面向对象”要解决的问题,不是什么“映射客观世界”,就这个问题,也还谈不上什么“继承多态”(“封装”勉勉强强,但根还不在这里)。

让我们再回头复习遍:已经有了一堆一堆的方法,再引入一个又一个的“类”,目的是什么?把方法装进一个又一个的类里面,分门别类,是不是为了照顾我们的“大脑”——这可怜的资源有限的人脑?电脑就没这些麻烦,方法都不用,01010010000101001001……就OK了。所以,假设有50个类,是不是每个类里的方法数目都差不多,匀称一些,我们的分类就更有意义一些?

假设User.Publish(Blog)的逻辑成立的话,是不是还会有User.Publish(Comment),User.Agree(Blog),User.Logon(),……,User.FlyToSky()……一个系统,是不是几乎所有的操作,都是User干的?这User不是要上天啊!我们“分门别类”的工作,是不是就没有意义了?以前是记一堆函数,现在是记User下面的一堆函数,有个毛用啊!

 

但我经常看到类似User这样的万能类,有轻重程度的差别,但本质上,这种代码,就是“披着‘面向对象’的皮”,干着……干着什么事呢?干着乱七八糟的事。

当然,还有滥用继承,层层叠叠的像个十八层宝塔一样,又百转千回的像个死亡迷宫一样,你咕哝一句“整复杂了”,架构师一脸傲娇鼻孔朝天,“面向对象,高级货!哪那么容易的……”

 

码字才真心不容易——这博客从昨天写到今天,差不多了。

做个总结吧:

  1. 面向对象,以及所有的软件工程思想方法,其目的都是把复杂的问题简单化,而不是相反。
  2. 所谓“简单化”,指的是让我们人类的大脑觉得“简单”,而不是电脑。电脑?0101010010000010101010……才最简单。
  3. 记住上面两个原则,明白:软件开发的目的是为了解决问题,而不是“炫技”。尤其是不要为了“炫技”而把本来就复杂的问题搞得更复杂……

(⊙x⊙;)

 

就酱紫,我要继续愉快的撸代码去了,欢迎围观。

面向对象 编程 开发 软件工程
支持: 10 反对: 0
您还没有登录,不能发布评论。请登陆注册

评论 / 8
2017年10月13日 16点38分 --- 第 8 楼 --- dybai

精选

作为一个(自以为是)老码农的我看到这篇文章有一种酣畅淋漓的感觉,尤其是后面三点总结得真好。

“炫技”,想必是每个因为喜欢编程而走上这条路的程序猿都经历过的吧,想想自觉惭愧。不过后来一点点认识到了自己的无知,这就是成长吧。

2017年10月13日 12点07分 --- 第 7 楼 --- 叶飞

--- 回复: ---


精选

估计你们老师讲的是:“类”好比车,“对象”好比轿车、卡车、摩托车吧?

讲的是类和对象的关系。


至于我写的东西你目前看不懂:正常。呵呵,先实践,在实践中慢慢理解吧。

2017年10月13日 11点59分 --- 第 6 楼 --- Sunyelw

精选
我记得大学的Java课第一节讲这个,老师说面向对象就好比开车,车有小轿车,货车等等,而对象是什么,是具体到哪一辆小轿车.然后车有什么属性,比如最大速度啊,座位个数啊之类的.封装 ?看飞哥的这篇文章还是有点迷迷糊糊的....
2017年10月12日 22点13分 --- 第 5 楼 --- qing1970

精选
说得好,我不会编程都看懂了
2017年09月26日 15点49分 --- 第 4 楼 --- ghwolf

精选

对我来说,面向对象一直都是一种分工形的,多人合作形的一种模式。面向过程就是自己从头到位全都要会,中间出错很难排查,面向对象则是一群人干一件事,把一个一个的功能模块分开来,出了错好排查。


今天看到飞哥的文章,又加深了对面向对象的理解♪(^∀^●)ノシ (●´∀`)♪

2017年09月25日 17点23分 --- 第 3 楼 --- hoku

精选
说的很好,接地气
2017年09月04日 11点07分 --- 第 2 楼 --- tangdebing

精选

没有学过面向过程的语言(如C),直接搞面向对象的话,确实不太好理解。

根本上还是思维方式的不同,面向过程偏向于函数的使用。面向对象偏向于对象的使用。

2017年08月25日 12点40分 --- 第 1 楼 --- jpf3888

精选
哈哈哈,初学python的我在面向对象上也始终想不明白,这下不再纠结到底什么是面向对象了。谢谢楼主
关键字

换一批
即时消息

2017年11月23日 14点23分 qusongjie

意见建议的评论这种现象更多的还是因为提问者的问题不清,以及提问者... 被管理员奖励50分钟 时间币

2017年11月23日 14点22分 叶飞

意见建议更加完善的规则,期待你的意见qusongjie的新应答:这种现象更多的还是因为提问者的问题不清,以及提问者...

2017年11月23日 13点37分 xianyu

你感谢了求助html 图片显示问题叶飞的总结,获得系统 时间币 奖励1分钟

2017年11月23日 13点35分 xianyu

你感谢了求助求一个正则表达式ztw1122的总结,获得系统 时间币 奖励1分钟

2017年11月23日 13点26分 ztw1122

求助求一个正则表达式的总结被xianyu查看,获得 时间币 2分钟

全部消息
新注册用户

2017年11月24日 01点41分
2017年11月23日 20点57分
2017年11月23日 20点55分
jqz4132 男, 1990年5月天蝎座
2017年11月23日 19点16分
2017年11月23日 19点08分
chkl269 女, 1990年11月天蝎座
更多