脚本语言,维基百科上定义为,“为了缩短传统的编写—编译—链接—运行过程而创建的计算机编程语言。通常具有简单、易学、易用的特色,目的就是希望开发者以简单的方式快速完成某些复杂程序的编写工作”。
若照此说明返观目前琳琅满目的计算机语言,甚至可说当今天下三分,脚本语言既已占其二矣。复杂如Java、C#,普通如Ruby、Python,简单如Javascript、Lua之类,都是我们日有所闻,时有关心,往往所用的编程利器。之所以称其为利器,正是因为它们大都已独当一面,完全可以使用它们直接编写出完整功能的软件。而且脚本语言对开发者的素质要求并不高,开发过程也呈现短平快的趋势,版本迭代周期逐步缩短,前几年流行起来的极限编程也是借了这股东风才得以可能啊。就市场现状来看,使用脚本语言开发也是事实,若无必要软件公司绝不接触系统语言。
所以说目前市场上有所耳闻的系统语言,也不过诸如C、C++、Obj-C、Fortran和Pascal等寥寥数个,使用它们的开发者算是稀缺资源了,使用它们的公司可以说是大型高端企业了(似乎随着iOS平台的发展又有所反弹)。我甚至敢说有一辈子没碰过系统语言的开发者。
有上述说明也可以看出,系统语言与脚本语言最大区别就是,前者往往是直接生成可执行文件,具有对计算机系统良好的操作与驾驭能力,以及优秀的执行效率;后者则在附加的抽象机器层运行,屏蔽了对计算机系统的直接掌控特性,正因此也造成执行效率相对低下。
换而言之,(由于理论上都是基于图灵机或其等价模型)脚本语言能办到的事儿,系统语言肯定办得到;相反,系统语言能办到的事儿,脚本语言就算能勉强完成,其执行效率也可谓相差甚远。比如操作系统、编译系统之类系统软件,基本上都是会选择系统语言作为开发工具。当然也不排除使用脚本语言编写的,不过这也只能算是娱乐性的奇葩了,没哪位大侠会去用吧。
实际上,我们不是非得分出个青红皂白才肯罢休,系统语言与脚本语言各有其优势,扬长避短,求同存异才是我们应有的态度。这也是为什么我看好游戏编程的缘故,它不但完美融合了文学、绘画和音乐等多种艺术形式,而且技术层面的应用也恰到好处。从游戏编程中,我们至少可以学到一点,即区分主应用程序(游戏引擎)与模块应用程序(游戏内容)。也就是说我们将采用系统语言开发变化度不大的核心逻辑模块,而使用脚本语言开发经常变化的一些杂七杂八的模块,最终集成二者,或者说脚本嵌入主应用程序。
可是,这种方法并不是什么新奇玩意儿。因为我们可以使用动态连接模块,随便安装个大中型软件,看见一对.dll很正常吧。他们就是一些系统语言程序段,被编译成本地机器码,在主程序运行时链接装载。其执行效率和主程序是一样,而且能够达到上述模块化的目的,这不是我们梦寐以求的银弹吗?
那么,为什么我们硬是要在系统语言编程中嵌入脚本?为什么我们非得选择一个效率低下的解决方案呢?仅仅因为系统语言开发困难就冷落了它吗?这也未免太对不起马克思了吧。脚本语言的兴盛自然有对其内在的需求,原因大致无外乎以下几个:
1. 降低开发门槛,提高开发效率:
系统语言开发的困难度是勿需废话的。正所谓成也萧何,败也萧何,对硬件的操作能力,也致使开发者不得不关注机器底层,若不是科班出身,确实很难炉火纯青地应用它们,就算是科班出身也不见得会很熟练。总之就是很难得有人能发挥系统语言的真正实力。
况且,对于一般应用软件的开发,不需要多么地驾驭硬件,也就不需要系统语言中那些难以掌握的特性,使用系统语言无异于杀鸡用牛刀。
进一步说,对于软件公司的开发,软件的执行效率远不如开发效率重要,节约一分钟,赚进一万元呐。免去了那些繁杂的特性自然可以更加轻松地编程,甚至让压根没学过编程的人都可以快速部署开发,随时增加人手,而不会搅乱整个项目。所以越多采用脚本语言,越能让财源滚滚来,何乐而不为呢?
2. 增强开发的灵活性,更新的便捷性:
许多应用软件的功能和需求会随着项目的进展时刻变化,这可以说这是项目开发的常态。虽然提出什么开发前认真商量,多番询问,对需求弄得清清楚楚之类的要求。不过,计划总是赶不上变化啊,我们不得不经常修改已完成模块中的许多东西。
如果直接硬编码,在主程序中写死这些东西,即使是微不足道的一些修改也不得不完全重新编译整个工程。这在项目非常小时倒还可以接受;若是源文件就有几十上百兆,那可就等得蛋疼了。尤其是机子性能受限的话,还可能死机,一切付之东流矣。即便是采用链接库,仍然需要重新编译那个模块,然后重新链接加载,这也是很麻烦的。
更加值得期待的就是,现在许多应用软件都会在官网上发布先行版或体验版。它们只有完全版的部分功能,待到用户购买之后,再将其他部分以补丁的形式发放给用户。如果使用动态链接,用户不得不显式下载补丁包,然后安装链接半天,可能还遇到由于配置文件错误之类而失败回滚!相反,脚本可以直接利用后台网络隐式传输到目标机器后就可运行,或者下载补丁包后直接解压就OK。这样,开发者也可以随时解决Bug,增加新功能。(主程序更新那是大手术了,我就不说了)
3. 减小与主程序的耦合度:
人非圣贤,使用系统语言开发犯错是常事儿了,往往这些错误还很隐晦,查错与调试时极其痛苦。甚至在浪费了大量时间后,最终发现只是某个字符打错了。而且,就是这样一些微不足道的Bug还可能就直接Cut掉整个进程,这对于用户而言是一个悲剧啊,想想蓝屏吓死了多少老年人吧。
如果某个模块经常被更改,犯错的概率就更大了。别忘了,之所以模块化就是因为经常需要改动哟。因此我们需要减小这些模块与不会经常修改的主程序的耦合度,从而尽可能保证软件的稳定性。如果采用动态链接库,实际上其耦合度在运行时并没有多么显著地降低,因为始终是链接成为一个整体,在本机上运行,一出错照样Cut,绝不怠慢。
相反,脚本语言是运行在解释器或虚拟机中,隔离了真实机器(所谓真实还是个硬件抽象层)。并且,它们往往都有异常处理的功能,能够很容易地捕捉到脚本运行的异常情况,并做出相应的处理,使软件运行不会因为一些小Bug而立刻崩溃。
4. 增强代码复用性:
正如Java的广告“一次编译,四处运行”,这可以说也是我们梦寐以求的特性,节省了大量的精力与体力。系统语言也说可移植性良好,不过那顶多做到源文件复用,而脚本语言完全能做到可执行文件复用。
这样我们在开发不同平台的不同版本时,就不需要重新编译源文件了。更有甚者,不需要因为不同平台对库的支持不同(比如DirectX与OpenGL),而进行大刀阔斧地开刀了。
不但如此,这个项目所编写的脚本甚至可以在其他项目里直接使用,仅仅只需复制粘贴那样的直接使用,根本不需要区分什么SDK与运行时了。
5. 阻碍用户做逆向工程:
系统语言直接编译连接成可执行文件在本机上运行,就一定能够得知其运行逻辑,没有什么软件不能破解的。但是脚本语言往往被编译成字节码,而且还经过特殊的编码,至少没有现成的反编译工具可以使用。就算利用某些调试工具观察时,也不过是看见在虚拟机或解释器中的运行情况。这样就大大加大了阅读难度,不过完全安全是不可能的,想破解总可以破解啊。
上述5点,归根结底就是脚本语言通过增加了一个运行抽象层,而减少了本地运行的一系列繁琐过程,增强了可执行文件的可移植与安全性。由此可见,采用脚本语言来辅助系统语言进行开发的好处是几乎可以抵消掉其坏处的,也带来了许多方便,选择脚本语言开发是一桩划算的买卖。
本文地址:http://www.nowamagic.net/librarys/veda/detail/1654,欢迎访问原出处。