问题

大型项目中面向过程思想 vs 面向对象思想,哪种开发效率更高?

回答
在大型项目的开发实践中,我们常常会遇到一个核心的讨论:究竟是面向过程的思想,还是面向对象的设计,更能带来更高的开发效率?这个问题没有一个绝对的答案,因为效率的衡量标准和项目本身的特性都会影响结论。不过,我们可以深入剖析这两种思想在大型项目中的表现,来理解它们各自的优劣以及在不同场景下的适用性。

首先,我们来回顾一下这两种思想的核心:

面向过程(Procedural Programming)

面向过程的思想,顾名思义,是将程序看作是一系列顺序执行的指令集合。它关注的是“如何做”,也就是解决问题的步骤、算法和函数。在面向过程的开发模式中,程序被分解成一系列的函数(或子程序),每个函数负责完成一个特定的任务。数据和操作数据的函数是相对分离的。

在大型项目中,纯粹的面向过程开发,如果组织不当,可能会出现以下情况:

全局数据的滥用: 为了方便在不同的函数之间共享数据,容易倾向于使用大量的全局变量。这使得数据的流动变得复杂且难以追踪,一旦某个全局变量被意外修改,整个程序的行为都可能受到影响,调试起来异常困难。
函数之间的耦合度高: 当一个函数依赖于另一个函数的具体实现细节时,它们之间的耦合度就很高。任何对某个函数内部逻辑的修改,都可能需要同步修改依赖它的其他函数,形成连锁反应。在大型项目中,这种依赖关系一旦蔓延开来,维护成本会急剧升高。
代码的复用性受限: 虽然函数本身可以复用,但如果函数与特定的数据结构或上下文紧密绑定,那么在新的场景下复用这些函数就会变得困难。比如,一个处理特定格式文件数据的函数,在需要处理另一种格式文件时,很可能需要重写大量代码。
可维护性差: 随着项目规模的扩大,面向过程的代码库会变得越来越庞大,逻辑也越来越纠缠在一起。理解和修改其中的任何一部分都需要花费大量的时间去梳理和理解代码之间的依赖关系。新成员加入项目,需要更长的学习曲线来熟悉整个代码结构。

那么,在大型项目中有哪些面向过程的“优势”或“误区”呢?

有时候,人们会误认为“直接写代码”就是面向过程。在某种程度上,对于一些规模较小、功能明确的项目,或者在某些特定领域(比如底层驱动、性能敏感的算法实现),结构化、模块化的面向过程设计(而非混乱的跳转和全局变量堆砌)是可以提供清晰的控制流和高效的执行效率的。但这里的关键在于“结构化”和“模块化”,这已经接近了良好的软件工程实践,而不仅仅是“写过程”。

例如,一个精巧的算法实现,用纯粹的函数式编程或结构化编程来表达,可能比一个臃肿的对象模型更直接、更高效。如果一个大型项目主要是由一系列独立且易于管理的“流程”构成,并且数据结构相对简单,那么面向过程的思路或许在初期能带来较快的编写速度。

面向对象(ObjectOriented Programming)

面向对象思想则将世界抽象为一系列“对象”,每个对象都封装了自己的数据(属性)和操作这些数据的方法。它强调“是什么”,关注的是实体及其行为。核心概念包括封装、继承和多态。

在大型项目中使用面向对象的思想,其潜在的优势体现在:

封装性: 将数据和操作数据的行为绑定在一起,隐藏了实现的细节。外部只需要通过对象的公共接口来与其交互,大大降低了对内部复杂性的认知负担。这意味着,你可以放心地修改一个对象的内部实现,只要其公共接口不变,就不会影响到使用该对象的其他部分。在大型项目中,这就像是搭积木,每个积木都有标准的接口,你可以轻松地更换或组合它们。
继承性: 允许创建新的类(子类)来复用已有类(父类)的属性和方法,并在此基础上进行扩展或修改。这极大地提高了代码的复用性,避免了重复造轮子。在大型项目中,继承可以构建出清晰的层级结构,比如不同类型的“用户”(普通用户、管理员用户、VIP用户)都可以继承自一个基础的“用户”类。
多态性: 允许不同类的对象对同一个方法调用做出不同的响应。这使得代码更加灵活,能够处理多种不同类型的对象,而无需显式地判断对象的具体类型。例如,一个“播放”方法,可以被“视频播放器”对象、“音频播放器”对象分别实现,但调用者只需要调用“播放”即可,具体播放什么由对象自己决定。这在需要处理大量相似但又各有不同的功能时,显得尤为强大。

