What is your famous web programming language?

PHP

PHP(PHP:Hypertext Preprocessor)是一种在计算机上运行的脚本语言,主要是用途在于处理动态网页,也包含了命令行运行接口(command line interface),或者产生图形用户界面(GUI)程序。

PHP 最早由 Rasmus Lerdorf 在1995年发明,而现在PHP的标准由PHP Group和开放源代码社区维护。PHP 以 PHP License 作为许可协议,不过因为这个协议限制了PHP名称的使用,所以和开放源代码许可协议GPL不兼容。

PHP 的应用范围相当广泛,尤其是在网页程序的开发上。一般来说 PHP 大多运行在网页服务器上,通过运行PHP代码来产生用户浏览的网页。PHP 可以在多数的服务器和操作系统上运行,而且使用 PHP 完全是免费的。根据2007年4月的统计数据,PHP 已经被安装在超过2000万个网站和100万台服务器上。

开发历史

PHP 原本的简称为 Personal Home Page,是Rasmus Lerdorf 为了要维护个人网页,而用c语言开发的一些CGI工具程序集,来取代原先使用的 Perl 程序。最初这些工具程序用来显示 Rasmus Lerdorf 的个人履历,以及统计网页流量。他将这些程序和一些窗体解释器集成起来,称为 PHP/FI。PHP/FI 可以和数据库连接,产生简单的动态网页程序。Rasmus Lerdorf 在1995年6月8日将 PHP/FI 公开释出,希望可以通过社区来加速程序开发与查找错误。这个释出的版本命名为 PHP 2,已经有今日 PHP 的一些雏型,像是类似 Perl 的变量命名方式、窗体处理功能、以及嵌入到 HTML 中运行的能力。程序语法上也类似 Perl,有较多的限制,不过更简单、更有弹性。

在1997年,任职于 Technion IIT 公司的两个以色列程序设计师:Zeev Suraski 和 Andi Gutmans,重写了 PHP 的解析器,成为 PHP 3 的基础,而 PHP 也在这个时候改称为PHP: Hypertext Preprocessor.。经过几个月测试,开发团队在1997年11月释出了 PHP/FI 2,随后就开始 PHP 3 的开放测试,最后在1998年6月正式释出 PHP 3。Zeev Suraski 和 Andi Gutmans 在 PHP 3 释出后开始改写 PHP 的内核,这个在1999年释出的解析器称为 Zend Engine,他们也在以色列的 Ramat Gan 成立了 Zend Technologies 来管理 PHP 的开发。

在2000年5月22日,以Zend Engine 1.0为基础的PHP 4正式释出,2004年7月13日则释出了PHP 5,PHP 5则使用了第二代的Zend Engine。PHP包含了许多新特色,像是强化的面向对象功能、引入PDO(PHP Data Objects,一个访问数据库的延伸库)、以及许多效能上的增强。目前PHP 4已经不会继续更新,以鼓励用户转移到PHP 5。

2008年PHP 5成为了PHP唯一维护中的稳定版本。将来的PHP 5.3将会加入Late static binding和一些其他的功能强化。

PHP 6 的开发也正在进行中,主要的改进有移除register_globals、magic quotes 和 Safe mode的功能。

应用

PHP 是一个应用范围很广的语言,特别是在网络程序开发方面。一般来说 PHP 大多在服务器端运行,通过运行 PHP 的代码来产生网页提供浏览器读取,此外也可以用来开发命令行脚本程序和用户端的GUI应用程序。PHP可以在许多的不同种的服务器、操作系统、平台上运行,也可以和许多数据库系统结合。使用 PHP 不需要任何费用,官方组织 PHP Group 提供了完整的程序源代码,允许用户修改、编译、扩充来使用。

语法

PHP的语法参考了Perl、C语言,而且可以集成在HTML之中,以下是一个简单的Hello World程序:

<?php echo 'Hello World!'; ?>

PHP解析引擎只解析<?php到?>之间的代码,而不包含在<?php到?>之间的内容则会直接送出,所以可以用以下的方式来将PHP代码嵌入在HTML之中:

<?php //-PHP程式码 ?>

html内容

<?php //-PHP程式码 ?>

但是在判断语句中的HTML代码并不会被直接送出:

<?php if (false) { ?>

HTML Code

<?php } ?>

PHP可以用三种注解的形式:C与C++所使用的“//”与“//”,和Perl的“#”。

Active Server Pages

动态伺服器网页(Active Server Pages),由微软公司开发的伺服器端执行的指令码平台,它被Windows下Internet Information Services (IIS)的程式所管理。透过ActiveX server 的技术让不同的使用者能有不同的画面,或需要让他们可以存取伺服器 (server)上的资料时,使用ASP3.0中提供了五个内建的物件建立类比和安全性的动态内容,来协助程式设计师隐藏复杂的沟通机制,让程式设计师可以专注在解决问题和应用之上,这样可以更快速地开发动态网页的同时每一个零件都是可以由一组富有经验的程式设计师根据动态网页最常用的功能而独立开发。

五个零件包括:
[list]
[li]Application:在一个 ASP-based application 让不同使用者共享资讯。[/li]
[li]Request:从使用者处理取得资讯[/li]
[li]Response:将资讯送给使用者[/li]
[li]Server:提供一些 Web Server 的工具[/li]
[li]Session:储存在一个 session 内使用者的资讯[/li]
[/list]

ASP 的特色

ASP隐藏了网页伺服器与瀏览者之间沟通的烦琐机制的同时也基於script base的特性,网页撰写员可以专心撰写应用的程式的逻辑部份,再者ASP也像 HTML 般透过撰写程式来即时测试网页是否安全地执行,而不必担心程式和伺服器不能沟通的问题,另外因为那些 script 是於发送前於伺服器中先行转译处理成为HTML后再而发送至代理伺服器边的动态网页技术,不必担心瀏览器的支援性及,网页撰写员的程式逻辑像 client-side script 会被盗用,因此最终瀏览者只会是使用 HTML 来瀏览。
利用ASP程式最常用的是Cookies,它利用Session零件实作的。同时还可以利用第三方零件延伸ASP的作用,如利用MailSender零件发送电子邮件。
透过ASP我们可以结合HTML网页、ASP指令和ActiveX元件建立动态、互动且高效的WEB伺服器应用程式。同时,ASP也支援VBScript和JScript等指令码语言,预设为VBScript。其中JScript是微软公司的ECMAScript标準的实作,并且有自己的扩充套件。

物件的支援

ASP对 COM 的支援会允许撰写员使用 server component(或OLE Automation server)。透过它撰写员可以发展自已的物件,或将把程式转成 Web-base 的介面。

状态 (State) 的管理

状态管理是ASP的重要功能之一,原因为HTTP是一个stateless的协定,当有匿名的 request进入时,瀏览者无法辨认这些的request 是否安全,或那些request 之间的关连性时,便无法透过瀏览者取得资讯如帐户及密码等,对交易特性的 Web 应用程式造成了阻碍。因此ASP透过 cookie的包装和使用让瀏览者可以简单地管理眾多使用者名称的不同状态。
ASP 对的管理更是令人称讚,我们知道,HTTP 本身是一个 stateless 的协定,也就是说对於匿名的 request,你无法分辨这些 request 是属於谁的、或这些 request 之间的关连性,这对发展一个有交易特性的 Web 应用程式实在是个伤脑筋的问题。现在,ASP 透过 cookie 的包装和使用,让你可以简单的管理不同使用者的不同 state。

版本

