Flash务实主义七——构建易维护的程序:高效修改

一般程序开发完成后就进入了繁琐无趣的后期维护阶段,请不要以为一个不停更新的项目后期维护是一件轻松的事情,它会暴露出开发过程中的所有硬伤,不规范的写法、混乱的逻辑结构、高耦合导致地牵一发而动全身。虽然开发内容实际上减少了,但人力成本反而更高。

要提高这方面效率有很多技巧,本文介绍的内容只是起点--如何快速找到项目中需要修改的代码。

一般出现问题首先看到得是表现部分,例如对话框,关系到一些具体逻辑或某个服务端请求,即使不是很清晰的部分也一定有临近的区域。根据表现找到其对应代码,我将其称为定位。

搜索关键字:泛用但低效

搜索关键字是广泛使用的方法。例如,你在节目上看到某个图片,找到图片标志,在所有代码中搜索图片标志,一定可以找到调用这个图片的代码。再如,屏 幕中显示的文本,也能找到对应的语言包标识,找到相关代码。然而,这种做法效率很低,因为你要找到标识的具体拼写,搜索项目代码查找关键字也需要时间。所 以下面主要介绍如何不借助搜索直接找到目标代码。

包结构

类一般可以从两个维度分类,一个维度是结构类别,如模型、视图、控制器,甚至工具类、组件,另外一个维度是业务类别,如商店、人物、战斗等各种不同模块。

目录里的文件只有一个根,类似单继承,所以你只能用一个分类做为大类别。一般情况都是用结构类别做为大类别,因为结构类别一般是固定不变地,而业务类别可能会经常变化。例如下图所示情况:

这样做是为了避免大量类混杂在一起,只有分到不同目录才能彻底解决这个问题(目录可折叠,必要时子目录或文件命名可重复)。开发模块时,只需展开关心的目录,避免其他文件干扰。

文件命名

推荐文件名根据结构类别做前缀,如视图以UI开头、后台请求以Rpc开头等。如果没有前缀,命名时很容易遇到重复的情况。再以业务类型设定第二个前缀,使得没有目录时,按字母排序时同一系统中的类被排到一起,当然也可以防止重名。

恰当的命名会在利用代码提示引入类时提供便利,而且在打开类(ctrl+shift+T)对话框里也比较容易找到需要的类。当然,主要还是在查看包资源时,列表会比较整齐,方便找到特定文件。

以上是为了帮助你在知道类的功能和类别却不确定具体命名时使用的,你可能不记得具体名字,但应该可以判断出它所在的包,但仅仅这样是不够的。

逻辑分离是前提

逻辑要按一定规则分开到不同类中,否则你的查找目标本身就不存在。

MVC是实现逻辑分离的方法之一。根据MVC思想将类分开,你就会很清楚知道,与用户交互、显示有关的类是在视图中,与数据格式转换、获取特定数据 (诸如获得图标实例)、判断(诸如isPropTask()之类)、修改数据逻辑(诸如修改经验值触发升级)是在模型中,而制定特定服务器请求、设置模型 数据、引起数个视图更新的代码一定是在服务器请求类的result中。这样就能确定目标位置,即使不能确定具体某个类,也能界定到某个包范围内。

当然这是需要事先约定的,但只要开发者理解并遵守这个约定,就可以做到不依赖搜索关键字也能立即找到需要修改的代码。毫无疑问这种做法是值得的。

从视图着手

视图是最容易找到的部分,然后根据交互事件模拟用户操作过程,通过调用关系一层层查找,最后就能找到需要的部分。

无论你的代码结构如何,这种方法都是通用可行的。如果你的目标就是视图,需要修改的是诸如布局、颜色、数据填充逻辑,这样做就可以了。但如果你的目标不是视图,这并不是最好的办法,因为毕竟需要从视图一层层中转,会多几个步骤而不是直接找到,这自然影响效率。

模型

模型不只是数据。

很多人不明白为什么要在数据之外套一层模型。代码放哪里比较好要以可复用性做为标准,放在模型里的逻辑应该是和数据密切交流的,最基本的是数据序列 化和反序列化。这些内容不少人认为应该写在请求完成函数里,而实际应该写在模型中,因为同一个模型可能会由不同请求生成,它们传入的数据格式是一样的,只 有在模型中解析才能重复利用这段功能代码。

此外模型还需要负责和数据相关的逻辑,以某个RPG游戏为例:

  • 人物属性变化:包括金钱变化(钱不够会失败并提示充值),经验变化(可能需要升级),还有数据更新后对应视图更新;
  • 道具管理:增加/删除道具,获得道具数量,判断道具满;
  • 计算:诸如保存地图模型可以提供计算A*的方法;

上述逻辑是针对游戏玩家的,只会存在一个模型,数据模型是固定的,所以无论放在哪里只要集中都容易查找,但显然放在模型里最好理解,而且这样即使出现多角色需求,需要修改的地方也很少。