在大型项目上,面向对象是如何提升开发效率的?

1. 可维护性与可读性的大幅提升:
模块化和独立性: 每个对象都是一个相对独立的单元,易于理解和管理。当你需要修改一个功能时,你通常只需要关注相关的几个类,而不是在整个代码库中大海捞针。
清晰的职责划分: 对象的设计鼓励将特定的功能和数据封装在一起,使得代码的职责更加清晰。这对于新成员加入团队,或者在团队成员之间分配任务时非常有益。每个人都能更快地理解自己的工作范围,减少沟通成本。
降低认知负荷: 通过封装,开发者无需关心对象内部的复杂实现,只需要了解其接口即可。这使得开发者能够更专注于解决更高层次的业务逻辑,而不是纠结于底层细节。

2. 代码复用率的提高:
库和框架的基石: 大多数现代的软件库和框架都是基于面向对象思想构建的。利用这些现成的组件,可以极大地加速开发进程,避免重复劳动。比如,你需要处理数据库操作,可以直接使用成熟的ORM框架,而不是从头编写数据库连接和查询的代码。
易于扩展: 通过继承和多态,可以在现有代码的基础上轻松地添加新功能或修改现有行为,而无需修改原有代码。这对于需求频繁变更的大型项目至关重要。

3. 团队协作的优化:
明确的接口定义: 对象之间的交互通过明确定义的接口进行,这使得不同开发者或不同团队之间可以并行开发,只要遵守接口约定,最终就能无缝集成。
减少冲突: 由于代码被封装在对象中,不同开发者修改同一功能的可能性降低,从而减少了代码合并时的冲突。

4. 对复杂性的管理:
抽象化: 面向对象思想提供了一套强大的抽象机制,可以将复杂的现实世界问题分解为更小、更易于管理的对象模型。这使得开发者能够逐步构建出能够处理复杂业务逻辑的系统。
可测试性: 由于对象是独立的单元,并且可以通过接口进行交互,因此更容易对单个对象或对象之间的交互进行单元测试和集成测试。这有助于在早期发现和修复bug,从而节省后期调试的时间和成本。

对比与总结:哪种效率更高?

在大多数情况下,对于现代大型项目的开发,面向对象思想在“长期开发效率”和“整体项目质量”方面往往表现出更高的效率。

原因如下:

规模效应: 随着项目规模的增长,面向过程的缺点(如全局变量、高耦合度)会呈指数级放大。而面向对象的优点(封装、继承、多态)则能更好地控制这种复杂性,保持代码的可管理性和可维护性。
变化与演进: 大型项目很少是静态的,需求会不断变化。面向对象的设计(尤其是利用好继承和多态)使得系统更容易适应变化,减少了修改带来的风险和成本。
团队规模与协作: 大型项目通常涉及多个开发者和团队。面向对象提供的清晰的接口定义和模块化,是实现高效团队协作的关键。

然而,我们也不能一概而论:

某些特定领域: 如果一个大型项目主要是围绕一个非常明确、流程化的算法或数据处理任务展开,且不涉及太多复杂的业务逻辑和频繁的变化,那么采用高度结构化、模块化的面向过程方法,配合良好的设计模式(例如,函数式编程的一些思想),可能在某些方面(如绝对的执行速度或内存占用)更具优势。
过度设计: 如果过度设计,创造出太多不必要的类和继承关系,反而会增加项目的复杂性,降低开发效率。面向对象需要恰当的使用,避免“为了面向对象而面向对象”。
团队经验: 团队成员对面向对象思想的熟悉程度和实践经验也至关重要。一个缺乏经验的团队,即使采用面向对象,也可能写出“脏乱差”的代码。反之,一个经验丰富的团队,即使使用面向过程,也能做到高度的结构化和模块化。

结论:

在大型项目的开发中,面向对象思想通常更能带来更高的、可持续的开发效率,尤其是在可维护性、可扩展性和团队协作方面。 它提供了一种更有效的管理复杂性的方法,使得项目能够更好地应对长期的发展和变化。

但这并不意味着面向过程思想一无是处。良好的结构化和模块化的面向过程编程,在特定场景下依然是有效且高效的。关键在于理解两种思想的精髓,并在项目实际需求的基础上做出明智的选择,或者更常见的,在现代开发中,倾向于混合使用,即在宏观架构上采用面向对象的思想来组织模块和管理关系,而在具体功能的实现上,可能会借鉴面向过程的清晰流程和算法思路。 最终的目标,是在效率、可维护性、可扩展性、性能和代码质量之间找到一个最佳的平衡点。

网友意见

user avatar

简单说,软件开发模型有瀑布模型(自顶向下模型)、自底向上模型、快速原型法以及后来的敏捷开发模型等不同的项目分解、实施思路——至于面向对象和面向过程……这是编程语言支持的接口/模块设计的风格差异:相对于项目设计方案,它过于初级了,是风马牛不相干的两件事


打个比方的话,要打仗了,我们要制定个作战计划;然后告诉第一军团,你们负责这个;第二军团,你们负责那个……

然后,每个军团接到任务后,再把任务分解了——第一军团司令部令,第一军第一师,你们负责这个;第一军第二师,你们负责那个……

依此类推。


这里面没有面向对象/面向过程插嘴的余地。它们实在太初级,不配在作战会议上发言。


那么,面向过程/面向对象的差异,究竟体现在哪里呢?


喏:

这是面向过程风格的接口。你得自己知道其中的每个表头/每个指针/每个按钮都是干什么的——不知道就自己查手册或者问师傅——这才知道该怎么看它。


而这是面向对象风格的接口:

带个tooltips,看一眼就知道每个接口是干什么的、能不能随便碰——当然,过于技术性的东西,比如遇到什么数值应该采取什么措施,还是只能看课本/问师傅。

但能够少查一些手册,这已经非常值得了。


如果你是程序员,那当然是面向对象风格的接口简单、清晰,对吧:

1、从一个类继承了哪些基类,我们马上就知道它可以支持哪些功能(比如editable控件肯定支持编辑操作);

2、从一个类方法是不是public,我们马上就知道我们可不可以调用它;

3、最帅的,不光你知道,我知道,编译器也知道!所以它可以自动提示我们,你做错了!


接口自带tooltips,这就是项目设计师眼中面向对象风格的所有好处。别的没了。


其他好处,都是从设计里来的。

比如Linux kernel是C写的,但却有一个“泛文件抽象”——清清爽爽的单根结构,彻彻底底的面向对象,对吧。


而你过去见到的那些低水平项目呢,它们压根没有设计。


没有功能分区,没有操作保护,没有威胁隔离……乱糟糟一团:

这是那些项目看起来累的根本原因。


反之,如果我们在项目设计时花了心思,把功能、逻辑、接口都理的清清楚楚,再拿不同颜色区分的明明白白:

爽了吧。


当然了,事实上,软件开发者面对的情况并不仅仅是面板接线。

那是更复杂、更严峻的、动态而微妙的、啮合的逻辑——以至于我都不敢在知乎上提及。

不然哪怕最最初级的技术,得到的回应必然是“太长不看”。


这种东西要理清楚、整明白,显然比面板接线是难太多了:

这就是为什么优秀软件工程师无论是开发效率还是错误定位速度全都十倍百倍碾压普通码农的根本原因。


很明显,无论最终你搞成面向过程风格还是面向对象风格,两者都是换汤不换药:你理清楚了,那么你是按面向过程风格要求使用者查手册、对编码,还是按面向对象风格在上面贴便签,都一样方便;但如果你没理清楚、乱糟糟一团,那什么风格都救不了你。


只不过,把软件功能、逻辑都理清楚、模块划分搞好、在动手之前就把一切理的清清爽爽实在太难,这才让一大群只懂面向对象的家伙抢了风头……反正都是看不懂,而面向对象起码还有点比喻,让人感到似乎透了那么一点点亮……

那么,这玩意儿被外行追捧,也就不奇怪了。


——尤其是,业界很多混子大师、以及捧混子大师臭脚的外行、骗钱的营销号,更是把面向对象都捧上了天;却不知道面向对象恰恰是极其反常识的东西甚至“类”这个命名本身就是误导(正确理解用术语表示叫is-a),硬生生把软件开发搞成了跳大神。


如此理解面向对象编程

“面向对象编程是一个极其糟糕的主意,只有硅谷里的人能干出这种事情。”Edsger W. Dijkstra(图灵奖获得者)

“面向对象设计是用罗马数字做计算。” — Rob Pike(Go语言之父)

“‘面向对象’这个词包含很多意思。有一半是显而易见的,而另一半是错误的。”— Paul Graham(美国互联网界如日中天的教父级人物)

“实现上的继承就跟过度使用goto语句一样,使程序拧巴和脆弱。结果就是,面向对象系统通常遭受复杂和缺乏复用的痛苦。” — John Ousterhout( Tcl and Tk 的创始人) Scripting, IEEE Computer, March 1998

“90%的这些胡说八道都称现在它很流行,非要往我的代码里搓揉进面向对象的石粒。” — kfx

“有时,优雅的实现只需要一个函数。不是一个方法。不是一个类,不是一个框架。只是一个函数。” — John Carmack(id Software的创始人、第一人称射击游戏之父)

“面向对象编程语言的问题在于,它总是附带着所有它需要的隐含环境。你想要一个香蕉,但得到的却是一个大猩猩拿着香蕉,而其还有整个丛林。” — Joe Armstrong(Erlang语言发明人)

“我一度曾经迷恋上了面向对象编程。现在我发现自己更倾向于认为面向对象是一个阴谋,企图毁掉我们的编程乐趣。” — Eric Allman(sendmail的创造者)



谁告诉你面向对象的“类”这个比喻可以方便你理解,他就一定是骗子。

这个事实,我们在199x年代末已经理的清清楚楚、剖析的明明白白。到现在还不知道的,那是既无知又……

你不怕死,尽管跟着学。

user avatar

简单来说你需要找个人带一下,了解游戏的领域知识,正如很多公司招了实习生要给配个mentor一样。这和用什么语言关系,用什么编码范式关系并不大。

在看代码之前,首先要先了解系统的“设计”。一般会有很多设计文档从高层次去描述我这个系统里有哪些概念,这些概念的关系是什么,如何交互等。没有这个理解,很难去直接通过看代码来了解整体设计思路(如果你能做到,一定有数十年功力了,也就不会来问这个问题)。

其次,一个设计的好坏有很多维度。比如代码可读性,性能等。代码的性能好,并不一定说明可读性就好。实际上存在很多性能优化的奇技淫巧,其他人看来都是WTF。比如可以写一段汇编怎对特定类型CPU的寄存器进行优化编码,可能能得到比通用编译器更好的效果。

而可读性不好,并不一定是真的不好读,而是存在一个认知门槛。在达到门槛之前,是很难理解。这就像是,如果你没学过开飞机,看到飞机驾驶舱里的各种按键仪表就会懵逼。而当你玩了一年微软模拟飞行后,你会对各种功能如数家珍,倒背如流,闭着眼睛也能找到。而这一年里就是需要去阅读大量的手册和资料,去理解这些功能背后的动机,设计,操控方式,反馈。

而一个设计看起来很简单的,很直观的程序。其“简单”可能主要是因为他by design要解决的问题就少。而那些他不解决的问题,大幅降低了门槛。让其“容易看懂”。但这也只能说明这个项目更适合初学而已。正如你自己写程序加个锁可能就lock一下,而mysql的锁的种类,行为,配置多得令人抓狂。而从mysql角度,只有实现成那样的锁才能有效支持ACID语义,同时保证性能上可接受。

但既然问到了就顺便扯一扯。

什么是面向过程?

面向过程是一种以过程为中心的编程思想,即编程直接对应于要执行的动作。对于CPU而言,他只需要知道要下一步执行的代码在内存的什么位置即可。把尺度放大,比如做一笔交易要“扣库存”-“产生订单”-“完成支付”三步。
为了支持这个机制,通常编程语言会提供顺序执行,分支(if),循环(for),函数,goto等来方便开发者来控制”执行流“。

什么是面向对象?

最早的面向对象来自于20世纪60年代的模拟系统的研究。可追溯的最早的面向对象语言是Simula。其主要涉及思想是对事务的模拟。所以衍生了class,实例,继承(is-a)等概念。

20世纪70年代后,诞生了另外一门面向对象语言smalltalk。其设计思想是把一个系统想象为像很多细胞组成的复杂组织。但细胞之间只通过消息传播。细胞各自维护自己的独立性和内部状态,而不得直接干涉其他细胞的”内政“。smalltalk和基于smalltalk开发的一系列系统证明基于这个思路可以构建庞大和复杂的软件系统。

这两个派系思想相互融合,逐步诞生了后续一系列面向对象语言,如C++,Java,Ruby,Erlang等。一般面向对象语言的使用者会将面向对象简单抽象为“封装”+“继承”+“多态“。但回归本源,这三个特征完全是3个相对独立的解决问题的思路。如”封装“可以立即为上面提到的”细胞“内部细节不对外暴露。”继承“是由于模拟系统里两类事务可以产生is-a的关联,而在实现中,这种机制可以在一定程度上帮助复用代码(但有副作用)。而”多态“其实和面向对象没多大关系。比如java里可以定一个interface,所有实现interface的对象都可以在执行相同方法时,发起不同的动作。而在如javascript的函数里,不管对象有没有关系,只要实现了同名的函数都可以被执行。