ASP 目前最新的版本为 3.0,与 Windows 2000 一起发行,并内植於 IIS 5.0 中。
ASP 1.0 内含於 Windows NT 4.0 Service Pack 3 (IIS 3.0) 发行。
ASP 2.0 内含於 Windows NT 4.0 Option Pack,与 IIS 4.0 一起亮相。
自 ASP 3.0 发行后,除了各版本对它的安全性或问题修补外,对主要功能都没有再进一步的更新。 Windows Server 2003 发行的 ASP 也是 3.0 版本。
其后继者 ASP+(即 ASP.NET),已内含於 .NET Framework 中持续演化。

原理

ASP是经过伺服器解析之后再向网页瀏览器返回资料,所以有了ASP就不必担心客户的瀏览器是否能执行你所编写的代码。因为所有的程式都将在网页伺服器端执行,包括所有嵌在普通HTML中的指令码程式。当程式执行完毕后,伺服器仅将执行的结果返回给客户瀏览器,这样也就减轻了客户端瀏览器的负担,大大提高了互动的速度。

由於代码是需要经过伺服器执行之后才向瀏览器发送的,所以在客户端看到的只能是经过解析之后的资料,而无法获得原始码,故编写者不用担心自己的原始码会被别人剽窃。但不排除骇客利用系统漏洞窃取伺服器端的ASP原始码。

基於这样的解析方式,也导致执行ASP页面相对於普通的HTML页面要慢一点。因为普通的HTML页面只需要瀏览器就能够解析,而ASP则必须是伺服器将整页的代码都执行一遍之后再发送资料。

ASP提供与资料库的互动,如Microsoft SQL Server、Microsoft Access、MySQL和Oracle,比较流行的是ASP和Microsoft SQL Server的组合。

ASP.NET

ASP.NET是由微软在.NET Framework中所提供的,开发Web应用程式的类别库,封装在System.Web.dll档案中,显露出System.Web命名空间,并提供ASP.NET网页处理、扩充以及HTTP通道的应用程式与通讯处理等工作,以及Web Service的基础架构。ASP.NET是ASP技术的后继者,但它的发展性要比ASP技术要强大许多。

ASP.NET可以运行在安装了.NET Framework的IIS伺服器上,若要在非微软的平台上执行,则需要使用Mono平台,ASP.NET在2.0版本已经定型,在.NET Framework 3.5上则加上了许多功能,像是ASP.NET AJAX、ASP.NET MVC Framework、ASP.NET Dynamic Data与Microsoft Silverlight的伺服器控制项等。

很多人都把 ASP.NET 当做是一种程式语言,但它实际上只是一个由 .NET Framework 提供的一种开发平台 (development platform),并非程式语言。

发展缘起

ASP.NET的前身ASP技术,是在IIS 2.0上首次推出(Windows NT 3.51),当时与 ADO 1.0 一起推出,在IIS 3.0 (Windows NT 4.0)发扬光大,成为伺服器端应用程式的热门开发工具,微软还特别为它量身打造了Visual InterDev开发工具,在1994年到2000年之间,ASP技术已经成为微软推展Windows NT 4.0平台的关键技术之一,数以万计的ASP网站也是这个时候开始如雨后春笋般的出现在网路上。由於它的简单以及高度客制化的能力,也是它能迅速窜起的原因之一。

不过ASP的缺点也逐渐的浮现出来:
义大利麵型的程式开发方法,让维护的难度提高很多,尤其是大型的ASP应用程式。
直译式的VBScript或JScript语言,让效能有些许的受限。
延展性因为其基础架构扩充性不足而受限,虽然有COM元件可用,但开发一些特殊功能(像档案上传)时,没有来自内建的支援,需要寻求第三方软体商开发的元件。

1997年时,微软开始针对ASP的缺点(尤其是义大利麵型的程式开发方法)準备开始一个新专案来开发,当时ASP.NET的主要领导人Scott Guthrie刚从杜克大学毕业,他和IIS团队的Mark Anders经理一起合作两个月,开发出了下一代ASP技术的原型,这个原型在1997年的圣诞节时被发展出来,并给予一个名称:XSP[2],这个原型產品使用的是Java语言。不过它马上就被纳入当时还在开发中的CLR平台,Scott Guthrie事后也认为将这个技术移植到当时的CLR平台,确实有很大的风险(huge risk),但当时的XSP团队却是以CLR开发应用的第一个团队。

为了将XSP移植到CLR中,XSP团队将XSP的核心程式全部以C#语言重新撰写(在内部的专案代号是 “Project Cool”,但是当时对公开场合是保密的),并且改名为ASP+,作为ASP技术的后继者,并且也会提供一个简单的移转方法给ASP开发人员。ASP+首次的Beta版本以及应用在PDC 2000中亮相,由Bill Gates主讲Keynote(即关键技术的概览),由富士通公司展示使用COBOL语言撰写ASP+应用程式,并且宣布它可以使用Visual Basic.NET、C#、Perl与Python语言(后两者由ActiveState公司开发的互通工具支援)来开发。

在2000年第二季时,微软正式推动.NET策略,ASP+也顺理成章的改名为ASP.NET,经过四年的开发,第一个版本的ASP.NET在2002年1月5日亮相(和.NET Framework 1.0),Scott Guthrie也成为ASP.NET的產品经理(到现在已经开发了数个微软產品,像ASP.NET AJAX和Microsoft Silverlight)。目前最新版本的 ASP.NET 4.0 以及 .NET Framework 4.0 仍在开发中。

ASP.NET处理架构

ASP.NET 运行的架构分为几个阶段:
[list]
[li]在 IIS 与 Web 伺服器中的讯息流动阶段。[/li][li]在 ASP.NET 网页中的讯息分派。[/li][li]在 ASP.NET 网页中的讯息处理。[/li][/list]
Web伺服器的讯息流动阶段

当装载(hosting) ASP.NET 的 Web 伺服器接收到 HTTP 要求时,HTTP 聆听程式 (HTTP Listener) 会将要求转交给 URL 指定的网站应用程式的工作流程 (Worker Process)[3],ASP.NET 的工作流程处理器(aspnet_isapi.dll,若是 IIS 5.0 时则是 aspnet_wp.exe)会解析 URL,并啟动位於 System.Web.Hosting 命名空间中的 ISAPIRuntime(视版本)物件,接收 HTTP 要求,并呼叫 HttpRuntime,执行 HttpRuntime.ProcessRequest(),在 ProcessRequest() 中使用 HttpApplicationFactory 建立新的 HttpApplication(或是指定的 IHttpHandler 处理器),再分派给 Page 中的 ProcessRequest() 或是 IHttpHandler 的 ProcessRequest() 方法,执行之后,再传回到 ISAPIRuntime,以及 aspnet_isapi.dll,最后交由 HTTP Listener 回传给用户端,因为执行程序有如管线般顺畅的执行,因此称为 HTTP Pipeline Mode。

ASP.NET 内部的 HTTP 处理器有:
[list]
[li]ISAPIRuntime:由 aspnet_isapi.dll 呼叫,初始化 HttpWorkerRequest 物件(会由IIS的版本决定要初始化的版本)。[/li][li]HttpRuntime:提供要求佇列 (Request Queue)、呼叫 HttpWorkerRequest 中的 ProcessRequest() 方法,以及后续的处理工作。[/li][li]HttpWorkerRequest:產生 HttpApplication、HttpRequest、HttpResponse 等基础物件的 HTTP 要求物件,并将要求转送到要处理的物件(并呼叫它的 ProcessRequest() 方法)。[/li][li]IHttpHandler 与 IHttpAsyncHandler:负责处理 HTTP 要求的单元,由 ProcessRequest() 来分派与执行要求。[/li]
[/list]

