CWDG论坛-专业魔兽插件's Archiver

simonw 发表于 2007-7-5 20:33

Eva Framework 编程最佳实践

[size=3][color=#000000][font=Calibri]作者: [url=http://simonw.cnblogs.com/]simonw[/url]  From [url=http://cwowaddon.com]CWDG[/url]  [/font][/color][/size][font=Calibri][size=3][color=#000000]转载请注明出处.[/color][/size][/font]
[font=Calibri][size=3][color=#000000][/color][/size][/font]
[size=3][color=#000000][font=Calibri]Eva Framework [/font][font=宋体]可以把他理解为[/font][font=Calibri]WoW[/font][font=宋体]插件开发中的[/font][font=Calibri]MVC[/font][font=宋体]框架或者更简单的说使用了[/font][font=Calibri]Façade[/font][font=宋体]模式统一了一系列触发行为与执行过程的聚合物[/font][font=Calibri]. [/font][font=宋体]那么究竟统一了哪些呢[/font][font=Calibri]?[/font][/color][/size]
[font=Calibri][size=3][color=#000000][/color][/size][/font]
[font=Calibri][size=3][color=#000000][quote][/color][/size][/font]
[size=3][color=#000000][font=宋体]程序的触发行为在[/font][font=Calibri]WoW[/font][font=宋体]中总共分为[/font][font=Calibri]5[/font][font=宋体]种[/font][font=Calibri]([/font][font=宋体]目前[/font][font=Calibri]4,5[/font][font=宋体]未实现[/font][font=Calibri])[/font][/color][/size]
[color=#000000][font=Calibri][font=Calibri][size=3][color=#000000][font=Calibri][font=Calibri][size=3]1.[/size][/font][/font][font=宋体][size=3]系统事件[/size][/font][/color]
[color=#000000][font=Calibri][font=Calibri][size=3]2.[/size][/font][/font][font=宋体][size=3]窗体事件[/size][/font][/color]
[color=#000000][font=Calibri][font=Calibri][size=3]3.[/size][/font][/font][font=Calibri][size=3]Slashcommand[/size][/font][/color]
[color=#000000][font=Calibri][font=Calibri][size=3]4.[/size][/font][/font][font=宋体][size=3]按键绑定[/size][/font][/color]
[color=#000000][font=Calibri][font=Calibri][size=3]5.[/size][/font][/font][font=宋体][size=3]宏[/size][/font][/color][size=3][color=#000000]
[/color][/size][/quote][/size][/font][/font][/color]
[size=3][color=#000000][font=宋体]面对各种不同的触发方式我们在编写插件的时候往往很容易与业务模块混杂在一起[/font][font=Calibri], [/font][font=宋体]这部分称之为[/font][font=Calibri]UI[/font][font=宋体]控制逻辑[/font][font=Calibri]. [/font][font=宋体]混杂的结果就会造成代码不易阅读不易维护和复用[/font][font=Calibri]. Eva Framework[/font][font=宋体]实现了一个[/font][font=Calibri]controller[/font][font=宋体]来负责分发各种不同的请求[/font][font=Calibri], [/font][font=宋体]这样达到使业务模块与[/font][font=Calibri]UI[/font][font=宋体]部分分离从而既能够达到快速开发的目的又能使你的代码复用性提高很多[/font][font=Calibri].[/font][/color][/size]
[font=Calibri][size=3][color=#000000][/color][/size][/font]
[size=3][color=#000000][font=宋体]在[/font][font=Calibri]Eva Framework[/font][font=宋体]包含一个统一的命令执行引擎[/font][font=Calibri], [/font][font=宋体]从[/font][font=Calibri]Façade[/font][font=宋体]接收到的请求被分发到不同的[/font][font=Calibri]Handler[/font][font=宋体]之后最后都统一交给命令执行引擎来执行[/font][font=Calibri], [/font][font=宋体]这个命令执行引擎最大化的利用了[/font][font=Calibri]WoW[/font][font=宋体]的执行能力从而可以在非安全相关的动作中实现复杂的延时[/font][font=Calibri],[/font][font=宋体]挂起[/font][font=Calibri],[/font][font=宋体]甚至多线程[/font][font=Calibri].[/font][/color][/size]
[size=3][color=#000000][font=宋体]注[/font][font=Calibri]: [/font][font=宋体]多线程[/font][font=Calibri], [/font][font=宋体]这里并不是只传统意义上的多线程[/font][font=Calibri], [/font][font=宋体]他同时包含多进程的概念[/font][font=Calibri]. [/font][font=宋体]具体行为是[/font][font=Calibri], [/font][font=宋体]他们并不是共同处理一项任务[/font][font=Calibri], [/font][font=宋体]而是并行处理多个同样的任务[/font][font=Calibri], [/font][font=宋体]但他们共享一个数据空间[/font][font=Calibri], [/font][font=宋体]自己保存自己独立的上下文[/font][font=Calibri], [/font][font=宋体]互相之间可以通讯[/font][font=Calibri].[/font][/color][/size]
[font=Calibri][size=3][color=#000000][/color][/size][/font]
[size=3][color=#000000][font=宋体]为了有个更未感性的认识[/font][font=Calibri], [/font][font=宋体]看看如果具体开始[/font][font=Calibri]. [/font][font=宋体]这里以[/font][font=Calibri][url=http://http//bbs.cwowaddon.com/thread-689-1-1.html]ShortStory[/url][/font][font=宋体]为例[/font][font=Calibri], [/font][font=宋体]这是一个根据不同的用户文字输入来实现不同的文字内容点播的插件[/font][font=Calibri], [/font][font=宋体]除去注释只有不到[/font][font=Calibri]200[/font][font=宋体]行的代码[/font][font=Calibri], [/font][font=宋体]也许你不敢相信如此少的代码竟能实现如此强大的功能[/font][font=Calibri]([/font][font=宋体]夸大了[/font][font=Calibri],[/font][font=宋体]呵呵[/font][font=Calibri], [/font][font=宋体]别扁我[/font][font=Calibri], [/font][font=宋体]如同[/font][font=Calibri]SUN[/font][font=宋体]和[/font][font=Calibri]MS[/font][font=宋体]都在夸大自己平台下的[/font][font=Calibri]PetShop).[/font][/color][/size]
[font=Calibri][size=3][color=#000000][/color][/size][/font]
[size=3][color=#000000][font=宋体][font=Calibri][quote] [/font]文件结构[/font][font=Calibri]:[/font][/color][/size][font=Calibri][size=3][color=#000000] [/color][/size][/font]
[font=Calibri][size=3][color=#000000][font=Calibri][size=3][color=#000000]ShortStory.toc[/color][/size][/font]
[font=Calibri][size=3][color=#000000]ShortStory.lua[/color][/size][/font]
[font=Calibri][size=3][color=#000000]ShortStoryEntry.lua[/color][/size][/font]
[font=Calibri][size=3][color=#000000]ShortStoryConfig.lua[/color][/size][/font]
[/quote][/color][/size][/font][font=Calibri][size=3][color=#000000] [/color][/size][/font]
[size=3][color=#000000][font=宋体][font=Calibri][quote][/font]层次化结构的插件开发[/font][font=Calibri], [/font][font=宋体]由高至底[/font][font=Calibri].[/font][/color][/size]
[color=#000000][font=Calibri][font=Calibri][size=3][color=#000000][font=Calibri][font=Calibri][size=3]1.[/size][/font][/font][font=Calibri][size=3]UI[/size][/font][font=宋体][size=3]层([/size][/font][/color][size=3][color=#000000][font=宋体]这个示例中没有[/font][font=Calibri], [/font][font=宋体]一般是[/font][font=Calibri]XML[/font][font=宋体]界面)[/font][/color][/size]
[color=#000000][font=Calibri][font=Calibri][size=3]2.[/size][/font][/font][font=Calibri][size=3]UI[/size][/font][font=宋体][size=3]控制逻辑层[/size][/font][/color]
[color=#000000][font=Calibri][font=Calibri][size=3]3.[/size][/font][/font][font=Calibri][size=3]Service[/size][/font][font=宋体][size=3]层[/size][/font][/color]
[color=#000000][font=Calibri][font=Calibri][size=3]4.[/size][/font][/font][font=宋体][size=3]业务层[/size][/font][/color][/size][/font][/font][/color]
[font=Calibri][size=3][color=#000000]这里只有上层依赖下层, 切忌不同层次间互相引用, 这样造成的耦合会带来很多困扰.[/color][/size][/font]
[font=Calibri][size=3][color=#000000][/quote][/color][/size][/font]
[font=Calibri][size=3][color=#000000][/color][/size][/font]
[font=Calibri][size=3][color=#000000]提示: 引入行如命名空间的方式, 保持尽量少的全局变量的声明. [/color][/size][/font]
[quote]
[font=Fixedsys]ShortStory = {
[color=#000000]Scheduler = {}[/color]
[color=#000000]}[/color][/font]
[/quote]


[font=Calibri][size=3][color=#000000][b]UI[font=宋体][size=3]控制逻辑层[/size][/font][/b][/color][/size][/font]
[size=3][color=#000000][font=宋体]在[/font][font=Calibri]ShortStoryEntry.lua[/font][font=宋体]中[/font][font=Calibri],[/font][font=宋体]响应各种请求[/font][font=Calibri],[/font][font=宋体]这里就是各种[/font][font=Calibri]block[/font][font=宋体]配置对象,他们负责监听来自UI的请求后传递给相应的Service层对应函数[/font][font=Calibri].[/font][/color][/size]

[font=Calibri][size=3][color=#000000][/color][/size][/font][quote]
[font=Fixedsys][color=#008000]--创建并初始化插件[/color]
[color=#0000ff]local [/color][color=#000000]ShortStoryAddon = EVA.Addon:New()[/color]
[color=#008000]--设置插件相关描述[/color]
[color=#000000]ShortStoryAddon.Name = [/color][color=#ff00ff]"ShortStory"[/color]
[color=#000000]ShortStoryAddon.Version = [/color][color=#ff00ff]"1.3"[/color]
[color=#000000]ShortStoryAddon.Description = [/color][color=#ff00ff]"auto play story. By simonw. URL[[url=http://wiki.cwowaddon.com/]http://wiki.cwowaddon.com/[/url]]"[/color]
[color=#008000]--将插件添加到插件注册表中[/color]
[color=#000000]EVA.AddonRegistry:Add(ShortStoryAddon)[/color]

[color=#0000ff]local [/color][color=#000000]Scheduler = ShortStory.Scheduler[/color]

[color=#008000]--创建功能集[/color]

[color=#0000ff]local [/color][color=#000000]initBlock = {[/color]
        [color=#000000]Name = [/color][color=#ff00ff]"Init Block"[/color][color=#000000],[/color]
        [color=#000000]Description = [/color][color=#ff00ff]"Init story"[/color][color=#000000],[/color]
        [color=#000000]RequestTypes = {[/color][color=#ff00ff]"Event"[/color][color=#000000]},[/color]
        [color=#000000]Events = {[/color][color=#ff00ff]"PLAYER_LOGIN"[/color][color=#000000]},[/color]
        [color=#000000]Enabled = [/color][color=#800080]1[/color][color=#000000],[/color]
        [color=#000000]Commands = {[/color]
                [color=#000000]{Description = [/color][color=#ff00ff]"Init story"[/color][color=#000000], Function = Scheduler.Init},[/color]
        [color=#000000]}[/color]
[color=#000000]}[/color]

[color=#0000ff]local [/color][color=#000000]playBlock = {[/color]
        [color=#000000]Name = [/color][color=#ff00ff]"Play Block"[/color][color=#000000],[/color]
        [color=#000000]Description = [/color][color=#ff00ff]"Display story"[/color][color=#000000],[/color]
        [color=#000000]RequestTypes = {[/color][color=#ff00ff]"EventChatCommand"[/color][color=#000000]},[/color]
        [color=#000000]Events = {[/color][color=#ff00ff]"CHAT_MSG_WHISPER"[/color][color=#000000],[/color][color=#ff00ff]"CHAT_MSG_RAID"[/color][color=#000000],[/color][color=#ff00ff]"CHAT_MSG_SAY"[/color][color=#000000],[/color][color=#ff00ff]"CHAT_MSG_PARTY"[/color][color=#000000]},[/color]
        [color=#000000]Permission = {AllowList = {[/color][color=#ff00ff]"&Player"[/color][color=#000000], [/color][color=#ff00ff]"&Friend"[/color][color=#000000], [/color][color=#ff00ff]"&Everyone"[/color][color=#000000]}},[/color]
        [color=#000000]Enabled = [/color][color=#800080]1[/color][color=#000000],[/color]
        [color=#000000]Commands = {[/color]
                [color=#000000]ChatCommand = [/color][color=#ff00ff]"list"[/color][color=#000000],[/color]
                [color=#000000]{Description = [/color][color=#ff00ff]"get process"[/color][color=#000000], Function = [/color][color=#0000ff]function[/color][color=#000000](context) ShortStory.Context = context [/color][color=#0000ff]end[/color][color=#000000]},[/color]
                [color=#000000]{Description = [/color][color=#ff00ff]"show start info"[/color][color=#000000], Function = Scheduler.PlayTip},[/color]
                [color=#000000]{Description = [/color][color=#ff00ff]"show story content"[/color][color=#000000], Function = Scheduler.PlayStory, Timer = {Interval = [/color][color=#800080]2[/color][color=#000000], Times = -[/color][color=#800080]1[/color][color=#000000]}},[/color]
        [color=#000000]}[/color]
[color=#000000]}[/color][/font]
[font=Fixedsys][color=#000000][/color][/font]
[font=Fixedsys][color=#000000].......................[/color]

[color=#008000]--将功能集合添加到插件中[/color]
[color=#000000]ShortStoryAddon:Add(EVA.Block:New(initBlock))[/color]
[color=#000000]ShortStoryAddon:Add(EVA.Block:New(playBlock))[/color]
[color=#000000]ShortStoryAddon:Add(EVA.Block:New(stopBlock))[/color]
[color=#000000]ShortStoryAddon:Add(EVA.Block:New(listBlock))[/color]
[/font][/quote]


[size=3][color=#000000][b][font=Calibri]Service[/font][font=宋体]层[/font][/b][/color][/size]
[size=3][color=#000000][font=Calibri]ShortStory.lua[/font][font=宋体]中[/font][font=Calibri], Scheduler[/font][font=宋体]部分[/font][font=Calibri],[/font][font=宋体]负责处理来自UI控制逻辑层的请求参数及流程上下文并传入业务对象,他只是简单的包装了业务逻辑需要为用户公开的接口部分, 在这里不应包含具体的业务逻辑.[/font][/color][/size]
[font=宋体][size=3][color=#000000][/color][/size][/font]
[quote]
[font=Fixedsys][color=#008000]--从ShortStory.Words中获取故事标题,插件数据初始化行为[/color]
[color=#0000ff]function [/color][color=#000000]Scheduler.Init()[/color]
        [color=#000000]ShortStory:SetTitles()[/color]
[color=#0000ff]end[/color]
[/font]
[font=Fixedsys]...................[/font]
[font=Fixedsys]
[color=#008000]--打印故事内容[/color]
[color=#0000ff]function [/color][color=#000000]Scheduler.PlayStory(context)[/color]
        [color=#0000ff]if [/color][color=#000000]([/color][color=#0000ff]not [/color][color=#000000]context.itemIndex) [/color][color=#0000ff]then[/color]
                [color=#000000]context.itemIndex = [/color][color=#800080]1[/color]
        [color=#0000ff]end[/color]

        [color=#0000ff]local [/color][color=#000000]result = ShortStory:PlayStory([/color][color=#0000ff]tonumber[/color][color=#000000](context.Event_ChatArgs[[/color][color=#800080]1[/color][color=#000000]]), context.itemIndex)[/color]

        [color=#0000ff]if [/color][color=#000000](result) [/color][color=#0000ff]then[/color]
                [color=#000000]context.itemIndex = context.itemIndex + [/color][color=#800080]1[/color]
        [color=#0000ff]end[/color]
[color=#0000ff]end[/color]

[color=#008000]--故事停止[/color]
[color=#0000ff]function [/color][color=#000000]Scheduler.PlayStop(context)[/color]
        [color=#000000]ShortStory:PlayStop()[/color]
[color=#0000ff]end[/color][/font]
[/quote]


[font=宋体][size=3][color=#000000][b]业务层[/b][/color][/size][/font]
[size=3][color=#000000][font=Calibri]ShortStory.lua[/font][font=宋体]中[/font][font=Calibri], ShortStory[/font][font=宋体]业务模型本身[/font][font=Calibri],[/font][font=宋体]只包含业务逻辑[/font][font=Calibri],[/font][font=宋体]不应包含任何与请求有关代码[/font][font=Calibri].这样你能获得更容易维护和复用的Buff[/font][/color][/size]
[font=Calibri][size=3][color=#000000][/color][/size][/font]
[quote]
[font=Fixedsys][color=#0000ff]function [/color][color=#000000]ShortStory:PlayList()[/color]
        [color=#0000ff]for [/color][color=#000000]index, title [/color][color=#0000ff]in ipairs[/color][color=#000000](self.Titles) [/color][color=#0000ff]do[/color]
                [color=#000000]self:Print(self.Formats[[/color][color=#ff00ff]"Title"[/color][color=#000000]], index, title)[/color]
        [color=#0000ff]end[/color]
[color=#0000ff]end[/color]

[color=#0000ff]function [/color][color=#000000]ShortStory:PlayTip(index, sender)[/color]
        [color=#0000ff]if [/color][color=#000000](index) [/color][color=#0000ff]then[/color]
                [color=#000000]self:Print(self.Formats[[/color][color=#ff00ff]"Tip"[/color][color=#000000]], sender, index)[/color]
        [color=#0000ff]end[/color]
[color=#0000ff]end[/color][/font]
[font=Fixedsys][color=#0000ff][/color]
.............[/font]
[font=Fixedsys]
[color=#0000ff]function [/color][color=#000000]ShortStory:SetTitles()[/color]
        [color=#000000]self.Titles = {}[/color]
        [color=#0000ff]for [/color][color=#000000]index, article [/color][color=#0000ff]in ipairs[/color][color=#000000](self.Words) [/color][color=#0000ff]do[/color]
                [color=#000000]self.Titles[index] = self:GetArticleItem(article, [/color][color=#800080]1[/color][color=#000000])[/color]
        [color=#0000ff]end[/color]
[color=#0000ff]end[/color][/font]
[/quote]

[size=3][font=Calibri][color=#000000]最后你需要注意toc中的载入顺序. 欢迎各位提出各种问题,疑问,建议....无论好坏. 多谢捧场.[/color][/font][/size]
[font=Calibri][size=3][color=#000000][/color][/size][/font]
[font=Calibri][size=3][color=#000000]EVA Framework相关资料:[/color][/size][/font]
[font=Calibri][size=3][color=#000000][url=http://bbs.cwowaddon.com/thread-94-1-1.html][font=Tahoma][size=2]意见征集[/size][/font][/url] [font=Tahoma][size=2][color=#333333][url=http://bbs.cwowaddon.com/thread-698-1-1.html]编程最佳实践[/url][/color][/size][/font][/color][font=Tahoma][size=2][color=#333333] [url=http://bbs.cwowaddon.com/thread-585-1-1.html][font=Calibri][size=3]下载[/size][/font][/url][font=Calibri][size=3][color=#000000] [/color][/size][/font][url=http://wiki.cwowaddon.com/EVA][font=Calibri][size=3]文档[/size][/font][/url][/color][/size][/font][/size][/font]

linsenliunan 发表于 2007-7-11 07:58

EVA是中国出的吗,还有这个时不时跟ACE2一个概念,要不就差不多.

simonw 发表于 2007-7-11 11:05

Eva Framework是由我编写的, 和ACE2的概念及定位完全不同.

heannt 发表于 2007-7-13 17:14

...这不是件容易的事吧......要有团队做才好..

支持下....

chjieni 发表于 2007-9-25 04:29

系统事件是否包括进入战斗和脱离战士?

simonw 发表于 2007-9-25 09:18

具体系统事件与EVA没有关系, wow支持什么EVA就支持什么.

mlongm 发表于 2008-6-6 12:01

刚看到这个 真不错 我喜欢 讨厌该死的LUA难看的样式

页: [1]

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.