面向对象比面向过程更高级吗?

明显不是。你会发现这俩完全实在解决不同的问题。对于明显是”流程“的问题,自然要用面向过程解决。设计时,自然会画个流程图,然后代码照着写。

而对于代码的组织问题,则可以用面向对象的思路去解决(但不一定非得这么做)。去思考哪些逻辑应该归属到一起形成一个“细胞”。规定每个“细胞”可以接收什么消息,接收到后会对内部状态产生什么效果,以及会进一步触发别的什么消息。

除了简单的脚本代码之外,一般常规软件系统中,流程问题和组织协作问题会同时存在。所以编码时,实际上是在同时用两种思路进行编码。而一个“面向对象”的语言,实际上是同时支持面向对象和面向过程的编码方式的。(难不成你用java写不了if和for?)只不过一般出于宣传的需要,面向对象语言会刻意的着重强调其面向对象的特征。

此时,在存在多个对象通过协作完成一个事务时,通常用“泳道图”表达。”泳道图“可以同时描述不同对象之间的交互关系的同时描述整个过程(包括跨对象的过程和某个对象内部的过程)。而对应的代码就是我们常见的不同对象调用来调用去的代码。但编码时那个“对象”,可以是一个表示模块的函数,可以是java的对象,可以是单例,可以是spring的service,可以是一个微服务或者互联网商开放的接口……。在设计层面上对象的形式与语言无关

因此把两个编程范式看成非此即彼,或者把对象看成真理和追求,是完全错误的。正如没人会比较改锥和扳手谁更高级一样。

一定要用面向对象语言写代码才是面向对象吗?

很明显不是。面向对象的思想首先要求把逻辑抽象为一个个对象。至于这个抽象怎么实现的并不重要。例如Linux内核实现为由进程、内存、文件系统、磁盘、网络等管理组件协作,实现操作系统对外的功能。只不过实现的机制是靠C编写的一个个函数实现。一个微服务系统是由大量的微服务通过某种rpc通讯,实现庞大的系统。

面向对象语言为了一些面向对象的特种提供了语法支持,比如继承,方法覆写,基于继承的多态,访问权限管控等。但用过的人都会发现这些要素对于真实业务往往太过于简单,以至于并没有什么卵用。必须增加更多的特性来支持日益复杂的逻辑编写。如常见的IoC,动态Proxy,动态字节码生成,trait…… 但如果还觉得不够用,开发者还自己构建组件来实现。

举个例子,一个游戏里可能有成千上万个可交互实体,且随着运营要求会不断的更新和变化。但倘若用class实现这些实体的建模,就意味着这些实体都要进行硬编码。每次变更都要改代码,测试,发布才能上线。代价极其高昂。一个变通的手段可以定义一个class Entity,区分不同type,不同的type的entity可以有相同的属性,也可以有自定义的扩展属性。系统启动时从数据库中去加载所有定义的资源数据。而这些数据可以通过运营系统由游戏策划、美工、运营等录入,全程无需编码。在工程中,这比纯class的方法好得多。但这依然是“面向对象”。从游戏玩家角度,那些实体依然是实体,在互相砍杀,掉金币,开箱子;从技术角度,被渲染的Entity和渲染器,数值管理器等组件在不断通讯,实现系统功能。

总之,面向对象关键点是【设计】,而不是语法支持。要把用面向对象的思路去设计,和用特定的语法去解决特定的编码问题看做是两件完全不同的事情。对于那些语法用着合适就用,不合适就去实现适用的方案。

同时,也要避免总是用“模拟”,“比喻”的方式来设计程序。现实中,几乎不存在“幼儿园名词卡片”的程序。

使用面向对象就能得到更容易维护的代码吗?

面向对象对比面向过程的优势是在代码量多了之后,可以更好组织代码,实现更低的变更成本和变更风险。但这里的关键问题是要对代码进行【正确】的设计后才能对代码产生正面效果。错误的设计会导致更加难以理解和维护的代码。

面向对象本身并不能自动做【正确】的设计,还是要靠开发者自己。主要要靠两个方面。首先是,是开发者对问题本身的理解和未来演进方向的把握。俗称懂业务。这就是上面提到的题主要恶补的地方。比如一个做游戏的,表面主要规则就是游戏中的各种元素(如人物,boss,NPC),在一定的规则下完成交互,变更相关的数值(如血量,经验值,道具数量)的系统。但表面之下还有很多要素,如数据收集,可靠性(限流,容灾),运营,安全……。游戏不光是一个看起来的模拟器,而是一个需要精心考虑各种要素的系统。

第二个是面向对象设计的方法论。比如如何对一个业务进行抽象,哪些适合作为“实体”,哪些适合作为“事件”,一个业务规则适合实现在哪一层次等等。例如DDD就是这么一套方法论,指导开发复杂业务做出设计。但坦率来讲,我不觉得这个世界上存在通用的方法论。好的方法论总是在实践中不断打磨出来的,与要解决的问题的领域紧密相关。比如做游戏的,做电商的,做在线文档编辑的,做推荐系统的,会采用完全不同的方法。

Human.Attack(Monster)是面向对象吗?是好的写法吗?

首先,这的确是面向对象的一种写法。它表达了向Human发一个Attack消息,消息的参数是Monster这个对象。对这个消息的处理函数会对Human的内部状态做一些修改。

但现实中,这明显不是一种好的设计。

一般来讲A攻击B时,A和B的状态都会发生变化。而A.Attack(B)的语法造成这个函数会被定义到A里,修改A的状态。如果要改变B的状态,就得要求再来一次B.AttackedBy(A)。那么就有两种可能性,一种是在A.Attack(B)里的实现里写B.AttackedBy(A)。这明显是很不好的设计,因为攻击和被攻击从概念上是对等的。而A.Attack(B)里的实现里写B.AttackedBy(A)会把它变成包含关系。如果这样可以,似乎也没有什么可以阻止有人在D.AttackedBy(C)时调用C.Attack(D)。这样就会引发混乱。当然,可以规定“所有的AttackedBy”都必须包含在Attack里。但如果交互规则更复杂,这种规则就会更多,程序员就要背诵,且无法用编译器或者linter等来检查确保执行。

这里还有一个问题是如果A.Attack()用来调用B.AttackedBy(),就意味着A.Attack()可能是“主控逻辑”。但主控逻辑还有很多别的,除了A和B之外的逻辑要做,比如做鉴权,做统计……,与A本身毫无关系。此外这些逻辑放在A.Attack()里,那么是不是B.Attack()要放,C.Attack()要放……类似的逻辑会散的到处都是。修改这段逻辑会触发巨大的修改量。

因此,这里把A和B作为两个独立的对象来设计是非常不妥的。除了能满足初学者对于“比喻式编程”的盲目追求和满足感之外,没有任何实际的好处。

另外一种设计是,弄一个【攻击Handler】。这个攻击Handler接收主客体A和B(可以扩展到任意多个参数),根据攻击的处理逻辑,把A和B要变更的数值计算出来,然后告诉A和B该怎么变。

更抽象一点,这个Handler可以不只处理攻击,而是可以从存储中动态加载任意类型动作的处理逻辑(加载的逻辑可以用js或者lua)。这样上游就可以调用handle(action, params) 这样形式处理任意逻辑。且因为规则是动态加载的,可以实现在线热变更。而对于A和B的变更,如果A和B没有什么其他逻辑的话,就可以简化为直接对A和B存储进行变更的指令,而不需要浪费CPU和内存去创建A对象,然后再GC掉。比如set(makeKey(A), property_HP, -100)表示扣掉A的HP 100点。

此时你说A不就没有封装性了吗?是的,没有了,因为业务需求上压根就不需要他有封装性。一个看得到的游戏人物,在显示器看起来就是一堆像素,在信号线里是一堆电信号,在数据库里是一行数据,在代码中是一个具有特定type的entity,在一个handler里是一个主体/客体参数+lua动态逻辑。整套系统里每个部分都用自己最舒服的形式抽象了这个“A”。但偏偏就是没有,也不需要对一个具体的A进行抽象——他不需要存在。而为啥要为一个不需要的东西增加封装特性呢?就因为语法支持?

为一个不需要的封装硬加一个封装是极其愚蠢的

但如果说,这里对A的数值变化就一定需要额外逻辑,这些逻辑就是不能放到主handler里,一定要“封装”呢?没问题,我们可以给A的数值变化再做一个不同的handler,这个handler再去加载动态逻辑,和主handler的逻辑一起得到最终要变更的数值,再写入A的存储即可。