模型通常也会提供一些简单的数据转换方法,例如:

  • 获得图标,类似的方法有获取格式化文本、获得ToolTip信息等;
  • 校验,一般一组条件的与 或关系或者大于 等于 小于判断,也可能有循环遍历数据进行统计等复杂表达式;

如果按照约定编码,将这些逻辑存放在模型中,这样就不能通过视图快速找到代码,但模型数量少、逻辑少,会比放在视图里找快很多。你也可以用查找引用方法找到调用模型方法的代码片段,以确定这个逻辑的入口,方便逆向追踪。这样只需修改一处,所有相关部分都会发生变化。

命令(Command/Action)

所谓命令,其实很大一部分都是用来请求服务端数据的,设计中有result方法可以在返回结果后处理一些事情,例如整理数据格式、设置模型、调用视图更新方法。虽然很多人将这些功能发明放在视图中,但显然放在Command里重用率更高且更易于定位。

服务端返回的数据会经常变换,虽然具体解析是在模型中完成,但返回的数据常常是多个数据拼凑在一起,可能是数组或者一些简单数据类型,这部分可以有 Command处理,做特殊解析并给相关模型赋值。由于这部分需要与服务端沟通,是容易出错的地方,放在Command里容易找到,修改时也可以省去不少 麻烦。

命令除了给模型赋值,也还会有一些触发操作。如果确定某个逻辑是请求返回一定执行的也可以放在这里。例如更新视图、触发附加逻辑、首次购买某物品的弹窗。这部分常发生变化,放在Command执行也易于调整。当然Command也可以与服务端请求无关,但道理是一样的。

总而言之,原则是尽可能不要将代码放在视图,而是放在联系更紧且数量少、代码少的一方,这样就能更快找到修改代码位置。Command一般用来调用模型和视图方法,是其他逻辑的入口,自己只有少量代码。

常量类

配置类数据只可能存在于三个地方:服务端,本地配置文件,常量类。

对于服务端数据配置,客户端只单纯接受,本地配置文件一般都保持经常更新的大量数据,所以零散数据配置通常都存在常量类里,例如等级上限、各级经验分配、特定功能花费。

很多开发者都喜欢偷懒,例如一个功能需要花费5元开启,开发者直接在代码里写5。这样看起来算不算神秘数字先不谈,要知道,这种数据即使说绝对不会 变而它未来变化的几率也会超过30%。所以常量是必须有的,哪怕数值是1,也应该写成常量,因为未来可能变成2,在代码里保留数字始终会有隐患。如果你设 置为常量,对于这类内容就可以直接找到常量修改,而不用关心其他部分,也很容易找到使用这个常量的代码片段。如果没有常量的话,就只能借助和这个数值相关 的内容引导并借助关键字搜索以确保修改无遗漏了。

此外,有多版本时配置可能会变化,如果硬编码写死在程序中,需求会很难实现。

其他

这里介绍是以通用MVC为例,因为熟悉的人较多,容易理解。游戏中除用户界面外,结构会更复杂,虽然也有类似模型视图这样的概念,但层次需要分得更 细致。其实这些分离方法都是约定的,既然要分离,就要更合理、更易于理解、更具有可复用性。高效修改首先要容易找到问题症结点,要达到这个目的,就要求代 码结构整理。良好的结构也可以让约定更加简洁,易于记忆和理解。

