作者NDark (溺於黑暗)
看板GameDesign
标题[程式] 资料驱动设计的比较
时间Wed Sep 5 20:40:11 2012
今天工作不爽.
就来谈一下资料驱动设计(Data-driven Design)好了.
我现在的专案的介面模组就是DDD.
有优点.这点我不会故意忽视.
透过资料档的更动.程式的结果就不同了.我想这是当初设计者使用DDD的原因.
然而,一直看不顺眼的原因我却一直到今天才明了.就是程式写太烂嘛.
设计概念好,实作烂
-就如同洋房的砖块是用沙堆黏起来般-又脆弱又难改,
一戳就破,一改就一连扯下一堆烂木版.
为了避免有人不知道Data-driven是什麽,
我还是要稍微说明一下,顺便连带带出我要比较的各种软体架构模型.
# Data-driven design 资料驱动设计.
系统本身不负责运作,系统本身只负责执行各项由资料端定义而来的反应.
资料端可能是一个xml的档案.定义配置,属性,以及各项事件.
比如说一个按钮按下的时候播放一个声音.
资料端就会这样定义这个按钮的位置,颜色,然後搭配按下的时候要执行的内容.
<Button id...>
<Press>
<PlaySound file=.../>
</Press>
</Button>
程式码可能像这样
ButtonPressed()
{
// trigger_button
switch( trigger_button->Action[j] )
...
case ePlaySound :
PlaySound( ... ) ;
}
当然有好处的不然不会这麽多人推这个做法.
第一个好处就是当我想改变这个按钮的行为的时候我就改xml.
改完再去执行程式,结果当然就不一样了.
要拿掉,新增,改变属性,改变行为都可以由编写xml的人员去独立进行.
这样的设计方式通常会有一小撮精英把底层架好(Engine).
然後由Artist来部署大量的xml.
第二个好处就是xml的可读性不错,编写xml的工人不难教育.
缺点我们等下在一起讲
# hard coded 透过程式码实现逻辑
相反地,把逻辑用程式码实现就叫硬抠.它正好就是DDD所解决的问题.
因为硬写.所以要改的时候要重新编译,再测试,再改再编译.也难怪会有人发明DDD.
程式码可能就像这样
ButtonPressed()
{
// trigger_button
{
PlaySound( ... ) ;
}
}
# script 透过脚本
第三种变形,会使用脚本的原因在DDD我们没有提及.
也就是xml不相容於我们的程式语言(以这里的例子就是c++),当然嘛它就是个"资料".
但是正因为不相容,我们必须写中继的程式,
以xml来说就是 xml parser ,把资料存入执行中的程式里面调用.
xml的规则越复杂, parser就越复杂,废工. 而同时复杂等於容易出错.
所以才有透过脚本的方式来替代(或是部份替代)xml.
脚本语言里面一样可以撰写配置,属性,事件.
相对於写parser,脚本语言的作法依然要写桥接的"介面".
但好处是因为脚本是程式语言,多半可与执行的程式语言有共通之处.
(譬如说可以使用同一组资料结构来传递资讯)
这样就可以少写了parse的部份.
脚本语言就会变这样
Script_Button_i_Pressed()
Script_PlaySound(...)
End
专案程式这里就是
ButtonPressed()
{
// trigger_button
{
run_script( "Script_Button_i_Pressed" )
}
}
# 其他组合型
譬如说flash + c++
由flash负责介面,然後c++负责触发与hard code其他的功能
ButtonPressed()
{
// trigger_button
{
flash_component->run( "ButtonPressed" ) ;
PlaySound( ... )
}
}
这种组合跟hard coded很像,但是又有桥接的部份,
以flash来说他也有action script,但是又不像一般脚本语言这样能够桥接到多功能,
所以说这样的写法跟脚本的作法又有雷同之处.
这边的flash模组就是一笔可活动封装良好的"资料",由flash engineer来制作.
若以象限图来看可以把这四种作法切成这样
Combine | DDD
----------|--------
Hard-Coded| Script
右方是修改的弹性良好
上方是资料端封装良好
最後要说明比较的部份,可能比较多人会跟我看法不同
. DDD:
就如同我开场所述,如果底层"功能"明确,制作完成後就不大改变,那麽就容易大量配置.
但是若底层撰写不良,或是功能陆续增加,就会慢慢发生混乱.
因为在陆续增加功能的情形下,
有可能是xml写错,有可能是parser写错,也有可能是新增的功能项写错.
增加的部份很广泛导致如果不严格控管,容易变成blob般肥大,
模组内部的运作全部混在一起,逻辑混乱.
而DDD的缺点也就会浮现出来,
运作的逻辑不显而易见,
新人(不是最初架构引擎的人)难以维护.
而xml的parse也都为人所诟病,若只parse一次,
改了资料後程式还是要重开,但又不能每个画格都去parse,会浪费很多效能.
这更考验xml的安排切割与最佳化.
. hard coded
其实我对hard coded的看法没有这麽糟糕.
在技术强度不高的团队中,它也并非是一个不可行的办法.
若在 "大架构上有良好的区隔" 的前提下
hard coded显而易见的第一优点就是模组清楚.哪里出错就是哪里的问题.责任相对清楚.
当我们要重构的时候最怕有一半正确,一半错误的模组,
hard coded的优点正来自他的缺点,整个模组抽掉就对了.
. script
script是不错的进阶选择,
可以与程式共用一些模组,可以少写一些程式,
缺点就是脚本语言管理,除错不方便,
要桥接的良好还是需要一点技术能量,
若要自己创script就需要更高一层的技术力.
. 组合型
越是封装越好的模组就就是除错不易.
但是封装的好,也代表污染不会蔓延.
优劣并立.
--
"May the Balance be with U"(愿平衡与你同在)
视窗介面游戏设计教学,讨论,分享。欢迎来信。
视窗程式设计(Windows CLR Form)游戏架构设计(Game Application Framework)
游戏工具设计(Game App. Tool Design )
电脑图学架构及研究(Computer Graphics)
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 1.164.51.135
※ 编辑: NDark 来自: 1.164.51.135 (09/05 20:40)
※ 编辑: NDark 来自: 1.164.51.135 (09/05 20:40)
1F:推 osanaosana:推...原来我曾经实作过DDD 09/05 21:40
2F:→ VVll:刚写完这东西 在ios上吃json的client 09/05 21:44
3F:推 GALINE:对*玩家*来说 Data Driven 还有 moddable 的好处 09/05 21:45
4F:→ GALINE:写死的话玩家只能改改贴图让女角裸体,完全 data driven 09/05 21:47
5F:→ GALINE:奇怪的游戏了 09/05 21:47
6F:→ NDark:然而,moddable的前提在於第一版的好玩. 09/05 23:16
7F:→ NDark:至少要吸引到第一批志愿者,才有後续的mod出现. 09/05 23:16
8F:→ NDark:如果在还没确定第一版就好玩的情形下就执着扩充性, 09/05 23:17
9F:→ NDark:风险是很大的. 09/05 23:17
10F:推 damody:快来写 lua 可惜不原生支援 unicode 09/05 23:18
11F:推 asoedarren:js渐渐变成script的主流 09/05 23:26
12F:推 lf21201:感觉很酷! 请问有没有关於DDD的实作范例@_@ 09/06 00:23
13F:推 Bencrie:Data Driven 的话想推 1997 的 Total Annihilation 09/06 09:20
14F:→ Bencrie:到现在还有人在做 mod,花样比原作还丰富 XD 09/06 09:21