<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>程式設計 遇上 小提琴 &#187; PHP</title>
	<atom:link href="http://blog.ez2learn.com/tag/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.ez2learn.com</link>
	<description>Victor&#039;s個人部落格，關於程式設計與小提琴</description>
	<lastBuildDate>Tue, 07 Feb 2012 03:26:25 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>如何評估比較程式語言</title>
		<link>http://blog.ez2learn.com/2010/01/08/how-to-compare-languages/</link>
		<comments>http://blog.ez2learn.com/2010/01/08/how-to-compare-languages/#comments</comments>
		<pubDate>Thu, 07 Jan 2010 19:32:47 +0000</pubDate>
		<dc:creator>victor</dc:creator>
				<category><![CDATA[中文文章]]></category>
		<category><![CDATA[分享]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[可寫性]]></category>
		<category><![CDATA[可讀性]]></category>
		<category><![CDATA[可攜性]]></category>
		<category><![CDATA[程式語言]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[programming language]]></category>

		<guid isPermaLink="false">http://blog.ez2learn.com/?p=928</guid>
		<description><![CDATA[有人提到以過去的觀點來看現在的PHP是不公平的，確實我有好一陣子沒有碰PHP，對於新版的PHP並不瞭解，因此我花了一些時間檢視新的PHP規格，的確新版的PHP遠比我預料的進步許多，很多之前提到的問題有所改善，我承認上一篇文章說PHP很爛是在發洩過去對於PHP的種種不滿，有人認為程式語言沒有好壞，全部都事在人為，而我認為程式語言的好壞有主觀也有客觀的部份，當你討厭或喜歡一個程式語言一定有某些原因，但就客觀的來看語言的設計來講，PHP在早期真的是爛得一榻糊塗，是公認的爛，但是在當時少有選擇，能選的工具不多，就只有PHP，在累積夠久的不滿後就會一次暴發開來，對於現在的PHP5.3還有未來的PHP6而言，他已經跳離了以前的單純語言設計上的爛，往更好的方向前進，我能說PHP的壞話少了很多，因為當語言層面的問題大部份都解決了，接著就是哲學和個人喜好的問題了，對與目前和新版的PHP的誤解在這邊說聲抱歉 所以這篇我想說的，怎樣看客觀地評估一款語言的好壞，還有主觀地評估好與壞，很多人說程式語言沒有好與壞，只有適合和不適合，基本上我不認同這樣的說法，如果說兩種差別很大用途不同的語言拿來一起比較就很奇怪，但是如果是性質接近的語言都符合你需求，就可以做好壞的比較，不然你要怎麼做選擇? 就如同我們買車子好了，你的目的是載貨，買的自然是卡車、貨車，但是如果是轎車呢? 就算是卡車也有選擇的，程式語言也一樣，目前大部份人所見到的程式語言，都是所謂的"通用目的"語言，也就是說這樣的語言沒有預設任何用途，基本上他可以拿來做任何用途，很多人因為不知道要從何比較起，所以都說程式語言沒有好壞之分，只有適合和不適合，如果有一堆工具都適合，既然沒有好壞之分，那你又該如何做出進一步的評估與選擇? 適不適合不就是透過比較而來的嗎? 不比較怎麼知道適不適合? 這不是自相矛盾嗎? 只靠喜好嗎? 閉著眼睛亂選? 大家都知道車子我們可以比較它的馬力、耗油、安全評等，但是大多數人不知道程式語言該比較些什麼，而我今天所要說的，就是程式語言該拿什麼來比較 客觀的評估條件 首先，客觀的評估條件並不是完全客觀的，在某些情況它會帶有主觀色彩，例如一個語法的可讀性如何，這就帶有某種程度的主觀，事實上有一個領域是在探討這些問題的，在資訊工程系開的一門課叫「程式語言」就有某部份在討論這些，但是對於這部份沒有很深入，而關於這些條件應該有更嚴僅學術上的方式來對這些條件進行評估，但是那超出我的知識範圍，我就我所知道的來說 可讀性 可讀性是指一個程式語言寫出來的語句是否容易閱讀 可讀性是程式語言很重要的一個優劣的參考指標，因為有一個事實就是 程式被讀比被寫還多次 一個程式的可讀性，關係到維護的人能否輕易的瞭解程式語言所表達程式的意圖，如果維護的人難以理解某段程式所要表達的事情，那麼這些程式就難以被維護，軟體工程中有個很重要的概念就是，程式開發的成本其實只佔一小部份，而維護其實所花的成本會比開發來得多，在這樣的情況下，如果寫出來的程式難以被讀懂，那麼接手的人將難以進行維護，如此一來可能要面臨整個程式重寫的情況，會使得維護的成本大大增加，程式碼也失去了重覆利用的價值，所以可讀性對於一款程式語言的好壞來說是很重要的一個指標 為了說明可讀性爛的程式語言，我找來最極端的例子，Brainfuck是一款以圖靈機為模型，所做出來最小化的程式語言，它所寫出來的Helloworld程式如下 ++++++++++[&#62;+++++++&#62;++++++++++&#62;+++&#62;+&#60;&#60;&#60;&#60;-] &#62;++.&#62;+.+++++++..+++.&#62;++.&#60;&#60;+++++++++++++++. &#62;.+++.&#8212;&#8212;.&#8212;&#8212;&#8211;.&#62;+.&#62;. 我想應該沒有太多人會反對我說Brainfuck可讀性很差 XD 我喜歡極端的例子，再來一個國際混亂碼大賽的參賽作品，這是一個要將程式寫到別人看不懂，但又要能夠運作，而且要夠創意的比賽，所以寫出來的程式都是可讀性0分的程式，下面這個是可以計算圓周率的程式 #define _ -F&#60;00&#124;&#124;--F-OO--; int F=00,OO=00;main&#40;&#41;&#123;F_OO&#40;&#41;;printf&#40;&#34;%1.3f\n&#34;,4.*-F/OO/OO&#41;;&#125;F_OO&#40;&#41; &#123; _-_-_-_ _-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ &#8230; <a href="http://blog.ez2learn.com/2010/01/08/how-to-compare-languages/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>有人提到以過去的觀點來看現在的PHP是不公平的，確實我有好一陣子沒有碰PHP，對於新版的PHP並不瞭解，因此我花了一些時間檢視新的PHP規格，的確新版的PHP遠比我預料的進步許多，很多之前提到的問題有所改善，我承認上一篇文章說PHP很爛是在發洩過去對於PHP的種種不滿，有人認為程式語言沒有好壞，全部都事在人為，而我認為程式語言的好壞有主觀也有客觀的部份，當你討厭或喜歡一個程式語言一定有某些原因，但就客觀的來看語言的設計來講，PHP在早期真的是爛得一榻糊塗，是公認的爛，但是在當時少有選擇，能選的工具不多，就只有PHP，在累積夠久的不滿後就會一次暴發開來，對於現在的PHP5.3還有未來的PHP6而言，他已經跳離了以前的單純語言設計上的爛，往更好的方向前進，我能說PHP的壞話少了很多，因為當語言層面的問題大部份都解決了，接著就是哲學和個人喜好的問題了，對與目前和新版的PHP的誤解在這邊說聲抱歉</p>
<p>所以這篇我想說的，怎樣看客觀地評估一款語言的好壞，還有主觀地評估好與壞，很多人說程式語言沒有好與壞，只有適合和不適合，基本上我不認同這樣的說法，如果說兩種差別很大用途不同的語言拿來一起比較就很奇怪，但是如果是性質接近的語言都符合你需求，就可以做好壞的比較，不然你要怎麼做選擇? 就如同我們買車子好了，你的目的是載貨，買的自然是卡車、貨車，但是如果是轎車呢? 就算是卡車也有選擇的，程式語言也一樣，目前大部份人所見到的程式語言，都是所謂的"通用目的"語言，也就是說這樣的語言沒有預設任何用途，基本上他可以拿來做任何用途，很多人因為不知道要從何比較起，所以都說程式語言沒有好壞之分，只有適合和不適合，如果有一堆工具都適合，既然沒有好壞之分，那你又該如何做出進一步的評估與選擇? 適不適合不就是透過比較而來的嗎? 不比較怎麼知道適不適合? 這不是自相矛盾嗎? 只靠喜好嗎? 閉著眼睛亂選?  大家都知道車子我們可以比較它的馬力、耗油、安全評等，但是大多數人不知道程式語言該比較些什麼，而我今天所要說的，就是程式語言該拿什麼來比較</p>
<p><span id="more-928"></span></p>
<h2>客觀的評估條件</h2>
<p>首先，客觀的評估條件並不是完全客觀的，在某些情況它會帶有主觀色彩，例如一個語法的可讀性如何，這就帶有某種程度的主觀，事實上有一個領域是在探討這些問題的，在資訊工程系開的一門課叫「程式語言」就有某部份在討論這些，但是對於這部份沒有很深入，而關於這些條件應該有更嚴僅學術上的方式來對這些條件進行評估，但是那超出我的知識範圍，我就我所知道的來說</p>
<h3>可讀性</h3>
<p>可讀性是指一個程式語言寫出來的語句是否容易閱讀</p>
<p>可讀性是程式語言很重要的一個優劣的參考指標，因為有一個事實就是</p>
<blockquote><p>程式被讀比被寫還多次</p></blockquote>
<p>一個程式的可讀性，關係到維護的人能否輕易的瞭解程式語言所表達程式的意圖，如果維護的人難以理解某段程式所要表達的事情，那麼這些程式就難以被維護，軟體工程中有個很重要的概念就是，程式開發的成本其實只佔一小部份，而維護其實所花的成本會比開發來得多，在這樣的情況下，如果寫出來的程式難以被讀懂，那麼接手的人將難以進行維護，如此一來可能要面臨整個程式重寫的情況，會使得維護的成本大大增加，程式碼也失去了重覆利用的價值，所以可讀性對於一款程式語言的好壞來說是很重要的一個指標</p>
<p>為了說明可讀性爛的程式語言，我找來最極端的例子，<a href="http://zh.wikipedia.org/zh-tw/Brainfuck">Brainfuck</a>是一款以<a href="http://zh.wikipedia.org/zh-tw/%E5%9B%BE%E7%81%B5%E6%9C%BA">圖靈機</a>為模型，所做出來最小化的程式語言，它所寫出來的Helloworld程式如下</p>
<blockquote><p>++++++++++[&gt;+++++++&gt;++++++++++&gt;+++&gt;+&lt;&lt;&lt;&lt;-]<br />
&gt;++.&gt;+.+++++++..+++.&gt;++.&lt;&lt;+++++++++++++++.<br />
&gt;.+++.&#8212;&#8212;.&#8212;&#8212;&#8211;.&gt;+.&gt;.</p></blockquote>
<p>我想應該沒有太多人會反對我說Brainfuck可讀性很差 XD</p>
<p>我喜歡極端的例子，再來一個<a href="http://zh.wikipedia.org/zh-tw/%E5%9B%BD%E9%99%85C%E8%AF%AD%E8%A8%80%E6%B7%B7%E4%B9%B1%E4%BB%A3%E7%A0%81%E5%A4%A7%E8%B5%9B">國際混亂碼大賽</a>的參賽作品，這是一個要將程式寫到別人看不懂，但又要能夠運作，而且要夠創意的比賽，所以寫出來的程式都是可讀性0分的程式，下面這個是可以計算圓周率的程式<br />
<code></p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"> <span style="color: #339933;">#define _ -F&lt;00||--F-OO--;</span>
 <span style="color: #993333;">int</span> F<span style="color: #339933;">=</span><span style="color: #208080;">00</span><span style="color: #339933;">,</span>OO<span style="color: #339933;">=</span><span style="color: #208080;">00</span><span style="color: #339933;">;</span>main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>F_OO<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>printf<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%1.3f<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span><span style="color: #0000dd;">4</span>.<span style="color: #339933;">*-</span>F<span style="color: #339933;">/</span>OO<span style="color: #339933;">/</span>OO<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #009900;">&#125;</span>F_OO<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
 <span style="color: #009900;">&#123;</span>
             _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
        _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
     _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
   _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
  _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
  _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
 _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
 _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
 _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
 _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
  _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
  _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
   _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
     _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
         _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
             _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
 <span style="color: #009900;">&#125;</span></pre></div></div>

<p></code><br />
當然，這是故意寫出來難懂的例子，有些程式語言天生寫出來的程式就較難懂，或是較容易寫出難懂的程式，舉個例子，Perl程式可讀性和Python比較起來就差很多，下面兩隻程式的目的都一樣，是一隻簡單的Web Proxy程式，Python版本是我參照Perl版寫出來的，特意按照同樣的架構下去寫，目的就是要能容易做比較</p>
<p>Perl版:<br />
<code></p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/usr/bin/perl</span>
<span style="color: #666666; font-style: italic;">#-------------------------------------------------------------------------</span>
<span style="color: #666666; font-style: italic;">#--     proxy.pl    -  A simple http proxy server.                      --</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;">#	The original program was from:</span>
<span style="color: #666666; font-style: italic;">#		http://www.cis.upenn.edu/sdt/proxy.pl</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;">#	The original program employs the basic socket library, which</span>
<span style="color: #666666; font-style: italic;">#		seems hard to understand for some beginners.</span>
<span style="color: #666666; font-style: italic;">#	That is why I modify it  by employing the </span>
<span style="color: #666666; font-style: italic;">#		IO::Socket::INET</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;">#	jay.s.liu@gmail.com</span>
<span style="color: #666666; font-style: italic;">#	Apr. 17, 2006</span>
<span style="color: #666666; font-style: italic;">#--                                                                     --</span>
<span style="color: #666666; font-style: italic;">#--     To run, type   proxy.pl [port-number]   at the shell prompt.    --</span>
<span style="color: #666666; font-style: italic;">#--     Default port number is 5364.                                    --</span>
<span style="color: #666666; font-style: italic;">#--                                                                     --</span>
<span style="color: #666666; font-style: italic;">#-------------------------------------------------------------------------</span>
<span style="color: #000000; font-weight: bold;">use</span> IO<span style="color: #339933;">::</span><span style="color: #006600;">Socket</span><span style="color: #339933;">::</span><span style="color: #006600;">INET</span><span style="color: #339933;">;</span>
<span style="color: #000066;">srand</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">time</span><span style="color: #339933;">||</span><span style="color: #0000ff;">$$</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#---  Define a friendly exit handler</span>
<span style="color: #0000ff;">$SIG</span><span style="color: #009900;">&#123;</span><span style="color: #ff0000;">'KILL'</span><span style="color: #009900;">&#125;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$SIG</span><span style="color: #009900;">&#123;</span>QUIT<span style="color: #009900;">&#125;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$SIG</span><span style="color: #009900;">&#123;</span>INT<span style="color: #009900;">&#125;</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">'exit_handler'</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">sub</span> exit_handler <span style="color: #009900;">&#123;</span>
    <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span> --- Proxy server is dying ...<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">close</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$SOCKET</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">exit</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">$|</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>	<span style="color: #666666; font-style: italic;">#Disable buffering</span>
&nbsp;
<span style="color: #666666; font-style: italic;">##--- Step 1 : Create Socket ---##	</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#--- Get the port number form commemd line	</span>
<span style="color: #0000ff;">$proxy_port</span> <span style="color: #339933;">=</span> <span style="color: #000066;">shift</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">@</span><span style="color: #000000; font-weight: bold;">ARGV</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>								
<span style="color: #0000ff;">$proxy_port</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">5364</span> <span style="color: #b1b100;">unless</span> <span style="color: #0000ff;">$proxy_port</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/\d+/</span><span style="color: #339933;">;</span>		
&nbsp;
<span style="color: #666666; font-style: italic;">#--- Create a socket that listens to a specific port</span>
<span style="color: #0000ff;">&amp;listen_to_port</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$SOCKET</span><span style="color: #339933;">,</span><span style="color: #0000ff;">$proxy_port</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>			
&nbsp;
<span style="color: #0000ff;">$local_host</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">`hostname`</span><span style="color: #339933;">;</span>	
<span style="color: #000066;">chop</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$local_host</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #0000ff;">$local_host_ip</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$SOCKET</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">sockhost</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot; --- Proxy server running on $local_host( $local_host_ip ) port: $proxy_port <span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#---  Loop forever taking requests as they come</span>
<span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">##--- Step 2 : Wait for request ---##</span>
    <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot; --- Waiting to be of service ...<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #0000ff;">$CHILD</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$SOCKET</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">accept</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #000066;">die</span> <span style="color: #ff0000;">&quot;accept $!&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#--- Get the ip address of clinet</span>
    <span style="color: #0000ff;">$inetaddr</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$CHILD</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">peerhost</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>					 
    <span style="color: #0000ff;">$port</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$CHILD</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">peerport</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;Connection from &quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$inetaddr</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;  port: $port <span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#---  Fork a subprocess to handle request.</span>
<span style="color: #666666; font-style: italic;">#---  Parent proces continues listening.</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">fork</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">wait</span><span style="color: #339933;">;</span>           <span style="color: #666666; font-style: italic;"># For now we wait for the child to finish</span>
        <span style="color: #b1b100;">next</span><span style="color: #339933;">;</span>           <span style="color: #666666; font-style: italic;"># We wait so that printouts don't mix</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
<span style="color: #666666; font-style: italic;">##---  Step 3 : Read first line of request and analyze it. ---##</span>
<span style="color: #666666; font-style: italic;">#---  Return and edited version of the first line and the request method.</span>
  <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$first</span><span style="color: #339933;">,</span><span style="color: #0000ff;">$method</span><span style="color: #339933;">,</span><span style="color: #0000ff;">$URL</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&amp;analyze_request</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">##---  Step 4 : Send request to remote host ---##</span>
    <span style="color: #000066;">print</span> <span style="color: #0000ff;">$URL</span> <span style="color: #0000ff;">$first</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">print</span> <span style="color: #0000ff;">$first</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#-- Read HTTP header and Send it to remote host</span>
    <span style="color: #0000ff;">$contentLength</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">&lt;</span><span style="color: #0000ff;">$CHILD</span><span style="color: #339933;">&gt;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$_</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">next</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/Proxy-Connection:/</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	<span style="color: #666666; font-style: italic;">#discard the line which begins with the string &quot;/Proxy-Connection:/&quot;</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/Content-length:(.*)/i</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #0000ff;">$contentLength</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$1</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$URL</span> <span style="color: #0000ff;">$_</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">last</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$_</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/^[\s\x00]*$/</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	<span style="color: #666666; font-style: italic;">#exit loop if the line only contains space and null character</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#Read HTTP content and Send it to remote host</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$method</span> <span style="color: #b1b100;">eq</span> <span style="color: #ff0000;">&quot;POST&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>			
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$contentLength</span> <span style="color: #339933;">!=</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		    <span style="color: #000066;">read</span> <span style="color: #0000ff;">$CHILD</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$data</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$contentLength</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span> 
		<span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
		    <span style="color: #0000ff;">$data</span> <span style="color: #339933;">=</span> <span style="color: #339933;">&lt;</span><span style="color: #0000ff;">$CHILD</span><span style="color: #339933;">&gt;;</span>
		<span style="color: #009900;">&#125;</span>
        <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;POST body: $data&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$URL</span> <span style="color: #0000ff;">$data</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000066;">print</span> <span style="color: #0000ff;">$URL</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">##---  Step 5 : Wait for response and transfer it to requestor. ---##	</span>
    <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot; --- Done sending. Response: <span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #0000ff;">$header</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
    <span style="color: #0000ff;">$text</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">&lt;</span><span style="color: #0000ff;">$URL</span><span style="color: #339933;">&gt;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$CHILD</span> <span style="color: #0000ff;">$_</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$header</span> <span style="color: #339933;">||</span> <span style="color: #0000ff;">$text</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>      <span style="color: #666666; font-style: italic;"># Only print header &amp; text lines to STDOUT</span>
            <span style="color: #000066;">print</span> <span style="color: #0000ff;">$_</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$header</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #0000ff;">$_</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/^[\s\x00]*$/</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #0000ff;">$header</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">#           if ($header &amp;&amp; $_ =~ /^Content-type: text/) {</span>
<span style="color: #666666; font-style: italic;">#               $text = 1;</span>
<span style="color: #666666; font-style: italic;">#           }</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000066;">close</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$URL</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">close</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$CHILD</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">exit</span><span style="color: #339933;">;</span>                       <span style="color: #666666; font-style: italic;"># Exit from child process</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">#-------------------------------------------------------------------------</span>
<span style="color: #666666; font-style: italic;">#--     analyze_request                                                 --</span>
<span style="color: #666666; font-style: italic;">#--                                                                     --</span>
<span style="color: #666666; font-style: italic;">#--     Analyze a new request.  First read in first line of request.    --</span>
<span style="color: #666666; font-style: italic;">#--     Read URL from it, process URL and open connection.              --</span>
<span style="color: #666666; font-style: italic;">#--     Return an edited version of the first line and the request      --</span>
<span style="color: #666666; font-style: italic;">#--     method.                                                         --</span>
<span style="color: #666666; font-style: italic;">#-------------------------------------------------------------------------</span>
<span style="color: #000000; font-weight: bold;">sub</span> analyze_request <span style="color: #009900;">&#123;</span>
<span style="color: #666666; font-style: italic;">#---  Read first line of HTTP request</span>
    <span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$first</span> <span style="color: #339933;">=</span> <span style="color: #339933;">&lt;</span><span style="color: #0000ff;">$CHILD</span><span style="color: #339933;">&gt;;</span>
    <span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$url</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$first</span> <span style="color: #339933;">=~</span> <span style="color: #000066;">m</span><span style="color: #339933;">|</span><span style="color: #009900;">&#40;</span>http<span style="color: #339933;">://</span><span style="color: #0000ff;">\S</span><span style="color: #339933;">+</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">|</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;Request for URL:  $url <span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#---  Check if first line is of the form GET http://host-name ...</span>
    <span style="color: #b1b100;">my</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$method</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$remote_host</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$remote_port</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> 
        <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$first</span> <span style="color: #339933;">=~</span> <span style="color: #000066;">m</span><span style="color: #339933;">!</span><span style="color: #009900;">&#40;</span>GET<span style="color: #339933;">|</span>POST<span style="color: #339933;">|</span>HEAD<span style="color: #009900;">&#41;</span> http<span style="color: #339933;">://</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #339933;">^/:</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">+</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:?</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">\d</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">!</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#---  If not, bad request.</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #0000ff;">$remote_host</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$first</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">&lt;</span><span style="color: #0000ff;">$CHILD</span><span style="color: #339933;">&gt;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066;">print</span> <span style="color: #0000ff;">$_</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">last</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$_</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/^[\s\x00]*$/</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;Invalid HTTP request from &quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">$inetaddr</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$CHILD</span> <span style="color: #ff0000;">&quot;I don't understand your request.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">close</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$CHILD</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">exit</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#---  If requested URL is the proxy server then ignore request</span>
	<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$local_host</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">`hostname`</span><span style="color: #339933;">;</span>	
	<span style="color: #000066;">chop</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$local_host</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$local_ip</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">gethostbyname</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$local_host</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">4</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>		<span style="color: #666666; font-style: italic;">#Get localhost ip (packed imformation)</span>
    <span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$remote_ip</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">gethostbyname</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$remote_host</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">4</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>		<span style="color: #666666; font-style: italic;">#Get remote ip (packed imformation)</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$remote_ip</span> <span style="color: #b1b100;">eq</span> <span style="color: #0000ff;">$local_ip</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$remote_port</span> <span style="color: #b1b100;">eq</span> <span style="color: #0000ff;">$proxy_port</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$first</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">&lt;</span><span style="color: #0000ff;">$CHILD</span><span style="color: #339933;">&gt;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066;">print</span> <span style="color: #0000ff;">$_</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">last</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$_</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/^[\s\x00]*$/</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot; --- Connection to proxy server ignored.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$CHILD</span> <span style="color: #ff0000;">&quot;It's not nice to make me loop on myself!.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">close</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$CHILD</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">exit</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
<span style="color: #666666; font-style: italic;">#---  Setup connection to target host and send request</span>
    <span style="color: #0000ff;">$remote_port</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;http&quot;</span> <span style="color: #b1b100;">unless</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$remote_port</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #0000ff;">&amp;open_connection</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$URL</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$remote_host</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$remote_port</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#---  Remove remote hostname from URL</span>
        <span style="color: #0000ff;">$first</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">s/http:\/\/[^\/]+//</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$first</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$method</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$URL</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#-------------------------------------------------------------------------</span>
<span style="color: #666666; font-style: italic;">#--     listen_to_port($SOCKET, $port)                                   --</span>
<span style="color: #666666; font-style: italic;">#--                                                                     --</span>
<span style="color: #666666; font-style: italic;">#--     Create a socket that listens to a specific port                 --</span>
<span style="color: #666666; font-style: italic;">#-------------------------------------------------------------------------</span>
<span style="color: #000000; font-weight: bold;">sub</span> listen_to_port <span style="color: #009900;">&#123;</span>
    <span style="color: #000066;">local</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$port</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">local</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$max_requests</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">local</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$return_value</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #0000ff;">$max_requests</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">30</span><span style="color: #339933;">;</span>          <span style="color: #666666; font-style: italic;"># Max number of outstanding requests</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">#--- Get localhost name</span>
	<span style="color: #0000ff;">$local_hostname</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">`hostname`</span><span style="color: #339933;">;</span>	
	<span style="color: #000066;">chop</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$local_hostname</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> IO<span style="color: #339933;">::</span><span style="color: #006600;">Socket</span><span style="color: #339933;">::</span><span style="color: #006600;">INET</span> <span style="color: #009900;">&#40;</span>
    						LocalHost <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">$local_hostname</span><span style="color: #339933;">,</span>
							LocalPort <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">$port</span><span style="color: #339933;">,</span>
							Proto <span style="color: #339933;">=&gt;</span> <span style="color: #ff0000;">'tcp'</span><span style="color: #339933;">,</span>
							Listen <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">$max_request</span><span style="color: #339933;">,</span>
							ReuseAddr <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">1</span>
                                                       <span style="color: #009900;">&#41;</span>  <span style="color: #339933;">||</span> <span style="color: #000066;">die</span> <span style="color: #ff0000;">&quot;socket: $!&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">local</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$cur</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #000066;">select</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
    <span style="color: #0000ff;">$|</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>                             <span style="color: #666666; font-style: italic;"># Disable buffering on socket.</span>
    <span style="color: #000066;">select</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$cur</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#-------------------------------------------------------------------------</span>
<span style="color: #666666; font-style: italic;">#--     open_connection($SOCKET, $remote_hostname, $port)                --</span>
<span style="color: #666666; font-style: italic;">#--                                                                     --</span>
<span style="color: #666666; font-style: italic;">#--     Create a socket that connects to a certain host                 --</span>
<span style="color: #666666; font-style: italic;">#-------------------------------------------------------------------------</span>
<span style="color: #000000; font-weight: bold;">sub</span> open_connection <span style="color: #009900;">&#123;</span>
    <span style="color: #000066;">local</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$remote_hostname</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$port</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">@_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">local</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$return_value</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#-- Get the port number by service name</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$port</span> <span style="color: #339933;">!~</span> <span style="color: #009966; font-style: italic;">/^\d+$/</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #0000ff;">$port</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">getservbyname</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$port</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;tcp&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #0000ff;">$port</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">80</span> <span style="color: #b1b100;">unless</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$port</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>				<span style="color: #666666; font-style: italic;">#If the service name is not valid, give it a default number(80)</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
    <span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$remote_addr</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">gethostbyname</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$remote_hostname</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">4</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #0000ff;">$remote_addr</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">die</span> <span style="color: #ff0000;">&quot;Unknown host: $remote_hostname&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
    <span style="color: #666666; font-style: italic;">#print &quot;Connecting to $remote_hostname port $port.\n\n&quot;;</span>
    <span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> IO<span style="color: #339933;">::</span><span style="color: #006600;">Socket</span><span style="color: #339933;">::</span><span style="color: #006600;">INET</span> <span style="color: #009900;">&#40;</span>
    						PeerAddr <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">$remote_hostname</span><span style="color: #339933;">,</span>
							PeerPort <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">$port</span><span style="color: #339933;">,</span>
							Proto <span style="color: #339933;">=&gt;</span> <span style="color: #ff0000;">'tcp'</span>
                            <span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #000066;">die</span> <span style="color: #ff0000;">&quot;socket: $!&quot;</span><span style="color: #339933;">;</span>   
&nbsp;
	<span style="color: #000066;">local</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$remote_ip</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">peerhost</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>									   
    <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;Connecting to $remote_ip port $port.<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>								
&nbsp;
    <span style="color: #000066;">local</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$cur</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #000066;">select</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>  
    <span style="color: #0000ff;">$|</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>                             <span style="color: #666666; font-style: italic;"># Disable buffering on socket.</span>
    <span style="color: #000066;">select</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$cur</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p></code></p>
<p>Python版:</p>
<p><code></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;&quot;&quot;This is a simple HTTP proxy written in Python that imitate the Perl one:
&nbsp;
http://liuj.fcu.edu.tw/net_pg/proxy-stu.pl.html
&nbsp;
I wrote this in Python for classmates to compare to the one in Perl, because the 
readability of Perl is awful. You can see the readaibility is much better than 
the Perl one. You can also read this article:
&nbsp;
http://www.garshol.priv.no/download/text/perl.html
&nbsp;
to see what's wrong with Perl, and why Python.
&nbsp;
To read this program, you might need the documents of python:
http://docs.python.org/index.html
&nbsp;
You can also find older version here:
http://www.python.org/doc/versions/
&nbsp;
To learn Python, you can browse my tutorials:
http://ez2learn.com/
&nbsp;
If you got any problem about this program, feel free to ask.
&nbsp;
Author: Victor Lin (bornstub@gmail.com)
        http://blog.ez2learn.com
&nbsp;
2009/4/27 - Create first version
2009/4/30 - Fix the problem of keep-alive (fore the connection closed)
&nbsp;
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">socket</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">urlparse</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">signal</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">datetime</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> listenToPort<span style="color: black;">&#40;</span>port<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Listen to specific port and return socket
&nbsp;
    @param port: port to listen
    @return: socket
    &quot;&quot;&quot;</span>
    <span style="color: #808080; font-style: italic;"># get name of host</span>
    host = <span style="color: #dc143c;">socket</span>.<span style="color: black;">gethostbyname</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">socket</span>.<span style="color: black;">gethostname</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># create socket and bind, listen</span>
    s = <span style="color: #dc143c;">socket</span>.<span style="color: #dc143c;">socket</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">socket</span>.<span style="color: black;">AF_INET</span>, <span style="color: #dc143c;">socket</span>.<span style="color: black;">SOCK_STREAM</span><span style="color: black;">&#41;</span>
    s.<span style="color: black;">bind</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>host, port<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    s.<span style="color: black;">listen</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> s
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> openConnection<span style="color: black;">&#40;</span>host, port<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Open a connection to remote host
&nbsp;
    @param host: host to connect
    @param port: port to connect
    @return: connection socket
    &quot;&quot;&quot;</span>
    <span style="color: #808080; font-style: italic;"># create socket for connecting remote host</span>
    remote = <span style="color: #dc143c;">socket</span>.<span style="color: #dc143c;">socket</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">socket</span>.<span style="color: black;">AF_INET</span>, <span style="color: #dc143c;">socket</span>.<span style="color: black;">SOCK_STREAM</span><span style="color: black;">&#41;</span>
    ip = <span style="color: #dc143c;">socket</span>.<span style="color: black;">gethostbyname</span><span style="color: black;">&#40;</span>host<span style="color: black;">&#41;</span>
    remote.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>ip, port<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> remote
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> analyzeRequest<span style="color: black;">&#40;</span>client<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Parse http request
&nbsp;
    @param child: file of client socket to read request and parse
    @return: (first line of request for http server, http method, socket to url)
    &quot;&quot;&quot;</span>
    first = client.<span style="color: #dc143c;">readline</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># parse first line</span>
    method, url, version = first.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># parse url</span>
    result = <span style="color: #dc143c;">urlparse</span>.<span style="color: #dc143c;">urlparse</span><span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>
    host = result<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> result<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>.<span style="color: black;">find</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">':'</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">!</span>= -<span style="color: #ff4500;">1</span>:
        host, port = host.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">':'</span><span style="color: black;">&#41;</span>
        port = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>port<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        port = <span style="color: #ff4500;">80</span>
    url = <span style="color: #dc143c;">urlparse</span>.<span style="color: black;">urlunparse</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span>, <span style="color: #483d8b;">''</span><span style="color: black;">&#41;</span> + result<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span>:<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># check is there a loop</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> host == <span style="color: #dc143c;">socket</span>.<span style="color: black;">gethostname</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">or</span> host == <span style="color: #483d8b;">'127.0.0.1'</span> <span style="color: #ff7700;font-weight:bold;">or</span> \
        host.<span style="color: black;">lower</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> == <span style="color: #483d8b;">'localhost'</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot; --- Connection to proxy server ignored.&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span> <span style="color: #008000;">file</span>, <span style="color: #483d8b;">&quot;It's not nice to make me loop on myself!.&quot;</span>
        client.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    remote = openConnection<span style="color: black;">&#40;</span>host, port<span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># the first line for remote socket</span>
    first = <span style="color: #483d8b;">&quot;%s %s %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>method, url, version<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> first, method, remote
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">1</span>:
        proxyPort = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span> 
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        proxyPort = <span style="color: #ff4500;">5364</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">##--- Step 1 : Create Socket ---##</span>
    s = listenToPort<span style="color: black;">&#40;</span>proxyPort<span style="color: black;">&#41;</span>
    ip, port = s.<span style="color: black;">getsockname</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot; --- Proxy server running on %s ( %s ) port: %d&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>
        <span style="color: #dc143c;">socket</span>.<span style="color: black;">gethostname</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, ip, port<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">##--- Step 2 : Wait for request ---##</span>
    <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff4500;">1</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot; --- Waiting to be of service ...&quot;</span>
        client, address = s.<span style="color: black;">accept</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        clientFile = client.<span style="color: black;">makefile</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        ip, port = address
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Connection from %s port: %d&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>ip, port<span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;">##---  Step 3 : Read first line of request and analyze it. ---##</span>
        first, method, remote = analyzeRequest<span style="color: black;">&#40;</span>clientFile<span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;">##---  Step 4 : Send request to remote host ---##</span>
        remoteFile = remote.<span style="color: black;">makefile</span><span style="color: black;">&#40;</span>bufsize=<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># write first line to remote server</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span> remoteFile, first
        <span style="color: #ff7700;font-weight:bold;">print</span> first
        <span style="color: #808080; font-style: italic;"># force the remote connection closed as finish this request</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span> remoteFile, <span style="color: #483d8b;">'Connection: close'</span>
        <span style="color: #808080; font-style: italic;"># read headers from client</span>
        contentLength = <span style="color: #ff4500;">0</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> line <span style="color: #ff7700;font-weight:bold;">in</span> clientFile:
            line = line.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">print</span> line
            <span style="color: #808080; font-style: italic;"># filter headers that we don't want they passed to server</span>
            match = <span style="color: #008000;">False</span>
            <span style="color: #ff7700;font-weight:bold;">for</span> header <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">'connection:'</span>, <span style="color: #483d8b;">'proxy-connection:'</span>, <span style="color: #483d8b;">'keep-alive:'</span><span style="color: black;">&#93;</span>:
                <span style="color: #ff7700;font-weight:bold;">if</span> line.<span style="color: black;">lower</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span>header<span style="color: black;">&#41;</span>:
                    match = <span style="color: #008000;">True</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> match:
                <span style="color: #ff7700;font-weight:bold;">continue</span>
            <span style="color: #808080; font-style: italic;"># get content length</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> line.<span style="color: black;">lower</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'content-length:'</span><span style="color: black;">&#41;</span>:
                _, length = line.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">':'</span><span style="color: black;">&#41;</span>
                contentLength = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>length<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span> remoteFile, line
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> line:
                <span style="color: #ff7700;font-weight:bold;">break</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> method == <span style="color: #483d8b;">&quot;POST&quot;</span>:            
            <span style="color: #ff7700;font-weight:bold;">if</span> contentLength <span style="color: #66cc66;">!</span>= <span style="color: #ff4500;">0</span>:
                data = clientFile.<span style="color: black;">read</span><span style="color: black;">&#40;</span>contentLength<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">else</span>:
                data = clientFile.<span style="color: #dc143c;">readline</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;POST body:&quot;</span>, data
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span> remoteFile, data
&nbsp;
        <span style="color: #808080; font-style: italic;">##---  Step 5 : Wait for response and transfer it to requestor. ---##    </span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot; --- Done sending. Response: &quot;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span>
&nbsp;
        contentLength = <span style="color: #008000;">None</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> line <span style="color: #ff7700;font-weight:bold;">in</span> remoteFile:
            line = line.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span> clientFile, line
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> line:
                <span style="color: #ff7700;font-weight:bold;">break</span>
            <span style="color: #ff7700;font-weight:bold;">print</span> line
            <span style="color: #ff7700;font-weight:bold;">if</span> line.<span style="color: black;">lower</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'content-length:'</span><span style="color: black;">&#41;</span>:
                _, length = line.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">':'</span><span style="color: black;">&#41;</span>
                contentLength = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>length<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> contentLength <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">None</span>:
            body = remoteFile.<span style="color: black;">read</span><span style="color: black;">&#40;</span>contentLength<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            body = remoteFile.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
        clientFile.<span style="color: black;">write</span><span style="color: black;">&#40;</span>body<span style="color: black;">&#41;</span>
&nbsp;
        remoteFile.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        clientFile.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p></code><br />
可讀性很明顯地Python優於Perl，我在這裡說明為什麼，原因其實很簡單，因為Perl加太多語法和用太多特殊符號在他的語言中，Perl對於正規表示法有語法，對於讀檔有特別的語法，對於向系統下指令有特別的語法，Perl對於這些瑣碎的功能加了太多的語法，使得用Perl寫出來的程式難以被簡單的理解，舉個最顯著的例子，就是他的特別變數，Perl有一系列$開頭的特別變數，在那程式裡就出現了幾次</p>
<blockquote><p>$$<br />
$|<br />
$_</p></blockquote>
<p>請問這三個特別變數在Perl中各代表什麼意思? 除非你真的對Perl很熟，否則答案肯定是我不知道，我得翻手冊，這就是為什麼Perl可讀性較差的原因之一，Perl的可讀性一直是很多人所詬病的，接著我們在裡面看到有一行很有趣的是有註解的，他這樣寫</p>
<blockquote><p>$| = 1;    #Disable buffering</p></blockquote>
<p>如果他不寫註解，我敢打賭沒幾個人能光看那一行知道這是在幹什麼的，因為我不太清楚它要disable buffering的原因，而disable buffering又是指哪個buffer? 網路? STDIO? 而且不那樣做也不會怎樣，所以我在Python版裡沒有照著寫這行，但是我們假設我們也需要在Python裡寫這行，那可能會是怎樣寫，我們假設他是要disable socket的buffering，而且我們假設Python有個函數叫disableBuffering()，所以我們相對應的Python版本就這樣寫</p>
<blockquote><p>disableBuffering()</p></blockquote>
<p>看出差別了嗎? 是的，Perl將這些符號做為特殊用途，加了很多特殊的語法，雖然讓程式較短較好寫，但是很明顯地讓可讀性大大地降低，在沒有查手冊之前根本沒辦法得知這一行到底是在做什麼用的，然而，因為用語法來實現太多功能，某種程度上算是不良的設計，因為他們都能夠用函式或函式庫來取代，而函式庫的取代雖然要寫多一點字，但是可讀性大大提升，光是看到disableBuffering()這樣的函數名稱就能很清楚地明白這一行是在做什麼用的，可讀性的差別就是這些語言的天性，也是判斷程式語言優劣的關鍵之一</p>
<h3>可寫性</h3>
<p>可寫性是指一款程式語言是否很容易撰寫</p>
<p>通常當一款程式語言很囉唆或不直覺時，他的可寫性會比較差，但相對的可讀性可能會比較好，反之亦然，以Perl為例子，如果你對那些符號很熟，你可以打很少的字，就寫出你要的功能，但是那樣犧牲了可讀性，但是其實某些情況下可讀性和可寫性都可以達到一個很不錯的平衡，我認為Python就是這樣的例子，Python因為語法限制性高，加上符號的定義也很簡短，所以寫Python的速度很快</p>
<h3>可靠性</h3>
<p>可靠性是指不易讓使用者犯錯，而犯錯也可以很容易的找出來</p>
<p>這比起可讀性和可寫性較難以解釋，但是我想這樣說，如果你受傷不會覺得痛，會發生什麼事? 答案很簡單，很快的你就會上西天，人類的痛覺是一種可以自我警告的系統，而程式的可靠性，所指的犯錯容易找出來也就是這個意思，試想一下，當你不小心打錯了程式，但是因為程式語言語法設計上很寬鬆，編譯一樣可以通過，他沒有警告你錯誤，程式可以執行，但是卻不是正確地執行，很明顯的後果就是開發者沒辦法輕易的得知這個問題，更糟的是因為沒有辦法偵測出錯誤，錯誤一樣還在那裡，如果你開發的是飛機的飛航系統，很快的你的程式在開發期間沒有讓你知道有問題，當真正運行時問題才暴發開來，這時麻煩就大了，這就是為什麼可靠性很重要的原因，舉個C語言的實例</p>
<pre lang="c++">int array[10];
int i = 13;
array[i] = 5; // oops</pre>
<p>請問上面這段程式碼會有什麼樣的結果呢? 首先，這樣寫語法正確，所以可以執行，而C語言為了效能考量並不會對陣列索引的邊界做檢查，所以當你的程式跑到最後一行，對一個超出你陣列範圍的整數做指派會發生什麼事? 答案是不知道，很簡單的原因是，這array是放在stack裡的，你今天對他做存取，它會從它在stack中分配到的空間位置往下加元素個數乘上索引的大小，因為他不做檢查，所以只是忠實地去做，所以要看在stack中那個位置到底是什麼，那個倒霉鬼可能是呼叫函數的位址，可能是某人分配的區域變數，端看當時的環境是怎樣，被蓋掉的那塊記憶體的用途不同，發生的事情也會不一樣，這個叫做行為未定義，你永遠沒辦法確切的說出會發生什麼事，就像你拿一塊石頭從101往下丟一樣，會不會砸到人、砸到誰根本都是無法預知的事情，這整個程式碼所要呈現的重點就在於，因為為了效率考量，不做檢查，所以出錯也沒辦法知道，C語言就是這樣自由的語言，因為這樣的特性使它在低階的應用上受到歡迎，但是也因為這樣，很多新手程式設計師難以駕禦C/C++就是這個原因，因為C/C++太自由了，他們常常會怎麼死的都不知道</p>
<p>因此，做為一款嚴僅的程式語言，最好要能盡早在程式的編譯時期，就讓使用者知道出錯了，語法錯誤的檢查某些程度上來說是這樣的用意，C++ meta-programming的觀念裡，也有一條讓錯誤盡早在編譯時期被發現，與其等程式執行了才出錯，在編譯時期就發現才是比較好的，因為程式執行的不確定性比較多</p>
<h3>可攜性</h3>
<p>可攜性是指一個程式語言對於環境的依賴性有多低</p>
<p>我們都習慣使用Windows作業系統，但是事實上世界上還有很多種不同的電腦作業的環境，程式是要在這些環境中執行的，一個可攜性好的程式語言應該要和平台沒有關聯，或是做適當的介面來降低藕合度，舉個例子，你如果用VB6.0寫一個視窗程式，那麼他可以在Linux下面跑嗎? 就我所知的答案應該是不行，而相對於Python，Python的語言基本上是和平台無關的，如果搭配一個一樣可攜性很好的視窗函式庫就能寫出跨平台的視窗程式，能在Windows下跑，也能在Linux跑，所以相較之下Python的可攜性就比VB6.0來得好很多，大多數常見的程式語言可攜性其實都很不錯，從C/C++、Java、Perl、Python等都能在各大平台看到這些語言的身影，但是也是有某種程度上的差別，有些語言雖然有可攜性，但並不是完全地可攜，C/C++就是很好的例子，同樣一隻程式，在不同的環境下，很多時候你可能得視你編譯的環境、平台來對程式做某種程度上的修改，才能在其它平台執行，因為他是屬於靜態的語言，所以沒有辦法，靜態語言的可攜性基本上會比動態語言差</p>
<h2>主觀的評估條件</h2>
<p>上面提到的那些是客觀的評估條件，照程式語言裡的話，其實還少了成本和一些瑣碎的部份，但因為太囉唆就不在這裡多提，接著要介紹的就是主觀的程式語言好壞的評估條件，基本上我所學的程式語言課程沒有提到這部份，是我自己加上來的，因為我覺得這是很重要的一個部份，在評估完上面這些項目後，要來看的就是主觀的評估項目</p>
<h3>語言哲學</h3>
<p>我所能想到最主要也最重要的主觀評估條件就是語言背後的哲學，很多語言設計都有思想的，不是高興隨便亂設計的，他們很多都是從這些中心思想出發來進行設計，當遇到設計上的兩難問題時，他們會以這些中心思想來做為發想，並不是每款程式語言都有顯著的哲學口號，或許是我不知道，我在想brainfuck的哲學思想是"Fuck your brain"嗎?</p>
<p>但是有一些語言的中心思想很明確，而且他們也都照著這個中心思想在發展，有趣的是有兩個完全相反的中心思想，剛好是做為語言設計的哲學例子，那就是Perl和Python，首先來看Perl的哲學:</p>
<blockquote><p><a href="http://en.wikipedia.org/wiki/There%27s_more_than_one_way_to_do_it">There&#8217;s more than one way to do it</a></p></blockquote>
<p>他的想法就是，可以有很多種方法可以辦到同樣的事情，而Zen of Python，也就是Python的禪道剛好相反</p>
<blockquote><p>There should be one&#8211; and preferably only one &#8211;obvious way to do it.</p></blockquote>
<p>我對於Perl的思想不瞭解，我不太明白他們那樣想的理由是什麼，但是我很清楚Python他所想表達的，相較於Perl，因為同一件事情可以有很多方法達成的話，那麼通常依照人的性格，一百個人可能就會寫出一百種不同的程式，而且在這些程式中有大部份都是濫用的程式，程式碼也因為可能性太多，會難以理解，但是以相反的哲學來設計的話，只有一個明確的方法，那麼就直接使用吧，一來不需要花額外的時間浪費在思考非解決問題的關鍵上，接著也因為只有一個明顯的方法來達成，可讀性自然也較佳，因為顯而易見，這是我對Python禪到的見解，但是佛曰: 不可說，即然他名為禪我想意思就是要你自己悟，這就是一個程式語言背後哲學有趣的地方</p>
<p>然而，上面Python提到的這句話，並不是Python禪道的全部，而是做為中心思想很重要的一句，事實上<a href="http://www.python.org/dev/peps/pep-0020/">Python的禪</a>是由好幾句組成的:</p>
<blockquote><p>Beautiful is better than ugly.<br />
Explicit is better than implicit.<br />
Simple is better than complex.<br />
Complex is better than complicated.<br />
Flat is better than nested.<br />
Sparse is better than dense.<br />
Readability counts.<br />
Special cases aren&#8217;t special enough to break the rules.<br />
Although practicality beats purity.<br />
Errors should never pass silently.<br />
Unless explicitly silenced.<br />
In the face of ambiguity, refuse the temptation to guess.<br />
There should be one&#8211; and preferably only one &#8211;obvious way to do it.<br />
Although that way may not be obvious at first unless you&#8217;re Dutch.<br />
Now is better than never.<br />
Although never is often better than *right* now.<br />
If the implementation is hard to explain, it&#8217;s a bad idea.<br />
If the implementation is easy to explain, it may be a good idea.<br />
Namespaces are one honking great idea &#8212; let&#8217;s do more of those!</p></blockquote>
<p>這麼多的句子，以我快十年寫程式的經驗，我都能很認同這些話所說的，不過有些我還是不太明白，像是Simple is better than complex.就顯而易見的是KISS原則，而後面的Complex is better than complicated.就不太瞭解他所表答的意思</p>
<p>做為一款優秀的語言，Python有他精深的哲學做為發展的中心思想，而這思想也深得我心，所以我喜歡Python，Python的所做所為都能體現出他寫的這些，每個人認同的哲學可能會不太一樣，而做為認同的這部份，就是較為主觀的評估條件，做為程式語言的哲學，上面那些客觀層面討論完之後，剩下的就是這些思想，而思想就很難分對錯，這也是為什麼程式語言討論好壞最後都變成無止盡的爭論，因為他們的中心思想不一樣</p>
<h2>結論</h2>
<p>寫了這麼多，就是希望大家能夠瞭解程式語言要怎樣比較，不是說程式語言沒有好壞之分來當做不知道怎麼評估的藉口，又或著只會單靠喜好來決定程式語言</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ez2learn.com/2010/01/08/how-to-compare-languages/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>以前的PHP有很多缺陷</title>
		<link>http://blog.ez2learn.com/2010/01/06/old-php-sucks/</link>
		<comments>http://blog.ez2learn.com/2010/01/06/old-php-sucks/#comments</comments>
		<pubDate>Wed, 06 Jan 2010 15:42:15 +0000</pubDate>
		<dc:creator>victor</dc:creator>
				<category><![CDATA[中文文章]]></category>
		<category><![CDATA[分享]]></category>
		<category><![CDATA[WTF]]></category>
		<category><![CDATA[爛]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[sucks]]></category>
		<category><![CDATA[TurboGears]]></category>

		<guid isPermaLink="false">http://blog.ez2learn.com/?p=907</guid>
		<description><![CDATA[有人在plurk上PO了一篇文章的連結，PHP 開發迷思 (三) – PHP 很糟糕？，因為我不認同那樣的看法，所以我回覆說php很爛，當你說一個語言很爛時，就要有心理準備有人準備要跟你戰了，果然有人不認同我的說法，當然任何人都可以不認同我所說的，而且好和爛是很主觀的，同時也是是相對的，但是我所說的是有根據的，說php爛不是我一個人的說法，而是已經被說到爛掉的說法，很多比我有經驗多的網頁程式設計師都異口同聲的說PHP很爛，為了解釋為什麼我認為PHP很爛(我在本文指的爛是指語言設計上的眾多嚴重缺陷)，我寫了這篇文章 更新: 我承認這篇寫得有點偏激，也是以前的觀點，也是在發洩以前對PHP的不滿，我沒有寫較新的PHP，所以我收回PHP很爛，改成以前的PHP有很多缺陷，我想表達的是一款語言的很多缺陷，而且是在以前的缺陷，現在PHP確實有改進很多，所以我寫了一篇 如何評估比較程式語言 另外我想表達的一件事是，當有人說你用的程式語言有問題時，為什麼一定要這麼抓狂呢? 如果一個程式語言它的缺陷沒有人罵，大家都愛語言如命，那麼語言的開發者或團隊要如何知道這語言要改進什麼呢? PHP有很多缺陷是事實，然而說出來很多人可能就不高興，然而我選擇用較激烈的字眼是因為他改進實在太慢了，我們可以看到以前的Magic quote、unicode問題等等，至今都仍未解決，要php6才會解決，這些問題不是只有我覺得很糟，而是我發現很多人都跟我一樣覺得這太差了，我每次罵PHP都真的很希望他在下一個版本就把這些鳥問題解決掉，但以我之前的經驗它都讓我失望，所以我怨念很深，這篇文章寫起來也特別偏激，但我想表達的是，我說PHP爛某種程度是希望他變好，那你可能會問，我為什麼不說Python爛，然後哪裡爛，很簡單的原因是我太喜歡Python，當你很喜歡一個東西時你是看不見這東西的缺點，如果有人說Python爛，我覺得很好，我想知道他有哪些缺陷，是我沒看到的 除此之外，對於初學者來說，PHP的低門檻讓他成為吸引新手的蜜罐，而很多人都只知道PHP可以寫網頁，但是不知道其實所有程式語言都能寫網頁，我希望透過罵PHP也能讓更多人知道其實還有更多選擇，但其實這會讓人覺得反感，我在這背後目的是希望其它語言能夠有更多人使用，有競爭才有進步，而對於國內大部份人都只用PHP在刻網頁我也覺得很失望，我同時也希望讓大家知道其實網頁的技術現在已經很先進了，很少有人使用框架等次世代的網頁技術，所以有興趣也可以看一些較新的技術，而不是土法煉鋼 美與醜 當路上走來一個女的，一個人說她很正，另一個人說她很醜，美醜好壞基本上都是主觀的，而且是相對的，如果說走在路上的那個女生是世界上唯一的女生，那麼何從比較她的美醜呢? 我今天說PHP很爛，是基於我的經驗，和看別人的經驗，我有用不同的語言、工具寫過網頁程式，在這樣的情況下，因為經過比較才有辦法知道好壞，有趣的是在Plurk裡的討論有人甚至懷疑我沒寫過PHP，我個人比較喜歡就事論事，不太喜歡用質疑對方的立場來證明自己的說法，當別人懷疑你經歷時，你一樣可以這樣懷疑別人，像是「你們有沒有用非PHP的平台寫過網頁程式?」，「你們有沒有用現代一點的平台像是Django、ROR寫過網頁程式?」，但是這樣會讓問題失焦，到後來變成在檢視對方背景來決定他講這話是否是對的，而沒有去看這些話是否是真的正確或有道理，即使這是一個主觀的問題，而我描述的只是依我經驗和認知所得到的想法，每個人都可以不同意我所說的，但是那些確實是我所經歷過的，我可以說謊「天阿~ PHP好棒，大家快去學」，或是選擇不發言，但是當我說出「PHP很爛」，千真萬確是我的心得 我的經驗 我在小學六年級時家裡有了撥接的網路，在那時候開始學習怎麼寫網頁，當時所謂的網頁，也只是到處亂貼一些資料，整畫面閃來閃去的GIF圖檔，都是那時候新手網頁的調調，更誇張一點會加一堆亂七八糟的特效，上傳到免費的空間，我還記得當時申請的空間叫台北酒巴什麼的，當時真的覺得做網頁是件很酷的事情，在我學習寫程式之前其實大多都在做網頁，做破破爛爛的網頁，但是樂在其中，當時覺得程式真是很神奇的東西，有時會載一些用perl寫的cgi程式來架架看，光是架那些留言板或聊天室之類的，就是一件大工程，當時對於行末少一個;就沒辦法執行這件事覺得很驚訝，居然程式只要一個符號錯了就不能跑，那到底要怎麼寫? 當我上國一開始自己學寫VB6.0之後，因為有了VB6.0的程式設計經驗，我終於漸漸瞭解perl的cgi怎麼寫，這之中我記得我也有碰過ASP，因為他語法和VB一樣，但是並沒有太深入，後來因為我父親想弄一個放他文章的網站，於是我就用Perl-CGI幫他寫了一套文章管理系統，自己也順便做了一個個人工作室的網站 Victor工作室 我可以透過後台管理系統來新增消息，或是檔案下載等等，同時我也用Perl-CGI寫了一個留言版系統 Victor工作室 &#8211; 留言版 1.1 Beta 可以在這裡下載，在寫了這麼多Perl-CGI的程式後，發現PHP這東西好像漸漸流行起來，越來越多用PHP寫的網站、免費的網頁程式等等，在這之前幾乎都是Perl-CGI的天下，PHP做為後起之秀取而代之，因為他的門檻比Perl還低，同時比起Perl，PHP的程式也好懂許多，所以我也開始學習PHP，PHP絕對是當時最佳選擇之一，當之無愧，在寫的過程中有遇過不少問題，像是許功蓋問題，處理SQL Injection的問題，PHP的自動引號取代問題(Magic quote)，這些是顯著的問題，但有些問題在當時一直感覺不太對勁，但是也說不出個所以然，像是它的形別等等問題，相較於我當時所會的VB，PHP是一款非常不嚴僅的語言，但是我在當時並不覺得它很爛，可能是因為不知道有其它選擇，又或著當時真的沒什麼選擇，所以一邊學PHP，一邊我就把之前寫的文章系統改成用PHP重寫，到今天我父親還在使用這套系統: 金門根本文采工作室 在這之後有很長的時間，寫網頁我也都是用PHP，直到我學會了Python，大約已經是大二以後的事了，在那時我選擇了TurboGears當網頁框架，那時我回首過去，才深深地發現PHP是一款多麼爛的語言，在當時他或許是開路先鋒，讓網頁程式開發的門檻降低到一定的程度，但是在我學習寫TurboGears時他還是一樣的爛，以前我遇過的那些問題大多數都還在，而且學會了Python這種清晰的語言更加地覺得PHP真的很污穢，在那之後我用TurboGears開發了一些網頁，我以前在PHP遇到的鳥問題從來都沒有再碰到過，開發的速度也大大加快，我能夠專注在我所想開發的功能上，而不是整天去處理那些鳥問題，安全性也大大提升，目前那些網頁還在跑的有 Walele創意投票系統 是一個線上投票系統，從決定到開發完成上線只用了一週的課餘時間，用的是TurboGears1 Now.In廣播平台 是一個線上廣播平台，目前還在beta版的階段，用的是TurboGears2 試鏡報名系統 用一個晚上寫出來的試鏡報名系統，可以上傳照片，後面還有一個後台可以看資料 我承認我寫的網頁程式其實不多，但是從我第一個寫的網頁到今天已經有十年以上，我看見網路的發展，網頁開發工具的演進，PHP在以前我不會說他爛，因為他是開路先鋒，沒有他網頁程式設計可能難以上手，但是這麼多年來他有在改進，但是改進實在太慢，問題還是一大堆，再加上他改進的方式都是疊床架屋，而不是正視問題並解決它，再者相較於現代的網頁開發工具，PHP真的是太落伍了，先天不良，後天失調，所以今天我才說PHP很爛，即使PHP有了不少網頁框架，還是擺脫不他那語言本身就一堆問題的原罪，他之所以會大流行，回首當時，不外乎就是當時正好缺少一個低門檻的網頁開發工具、平台，PHP來得正是時候，所以大紅大紫，但是即使再怎麼流行也不能抹掉PHP語言設計很爛的這個事實 &#8230; <a href="http://blog.ez2learn.com/2010/01/06/old-php-sucks/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>有人在plurk上PO了一篇文章的連結，<a href="http://www.jaceju.net/blog/?p=936">PHP 開發迷思 (三) – PHP 很糟糕？</a>，因為我不認同那樣的看法，所以我回覆說php很爛，當你說一個語言很爛時，就要有心理準備有人準備要跟你戰了，果然有人不認同我的說法，當然任何人都可以不認同我所說的，而且好和爛是很主觀的，同時也是是相對的，但是我所說的是有根據的，說php爛不是我一個人的說法，而是已經被說到爛掉的說法，很多比我有經驗多的網頁程式設計師都異口同聲的說PHP很爛，為了解釋為什麼我認為PHP很爛<strong>(我在本文指的爛是指語言設計上的眾多嚴重缺陷)</strong>，我寫了這篇文章</p>
<h3>更新:</h3>
<p>我承認這篇寫得有點偏激，也是以前的觀點，也是在發洩以前對PHP的不滿，我沒有寫較新的PHP，所以我收回PHP很爛，改成以前的PHP有很多缺陷，我想表達的是一款語言的很多缺陷，而且是在以前的缺陷，現在PHP確實有改進很多，所以我寫了一篇 <a href="http://blog.ez2learn.com/2010/01/08/how-to-compare-languages/">如何評估比較程式語言</a></p>
<p>另外我想表達的一件事是，當有人說你用的程式語言有問題時，為什麼一定要這麼抓狂呢? 如果一個程式語言它的缺陷沒有人罵，大家都愛語言如命，那麼語言的開發者或團隊要如何知道這語言要改進什麼呢? PHP有很多缺陷是事實，然而說出來很多人可能就不高興，然而我選擇用較激烈的字眼是因為他改進實在太慢了，我們可以看到以前的Magic quote、unicode問題等等，至今都仍未解決，要php6才會解決，這些問題不是只有我覺得很糟，而是我發現很多人都跟我一樣覺得這太差了，我每次罵PHP都真的很希望他在下一個版本就把這些鳥問題解決掉，但以我之前的經驗它都讓我失望，所以我怨念很深，這篇文章寫起來也特別偏激，但我想表達的是，我說PHP爛某種程度是希望他變好，那你可能會問，我為什麼不說Python爛，然後哪裡爛，很簡單的原因是我太喜歡Python，當你很喜歡一個東西時你是看不見這東西的缺點，如果有人說Python爛，我覺得很好，我想知道他有哪些缺陷，是我沒看到的</p>
<p>除此之外，對於初學者來說，PHP的低門檻讓他成為吸引新手的蜜罐，而很多人都只知道PHP可以寫網頁，但是不知道其實所有程式語言都能寫網頁，我希望透過罵PHP也能讓更多人知道其實還有更多選擇，但其實這會讓人覺得反感，我在這背後目的是希望其它語言能夠有更多人使用，有競爭才有進步，而對於國內大部份人都只用PHP在刻網頁我也覺得很失望，我同時也希望讓大家知道其實網頁的技術現在已經很先進了，很少有人使用框架等次世代的網頁技術，所以有興趣也可以看一些較新的技術，而不是土法煉鋼</p>
<p><span id="more-907"></span></p>
<h2>美與醜</h2>
<p>當路上走來一個女的，一個人說她很正，另一個人說她很醜，美醜好壞基本上都是主觀的，而且是相對的，如果說走在路上的那個女生是世界上唯一的女生，那麼何從比較她的美醜呢? 我今天說PHP很爛，是基於我的經驗，和看別人的經驗，我有用不同的語言、工具寫過網頁程式，在這樣的情況下，因為經過比較才有辦法知道好壞，有趣的是在Plurk裡的討論有人甚至懷疑我沒寫過PHP，我個人比較喜歡就事論事，不太喜歡用質疑對方的立場來證明自己的說法，當別人懷疑你經歷時，你一樣可以這樣懷疑別人，像是「你們有沒有用非PHP的平台寫過網頁程式?」，「你們有沒有用現代一點的平台像是Django、ROR寫過網頁程式?」，但是這樣會讓問題失焦，到後來變成在檢視對方背景來決定他講這話是否是對的，而沒有去看這些話是否是真的正確或有道理，即使這是一個主觀的問題，而我描述的只是依我經驗和認知所得到的想法，每個人都可以不同意我所說的，但是那些確實是我所經歷過的，我可以說謊「天阿~ PHP好棒，大家快去學」，或是選擇不發言，但是當我說出「PHP很爛」，千真萬確是我的心得</p>
<h2>我的經驗</h2>
<p>我在小學六年級時家裡有了撥接的網路，在那時候開始學習怎麼寫網頁，當時所謂的網頁，也只是到處亂貼一些資料，整畫面閃來閃去的GIF圖檔，都是那時候新手網頁的調調，更誇張一點會加一堆亂七八糟的特效，上傳到免費的空間，我還記得當時申請的空間叫台北酒巴什麼的，當時真的覺得做網頁是件很酷的事情，在我學習寫程式之前其實大多都在做網頁，做破破爛爛的網頁，但是樂在其中，當時覺得程式真是很神奇的東西，有時會載一些用perl寫的cgi程式來架架看，光是架那些留言板或聊天室之類的，就是一件大工程，當時對於行末少一個;就沒辦法執行這件事覺得很驚訝，居然程式只要一個符號錯了就不能跑，那到底要怎麼寫?</p>
<p>當我上國一開始自己學寫VB6.0之後，因為有了VB6.0的程式設計經驗，我終於漸漸瞭解perl的cgi怎麼寫，這之中我記得我也有碰過ASP，因為他語法和VB一樣，但是並沒有太深入，後來因為我父親想弄一個放他文章的網站，於是我就用Perl-CGI幫他寫了一套文章管理系統，自己也順便做了一個個人工作室的網站</p>
<p><a href="http://www.kinmen.info/vic/">Victor工作室</a></p>
<p>我可以透過後台管理系統來新增消息，或是檔案下載等等，同時我也用Perl-CGI寫了一個留言版系統</p>
<p><a href="http://www.kinmen.info/vic/book/index.pl">Victor工作室 &#8211; 留言版 1.1 Beta</a></p>
<p>可以在<a href="http://www.kinmen.info/vic/download.pl#2">這裡下載</a>，在寫了這麼多Perl-CGI的程式後，發現PHP這東西好像漸漸流行起來，越來越多用PHP寫的網站、免費的網頁程式等等，在這之前幾乎都是Perl-CGI的天下，PHP做為後起之秀取而代之，因為他的門檻比Perl還低，同時比起Perl，PHP的程式也好懂許多，所以我也開始學習PHP，PHP絕對是當時最佳選擇之一，當之無愧，在寫的過程中有遇過不少問題，像是許功蓋問題，處理SQL Injection的問題，PHP的自動引號取代問題(Magic quote)，這些是顯著的問題，但有些問題在當時一直感覺不太對勁，但是也說不出個所以然，像是它的形別等等問題，相較於我當時所會的VB，PHP是一款非常不嚴僅的語言，但是我在當時並不覺得它很爛，可能是因為不知道有其它選擇，又或著當時真的沒什麼選擇，所以一邊學PHP，一邊我就把之前寫的文章系統改成用PHP重寫，到今天我父親還在使用這套系統:</p>
<p><a href="http://www.kinmen.info/">金門根本文采工作室</a></p>
<p>在這之後有很長的時間，寫網頁我也都是用PHP，直到我學會了Python，大約已經是大二以後的事了，在那時我選擇了TurboGears當網頁框架，那時我回首過去，才深深地發現PHP是一款多麼爛的語言，在當時他或許是開路先鋒，讓網頁程式開發的門檻降低到一定的程度，但是在我學習寫TurboGears時他還是一樣的爛，以前我遇過的那些問題大多數都還在，而且學會了Python這種清晰的語言更加地覺得PHP真的很污穢，在那之後我用TurboGears開發了一些網頁，我以前在PHP遇到的鳥問題從來都沒有再碰到過，開發的速度也大大加快，我能夠專注在我所想開發的功能上，而不是整天去處理那些鳥問題，安全性也大大提升，目前那些網頁還在跑的有</p>
<p><a href="http://walele.com/">Walele創意投票系統</a> 是一個線上投票系統，從決定到開發完成上線只用了一週的課餘時間，用的是TurboGears1</p>
<p><a href="http://now.in">Now.In廣播平台</a> 是一個線上廣播平台，目前還在beta版的階段，用的是TurboGears2</p>
<p><a href="http://tiangeapp.ez2learn.com/screentest/form">試鏡報名系統</a> 用一個晚上寫出來的試鏡報名系統，可以上傳照片，後面還有一個後台可以看資料</p>
<p>我承認我寫的網頁程式其實不多，但是從我第一個寫的網頁到今天已經有十年以上，我看見網路的發展，網頁開發工具的演進，PHP在以前我不會說他爛，因為他是開路先鋒，沒有他網頁程式設計可能難以上手，但是這麼多年來他有在改進，但是改進實在太慢，問題還是一大堆，再加上他改進的方式都是疊床架屋，而不是正視問題並解決它，再者相較於現代的網頁開發工具，PHP真的是太落伍了，先天不良，後天失調，所以今天我才說PHP很爛，即使PHP有了不少網頁框架，還是擺脫不他那語言本身就一堆問題的原罪，他之所以會大流行，回首當時，不外乎就是當時正好缺少一個低門檻的網頁開發工具、平台，PHP來得正是時候，所以大紅大紫，但是即使再怎麼流行也不能抹掉PHP語言設計很爛的這個事實</p>
<h2>其它人的看法</h2>
<p>我知道我說的可能很多人不認同，又或著不相信，但如果是大部份有接觸過現代網頁開發平台，很有經驗的網頁開發者都異口同聲的說php sucks呢? 在Google搜尋 "php sucks"，可以找到一大堆的網頁，他們都在說PHP很爛，我在此引用幾篇他們寫的</p>
<h3><a href="http://maurus.net/resources/programming-languages/php/">I’m sorry, but PHP sucks.</a></h3>
<p>這篇文章清楚地條列出PHP哪裡爛，會遇到哪些麻煩的問題，像是字元支援的問題、不相容的問題、它莫名奇妙的形別系統等等</p>
<h3><a href="http://www.codinghorror.com/blog/archives/001119.html">PHP Sucks, But It Doesn&#8217;t Matter</a></h3>
<p>這篇文章引用其它人的說法，和他自己的經驗來說明PHP很爛，他這麼說道</p>
<blockquote><p>I&#8217;ve written both VB and PHP code, and in my opinion the comparison is grossly unfair to Visual Basic. Does PHP suck? Of course it sucks. Did you read any of the links in Tim&#8217;s blog entry? It&#8217;s a galactic supernova of incomprehensibly colossal, mind-bendingly awful suck. If you sit down to program in PHP and have even an ounce of programming talent in your entire body, there&#8217;s no possible way to draw any other conclusion. It&#8217;s inescapable.</p></blockquote>
<p>大略翻譯是:</p>
<p style="padding-left: 30px;">PHP很爛? 當然它很爛，你有讀Tim部落格裡引用的每個連結嗎? 它真的是宇宙超級霹靂無敵的爛，就算你有一身寫PHP的才能，也沒辦法下任何其它的結論，這是事實</p>
<h3><a href="http://www.tbray.org/ongoing/When/200x/2006/02/17/PHP">On PHP</a></h3>
<p>這篇文章整理了一整一大堆資深的網頁程式開發人員，對於PHP的看法，大略挑幾句來翻譯</p>
<blockquote><p>Adam Kalsey:</p>
<p>If you want some support on your foray into PHP, please let me know. I’d love to lend a hand. ¶</p>
<p>It’s easy to write bad code in PHP. Or in Perl. Or in C. Or Java. I think two things contribute to the perception that PHP code is crap. First of all, when you write spaghetti PHP, it still works just fine. So unless you’re a professional programmer or maintaining lots of code, you probably don’t care that the code is crap.</p>
<p>Secondly, since PHP is easy to learn, is ubiquitous, and there’s lots of PHP examples on the web, it’s easy for a non-pro to pick up PHP and start monkeying with it. They learn bad habits and then publish their code and teach others bad habits. Some of the most popular open source PHP applications ever are really poorly coded. Gallery and WordPress come to mind.</p>
<p>A hammer can be used to build a beautiful structure or a mis-shapen birdhouse. And it’s easy to flatten your thumb. With so many amateur PHP developers out there, it’s not surprising there’s a lot of flat-thumb code in the wild.</p></blockquote>
<p>大略翻譯:</p>
<p style="padding-left: 30px;">如果你想學PHP，請讓我知道，我很樂意幫助你</p>
<p style="padding-left: 30px;">PHP非常容易寫出很爛的程式碼，對Perl、C和Java來說也一樣，我想有兩件事情讓人對於PHP程式碼覺得很糟糕，首先，當你寫出了垃圾程式，它一樣運作的很好，除非你是專業的程式設計師，或是維護大量的程式碼，不然你根本不在意那程式碼是些垃圾。</p>
<p style="padding-left: 30px;">第二，因為PHP很容易學，很普及，在網路上有很多PHP的範例，很容易就有非專業的人用PHP來亂搞，他們學習糟糕的習慣，然後發表他們的程式教其他人這些壞習慣，很多流行的Open source PHP程式也寫得非常爛，說到這裡就想到Gallery和Wordpress</p>
<p style="padding-left: 30px;">它是一把可以建造漂亮結構或是歪曲鳥籠的槌子，還有它很容易敲爛你的姆指，有這麼多業餘的PHP開發者，所以在外面有這麼多爛程式也不令人意外</p>
<blockquote><p>Dominic Mitchell<br />
(略) Every time I’ve looked at PHP, I’ve been unable to find out how they use placeholders in code that talks to the database. Yes, every database adaptor provides a quote function, but nobody uses it (consistently). And people wonder why PHP code is always full of security holes.</p>
<p>It’s a real shame, as I can see that there’s a lot to like in PHP. But it really needs to clean its act up to appeal to people coming from other programming languages, instead of just people coming from dreamweaver.</p>
<p>I actually heard David Heinemeier Hansson (sp?) talking about rails the other day. One of the key points he made is that it should be easy to do the right thing. That’s why Rails hits a sweet spot for me. But when you look at PHP, yes, it’s easy to code, but it’s not easy to do the right thing. That’s where it falls down.</p></blockquote>
<p>大略翻譯:</p>
<p style="padding-left: 30px;">每次我看PHP的程式，都沒辦法找到他們怎樣在程式碼中用placeholders來和資料庫溝通，是的，所有資料庫介面都有提供過慮(quote 就是取代掉特殊符號)的函數，但是沒有人去用它 (一致的)，然後人們就很困惑為什麼PHP老是一堆安全性的漏洞</p>
<p style="padding-left: 30px;">真的很丟臉，我看見很多人喜歡PHP，但是它需要向上提升才能吸引更多其它程式語言的開發者來使用，而不是那些從Dreamweaver跳槽過來的使用者</p>
<p style="padding-left: 30px;">我前些天聽見David Heinemeier Hansson談到Rails (Ruby On Rails)，其中有個重點是他很容易把事情做對，那就是為什麼Rails能夠贏得我的歡心，但是反觀PHP，是的，他很容易寫，但是他不容易把事情做對，這就是他失敗的地方</p>
<h3><a href="http://www.bitstorm.org/edwin/en/php/">What I don&#8217;t like about PHP</a></h3>
<p>這裡面也提到並列出PHP的一些經典缺陷，像是namespace (雖然5.3版新增了，但是詭異的是用反斜線來做區分)，遞迴問題，Magic quote問題等等</p>
<blockquote><p>PHP has two advantages: it&#8217;s very easy and it&#8217;s widely supported by webhosting companies. But that doesn&#8217;t make it a good language.</p>
<p>For very small projects, it can be a nice programming language. But for larger and more complex projects, PHP can show its weakness. When you search long enough, you&#8217;ll find solutions (work arounds) to some of the mentioned problems. So when a solution is known, why isn&#8217;t it fixed? And why are the fixes not mentioned in the manual?</p>
<p>It&#8217;s good that an open source language is very populair. Unfortunately, it&#8217;s not a great language. I hope all problems will be solved once (in PHP 6?) and we will have an open source language that&#8217;s open source and good.</p>
<p>Until then, when you start a project larger than five scripted pages, you might also consider C#/ASP.Net or Java/JSP as a better solution. And if you want really good (distributed) performance, you can look at some initiatives which have been popping up the last couple of years. Just to mention a couple of them: Nginx, Couch DB and Node.js. They all blow existing systems away.</p></blockquote>
<p>大略翻譯</p>
<p style="padding-left: 30px;">PHP有兩個優點，它非常容易使用，還有廣範地被webhosting公司支援，但是這並沒有使他成為一個好的語言</p>
<p style="padding-left: 30px;">對所有的小專案來說，它可以是一個好的程式語言，但是<strong>對於大而且複雜的專案來說，PHP就顯得很弱</strong>，在你搜尋夠久時<strong>，你會發現部份這些提到的問題的解決方案，即然這些解決方案是已知的，為什麼這些問題沒有被解決? 還有為什麼這些修正沒有在手冊裡提到?</strong></p>
<p style="padding-left: 30px;">當一個open source的語言非常流行是一件好事，不幸的是他不是一個優良的語言，我希望所有問題都能一口氣被解決(在PHP6?)，這樣我們就會有一個好的open source語言</p>
<p style="padding-left: 30px;">直到現在，當你開始一個大於五個script檔案的專案時，你可能會考慮C#/ASP.Net 或 Java/JSP做為更好的解決方案，還有如果你真的想要好的(分散式)效能，你可以看某些這幾年創新的解決方案，例如Nginx, Couch DB還有Node.js，他們會趕走現存的系統。</p>
<h3><a href="http://www.ukuug.org/events/linux2002/papers/html/php/">Experiences of Using PHP in Large Websites</a></h3>
<p>這篇很詳細地從語言的層面說明PHP語言設計上到底有哪些缺陷</p>
<blockquote><p>Furthermore, PHP suffers from a related issue: the language was accreted, rather than ever having been designed. Most programming languages that have achieved genuine long-lasting popularity have been the work of at most a small team of gifted language designers. These designers have worked as much on deciding what to leave out of their languages as on what to put in. PHP’s creator, Rasmus Lerdorf, adopted a deliberate policy of letting others contribute freely to the development of the PHP implementation — and thus implicitly to that of the language itself. Where languages like C, C++, or Perl have had a Ritchie, Stroustrup, or Wall directing their evolution, Lerdorf does not seem to have applied the same sorts of controls to PHP. The result in some cases is that PHP lacks any sort of coherent world view. This in turn only increases the complexity for those trying to actually build working solutions with PHP.</p></blockquote>
<p>大略翻譯:</p>
<p style="padding-left: 30px;">除此之外，PHP受苦於相關的問題: 這語言是拼湊出來而不是被設計出來的，大部份有名望的程式語言都是由小部份天才語言設計者所組成的團隊的作品，這些設計師做了很多語言的某些特性是否該保留或新增的決定，而PHP的建立者，Rasmus Lerdorf採用討論的機制讓其他人自由地開發PHP的實作，也就是PHP語言的本身，像C, C++或Perl有Ritchie, Stroustrup, or Wall等人指導他們的演進，Lerdorf似乎沒有對PHP採用同樣的控制，做為結果就是PHP缺少了一貫的世界觀，這只使得要在PHP上建立解決方案變得更加複雜</p>
<p>從這段我們可以瞭解，<strong>PHP的設計的決定很多在亂搞一通</strong>，它原本的作者也對程式語言的設計沒有才能</p>
<blockquote><p>A similar problem crops up with relational operators. PHP’s simple variables can contain either a number or a string. PHP converts between numbers and strings whenever necessary, so that the programmer need not worry about the underlying type.</p>
<p>That’s the theory, anyway; in practice, this makes it extremely difficult to compare two values of different types for equality. The standard PHP equality-testing operator is spelled ==:</p>
<p>$n1 = 0;      $n2 = 10;<br />
$s1 = &#8216;foo&#8217;;  $s2 = &#8216;bar&#8217;;</p>
<p>$n1 == $n2;  // Numeric comparison, returns false<br />
$s1 == $s2;  // String comparison, returns false<br />
$n1 == $s1;  // Good question<br />
$s1 == $n1;  // Is this any different?</p>
<p>The problem is that, when the values are weakly typed, and there is only one equality-testing operator, the language cannot determine the programmer’s intention. PHP has a variety of kludges to deal with this:</p>
<p>* Some programmers recommend using !strcmp($n1, $s1) to force a string interpretation.<br />
* You can cast one or both sides to the intended type.<br />
* PHP 4 has a === operator. It works the same way as ==, except that it additionally requires both sides to have the same type. This sounds initially like the perfect solution — just use === wherever you would otherwise have used ==. Unfortunately, you lose the convenience of being able to treat numbers and strings interchangeably: it is no longer the case that 3 === "3&#8243;.</p>
<p>Perl has similar rules for its scalar variables: they can contain either a number or a string, and the language freely converts as necessary. However, Perl allows the programmer to express the intent: it offers both a numeric-equality operator == and a string-equality operator eq. PHP explicitly rejects this approach. The manual for PHP 2 says “Once you start having separate operators for each type you start making the language much more complex. You can’t use == for strings, you now would use eq. I don’t see the point, especially for something like PHP where most of the scripts will be rather simple and in most cases written by non-programmers who want a language with a basic logical syntax that doesn’t have too high a learning curve.” Unfortunately, in cases like this, the complexity is rather like an air bubble under freshly hung wallpaper: pushing it from one place to another will only leave more mess on the wall.</p></blockquote>
<p>大略翻譯:</p>
<p style="padding-left: 30px;">一個類似的問題在關係運算子出現，PHP的簡單變數可以包含數字或字串，PHP在需要時轉形成數字或字串，所以程式設計師不需要擔心底層的形別</p>
<p style="padding-left: 30px;">這只是理論，一般來說，這使比較兩個不同形別不同值是否相等變得極度的困難，標準的PHP相等測試運算為 ==:</p>
<p style="padding-left: 30px;">$n1 = 0;      $n2 = 10;<br />
$s1 = &#8216;foo&#8217;;  $s2 = &#8216;bar&#8217;;</p>
<p style="padding-left: 30px;">$n1 == $n2;  // Numeric comparison, returns false<br />
$s1 == $s2;  // String comparison, returns false<br />
$n1 == $s1;  // Good question<br />
$s1 == $n1;  // Is this any different?</p>
<p style="padding-left: 30px;">問題在於，當值是weakly type，且只有一種相檔測式運算子，語言與法判斷程式設計師的意圖，PHP有很多暫時的解決方案:</p>
<p style="padding-left: 30px;">* 有些程式設計師建議使用 !strcmp($n1, $s1)來強迫解釋成字串<br />
* 你可以轉型兩邊成為想要的型別<br />
* PHP4有一個 === 運算子，它運作和==一樣，除了他需要兩邊是同樣的類型，聽起來好像是完美的解決方案 &#8211; 只使用 ===在你使用 ==的地方，不幸的是你失去了數字和字串相容的方便性，再也不能使用 3 === "3&#8243;</p>
<p style="padding-left: 30px;">Perl有一個類似的規則給他的純量變數，他們可以包含一個數字或字串，語言可以自由的在需要的時候轉形，僅管如此Perl允許程式設計師表答他的意圖: 他提供了數字相等運算子 == 還有字串相等運算子 eq，PHP明確地拒絕這個方法，PHP2的手冊說到 "當你開始有兩種不同的運算子給不同的形別時，你開始讓語言變得更複雜，<strong>你無法對字串使用==，你要使用eq，我不瞭解這用意在哪裡</strong>，特別是對像PHP這種將會非常簡單的語言，<strong>且在大部份情況下，PHP都是由非程式設計師來寫，他們只是想寫基本邏輯語法而且不想要一個太高的學習曲線</strong>"，不幸的是，像這樣的情況，複雜的情況就像一個在璧紙後面隆起的泡泡，把它從這裡移到納裡只會把牆弄得更遭。</p>
<p>又一個<strong>業餘語言設計者在PHP所犯下的設計錯誤，而且程式語言也都設計在於討好初學者，而不是更嚴僅</strong></p>
<p>說了PHP這麼多壞話，這還只是冰山一角，任何有上過資工系"程式語言"課程的人都能發現PHP這程式語言一堆不合理的設計/實作，但是PHP也不是完全不可取，在寫小形專案時他就很不錯，這文章寫得真的很不錯，他列出了一個檢查表，讓你檢查什麼情況適合使用PHP</p>
<blockquote><p>We have identified a number of problems that arise when attempting to use PHP on large websites. However, we do not claim that PHP should never be used, only that these issues make its use inadvisable in certain circumstances. The following checklist suggests questions that should be considered before making a decision to use PHP for a given project.</p>
<p>*How much control will you have over the deployment platform? PHP’s one-size-fits-all approach to the php.ini file makes it hard to share servers with sites that were developed with different settings.<br />
*How many people will work on the site, now and in the future? PHP as a language lacks the features necessary to promote effective teamwork; the bigger your team, the greater the problems you’ll have.<br />
*How big will the site be, in terms of numbers of distinct pages? This is related to the previous item: the bigger the site, the greater your need will be for language features that promote teamwork.<br />
*How long will the site be expected to last? The longer it lasts, the more likely it is that significant design changes will be needed. If you use PHP in the obvious manner, major design changes are difficult. If you extend PHP with a templating system, whether ad hoc or carefully enforced, using PHP buys you little if anything.</p>
<p>*How experienced are the developers; and how complex will the site need to be? Experienced developers will find themselves hindered rather than helped by the language’s simplicity. Inexperienced developers will find the simplicity a significant boon — but if you have inexperienced developers trying to develop a complicated dynamic site, you will soon run into other problems.</p></blockquote>
<p>大略翻譯:</p>
<p style="padding-left: 30px;">我們確認了不少用PHP寫大型網站會遇到的問題，但是我們不宣稱PHP永遠不該被使用，只是那些問題造成在現在的情況下不宜使用，但是下面這個檢查表建議了一些可以在決定使用PHP來開發專案前需要考量的問題</p>
<p style="padding-left: 30px;">* 你對於你部署用的平台有多少控制權? PHP的設定檔php.ini的一次設定影響全部的方式使得要針對不同網站使用不同設定變得很困難</p>
<p style="padding-left: 30px;">* 有多少人開發這個網站? 現在? 還有未來? PHP是一個缺乏必要特性來增進有效團隊合作的語言，當你的團隊越大，你會遇到越多問題</p>
<p style="padding-left: 30px;">* 你的網站會有多大? 有幾個不同的頁面? 這關係到前一個項目，網站越大，你需要的語言特性就要越好來提升團隊的合作</p>
<p style="padding-left: 30px;">* 你的網站會運行多久? 你的網站運行越久，越有可能需要進行設計上的重大改變，如果你使用PHP是因為明顯的意圖，主要的設計改變將會非常困難，如果你用樣版系統延伸PHP，不管是臨時或是特製的，使用PHP都沒帶來什麼好處</p>
<p style="padding-left: 30px;">* 你有多少身為開發者的經驗; 還有網站將會有多複雜? 有經驗的開發者會發現他們因為語言的簡單受到阻礙而非幫助，沒經驗的開發者會發現簡單是一個重要的好處，但如果你有沒經驗的開發者來試圖開發一個複雜的動態網站，你很快會遇到其它問題</p>
<p>該文章作的結論是</p>
<blockquote><p>PHP is a convenient language for rapidly prototyping simple dynamic websites. Websites thus built can in many cases be deployed indefinitely, without spending time and money on refactoring code in a different language. PHP’s simplicity makes it a good language for inexperienced programmers, such as those moving from a pure page-design rôle to a site development one.</p>
<p>For more experienced developers, though, the language’s simplicity rapidly turns into complexity, slowing down the development process. These developers are the ones who have the skills needed to build large and/or complex websites; using PHP for such sites therefore tends to be a net loss. This tendency is reinforced by PHP’s lack of the linguistic features needed to promote working on large software projects. If your project is at all large or complex, it may be better to look elsewhere when choosing an implementation language.</p>
<p>In cases where PHP has been determined to be inappropriate, what language should be used? There is considerable choice here; few languages are as bad as PHP for doing serious development work. The author and his colleagues have had good results with Perl, and believe that languages such as C++, Java, and Python should serve equally well.</p></blockquote>
<p>大略翻譯:</p>
<p style="padding-left: 30px;">PHP是一個用於快速開發簡單動態網站原形的語言，在沒有花錢和時間重構成不同的語言前，網站在很多情況下都不能被明確地部署，PHP的簡單使它成為一個給沒有經驗的程式設計者的好語言，像是一個單純從事頁面設計開發的人</p>
<p style="padding-left: 30px;">對更多有經驗的開發者而言，語言的簡單很快的變成了複雜，減慢了開發的進度，這些開發者是有能力開發建置大形的複雜網站; 使用PHP在這樣的網站會傾向於成為平白的損失，這些傾向是來自於PHP缺乏對提升大形專案開發工作的語言特性，如果你的專案是大且複雜的，在選擇實做的語言之前最好去找其它的選擇</p>
<p style="padding-left: 30px;">當PHP被認為不適合時，該使用什麼語言? 有很多選擇; 對於開發重要專案，很少有像PHP這麼糟糕的語言，作者和他的同事用Perl有好的結果，且相信像C++、Java還有Python可以有同樣好的結果</p>
<p>雖然從設計哲學看來我不喜歡Perl的哲學:</p>
<blockquote><p>There&#8217;s more than one way to do it</p></blockquote>
<p>而比較喜歡Python的</p>
<blockquote><p>There should be one&#8211; and preferably only one &#8211;obvious way to do it.</p></blockquote>
<p>但是做為一個程式語言，Perl的設計絕對比PHP好上太多了，PHP真的是拼湊出來的</p>
<h2>PHP的問題</h2>
<p>你可以在上面這些文章中發現，現在是2010年了，以現今的眼光來看，PHP確實是爛到暴炸了，有人反對我所說的，是說程式是人寫的，所以程式的好壞是在人而不是在程式語言本身，而且也有很多人有提到PHP可以寫出很棒的程式，這我也很認同，但是如同這些人也有提到的，<strong>要寫出優良的PHP程式非常困難，為什麼? 因為他有太多缺陷了</strong>，是的，不可否認他的門檻真的很低，但是<strong>那些缺陷就像是地雷一樣，而它的門檻就像是雷區的鐵絲網，讓大部份人可以跳進雷區來玩，不懂那些瑣碎的語言缺陷，很容易就被滿地的地雷炸飛，只有少數的人能夠熟知地雷的位置，在這雷區中行走自如，那是非常困難的事</strong>，換言之，PHP的學習曲線一開始是很平緩的，大部份人都可以快速上手寫出簡單的程式，但是當要寫的東西越來越複雜，要懂的東西就不是一般的多和瑣碎，因為那些問題都來自語言的設計不良，不瞭解就很容易誤用或濫用，所以到後來的學習曲線會很抖，而<strong>就算你懂也會那些問題，還有另一個疑問，為什麼要堅持用這個破爛而不知進步的爛語言? 而不改用一個更優良的語言或開發平台呢?</strong></p>
<p>今天我會說他爛，有很大部份原因是因為我想讓大家瞭解，其實除了<strong>PHP以外還有很多網頁開發的平台</strong>，而和這些現代的網頁開發平台相較之下，單純用PHP開發網頁真的是宇宙超級霹靂無敵爛，拿框架比語言是很不公平，但是<strong>就算是比較語言本身，PHP一樣還是很爛</strong>，但是<strong>他也有他的優點，就是他非常流行，所以教學、資源、範例、現成的程式等等，都很豐富，而且門檻很低，進入地獄的低門檻</strong>，這樣的優勢能夠持續多久? PHP這麼流行，加上我們<strong>從上面看到引用的文章就知道，PHP改進的商討是笑話，一堆業餘的程式語言設計師在一起做出爛決定，很難做出痛改前非的重大且正確的改變</strong>，君不見PHP做出多少讓開發者罵到臭頭的爛決定，被罵了多少個版本才改回來，除非PHP真的改掉他那些壞毛病，不然<strong>如果想走向專業的話，我不建議學習PHP，但如果只是業餘和興趣，PHP真的是很不錯的玩具</strong></p>
<p>說他爛的同時，我也希望他能夠變得更好，但是以我過往的經驗，<strong>PHP所謂的改善，總是讓人失望加憤怒</strong>，以最有名的例子Magic quote來說，我有一次發現我的PHP程式出問題，才知道原來是新版本的PHP會自動幫你escape引號，他的出發點是好意防止SQL Injection，但是欠缺深思熟慮，他這樣做使得既有的程式碼，正確地以mysql_escape之類函數來escape特殊符號的程式，需要特地寫workaround來解決此問題，再加上這樣的特性是可以設定改變的，所以你得花更多一點心力去判斷它是否有啟動Magic quote，這是在<strong>懲罰程式設計師，討好初學者</strong>，我不知道為什麼PHP社群會做出這樣令人傻眼的更新，不可否認地這樣做確實是救到了很多不懂得過慮 SQL Injection的新手，<strong>討好了新手，打了老手巴掌，但是卻開啟了更多問題</strong>，這類的改進方式，我記得在PHP的改進過程中遇過不少，都是令人傻眼的"改善"</p>
<h2>替代的方案</h2>
<p>現在其實已經有太多新的網頁技術可以使用，不管是哪一個，都比直接寫PHP來得好，但是缺點就是入門門檻比較高，目前資源比較少，又或著在國外資源很多，但是國內中文資源很少，如果要走向專業的話，絕對值得投資，以下列出一些我所知道的解決方案</p>
<h3><a href="http://turbogears.org/">TurboGears</a></h3>
<p>集合各種Python最好的函式庫而成的網頁框架，可以說是集大成，它的特性是組件之間的藕合很鬆，所以可以換置組件，我個人就是使用TurboGears，他有一個有驚人的視訊影片，由TurboGears的作者親自示範如何在20分鐘裡寫出一個Wiki程式，有興趣可以下載來看看</p>
<p><a href="http://files.turbogears.org/video/20MinuteWiki2nd.mov">20分鐘寫Wiki影片</a></p>
<p>知名的Open source網站Sourceforge.com就是用TurboGears2寫的，可以參考這篇文章</p>
<p><a href="http://compoundthinking.com/blog/index.php/2009/07/16/turbogears-on-sourceforge/">TurboGears on Sourceforge</a></p>
<h3><a href="http://www.djangoproject.com/">Django</a></h3>
<p>不同於TurboGears的集大成，Django所有組件都是量身打造的，因此他的藕合度比較高，但是因為原本就是商業用途，所以有較多的實際商用經驗</p>
<h3><a href="http://www.rubyonrails.org.tw/">Ruby On Rails</a></h3>
<p>基於Ruby語言的網頁框架，因為我不懂Ruby，所以不太熟這款框架，但我知道網路上有高手在24小時之內在八八風災期間寫出物資需求回報的網頁程式，開發效率也相當好</p>
<h3>使用PHP的框架</h3>
<p>有人說PHP也有優秀的框架，而且用框架比語言很不公平，所以我加了這條，使用PHP的框架能提升一定程度的生產力，雖然他減清了某些負擔，但是少有框架是完全不用寫程式的，當<strong>你需要自己寫PHP的程式部份時還是得面對語言缺陷</strong>，以下是知名的PHP網頁框架</p>
<p><a href="http://www.symfony-project.org/">Symfony</a></p>
<p><a href="http://framework.zend.com/">Zend framework</a></p>
<p><a href="http://cakephp.org/">CakePHP</a></p>
<h2>成功的例子</h2>
<p>當然你聽到這些莫生的名詞，可能會懷疑這樣的東西真的可行嗎? 就像我當初的疑問一樣，但是現在已經有越來越多的網站往這些新世代的網頁以這些新的技術為基礎，或是舊的網站改用新的技術重新寫過，舉幾個我所知道以Python為語言的網站有這些</p>
<p><a href="http://plurk.com">Plurk</a></p>
<p><a href="http://youtube.com">Youtube</a></p>
<p><a href="http://sourceforge.com">Sourceforge</a></p>
<p><a href="http://reddit.com">Reddit</a></p>
<p><a href="http://justin.tv/">Justin.tv</a> (用的是<a href="http://twistedmatrix.com/trac/">Twisted</a>)</p>
<h2>最後</h2>
<p>我知道我講的這些可能聽起來很刺耳，但是確實是我所見所聞，你可以不認同我所說的，反駁我所說的，只要是理性的討論都歡迎並且尊重，請勿進行人身攻擊，還有我想知道有沒有用過現代的網頁技術，回頭去看PHP覺得是很好的，我也希望能瞭解這樣的想法</p>
<p>更新:</p>
<ul>
<li>2010/1/7 強調PHP爛在語言設計，拿掉一些太偏頗的比較(語言和框架)，和增加另兩個網站連結，以及PHP的框架，還有增加PHP腦殘設計決定和checklist的翻譯</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.ez2learn.com/2010/01/06/old-php-sucks/feed/</wfw:commentRss>
		<slash:comments>48</slash:comments>
<enclosure url="http://files.turbogears.org/video/20MinuteWiki2nd.mov" length="41351154" type="video/quicktime" />
		</item>
		<item>
		<title>WebFaction價目表中文版，再一次推薦WebFaction</title>
		<link>http://blog.ez2learn.com/2009/07/19/webfaction-plans/</link>
		<comments>http://blog.ez2learn.com/2009/07/19/webfaction-plans/#comments</comments>
		<pubDate>Sun, 19 Jul 2009 04:59:57 +0000</pubDate>
		<dc:creator>victor</dc:creator>
				<category><![CDATA[中文文章]]></category>
		<category><![CDATA[分享]]></category>
		<category><![CDATA[主機商]]></category>
		<category><![CDATA[虛擬空間]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[SSH]]></category>
		<category><![CDATA[SVN]]></category>
		<category><![CDATA[WebFaction]]></category>

		<guid isPermaLink="false">http://blog.ez2learn.com/?p=685</guid>
		<description><![CDATA[介紹WebFaction優秀的主機商，提供使用者完整的自主權，可以執行任何程式，包括自己寫的伺服器等等 <a href="http://blog.ez2learn.com/2009/07/19/webfaction-plans/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>最近因為要向客戶報價，使用的空間當然也要讓客戶知道，客戶原本案主要用的空間是貴到暴炸的國內空間，每年要價一萬多元，流量和空間更是小得可憐，拿國內和國外比當然是不能比，為了讓客戶瞭解差別在哪裡，所以就翻譯了一份WebFaction的Plans</p>
<p>下列資訊以<a href="http://www.webfaction.com/services/hosting?affiliate=victorlin">原網頁</a>內容為主，價錢單位為美金</p>
<p><span id="more-685"></span></p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="111" valign="top"><strong>類型</strong></td>
<td width="111" valign="top"><strong>分享型1</strong></td>
<td width="112" valign="top"><strong>分享型2</strong></td>
<td width="112" valign="top"><strong>分享型3</strong></td>
<td width="112" valign="top"><strong>分享型4</strong></td>
</tr>
<tr>
<td width="111" valign="top"><strong>付五年款</strong></td>
<td width="111" valign="top">$5.50/每月</td>
<td width="112" valign="top">$8.50/每月</td>
<td width="112" valign="top">$16.50/每月</td>
<td width="112" valign="top">$24.50/每月</td>
</tr>
<tr>
<td width="111" valign="top"><strong>付三年款</strong></td>
<td width="111" valign="top">$6.50/每月</td>
<td width="112" valign="top">$10.00/每月</td>
<td width="112" valign="top">$18.50/每月</td>
<td width="112" valign="top">$27.00/每月</td>
</tr>
<tr>
<td width="111" valign="top"><strong>付兩年款</strong></td>
<td width="111" valign="top">$7.50/每月</td>
<td width="112" valign="top">$11.50/每月</td>
<td width="112" valign="top">$20.50/每月</td>
<td width="112" valign="top">$29.50/每月</td>
</tr>
<tr>
<td width="111" valign="top"><strong>付一年款</strong></td>
<td width="111" valign="top">$8.50/每月</td>
<td width="112" valign="top">$13.00/每月</td>
<td width="112" valign="top">$22.50/每月</td>
<td width="112" valign="top">$32.00/每月</td>
</tr>
<tr>
<td width="111" valign="top"><strong>每月付款</strong></td>
<td width="111" valign="top">$9.50/每月</td>
<td width="112" valign="top">$14.50/每月</td>
<td width="112" valign="top">$24.50/每月</td>
<td width="112" valign="top">$34.50/每月</td>
</tr>
<tr>
<td width="111" valign="top"><strong>設定費用</strong></td>
<td width="111" valign="top">免費</td>
<td width="112" valign="top">免費</td>
<td width="112" valign="top">免費</td>
<td width="112" valign="top">免費</td>
</tr>
<tr>
<td width="111" valign="top"><strong>60</strong><strong>天退費保證</strong></td>
<td width="111" valign="top">有</td>
<td width="112" valign="top">有</td>
<td width="112" valign="top">有</td>
<td width="112" valign="top">有</td>
</tr>
<tr>
<td width="111" valign="top"><strong>硬碟空間</strong></td>
<td width="111" valign="top">10GB</td>
<td width="112" valign="top">20GB</td>
<td width="112" valign="top">40GB</td>
<td width="112" valign="top">60GB</td>
</tr>
<tr>
<td width="111" valign="top"><strong>每月頻寬</strong></td>
<td width="111" valign="top">600GB</td>
<td width="112" valign="top">1200GB</td>
<td width="112" valign="top">1800GB</td>
<td width="112" valign="top">2400GB</td>
</tr>
<tr>
<td width="111" valign="top"><strong>可用記憶體</strong></td>
<td width="111" valign="top">80MB</td>
<td width="112" valign="top">120MB</td>
<td width="112" valign="top">160MB</td>
<td width="112" valign="top">200MB</td>
</tr>
<tr>
<td colspan="5" width="558" valign="top"><strong>網站</strong></td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>可架設網站數量</strong></td>
<td colspan="3" width="335" valign="top">無限</td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>SSL(https) </strong><strong>支援 (</strong><strong>安全連線)</strong></td>
<td colspan="3" width="335" valign="top">有</td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>每日使用率統計</strong></td>
<td colspan="3" width="335" valign="top">有</td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>DNS</strong><strong>完全控制</strong></td>
<td colspan="3" width="335" valign="top">有</td>
</tr>
<tr>
<td colspan="5" width="558" valign="top"><strong>Email</strong></td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>Email </strong><strong>數量</strong></td>
<td colspan="3" width="335" valign="top">無限</td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>信箱</strong></td>
<td colspan="3" width="335" valign="top">無限</td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>SMTP, POP </strong><strong>和 IMAP </strong><strong>安全存取</strong></td>
<td colspan="3" width="335" valign="top">有</td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>網頁郵件安全存取</strong></td>
<td colspan="3" width="335" valign="top">有</td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>郵件列表</strong></td>
<td colspan="3" width="335" valign="top">無限</td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>強力垃圾郵件過慮</strong></td>
<td colspan="3" width="335" valign="top">有</td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>自動回覆以及伺服器端規則</strong></td>
<td colspan="3" width="335" valign="top">有</td>
</tr>
<tr>
<td colspan="5" width="558" valign="top"><strong>資料庫</strong></td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>資料庫數量</strong></td>
<td colspan="3" width="335" valign="top">無限</td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>MySQL</strong><strong>支援</strong></td>
<td colspan="3" width="335" valign="top">有</td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>PostgreSQL </strong><strong>支援</strong></td>
<td colspan="3" width="335" valign="top">有</td>
</tr>
<tr>
<td colspan="5" width="558" valign="top"><strong>Shell</strong></td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>完整的 shell </strong><strong>存取，包括SSH </strong><strong>以及 SFTP</strong></td>
<td colspan="3" width="335" valign="top">有</td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>可跑長期執行之程式，例如Rails</strong><strong>、Django</strong><strong>、其它</strong></td>
<td colspan="3" width="335" valign="top">有</td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>額外的SSH</strong><strong>及SFTP</strong><strong>使用者</strong></td>
<td colspan="3" width="335" valign="top">無限</td>
</tr>
<tr>
<td colspan="5" width="558" valign="top"><strong>備份</strong></td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>每天遠端完整地備份你所的資料</strong></td>
<td colspan="3" width="335" valign="top">有</td>
</tr>
<tr>
<td colspan="5" width="558" valign="top"><strong>軟體</strong></td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>單鍵安裝多種應用程式，包括Rails</strong><strong>、Django</strong><strong>、Drupal</strong><strong>、WordPress</strong><strong>還有其它很多</strong></td>
<td colspan="3" width="335" valign="top">有</td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>安全的Linux</strong><strong>系統包含上千個預先安裝好的工具</strong></td>
<td colspan="3" width="335" valign="top">有</td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>Apache</strong><strong>架設PHP</strong><strong>，包含SSI</strong><strong>、.httpaccess</strong><strong>檔案</strong></td>
<td colspan="3" width="335" valign="top">有</td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>可以執行任何用PHP</strong><strong>、Python</strong><strong>、Ruby</strong><strong>、Perl</strong><strong>或Java</strong><strong>配合MySQL</strong><strong>、Postgresql</strong><strong>或sqlite</strong><strong>之程式</strong></td>
<td colspan="3" width="335" valign="top">有</td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>可以編譯及安裝任何你需要的軟體在HOME</strong><strong>資料夾</strong></td>
<td colspan="3" width="335" valign="top">可</td>
</tr>
<tr>
<td colspan="5" width="558" valign="top"><strong>額外</strong></td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>額外的硬碟空間</strong></td>
<td colspan="3" width="335" valign="top">+$5/每月4GB</td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>額外的頻寬</strong></td>
<td colspan="3" width="335" valign="top">+$5/每月200GB</td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>額外的記憶體</strong></td>
<td colspan="3" width="335" valign="top">+$7/每月 40MB</td>
</tr>
<tr>
<td colspan="2" width="223" valign="top"><strong>私人IP</strong></td>
<td colspan="3" width="335" valign="top">+$5 每月</td>
</tr>
</tbody>
</table>
<h2>WebFaction不止是虛擬主機，他給你完整的自主權</h2>
<p>起初我也以為WebFaction就一般的虛擬主機，跑跑網頁程式這樣，我一直很困擾有一些自己寫的非網頁Server要跑，租實體主機又很太貴了，如果有虛擬主機可以跑我自己寫的Server就好了，後來我才發現，原來<strong>WebFaction也可以跑自己寫的Server</strong>，所以我的<a href="http://blog.ez2learn.com/2009/07/15/dream-on-line-chat-roo/">夢想線上聊天室</a>的伺服器，是我自己用Python + Twisted寫的，就是擺在WebFaction上，因為他開放完整的linux用戶可以使用，所以你可以先在他的控制面版建立一個custom server，它會幫你開一個port，接著只要你的Server port設成他分配的那個，接著用crontab來定期檢查你的server，確定他都有在線上就可以了，而且這個部份我不太懂，寫給客服他們一樣跟我說明要怎麼做，除了自訂的伺服器，<strong>WebFaction一樣可以開SVN等等的服務</strong>，可以參考<a href="http://blog.ez2learn.com/2008/11/03/develop-website-with-svn/">這篇</a>，而且沒限制可以開多少個，唯一數量上的限制是長時間執行的程式加總起來的記憶體用量，像是Rails、Django、TurboGears這類的程式，如果不是的話，<strong>像PHP之類的網站，要架多少都可以</strong>，只要空間和流量夠用，問題是要把那樣的流量和空間用完是非常困難的事，我自己在上面就不知道放了多少東西，感覺真的物超所值，目前我需要跑的還沒遇過跑不了的，除了我說的這些，其它在列表裡提到的都是很棒的特點，不止是可以跑script語言的程式，你要自行編譯程式也是可以的</p>
<h2>不懂Linux之類的鬼東西也能用嗎</h2>
<p>很多人可能擔心不懂Linux之類的什麼鬼東西到底怎麼用，其實那一點都沒關係，因為WebFaction有提供強大的控制面版功能，內建各種流行的程式，只要點點按鍵，他就會自動幫你生成整個網站，像是這個部落格wordpress，就是透過它的控制面版生成的，剩的就只是較細節上的修改，像是樣版和安裝外掛，這都可以透過Wordpress介面很簡單就可以辦得到，而除了Wordpress，其它常見的流行程式他們都有支援，像是Joomla、Drupal之類的都可以透過它的控制面版單鍵架好，在這有<a href="http://www.webfaction.com/demos/control-panel?affiliate=victorlin">官方的影片來示範怎麼操作他們的控制面版</a>，像這類用PHP寫的東西你想要架幾個都可以，之前看到有部落格只是有獨立網域而以就要天價，真的是冤大頭，有自己的網域辦得到嗎? 當然可以，你要設定多少個都可以，一樣可以透過他們的控制面版設定好，半行指令都不用知道，同樣的價錢用WebFaction可以讓你架無限個獨立網域的部落格，只要流量和空間許可</p>
<h2>優秀的客服</h2>
<p>他們的客服真的是我見過最優秀的，如果你租的是台灣的主機，你可能遇過且發現和客服溝通是件很痛苦的事情，接起電話的可能是不知道哪裡請來的工讀小妹，一問三不知，寫信說你有要緊的事情請幫忙處理一下，結果信件石沉大海，但是WebFaction的客服不一樣，他們的客服團隊有優秀的技術背景，你在使用上遇到任何問題，只要問他們，他們都很樂意回答，而且也都答得出來，願意教你怎麼做，甚至可以幫你解決，可以參考我先前寫的<a href="http://blog.ez2learn.com/2008/09/28/hosting-of-this-site/">這篇文章</a></p>
<h2>使用了一年</h2>
<p>使用了將近一年，這家主機商從來沒有讓我失望過，而且也都能夠滿足我的需求，雖然我已經寫過很多文章推薦過這家主機商，過了一年我還是想再次推薦這家主機商，關於要如何申請，可以參考<a href="http://blog.ez2learn.com/2008/10/25/guide-to-buy-webfaction-service/">這篇文章</a>，或許你會覺得如果我是在嘴砲，沒有我說的這麼好但已經買了該怎麼辦，關於這點，<strong>他們有60天保證無條件退款</strong>，所以在試用60天以內，都可以把錢拿回來，而且換算成台幣，最初階的主機也只要每年三千多元，而且已經能滿足大部份人的需求，所以我真的很希望這樣優秀的主機商可以有更多人使用</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ez2learn.com/2009/07/19/webfaction-plans/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
	</channel>
</rss>