ASP.NET网页中的事件程序

当 HttpWorkerRequest 呼叫 ASP.NET 网页(System.Web.UI 命名空间的 Page 类别)的 Page.ProcessRequest() 方法时,它会依序的引发 Page 内的各个事件,并同时呼叫在 Page 中所有控制项的相关事件,其引发顺序为:
[list]
[li]PreInit 事件:执行预先初始化的工作,在ASP.NET 2.0中,若要动态调整主版页面 (Master Page)、佈景主题 (Theme) 时,要在这个事件中调整。[/li][li]Init 事件:执行初始化工作。[/li][li]InitCompleted 事件:在完成初始化工作后引发。[/li][li]Preload 事件:执行预先载入的工作。[/li][li]Load 事件:执行载入的工作,大多数的网页都拥有 Page_Load 事件处理常式,使用者控制项 (user control) 中也有 Page_Load 事件常式,都会在此时呼叫。[/li][li]控制项的 PostBack 变更通知:当网页侦测到是 PostBack 要求时,会引发 PostBack 讯息通知的事件。[/li][li]控制项的 PostBack 相关事件:当网页侦测到是 PostBack 要求时,会引发 PostBack 讯息指定的控制项的事件。[/li][li]LoadCompleted 事件:执行载入完成后的工作。[/li][li]PreRender 事件:处理在產生 HTML 结果前的工作。[/li][li]SaveStateCompleted 事件:处理页面状态(ViewState 与 ControlState)储存完成后的事件。[/li][li]Render 事件:处理產生 HTML 的工作。[/li][li]Unload 事件:处理结束网页处理时的工作。[/li]
[/list]
如果 HttpWorkerRequest 呼叫的是实作 IHttpHandler 介面的 HTTP 处理常式 时,它只会呼叫 IHttpHandler.ProcessRequest() 方法,由它来处理程式的输出,不像 Page.ProcessRequest() 会处理事件顺序,因此 HTTP Handler 很适合轻量级的资料处理,像是输出档案资料流或是图片资料流等。

ASP.NET的事件模型

ASP.NET 的原始设计构想,就是要让开发人员能够像 VB 开发工具那样,可以使用事件驱动式程式开发模式 (Event-Driven Programming Model) 的方法来开发网页与应用程式,若要以ASP技术来做到这件事的话,用必须要使用大量的辅助资讯,像是查询字串或是表单栏位资料来识别与判断物件的来源、事件流向以及呼叫的函式等等,需要撰写的程式码量相当的多,但 ASP.NET 很巧妙利用表单栏位和JavaScript指令码把事件的传递模型隐藏起来了。

ASP.NET 的事件模型是由 以及数个 Hidden Field 组合而成,基於 HTTP 模型的限制,所有的网页程式在执行结果输出到用户端后,程式就会结束执行,为了维护在 ASP.NET 网页与控制项的状态资料,因此在输出 ASP.NET 控制项时,ASP.NET 会将部份状态资料储存到网页的 Hidden Field 中,这类型的状态资料称为 ViewState(ID 为 __VIEWSTATE),在伺服器端即会被解译出状态与事件资料。在大多数的内建 Web 控制项中都有使用到这个机制,因此在使用大量 ASP.NET Web 控制项的网页中,会有许多的 ViewState 会存放在网页中并随著 HTTP 资料流输出到用户端,ViewState 在输出时,会被加密为一组乱码字串,其金钥值定义在电脑中,并且每一个物件都会被序列化 (serialize) 成字串(因此若是自订物件要放到 ViewState 时,则应要让它支援序列化),再输出到 __VIEWSTATE 栏位中,在每次的网页来回时都会被传输,较大的 ViewState 会让网页大小膨胀,不利於快速的网路传输,不过 ASP.NET 本身有提供将 ViewState 关闭的功能,因此如果控制项不需要状态保存时,可将它关闭以减少输出的大小。

为确保控制项的事件能够确实被引发,让事件驱动能够被执行,因此控制项事件引发命令时需要的参数,是交由 JavaScript 指令码在用户端引发时,填入另一个 Hidden Field(ID 为 __EVENTTARGET 以及 __EVENTARGUMENT),并且引发表单的送出指示 (submit),传送到伺服端后,伺服端的 HttpApplication 中的工具函式会解析 __EVENTTARGET 和 __EVENTARGUMENT 栏位中的资讯,并且交由控制项所实作的 RaisePostBackEvent() 来引发事件,并由 .NET Framework 内部的事件处理机制接手处理(呼叫控制项设定的事件处理常式)。

ASP.NET的来回模式

ASP.NET 运行的时候,经常会有网页的来回动作 (round-trip),在 ASP.NET 中称为 PostBack,在传统的 ASP 技术上,判断网页的来回是需要由开发人员自行撰写,到了 ASP.NET 时,开发人员可以用 Page.IsPostBack 机能来判断是否为第一次执行(当 ASP.NET 发现 HTTP POST 要求的资料是空值时),它可以保证 ASP.NET 的控制项事件只会执行一次,但是它有个缺点(基於 HTTP POST 本身的缺陷),就是若使用者使用瀏览器的重新整理功能(按 F5 或重新整理的按钮)刷新网页时,最后一次执行的事件会再被执行一次,若要避免这个状况,必须要强迫瀏览器清空快取才可以。

ASP.NET 2.0 中有新增三个来回模式:
[list]
[li]Cross Page Postback:允许跨不同的网页执行 PostBack,伺服端可使用 Page.IsCrossPostBack 来判断是否是跨网页型的来回。[/li][li]Async Page Mode:允许网页使用非同步的方式执行,伺服端可用 Page.IsAsync 来判断。[/li][li]Callback:ASP.NET 2.0 新增的由网页回呼用户端指令的功能,伺服端可用 Page.IsCallback 来判断是否要求是来自 Callback。[/li]
[/list]
来回模式不仅是 ASP.NET 运作时的核心,它也是 ASP.NET 应用程式的一个主要缺点,尤其是在设计复杂度高的页面时,在网页中隐藏的 ViewState 的大小会相当大,而在每次的来回动作中,都会传送 ViewState 在内的表单资讯,大量的 ViewState 会使得传送的时间拉长,而且每次来回动作都会让整个网页被刷新,而出现闪烁的情况(就算在本地端也一样),但在AJAX技术尚未成熟时,只能够忍受这种因底层限制所带来的问题,在ASP.NET AJAX技术发展出来后,透过UpdatePanel成功的缓解了这个问题(但 ViewState 传送的问题仍然未根本的解决,必须要使用像 Page Method 这样的方式才能彻底的解决)。

绘製技术

熟悉 ASP 技术的人都知道,程式码都是混在 HTML 标籤之间,以输出预期需要的 HTML 指令,这个技术在 ASP.NET 中,由各控制项的绘製 (Render) 机制包装起来了,绘製机制装载了 HtmlTextWriter 物件,由它来產生 HTML 指令,它会输出至 HttpContext 的 Response 输出资料流中(即 ASP 技术的 Response.Write()),下列程式码为绘製技术的示例:

[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")] 
protected override void Render(HtmlTextWriter output) 
{
   if ( (HasControls()) ;; (Controls[0] is LiteralControl) ) 
   {
   output.Write("<H2>Your Message: " + ((LiteralControl) Controls[0]).Text + "</H2>");
   }
}

为了让控制项的输出有阶层性,ASP.NET 开发了一个可以阶层化输出控制项 HTML 指令的方式,称为控制项树 (Control Tree),藉由控制项树,可以让各个控制项的输出可以阶层化,不论是否是收纳型控制项,还是一般型的控制项,都可以按照控制项的顺序来输出。

状态管理

状态管理 (state management) 在Web应用程式中,一向是很重要的课题,良好的状态管理可以帮助开发人员发展出具有状态持续能力的应用程式(像是工作流程型应用程式或是电子商务应用程式),但状态管理功能会视应用程式的部署状态以及资讯的共用程度来选择,在 ASP.NET 中,分为伺服器端状态管理以及用户端状态管理,用户端状态管理为ViewState以及Cookies,伺服端状态管理则是Session与Application物件。它们的差异点在於:
[list]
[li]ViewState 是加密的资料流,和 HTML 一起输出到用户端。[/li][li]Cookies 是加密(也可不加密)的小型资料,和 HTML 不同,它可以快取在用户端瀏览器中。[/li][li]Session 是伺服器端的状态保存机制,每个用户端均有独立的空间(以瀏览器执行个体来赋与唯一的SessionID值)。[/li][li]Application 是伺服器端的状态保存机制,但应用程式所有的用户端共用同一份状态资料。[/li][/list]

应用程式层级物件

Application 物件会在应用程式的 Application_OnStart 事件中初始化,并使用名称来识别资料(它是一个 NameObjectCollectionBase 集合的实作品),它会储存在应用程式的范围内,所有的连线(使用者)都可以使用,属於共用型的储存体,适合储存所有使用者都可使用的资料,在多人使用的情况下,可以适当的使用 Lock/Unlock 的机制来确保应用程式状态的更新。

Application.Lock();
Application["PageRequestCount"] = 
   ((int)Application["PageRequestCount"])+1;
Application.UnLock();

连线层级物件

连线层级的物件是 Session,以瀏览器的执行个体为识别单位,资料依瀏览器的执行个体来储存,在瀏览器的执行个体第一次连到应用程式时,ASP.NET会设定一个Session ID,并且使用它来识别 Session,每一个 Session 都是 ICollection 与 IEnumerate 的实作,用 key 来识别资料值,并且具有时间的限制 (timeout),若超出时限时伺服器会自动清理掉,预设的 Session 时限为 20 分鐘。Session ID 的演算法是由 RNGCryptoServiceProvider(密码编译乱数產生器提供者)產生,并编码成一个 Session ID 字串(例如 anf4vuup3xiq0arjlqla2l55 这样的字串)储存在伺服器中,用以识别不同的 Session 个体。

为因应不同的用户端,ASP.NET 设计了不同的 Session ID 存放机制,像是旧式的瀏览器或是行动用户端这种不支援本地储存cookie的装置时,ASP.NET 可以直接在 URL 中加上 Session ID 的识别,像是 http://www.acme.com.tw/(anf4vuup3xiq0arjlqla2l55)/profile.aspx 这样的 URL,可以由开发人员自行设定,或是使用 AutoDetect 设定来让 ASP.NET 自行判断要使用的 Session ID 存放方式。

Session ID 的產生方法可以由程式开发人员自订,藉由覆写 SessionIDManager 的 CreateSessionID() 方法来自订。

using System;
using System.Configuration;
using System.Web.Configuration;
using System.Web;
using System.Web.SessionState;
 
 
namespace Samples.AspNet.Session
{
 
  public class GuidSessionIDManager : SessionIDManager
  {
 
   public override string CreateSessionID(HttpContext context)
   {
   return Guid.NewGuid().ToString();
   }
 
 
   public override bool Validate(string id)
   {
   try
   {
   Guid testGuid = new Guid(id);
 
   if (id == testGuid.ToString())
   return true;
   }
   catch
   {
   }
 
   return false;
   }
  }
}

跨机器状态管理

状态管理在单一伺服器上,可以储存在伺服器的记忆体中,但若是在大型网站中,使用许多的 Web 伺服器来实行负载平衡(Load Balancing)处理时,会有状态储存在哪个位置的问题,因此需要有一个可以在每个 Web 伺服器之间做状态储存的媒介,像是独立的伺服器或是资料库等等。在 ASP.NET 中支援了四种状态储存的媒介:
[list]
[li]InProc:储存与 ASP.NET 相同的执行行程中 (in-procedure state),适合单一伺服器的状态储存。[/li][li]StateServer:储存在 ASP.NET 状态伺服器 (state server) 中,适合跨伺服器的状态储存,但因为它使用的通讯埠,因此在使用上需要注意防火墙的问题。[/li][li]SQLServer:储存在独立的 SQL Server 资料库中,适合跨伺服器的状态储存。[/li][li]Custom:以自行实作的状态提供者 (state provider)。[/li][/list]

部件

ASP.NET 是开发 Web 应用程式的基础架构 (framework),除了它内部的运作方法外,对外也显露了许多的开发支援,让开发人员可以利用它来发展出许多强大的 Web 应用程式解决方案。

网页

ASP.NET 最基础的底层为网页 (Page),网页由 System.Web.UI.Page 类别来提供基础支援,包含了页面的事件以及物件绘製的引发点(Page 类别本身是一个 HTTP Handler 的实作品)。ASP.NET 网页在微软的官方名称中,称为 Web Form,除了是要和Windows Forms作分别以外,同时也明白的刻划出了它的主要功能:「让开发人员能够像开发 Windows Forms 一样的方法来发展 Web 网页」。因此 ASP.NET Page 所要提供的功能就需要类似 Windows Forms 的表单,每个 Web Form 都要有一个 区块,所有的 ASP.NET 伺服器控制项都要放在这个区域中,这样才可以让 ViewState 等伺服器控制能够顺畅的运作。

在网页中也可以使用程式码,以类似於ASP时代的撰写方式来开发,此种开发方式称为 inline code,在 ASP.NET 的程式开发模式中,inline code ,要放在 区域中,如下列的范例程式:

<%@ Page Language="C#" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<script runat="server">
 
   protected void Page_Load(object sender, EventArgs e)
   {
   Label1.Text = DateTime.Now.ToLongDateString();
   }
 
</script>
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
   <title>Sample page</title>
</head>
<body>
   <form id="form1" runat="server">
   <div>
   The current time is: <asp:Label runat="server" id="Label1" />
   </div>
   </form>
 
</body>
</html>

另一种模式则是将程式码和网页分离,这种模式称为程式码后置 (Code-Behind),这个方法可以将程式码独立到一个档案中,网页可以保持较乾净的状态,让维护网页程式的复杂度降低很多,在网页的提示指令 (directive) 中,可以设定程式码后置的参数,像是 Inherit、CodeFile、Class 等参数。

<%@ Page Language=“C#” CodeFile=“SampleCodeBehind.aspx.cs” Inherits=“Website.SampleCodeBehind” AutoEventWireup=“true” %>
而一个典型的程式码后置例子为:

using System;
 
namespace Website
{
   public partial class SampleCodeBehind : System.Web.UI.Page
   {
   protected override void Page_Load(EventArgs e)
   {
   base.OnLoad(e);
   }
   }
}

使用程式码后置模式的设定时,可以让 ASP.NET 执行引擎在载入网页时,由程式码后置参数取得对应的类别资讯,藉以使用 Reflection 的方式来执行后置的程式码。
ASP.NET 可以支援HTML和XHTML两种网页内容,但在Visual Studio.NET中,预设是使用 HTML,但在Visual Studio 2005以后的版本,则一律都改用XHTML格式。

Perl

Perl是一种脚本语言。 最初的设计者为拉里·沃尔(Larry Wall),它於1987年12月18日发表。Perl借取了C、sed、awk、shell scripting 以及很多其他程式语言的特性。其中最重要的特性是他内部集成了正则表达式的功能,以及巨大的第三方代码库 CPAN。

Perl简介

Perl原名pearl,但是在这个语言官方发表前,拉里·沃尔发现已经有个程式语言「pearl」,便将这个程式语言的名字改成Perl。对於Perl这四个字母,有一些解释,包括充满幽默感的「Pathologically Eclectic Rubbish Lister」。「Practical Extraction and Report Language」曾经出现在很多有关Perl的资料里,包括官方的主页。不过事实上这个长名字是后来凑出来的。它的名字第一个字母大写(Perl)时就指这个程式语言,无大写字母(perl)时就指它的直译器。将Perl写成「PERL」是不适当的,因为它并非一个缩写字。

Perl 语言的中心思想

Perl 语言的中心思想可以集成为一句话「TMTOWTDI」:

There’s More Than One Way To Do It.(不只一种方法来做这件事。)

Perl 的作者 Larry Wall 建议可以把这个缩写词念成「Tim Toady」。
另一个 Perl 程式设计师常常想起的 Perl 俗语是:

Easy things should be easy, and hard things should be possible.

Perl的骆驼图案

Perl骆驼是欧莱礼媒体(O’Reilly Media)设计给Perl程式语言的图标。牠也是一种骇客的象徵,出现在某些T-shirt和其他衣服标籤上。

欧莱礼拥有此图像之商标,并且宣称,唯有在捍卫「符号之完整性」时,才会行使其法律上的权力。[1] 欧莱礼允许此商标在非商业目的之前提下被使用,并同时供了 Programming Republic of Perl 的图像以及 Powered by Perl 的按钮图。[2] 然而,骆驼其实从未被考虑成为 Perl 的官方识别符号,真要说有的话,其识别符号其实是洋葱。

优点

为了实现这样的目标,并且又因为 Larry Wall 本人也是一个语言学家,他设计Perl语言时使用了很多语言学的思维。相比 C、Pascal 这样的「高级」语言而言,Perl语言直接提供泛型变数、动态数组、Hash表等更加便捷的编程元素。Perl 具有动态语言的强大灵活的特性,并且还从C/C++、Basic、Pascal 等语言中分别借鉴了语法规则,从而提供了许多冗餘语法。使得程式设计师可以忽略计算机内部资料存储、类型、处理方法、运算规则、甚至内存越界等等的细节,而将思考中心放在所需要的程序逻辑上。就这一点而言,很多 Perl 程式设计师认为目前只有 Perl、Python等泛型语言才能称为「高级」语言,而 C、Pascal 甚至 C++ 这些只能称为「中高级」语言而已。可以说,在统一变数类型和掩盖运算细节方面,Perl 做得比 Python 更为出色。

由於从其他语言大量借鉴了语法,使得从其他程式语言转到 Perl 语言的程式设计师可以迅速上手写程序并完成任务,这使得 Perl语言是一门容易用的语言。但问题是这样写出来的「类xx语言」的 Perl 程序对不熟悉这种语言的程式设计师却如同天书,这使得 Perl 语言易写不易读。

缺点

也正是因为 Perl 的灵活性和「过度」的冗餘语法,也因此获得了 write-only 的「美誉」,因为许多 Perl 程序的代码令人难以阅读,实现相同功能的程序代码长度可以相差十倍百倍。 但 Perl 同样可以将代码书写得像 Python 或 Ruby 等语言一样优雅。

Perl 的语法

Perl 的 Hello World 程式
下面是一个在标準输出设备上输出 Hello World 的简单程式,这种程式通常作为开始学习程式语言的第一个范例:

#!/usr/bin/perl
print "Hello, world!\n";

这个程序将输出一行字元串:「Hello,world!」,以及一个回车换行符。

变数

Perl 是一种 无类型语言(untyped),换句话说,在语言层面上,Perl 和大多数程式语言不同,不把变数分成整数、字元、浮点数等等,而只有一种能接受各种类型数据的「无类型」变数。Perl的变数以$字元开头。例如$a=5;$b=“Hello”;$c=3.2;都是合法的 Perl 语句。

Perl中各种变数的运算也很自由,数和含有数的字元串是等效的,可以把数字字元串参与数学计算,也可以反之,让数字参与字元串的构成和操作。

除单个变数(Perl 称为 Scalar)之外,Perl 还有两种集合类型,分别是数组(Array,用@字元开头)和关联数组(Associative array,或者称为Hash,用%开头。类似 C++ 的 STL map 和 Python 的 Dictionary)。数组可以内含任意可变数目的变数。而Hash表,则可以在变数之间建立一一映射,就像字典一样,可以把不同的变数按照他们的逻辑关係组织起来。

判断语句

因为Perl大量的创造冗餘的语法,并且从其他语言中大量的借鉴语法,使得Perl的语法极其丰富和灵活。Perl共有下列几种判断语句:

if模块

if ($hour > 22) {
   print "should sleep...\n";
}

if语句

print "hello" if $guest >= 1;
unless模块
unless ($credit > 100) {
   print "You can not graduate!\n";
}

unless语句

print "eat\n" unless $food == 0;

由於逻辑运算元的作用,还可以写出不用关键字if或unless的判断语句,如常用的打开文件语句:

open(DATA, "< $filename") or die "Can't open $filename: $!\n";

循环语句

Perl中的循环语句也是非常的丰富。主要有:

Perl自己的for或者foreach循环:

@group = 1 .. 10;
for (@group) {
   print "$_\n";
}

foreach (@group) {
print “$_\n”;
}

从C语言借鉴来的for循环:

for ($i = 0; $i < 10; $i++) {
   print "$group[$i]\n";
}

while循环:

$i=0;
while ($i < 10) {
   print "$group[$i]\n";
   $i++;
}

do…while循环:

$i = 0;
do {
   print "$group[$i]\n";
   $i++;
} while ($i < 10);

until循环:

$i = 0;
until ($i == 10) {
   print "$group[$i]\n";
   $i++;
}

从PASCAL语言借鉴来的do…until循环:

$i = 0;
do {
   print "$group[$i]\n";
   $i++;
} until ($i == 10);

甚至还有利用动态语言特性,用map关键字也可以做循环:

print map { "$_\n" } @group;

其实还有其他的循环方式。总而言之,就是TMTOWTDI。

函数

Perl提供了可以直接调用的、数目眾多的函数。可以对以下对象进行操作:
[list]
[li]数组:chomp, join, keys, map, pop, push, reverse, shift, sort, splice, split, unshift, values[/li][li]资料库:dbmclose, dbmopen[/li][li]目录:chdir, closedir, mkdir, opendir, readdir, rewinddir, rmdir, seekdir, telldir[/li][li]文件:binmode, chdir, chmod, chown, chroot, close, eof, fnctl, fileno, flock, getc, glob, ioctl, link, lstat, open, print, printf, read, readdir, readlink, rename, rmdir, seek, select, stat, symlink, sysopen, sysread, syswrite, tell, truncate, umask, unlink, utime, write[/li][li]组:endgrent, getgrent, getgrgid, getgrname, getpgrp, setgrent, setpgrp[/li][li]Hash: delete, each, exists, keys, values[/li][li]主机:endhostent, gethostbyaddr, gethostbyname, sethostent[/li][li]输入:getc, read, sysread[/li][li]处理器间通讯:msgctl, msgget, msgrcv, msgsnd, pipe, semctl, semget, semop, shmctl, shmget, hmread, shmwrite[/li][li]数学:abs, atan2, cos, exp, hex, int, log, oct, rand, sin, sqrt, srand[/li][li]消息队列:msgctl, msgget, msgrcv, msgsnd[/li][li]其他:bless, defined, do, eval, formline, import, ref, scalar, syscall, tie, tied, undef, untie, wantarray[/li][li]网路:endnetent, getnetbyaddr, getnetbyname, getnetent, setnetent[/li][li]输出:die, print, printf, syswrite, warn, write[/li][li]口令:endpwent, getpwent, getpwname, getpwuid, setpwent[/li][li]进程:alarm, die, dump, exec, exit, fork, getlogin, getpgrp, getppid, getpriority, kill, setpriority, sleep, system, times, umask, wait, waitpid[/li][li]协议:endprotent, getprotobyname, getprotobynumber, getprotoent, getservbyname, getservbyport, getservent, setprotoent[/li][li]正则表达式:grep, pos, quotemeta, reset, split, study[/li][li]范围:caller, local, my[/li][li]服务:endservent, getservbyname, getservbyport, getservent, setservent[/li][li]套节字:accept, bind, connect, gethostbyaddr, gethostbyname, gethostent, getpeername, getservbyname, getservbyport, getservent, getsockname, getsockopt, listen, recv, select, send, setsockopt, shutdown, socket, socketpair[/li][li]字元串:chop, chr, crypt, hex, index, join, lc, lcfirst, length, oct, Ord, pack, q, qq, quotemeta, qw, qx, reverse, rindex, split, sprintf, substr, uc, ucfirst, unpack, vec[/li][li]时间:gmtime, localtime, time[/li][li]UNIX: chmod, chown, chroot, dump, endgrent, endhostent, endnetent, endprotent, endpwent, endservent, fnctl, fork, getgrent, getgrgid, getgrname, gethostent, getlogin, getnetent, getpgrp, getppid, getpriority, getprotobyname, getprotobynumber, getprotoent, getpwent, getpwname, getpwuid, getservbyname, getservbyport, getservent, ioctl, link, lstat, readlink, select, setgrent, sethostent, setnetent, setpgrp, setpriority, setprotoent, setpwent, setservent, sleep, syscall, times, umask, wait, waitpid[/li]

Perl的应用

Perl主要应用在Unix平台和网页中(PHP,CGI)。Perl拥有海量的模块支持,在解决问题时非常方便。CPAN是Perl模块的集中营。

Perl Data Language

Perl Data Language(简称PDL)是Perl的一个外接模块,也是对Perl功能的一个重要拓展。它使得Perl语言可以直接对2至多维的矩阵直接操作,进行快速的矩阵运算,完成基础的Perl所不能完成的运算,大大拓展了Perl的适用范围。所以PDL本身也是很多其他模块的基础。

而且PDL提供了与很多其他软体包的介面,例如FFTW(一个快速傅立叶变换的软体包),又或者是Mesa(Linux上的OpenGL三维图形渲染包),这些包原来往往仅提供C/C++语言介面。这一功能使PDL成为拓展Perl功能的一个中间层。

Perl诗经

和C语言一样,在Perl界,难以读懂的程式码大赛是个有名的活动。近似难以读懂的程式码,但方向不同,Perl Poetry是可以被perl编译的诗。新的诗经通常会在Perl Monks网站发表。
另一个Perl hackers的有趣活动是写JAPHs。

竞争对手

因为许多Perl程序的代码难以阅读,加上它的物件导向功能被视为不是真正的物件导向,於是很多人拿Perl和其他动态语言来比较。
最常见是比较对象是Python,有人写了篇文章叫What’s wrong with Perl,指出Perl的缺点,鼓励别人学Python。著名骇客埃里克·史蒂芬·雷蒙写Why Python?,该文中一个重要的比较对象就是Perl。
Ruby的作者(松本行弘,Matz)甚至直认他想Ruby作为Perl的后继者。

Perl 6

Perl 6正在开发中,它将会与现在的Perl版本有很大不同,但相信还要开发一段长时间。 其中最主要的改变是,Perl 6 会是完全物件导向的,有专用於宣告类别的语法

class Foo is Universal { # inherit form Universal 
   has $member_variable
 
   method member_function {
   print "some string";
   }
}

Ruby

Ruby,一种为简单快捷物件导向编程(物件导向程序设计)而创的脚本语言,在20世纪90年代由日本人松本行弘(まつもとゆきひろ/Yukihiro Matsumoto)开发,遵守GPL协议和Ruby License。它的灵感与特性来自於 Perl、Smalltalk、Eiffel、Ada 以及 Lisp 语言。由 Ruby 语言本身还发展出了JRuby(Java 平台)、IronRuby(.NET 平台)等其他平台的 Ruby 语言替代品。

歷史

Ruby的作者於1993年2月24日开始编写Ruby,直至1995年12月才正式公开发佈於fj(新闻群组)。之所以称为Ruby,是因为Perl的发音与6月的诞生石pearl(珍珠)相同,因此Ruby以7月的诞生石ruby(红宝石)命名。

Ruby明显比其他类似的程式语言(如Perl或Python)年轻,又因为Ruby是日本人发明的,所以早期的非日文资料和程式都比较贫乏,所以现在在网上仍然可以找到Ruby的资料太少之类的批评。约於2000年,Ruby开始进入美国,英文的资料开始发展。

Ruby 的理念

减少编程时候的不必要的琐碎时间,令编写程序的人高兴,是设计 Ruby 语言的 Matz 的一个首要的考虑;其次是良好的界面设计。他强调系统设计必须强调人性化,而不是一味从机器的角度设想。

人们特别是电脑工程师们,常常从机器著想。他们认为:「这样做,机器就能运行的更快;这样做,机器运行效率更高;这样做,机器就会怎样怎样怎样。」实际上,我们需要从人的角度考虑问题,人们怎样编写程序或者怎样使用机器上应用程序。我们是主人,他们是僕人。

遵循上述的理念,Ruby 语言通常非常直观,按照编程人认为它应该的方式运行。

Ruby的作者认为Ruby > (Smalltalk + Perl) / 2,表示Ruby是一个语法像Smalltalk一样完全物件导向、脚本执行、又有Perl强大的文字处理功能的程式语言。其他特色包括:
[list]
[li]运算符重载[/li][li]垃圾回收[/li][li]弱类型(动态类型 | 纯量变数)[/li][li]变数无需声明(不必事先宣告变数)[/li][li]在Windows上,载入DLL[/li][li]巨大的函式库[/li][/list]

语意

Ruby 是完全物件导向的:任何一点数据都是物件,包括在其他语言中的基本类型(比如:整数,布尔逻辑值),每个过程或函数都是方法。

Ruby 的 Hello World 程序

下面是一个在标準输出设备上输出 Hello World 的简单程序,这种程序通常作为开始学习程式语言时的第一个程序:

#!/usr/bin/env ruby
puts "Hello, world!"

或者是在 irb 互动式命令列的模式下:

>>puts "Hello, world!"
Hello, world!
=> nil

程式范例

下面的代码可以在 Ruby shell 中运行,比如 irb 互动式命令列,或者保存为文件并运行命令 ruby 。
一些基本的 Ruby 代码:

# Everything, including a literal, is an object, so this works:
-199.abs                                                # 199
"ruby is cool".length                                   # 12
"Rick Astley".index("c")                                # 2
"Nice Day Isn't It?".downcase.split(//).sort.uniq.join  # " '?acdeinsty"

一些转换:

puts "What's your favorite number?"
number = gets.chomp
outputnumber = number.to_i + 1
puts outputnumber.to_s + ' is a bigger and better favorite number.'

字元串
在 Ruby 中定义字元串的各种方法
下面的转换同双引号的字元串是等价的:

a = "\nThis is a double quoted string\n"
a = %Q{\nThis is a double quoted string\n}
a = <<BLOCK
This is a double quoted string
BLOCK

这是双引号字元串的多行形式:
BLOCK

a = %/\nThis is a double quoted string\n/

下面的转换同单引号字元串是等价的:

a = 'This is a single quoted string'
a = %q{This is a single quoted string}

集合
构造和使用数组:

a = [1,'hi', 3.14, 1, 2, [4, 5]]
 
p a[2]           # 3.14
p a.[](2)        # 3.14
p a.reverse      # [[4, 5], 2, 1, 3.14, 'hi', 1]
p a.flatten.uniq # [1, 'hi', 3.14, 2, 4, 5]

构造和使用关联数组:

hash = { :water => 'wet', :fire => 'hot' }
puts hash[:fire] # Prints:  hot
 
hash.each_pair do |key, value| # Or:  hash.each do |key, value|
  puts "#{key} is #{value}"
end
 
# Prints:  water is wet
#          fire is hot
 
hash.delete :water # Deletes :water => 'wet'
hash.delete_if {|k,value| value=='hot'} # Deletes :fire => 'hot'

区块和迭代器

有两个语法用於创建区块:

{ puts "Hello, World!" } # Note the { braces }
#or
do puts "Hello, World!" end

传参数的区块使用闭包Closure:

# In an object instance variable (denoted with '@'), remember a block.
def remember(;a_block)
  @block = a_block
end
 
# Invoke the above method, giving it a block which takes a name.
remember {|name| puts "Hello, #{name}!"}
 
# When the time is right (for the object) -- call the closure!
@block.call("Jon")
# => "Hello, Jon!"

从方法中返回闭包:

def create_set_and_get(initial_value=0) # Note the default value of 0
  closure_value = initial_value
  return Proc.new {|x| closure_value = x}, Proc.new { closure_value }
end
 
setter, getter = create_set_and_get  # ie. returns two values
setter.call(21)
getter.call # => 21

迭代调用调用时提供的区块:

def use_hello
  yield "hello"
end
 
# Invoke the above method, passing it a block.
use_hello {|string| puts string} # => 'hello'

使用区块迭代数组:

array = [1, 'hi', 3.14]
array.each { |item| puts item }
# => 1
# => 'hi'
# => 3.14
 
array.each_index { |index| puts "#{index}: #{array[index]}" }
# => 0: 1
# => 1: 'hi'
# => 2: 3.14
 
(3..6).each { |num| puts num }
# => 3
# => 4
# => 5
# => 6

像 inject() 方法可以接收一个参数和一个区块。迭代的注入列表的每一个成员,执行函数时保存总和。这同函数程式语言中的 foldl 函数相类似,比如:

[1,3,5].inject(10) {|sum, element| sum + element} # => 19

首先区块接收到了 10(inject 的参数)当作变数 sum,并且 1(数组的第一个元素)当作变数 element;这会返回 11。11 又被当作下一步的 sum 变数,它加上 3 得到了 14。14 又被加上了 5,最终返回结果 19。
区块运行在内置的方法中:

File.open('file.txt', 'w') do |file| # 'w' denotes "write mode".
  file.puts 'Wrote some text.'
end                                  # File is automatically closed here
 
File.readlines('file.txt').each do |line|
  puts line
end
# => Wrote some text.

使用枚举器和块求 1 到 10 的平方:

(1..10).collect {|x| x*x} # => [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

类别

面的代码定义一个命名为 Person 的类别。含有一个「initialize」方法,用於构选创建一个新对象,它还有两个方法,一个重载了 <=> 比较运算符(这样 Array#sort 可以使用 age 排序)另一个重载了 to_s 方法(这样 Kernel#puts 可以格式化输出),attr_reader 是 Ruby 中元数据编程的例子:attr_accessor 为实例变数定义了 getter 和 setter 方法,attr_reader 只是一个 getter 方法。另外,方法中最后的声明是它的返回值,也允许显式的使用「return」语句。

class Person
  attr_reader :name, :age
  def initialize(name, age)
   @name, @age = name, age
  end
  def <=>(person) # Comparison operator for sorting
   @age <=> person.age
  end
  def to_s
   "#@name (#@age)"
  end
end
 
group = [
  Person.new("Bob", 33), 
  Person.new("Chris", 16), 
  Person.new("Ash", 23) 
]
 
puts group.sort.reverse

下面按 age 倒序输出了三个名字:

Bob (33)
Ash (23)
Chris (16)

元数据编程

Ruby 为程式设计师在运行时期间向标準库加入或修改方法的能力,同样 Ruby 在执行时修改它自身而无需生成代码,这种技术被称为元数据编程。这是一个为标準库的 Time 类添加方法的简单例子:

# re-open Ruby's Time class
class Time
  def yesterday
   self - 86400
  end
end
 
today = Time.now # => Thu Aug 14 16:51:50 +1200 2008
yesterday = today.yesterday # => Wed Aug 13 16:51:50 +1200 2008

Ruby 的特点

完全物件导向
在Ruby语言中,任何东西都是物件,包括其他语言中的基本数据类型,比如整数。

变数没有类型
Ruby的变数可以保有任何类型的数据。

任何东西都有值
不管是数学或者逻辑表达式还是一个语句,都有值。

变数命名规则
Ruby的变数有以下几种:
[list][li]一般小写字母、底线开头:变数,变量 (Variable)。[/li][li]$开头:全域变数,全局变量 (Global variable)。[/li][li]@开头:实体变数,实例变量 (Instance variable)。[/li][li]@@开头:类别变数,类变量 (Class variable)。[/li][li]大写字母开头:常数 (Constant)。[/li][/list]

已经定义的类可以在运行时修改
Ruby是动态语言,你可以在程序中修改先前定义过的类。 也可以在某个类的实例中定义该实例特有的方法,这叫做原型方法(prototype)。

class MyClass
  def the_method
   "general method"
  end
end
 
mc = MyClass.new
def mc.the_method
  "special for this instance."
end
 
mc.the_method

JRuby

JRuby,类似Python的Jython,一个可於Java上执行Ruby的语言,支援Java的介面和类别。最新发布版为1.1.4(2008-8-28),与Ruby 1.8.6兼容。它的官方网站为jruby.codehaus.org

和 Perl 6 比较

[list=1][li]CPAN 上排名第一名,同时也是 Perl 6 的开发者的唐凤(Autrijus / Audrey)说:「Ruby 就是『没有到处打广告的 Perl 6』」。[/li][li]松本行弘在接受欧莱礼(O’Reilly)访问时,提到「Ruby 借用了很多 Perl 的东西……,Python 远比 Perl 要少……」、「我认为 Ruby 这个名字作为 Perl 之后的一门语言的名字真是再恰当不过了。」[/li][li]Perl 之父拉里·沃尔(Larry Wall)说:「很多方面上我还是很喜欢 Ruby 的,这是因为那些部分是从 Perl 借过去的。:-)」、「我还喜欢 Ruby 的 C<*> 一元星号操作符,所以我把它加到 Perl 6 裡面。」[/li][/list]

Python

Python([KK] 英语发音: /'paɪθɑn/, [DJ] 英语发音: /ˈpaiθən/),是一种物件导向、直译式电脑程式语言,也是一种功能强大而完善的通用型语言,已经具有十多年的发展歷史,成熟且稳定。

这种语言具有非常简捷而清晰的语法特点,适合完成各种高层任务,几乎可以在所有的作业系统中执行。

目前,基於这种语言的相关技术正在飞速的发展,使用者数量急剧扩大,相关的资源非常多。

发展歷史

Python的创始人为Guido van Rossum。在1989年圣诞节期间的阿姆斯特丹,Guido为了打发圣诞节的无趣,决心开发一个新的指令码解释程式,作为ABC语言的一种继承。之所以选中 Python(大蟒蛇的意思)作为程式的名字,是因为他是一个Monty Python的飞行马戏团的爱好者。

ABC是由Guido参加设计的一种教学语言。就Guido本人看来,ABC这种语言非常优美和强大,是专门为非专业程式设计师设计的。但是ABC语言并没有成功,究其原因,Guido 认为是非开放造成的。Guido 决心在 Python 中避免这一错误(的确如此,Python 与其它的语言如C、C++和Java结合的非常好)。同时,他还想实作在 ABC 中闪现过但未曾实作的东西。

就这样,Python在Guido手中诞生了。实际上,第一个实作是在Mac机上。可以说,Python是从ABC发展起来,主要受到了Modula-3(另一种相当优美且强大的语言,为小型团体所设计的)的影响。并且结合了Unix shell和C的习惯。

作为编程语言的设计定位

虽然 Python 可能被粗略地分类为「指令码语言」(script language),但实际上一些大规模软体开发计划例如 Zope、Mnet 及 BitTorrent,Google 也广泛地使用它。 Python 的支援者较喜欢称它为一种高阶动态编程语言,原因是「指令码语言」泛指仅作简单编程任务的语言,如 shell script、JavaScript 等只能处理简单任务的编程语言,并不能与 Python 相提并论。

此外,由於 Python 对於 C 和其他语言的良好支援,很多人还把 Python 作为一种「胶水语言」(glue language)使用。 使用 Python 将其他语言编写的程式进行整合和封装。 在 Google 内部的很多专案使用 C++ 编写性能要求极高的部分,然后用Python呼叫相应的模组。

标準函式库

Python之所以有这么大的魅力,原因之一就是它有一个强大的标準函式库[1]。可以使你之前写的工具能适应於许多其他的任务,标準函式库可以由使用者自订扩充,如用C或Python写的函式库。 藉助於拥有基於标準函式库的大量工具、能够使用低阶语言如C和可以作为其他函式库介面的C++,Python已成为一种强大的应用於其他语言与工具之间的胶水语言。 由於支援多种标準格式和协定如MIME和HTTP,Python非常适於编写面向网路的应用,如:使用者图形模组、连线到关联式资料库、任意精度的科学运算、正规表式的支援和进行单元测试。

语言特色

Python是一门跨平台的指令码语言,Python规定了一个Python语法规则,实作了Python语法的解释程式就成为了Python的直译器,我们用的比较多的是 C 版本的Python,也就是使用C语言实作的Python直译器,除此之外还有使用Java实作的Jython和使用.NET实作的IronPython,这些实作可以使Python使用者充分利用己有的Java及.NET资源。

同时,Python支援几乎所有常用的作业系统,包括:Windows/DOS、Macintosh、Linux 及 FreeBSD。及很多不常用的作业系统,包括AIX、AS/400 (OS/400)、BeOS、OS/2、OS/390与z/OS、Palm OS、PlayStation与PSP、Psion、QNX、RISC OS、Series 60、Sparc Solaris、VMS、VxWorks、Windows CE或Pocket PC、Sharp Zaurus、MorphOS等。

可扩充性可说是Python作为一种编程语言的特色。新的内置模组(module)可以用C 或 C++写成。而我们也可为现成的模组加上Python的介面。Python可以使使用者避免过分的语法的羈绊而将精力主要集中到所要实作的程式任务上。

因此Python具有非常庞大的程式函式库,透过它们可以快速完成绝大部分常用的任务,如:从某个URL中获取资讯、正规表式、获得某个档案或字串的MD5特徵字串、多执行绪、XML及HTML的分析等。

Python也被称为是一门清晰的语言。因为它的作者在设计它的时候,总的指导思想是,对於一个特定的问题,只要有一种最好的方法来解决就好了。这在由Python资深开发者Tim Peters所作的Python格言(The Zen of Python)[3]裡面表述为:

There should be one-- and preferably only one --obvious way to do it.

另外,在 Chris DiBona(Google 开源码网站负责人)和 Leo Laporte(Twit 网站创始人) 的访谈中,Guido van Rossum 也提出一个口号:

There is only one way to do it.(做一件事情只有一个方法。)

有意思的是,这正好和Perl 语言(另一种功能类似的高阶动态语言)的中心思想TMTOWTDI(There’s More Than One Way To Do It.)完全相反,这似乎是人们常把Perl和Python互相比较的重要原因。

著名Python培训专家Mark Lutz则表示,Peters的话中最值得一提的是:

Explicit is better than implicit.(明言胜於暗示。)

这句话在Python使用者社群中通常简写作EIBTI(Explicit Is Better Than Implicit.)。Lutz认为这一特色性原则是Python和其他各种程式语言之间最重要的区别。
Python语言是一种清晰的语言的另一个意思是,它的作者有意的设计限制性很强的语法,使得不好的程式习惯(例如if语句的下一行不向右缩排)都不能透过编译。这样有意的强制程式设计师养成良好的程式习惯。其中很重要的一项就是Python的缩排规则。

例如 if 语句:

if age < 21:
   print "You cannot buy wine!\n"
   print "But you can buy chewing gum.\n"
print "this is outside if\n"

一个和其他大多数语言(如C语言)的区别就是,一个语句块的界限,完全是由每行的首字元在这一行的位置来决定的(而C语言是用一对花括弧{ }来明确的定出语句块的边界的,与字元的位置毫无关联)。这一点曾经引起过争议。因为自从C这类的语言诞生后,语言的语法含义与字元的排列方式分离开来,曾经被认为是一种程式语言的进步。不过不可否认的是,透过强製程序员们缩排(包括if,for和函式定义等所有需要使用模组的地方),Python确实使得程式更加清晰和美观。

另外Python在其他部分的设计上也坚持了清晰划一的风格,这使得Python称为一门易读性、易维护性好,并且被大量使用者所欢迎的、用途广泛的语言。

Python 3.0

Python 的 3.0 版本,在开发阶段被称为 Python 3000,或简称 Py3k[6]。相对於 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候就没有考虑向下相容。许多针对早期 Python 版本设计的程式都无法在 Python 3.0 上正常执行。为了照顾现有程式,Python 2.6 作为一个过渡版本,基本使用了 Python 2.x 的语法和函式库,同时考虑了向 Python 3.0 的迁移。基於早期 Python 版本而能正常执行於 Python 2.6 并无警告的程式可以透过一个 2 to 3 的转换工具无缝迁移到 Python 3.0。

主要变化

Python 3.0 的变化主要在以下几个方面:
部分函式和语句的改变:
最引人注意的改变是 print 语句没有了,取而代之的是 print 函式;
字串和位元组:
类似 Java,str类表示一个 Unicode 字串,代替了早期版本的 unicode 类。而一堆位元组则用类似 b"abc" 的语法创建,用 bytes 类表示;