你可能说,那如果这些handler太多了,已经搞不清楚一次动作到底会触发多少个handler了怎么办?也很简单,每次请求产生一个唯一id,作为上下文,传递到每一个handler里。每个handler在执行时通过埋点/log上报自己的名称,参数和计算结果。这些上报信息被数据收集后就能画一个“链路图”。于是就可以非常清晰的看到实时的handler是怎么工作的。

所以你以为的面向对象是Human和Monster。而实际的对象是各种handler,存储IO组件和数据收集Agent。而后者的设计具有好的得多的灵活性和可维护性。

总之,编码问题不可能因为一句“面向对象”,或者“抽象”,“封装”,“多态”等特征或者语法就自动变成优秀的设计。用是不是面向对象来描述一段代码是否优秀是完全没有意义。

类似的话题

  • 回答
    在大型项目的开发实践中,我们常常会遇到一个核心的讨论:究竟是面向过程的思想,还是面向对象的设计,更能带来更高的开发效率?这个问题没有一个绝对的答案,因为效率的衡量标准和项目本身的特性都会影响结论。不过,我们可以深入剖析这两种思想在大型项目中的表现,来理解它们各自的优劣以及在不同场景下的适用性。首先,.............
  • 回答
    这绝对是个灾难性的场景,一击毙命,元首与核心班底全没了,国家瞬间陷入真空。要说接管,得看几个关键点:1. 谁能站出来? 预备指挥体系的启动: 这是最理想但可能性最低的情况。所有现代国家都有层层备份的指挥链,比如国防部长、参谋长联席会议主席、以及各军种司令。即使首都炸了,只要这些关键人物当时不在,.............
  • 回答
    浩瀚的宇宙中,漂浮的国际空间站(ISS)一直是我们对太空生活最直观的想象。许多人对它充满了好奇,尤其是关于“人造重力”的疑问。那么,在太空中,一个旋转的大型空间站真的能制造出我们熟悉的“重力”吗?现行的国际空间站又是否有采用这种方法呢?首先,我们来聊聊这个“人造重力”的原理。简单来说,它依赖的是一种.............
  • 回答
    .......
  • 回答
    长时间的大型手术,就好比在刀尖上跳一支精细的探戈,需要医生们付出超乎常人的毅力和专注。这种高强度的精神与体力消耗,常常让人好奇:他们究竟是怎么做到的?这背后,绝非仅仅是“医生的责任感”这么简单,而是一整套科学的策略和精湛的技巧在支撑。生理与心理的双重准备:身体是革命的本钱首先,确保医生在手术前能够达.............
  • 回答
    关于“女孩不能养中大型公狗”的说法,其实是个挺有意思也挺容易引起误会的话题。咱们得把它掰开了揉碎了说,别让那些模棱两可的说法给忽悠了。首先,咱们得明确一点:这完全不是一个绝对的“不能”的问题,而是一个“是否适合”和“能否胜任”的问题。 就像不是所有人都适合养猫,也不是所有人都适合养小型犬一样,养狗这.............
  • 回答
    这个问题很直接,答案也同样直接:赤手空拳的人,面对中大型猛犬,几乎不可能赢,胜算微乎其微。我们得先明白几个关键点:1. 猛犬的先天优势: 力量与速度: 中大型猛犬,比如比特犬、罗威纳犬、德牧(德国牧羊犬)、杜宾犬等等,它们天生就是为狩猎、甚至搏斗而培育出来的。它们的肌肉结构、骨骼密度、爆发力都远.............
  • 回答
    这是一个非常有意思的问题,涉及到航空工程中几个核心的权衡和发展趋势。随着发动机尺寸的增加,中大型民航客机重新采用上单翼布局的可能性,确实存在,但也伴随着一系列挑战和权衡。下面我将尽可能详细地分析一下这个问题。首先,我们要理解为什么目前的绝大多数中大型民航客机都采用下置式机翼(也就是我们常说的“下单翼.............
  • 回答
    这个问题很复杂,结果很大程度上取决于很多因素,没有一个绝对的答案。我们可以从几个方面来详细分析:一、 人和犬的个体差异: 人的因素: 力量和技巧: 普通成年人虽然有使用工具,但力量、速度和格斗技巧都与经过训练的猛犬相差甚远。能否准确、有力地击中目标是关键。 胆量和心理素质.............
  • 回答
    要评价知乎在大型社交网站中的架构水平,得从几个关键维度去审视。不能简单地说它属于“顶尖”或“一般”,而是要看它在满足海量用户并发访问、数据存储、内容分发、实时交互以及应对业务快速迭代这些核心挑战时,展现出的设计思路和技术实现。首先,在高并发处理方面,知乎作为国内知名的问答社区,用户量级庞大,尤其是在.............
  • 回答
    当然,写好大型场面是网络小说中提升作品吸引力和阅读体验的关键之一。这不仅仅是简单堆砌人数和物体的数量,更重要的是如何通过细节、情绪和节奏,将读者的感官和情感调动起来,让他们身临其境地感受到那份宏大与震撼。下面我将从几个方面,详细拆解如何在网络小说中描写大型场面,尽量让你感受不到AI的痕迹,而是更像是.............
  • 回答
    大型科研项目方案的评审,是一项极其严谨且复杂的工作。要确保论证结果的公平、科学,并妥善平衡各方利益,需要一套成熟、系统且不断优化的机制。这不是一蹴而就的,而是需要多方面、多层次的努力。一、 确保论证结果的科学性:基石牢固,严谨至上科学性是科研项目方案评审的生命线。为此,我们需要从以下几个方面着手: .............
  • 回答
    一场规模空前的核战争,将把人类文明推入一片炼狱。在这种极端情境下,那些我们曾经引以为傲的宏伟建筑——大型水利设施,它们的命运又将如何?它们能否在核爆的狂轰滥炸中幸存下来?如果它们不幸被毁,又会对我们赖以生存的流域造成怎样毁灭性的打击?大型水利设施在全面核战中的生存可能要回答这个问题,我们首先需要了解.............
  • 回答
    好的,我们来聊聊游戏界那些令人闻风丧胆,或是让人充满期待的大型公司、财阀和社团。这些组织往往不仅仅是游戏开发者,它们本身就是游戏世界的一部分,用自己的力量塑造着整个行业的格局。一、 巨头中的巨头:无可撼动的游戏帝国当我们提到游戏行业,有一些名字是绕不开的。它们如同巨兽般盘踞在行业顶端,拥有庞大的资源.............
  • 回答
    在现代战争的背景下,设想通过空降方式直接夺取敌方大型水面舰只(尤其是像航空母舰这样的巨舰)的控制权,这无疑是一个极具挑战性且充满科幻色彩的设想。从现实军事操作的视角来看,其可行性可以说是微乎其微,甚至可以讲接近于零。但我们可以尝试剖析一下其中的难点和可能存在的极端设想,尽力还原一个真实的军事分析。首.............
  • 回答
    大型药企招聘董秘,要求年龄在20岁以下?这事儿,怎么说呢,听着就让人觉得挺……稀奇的。咱们得好好掰扯掰扯,这到底是怎么个情况,以及为什么会有人这么想。这要求合理吗?直接说,很不合理,甚至可以说荒谬。为什么这么说?我们得从“董秘”这个职位本身,以及“大型药企”的属性来看。 董秘(董事会秘书)是什么.............
  • 回答
    解放战争中,国民党军队在正面战场上屡屡败给中共野战军,这确实是一个令人费解的现象,尤其考虑到其中许多国军将领曾是抗日名将,身经百战。这背后绝非简单的“谁更英勇”就能解释,而是涉及一系列复杂的因素,从战略、战术到政治、经济、人心向背,环环相扣,最终导致了这场军事上的巨大落差。一、 战略层面的失误与僵化.............
  • 回答
    这个问题很有意思,也很真实。确实,在很多大型历史策略游戏里,你会发现扮演一个专制君主往往比扮演一个民主国家的领导人要顺畅得多,也更容易获得“优势”。这背后其实有很多原因,咱们就来掰开了揉碎了聊聊。首先,得从游戏的设计逻辑和核心玩法说起。很多历史策略游戏的核心乐趣在于“掌控一切”和“达成宏大目标”。无.............
  • 回答
    现在像中交、省院这样的大型设计院之所以大力投入科研项目,可不是一时兴起,而是多方面因素共同作用下的战略选择,并且这已经成为行业内普遍趋势。咱们不妨从几个关键点来掰开了讲讲。一、生存与发展的内在驱动:从“跟着做”到“引领者”的转变过去很多大型设计院,尤其是像中交这类有国家背景的,主要承担的是国家重大工.............
  • 回答
    嗯,这是一个很有趣的问题,尤其是在考虑我们现在的能力时。要回答“我们能不能对付哥斯拉这种级别的大家伙”,得先拆解一下这到底是个什么级别的挑战。首先,我们得明确“哥斯拉”到底是个什么概念。在不同的电影里,哥斯拉的体型、力量、甚至能力都有所不同,但普遍来说,它是一个体型堪比摩天大楼,能够轻松摧毁城市,拥.............

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有