上述这些内容,框架并不能帮到你,因为框架大多是限制你分成几部分,而没有也无法限定这几部分具体是什么内容。因此你需要刻意地约定,而这个刻意地行为,对于减少修改维护时的人力成本,比框架重要百倍。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


  译序:JWMediaPlayer是开源的网页使用的Flash播放器。本文采摘于JWPlayer的官方文档,讲解了JWPlayer对于RTMP的使用方法,我们可以从JWPlayer客户端的角度来了解RTMP协议。以下是官方原文:      简介    RTMP(RealTimeMessagingProtocol
    Flash编程原理都是只能将1写为0,而不能将0写成1.所以在Flash编程之前,必须将对应的块擦除,而擦除的过程就是将所有位都写为1的过程,块内的所有字节变为0xFF.因此可以说,编程是将相应位写0的过程,而擦除是将相应位写1的过程,两者的执行过程完全相反.一、Nor和NandFlash
 上传setenvgatewayip192.168.1.1;setenvserverip192.168.1.7;setenvipaddr192.168.1.156;mw.b0x820000000xff0x1000000sfprobe0sfread0x8200000000x1000000tftp0x82000000test.bin0x1000000 下载mw.b82000000ff1000000tftp82000000test.bi
Error:FlashDownloadFailed-"Cortex-M3"出现一般有两种情况:1.SWD模式下,Debug菜单中,Reset菜单选项(Autodetect/HWreset/sysresetReq/Vectreset)默认是AutoDetect,改成SysResetReq即可。2.Jtag模式下,主要是芯片大小选错。Flash->ConfigureFalshTools配置窗口,切换到“Utilities"
jPlayer是一个用于控制和播放mp3文件的jQuery插件。它在后台使用Flash来播放mp3文件,前台播放器外观完全可以使用XHML/CSS自定义。支持:有一点比较好的是,在支持html5的浏览器上会使用html5的标签audio或者video,而不支持的浏览器上使用swf来播放选择需要播放的Mp3文件。播放、暂停
#ifndef__FONTUPD_H__#define__FONTUPD_H__#include"sys.h" //字库信息结构体定义33字节__packedtypedefstruct{u8fontok;//字库存在标志,0XAA,字库正常;其他,字库不存在u32ugbkaddr;//unigbk的地址u32ugbksize;//unigbk的大小u32f12addr;//gbk12地址u32g
ROM(ReadOnlyMemory)和RAM(RandomAccessMemory)指的都是半导体存储器。ROM在系统停止供电的时候仍然可以保持数据,而RAM通常都是在掉电之后就丢失数据,但是访问速度快。典型的RAM就是计算机的内存。RAM有两大类,一种称为静态RAM(StaticRAM/SRAM),SRAM速度非常快,是目前读写最快的存储
JSpc端和移动端实现复制到剪贴板功能实现在网页上复制文本到剪切板,一般是使用JS+Flash结合的方法,网上有很多相关文章介绍。随着HTML5技术的发展,Flash已经在很多场合不适用了,甚至被屏蔽。本文介绍的一款JS插件,实现了纯JS方法复制文本到剪切板。插件名是Clipboard.js,该插件不依
例子:R0=1R1=1R2=10R3=e000ed10R12=0LR=fffffff9(中断返回值)PC=0PSR=60000013或60000016或60000036(Z、C、EXCEPT_NUM:RTC_WKUP_IRQn、EXTI0_IRQn、USART2_IRQn)BFAR=e000ed38(不关心)CFSR=20000(INVSTATE:Invalidstateusagefault thePCvaluestackedf
 内存接口概念首先来分析下操作GPIO控制器和操作UART控制器两者的区别如图是S3C2440是个片上系统,有GPIO控制器(接有GPIO管脚),有串口控制器(接有TXDRXD引脚)配置GPIO控制器相应的寄存器,即可让引脚输出高低电平;配置UART控制器相应的寄存器,即可让引脚输出波形。前者相对简单,类
小编导语:    近几年来,网页游戏成为了游戏界关注的焦点,由于其制作简单,成本低并且收益率较高,因此成为了众多游戏厂商追逐的对象,但是除了商家夸张的炒作宣传外,很少有页游佳作出现。然而,随着Unity3D游戏引擎的出现,网页游戏的3D化成了页游冲出重围的杀手锏,那么在flash网页游戏称
1.指定数组到特定的Flash单元#pragmalocation=0x000FFF00 __rootconstcharFlash_config[]={0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0
继续研究发现,计算机的固件真的很有趣。参考了一些重要的资料,比如http://donovan6000.blogspot.com/2013/06/insyde-bios-modding-advanced-and-power-tabs.html等,对于IDA的使用也了解了一些。最后,总结一下目前看来可行性的方案:0.基础知识储备,包括UEFIBIOS的概念,InsydeBIOS的
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>navigator对象<itle></head><body><buttononclick="checkFlash()">检测</button>
修改网上流传的flash-marker.js(function(global,factory){typeofexports==='object'&&typeofmodule!=='undefined'?module.exports=factory():typeofdefine==='function'&&define.amd?define(factory
shareObject本地缓存存储位置:win7系统用户到C:\Users\[你的用户名]\AppData\Roaming\Macromedia\FlashPlayer\#SharedObjects\XP或2003用户到:C:\DocumentsandSettings\用户名\ApplicationData\Macromedia\FlashPlayer\#SharedObjects\ ---------------------作者:iteye_
安装谷歌浏览器之后经常遇到Flash崩溃或者浏览器在浏览Flash内容时卡死的情况。在网上查找资料大多都认为应该是浏览器自带的Flash插件工作模式引起的问题,解决方法如下:首先在地址栏输入chrome://plugins/显示浏览器使用的插件。点击右上角的详细信息,可以看到Flash插件为进程外
之前一直使用的W25Q16spiflash都没问题,换了一款W25Q80后发现工作不正常,经过测试,初步定位到问题在于初始化SPI后是否将CS拉高。于是又去查看了一下原厂代码:发现原厂的代码初始化SPI接口时是专门拉高CS的。结论:网上很多代码初始化SPI接口时没有专门拉高CS,对某些型号可能确实
======================================================NANDFlash最小存储单元:写数据操作:通过对控制闸(ControlGate)施加高电压,然后允许源极(SOURCE)和汲极(RRAIN)间的N信道(N-Channel)流入电子,等到电流够强,电子获得足够能量时,便会越过浮置闸(FloatingGate)底下的二氧化硅层(S
安装CnarioPlayer3.8.1.156或其他版本时,有时会出现如下提示:Warning4154.AdobeFlashPlayer13...notcorrectlyinstalled:请前往AdobeFlash网站,并选择下图示的版本下载安装: