:::

論文進度報告(2010/7/24):從Model到View

布丁布丁吃布丁

論文進度報告(2010/7/24):從Model到View

image

上週末終於把Model的部份寫完了,也就是說,PHP的部份告一段落,而接下來要進入JavaScript的部份。進度的概況大概就是完成上面那張圖中的右下角部分,而其他都還要繼續做。

類別 應完成 已完成 已完成百分比 程式語言
Model 100 100 100% PHP
View 73 0 0% JavaScript
Controller 9 0 0% PHP
總計 182 100 54.9%  

以程式數量來看進度的話,就是上面的表格。大概完成了一半,現在進入下半場:JavaScript。


Model完結之傷感

回顧一個月多前開始撰寫PHP的部分時,需要熟悉PHP物件導向、CodeIgniter、撰寫PHPDoc、單元測試的開發方法,讓我摸索了好一段時間。到現在Model完成了,單元測試也十分稱職地完成了他的工作,現在又要暫時把它擱在一旁,是覺得有點捨不得。

我在撰寫Model時,實際上撰寫的檔案數量為141個,細表如下:

類別 數量
Libriaries 107
Extension Libraries 4
Languages 1
Helpers 3
Unit Test 24
Views 2
總數 141

在開發過程中有不少重新思考UML架構的時候。如果繪製UML時能夠熟悉CI跟PHP的話,也許那時系統分析的數量會更為準確也說不定。

image

同時,這些程式全部通過單元測試。單元測試共34頁、456項測試。這是程式品質的一種保證。

而且我也把核心的工具整理成toolkit類別,包括Generic Object、Collection、Iterator等等,在未來開發PHP專案時又可以將之拿來使用,是非常寶貴的程式結晶。

雖然是這樣說,但到目前為止,仍然沒有什麼很令人亮眼的東西可以拿出來跟大家講。Meeting報告時看老師聽我講這些抽象的東西感覺像是有點無聊,我也沒有辦法orz

要看到實際上可以用的程式,還要把View跟Controller組合起來才有可能。再怎樣也是急不得的。


View開始之困惑:學習撰寫JavaScript

說要完結Model、開始撰寫View之後,已經過了一個禮拜了。老實說,到現在我還是很困惑,我到底該怎麼辦才好?跟一個多月以前寫PHP一樣,JavaScript是一個我很熟悉的程式語言,但是我一直沒有很正式地去學習它。說到JavaScript,一般會想到表單驗證啦、jQuery動畫特效啦,但是我要寫的層次是比這些都還複雜很多,是要靠一個指令,帶出整個標註工具,並且要由純JavaScript來跟伺服器溝通、交換資料。這種在別人網頁上進行從無到有的架構,對我來說是從未經歷過的高難度境界。

為了要將JavaScript嚴謹地架構起來,最近我開始學習更多相關技術:

JSDoc

JavaScript很自由,但是因為太過自由了,所以他的物件導向特性並不是很明確。JSDoc是類似JavaDoc的JavaScript專用程式註解格式,一個搭配JSDoc的JavaScript程式大概會長得如下列程式碼一樣:

/**
* 驗證是否為陣列
* @param $obj
* @return 驗證結果
* @type boolean
*/
jQuery.is_array = function ($obj)
{
    return (typeof($obj) == 'object' && ($obj instanceof Array));
};

我們可以利用JSDoc來說明一個類別的繼承(@extends)、建構子(@constructor)、方法的參數(@param)、回傳資料(@return)與型態(@type)、所需類別(@requires)等等在程式中難以說明的特性,而使得我所使用的IDE:NetBeans可以正確地解讀複雜的JavaScirpt程式。

image

如果NetBeans能夠正確地解讀,那麼就能在撰寫程式時即時地提供說明與自動完成的功能。

然而,JSDoc卻是一把雙面刃。由於JavaScript並不像PHP是在伺服器端執行,而是必須讓使用者下載到他的電腦才能執行。也就是說,JavaScript的註解撰寫越多,表示它的體積越大、越吃網路流量。為此,我還需要一種JavaScript的壓縮打包技術。

Packer JavaScript en PHP

常常使用複雜framework,如jQuery、jQuery UI的人,一定有碰觸過min打包版程式的經驗。研究JavaScript打包技術(Packer)的Dean Edwards已經將之發展到很成熟的地步,而且支援.NET、perl,以及PHP來使用。

讓我們來看看打包到底能做到什麼程度:以下左圖是原始程式碼,總共13649位元組;右圖是打包壓縮的結果,只有5177位元組。壓縮到一半左右的大小,實在是很棒的成果。

原始程式碼(13649) 打包壓縮結果(4691)
image  image

打包壓縮其實並不是什麼很神祕的技術,大致上可以分成普通壓縮與Base 64、是否縮短變數名稱等選項。普通壓縮中,他刪除了註解、多餘的空格、對齊(tab)、換行,並將程式撰寫簡化,以節省空間。除此之外,使用Base 62則能獲得更高壓縮率的作法,在edikud的blog中介紹了一些提高壓縮率的守則,但似乎是寫錯了,所以我更正之後說明如下:

  1. 區域變數名稱前加上_,像是function的參數。例如「obj」改寫成「_obj」。
  2. 全域變數名稱前加上$。例如「TYPE_ID」改成「$TYPE_ID」。
  3. 最後補充一項:程式每行結尾都要加上「;」。原本JavaScript會把沒有「;」的換行補上「;」作為宣告的結尾,但是打包之後,換行會被刪去,所以就必須在一開始撰寫時就養成良好習慣地加上「;」才行。

至於測試方法則不是我關注的重點,所以就不特別去在意。

搭配CodeIgniter的網頁快取功能,我就可以把打包壓縮過後的JavaScript以cache的方式保存起來,既能在程式有所更改時立即地轉換成打包格式,也不會重複進行打包動作導致系統資源浪費。

QUnit:JavaScript的單元測試
image

為了養成撰寫程式時的良好習慣,即使是寫JavaScript,我也採用Unit Test單元測試的開發方法。Qunit是一個JavaScript的單元測試工具,用法也十分簡單,介紹網頁裡面已經把主要用法說明完畢。

只是我並不喜歡原始QUnit的介面與功能,所以修改了不少版面、加入型態判斷、例外捕捉並顯示錯誤訊息等功能,建立一個屬於我自己好上手的QUnit工具。透過QUnit來偵錯,我發現我逐漸改變以往使用alert來偵錯的方式,QUnit不僅能詳細地回報錯誤細節,速度與效率快上許多,因此更方便於跨瀏覽器之間的測試。

等待我把QUnit使用更熟悉之後,我會再把改良版的功能發佈出來跟大家共享。

JSONP:跨網域AJAX技術

以往在寫DSpace時,我是使用了很多AJAX技術,但那都是同一個網域底下的資料存取,而我的論文則是往更高的目標邁進:跨網域AJAX存取。

JSONP是一個天才想出來的非正式方案。這是利用<script>標籤的src載入JavaScript可以讀取不同網域的JavaScript檔的特性,只要在src的網址中以GET方式輸入參數,然後伺服器則回應相對應的資料並以JSON的方式讓使用者端的瀏覽器去做callback回呼的動作,就能夠達到跨網域AJAX的境界。詳細的作法可以先看看Hpyer的介紹

這個是很簡單的作法,但也是很危險的一種技術。因為參數以GET的方式傳遞,也就是說資料都會是以明碼來顯示,這就是一種容易被入侵的漏洞。對此我在思考利用公鑰私鑰的方式來為傳遞參數進行加密的作法,不過似乎是挺複雜的,我現在連基本的JavaScript物件導向都還沒熟悉呢。

此外,JSONP是以GET方式傳遞參數,而CodeIgniter又剛好最討厭GET傳遞參數。調整CodeIgniter讓他能支援JSONP,讓我花了不少功夫。等我真的把它馴服了,我們再來談談CodeIgniter的調整方法吧。

NetBeans對於JavaScript支援沒這麼強

習慣NetBeans對於PHP的支援之後,改寫JavaScript時就會明顯地感覺到不方便。這個不方便其實比起什麼功能都沒有的筆記本,或是只有語法顏色標示的編輯器來說還是強的很多。NetBeans提供了方法的自動完成(搭配JSDoc就如上述效果般)、可能錯誤的提示、自動補完()、{}、[]等括弧。

雖然不錯用,但跟PHP的支援比起來,少了兩個對我來說還蠻決定性的功能:

  1. 缺少變數名稱自動完成:也就是NetBeans無法取得JavaScript的變數前幾個字來猜出後面的字,這讓我寫function函數的時候就很不習慣,沒辦法快速帶出參數名稱。
  2. 方法自動完成的速度慢:要使用方法的自動完成,必須要在變數撰寫完畢之後加一個「.」以表示要使用方法時才會帶出來,但是選單速度非常慢,大概要等到1秒才完成,而且一旦自動完成輸入錯誤而想要回頭修改時,又必須要回到輸入「.」的情況才能再次帶出自動完成選單。非常地考驗耐心。

因此我正在找尋是否有NetBeans的Plugins能夠補強這兩個缺點,不然其他都很完美了說。


寫好系統只是興趣,並不代表研究順利

身為一個社會科學領域(表面上是文科)的研究生,我很瞭解理工科那種想把系統做好就算是完成論文研究的作法在這邊是行不通的。社會科學的研究講求結果分析能力,在好的環境中分析好的結果,在壞的環境下也可以分析出壞的原因,換句話說,不管研究對象的環境是好是壞,研究都能夠進行。

但是,其實我並不喜歡這種調調。並不是說這樣好或不好的問題,只是我個人看到問題擺在那邊,就會想要去動手解決,然後找出更好的方法之後,跟別人說明這些作法。就像我在這個Blog作的事情一樣,我的論文也是一樣的理念。

所以我不是用別人寫好但我並不滿意的系統,而是自我挑戰作一個系統,不僅只是作,而是以對我來說前所未有的嚴謹態度來撰寫一個系統。基於毛老師的理論,我今天用這種方式撰寫系統,以後我也應該會繼續用這種嚴謹的態度面對未來的工作,而這也是我的自我期許之一。

然而回到頭來,我很清楚這種想法至多仍只是能稱得上是一種興趣,而與研究進度無關。撰寫好系統,並不代表實驗能進行順利、問卷會設計、統計會分析,這些技術與知識都是不太相關的事情,而我則是抱著來一個我學一個的心態,一步一步慢慢地做完這個論文而已。

有些人也許看著我三不五時刻著系統進度,就以為我論文快完成了,但事實上兩者是不太有相關。那為什麼我要花這麼多時間在做系統呢?我會回答說這是一種興趣,更直接一點,我依然在耍任性,就跟寫書的時候一樣。

這種個性,真的是沒救啦。

(more...)

論文進度報告(2010/7/11)

布丁布丁吃布丁

論文進度報告(2010/7/11)

image

先來講一下進度報告好了。一樣地用一張表講完目前進度:

類別 應完成 已完成 已完成百分比
Model 100 54 54%
View 73 0 0%
Controller 9 0 0%
總計 182 54 29.7%

這是程式寫作到第21天的進度,已經完成了1/4,而核心的Model部分也做完了一半,可喜可賀。

image

不過現實層面是預定的專案進度是做不到了,所以日期必須往後順延。程式寫作的時間從15天延長到45天,可能到8/24才能有展示可以看了。詳細的資料就請上KALS Wiki去看囉。


強大的Collection

最近又學到Collection跟Iterator的技巧,跟上次的進度報告中提及到的Generic Object(其實也沒講到多少) 搭配使用之後,便可以應用到一般Model中許多常用的類別。

Collection(集合)是一種陣列的強化版本,不僅可以做到原本陣列大部分可以做的事情,還可以控制集合成員(members)的變更,並且實作延遲實體化(lazy initialization)的技巧。搭配Iterator之後,Collection還可以放進foreach去跑。只能說是好用到一種令人感動的境界,而且其實許多類別都是一種Collection,當初我太小看Collection這種工具了。

除了參考原本書中介紹的Collection來撰寫,並讓他擁有Iterator的功能之外,我又將之進化成一些特色類別,並組成我自己的toolkit。以下隨便介紹,看不懂很正常,反正一般只要知道有八成的類別都可以拿來套用這些toolkit就對了

Generic Collection

image 

將Generic Object作為成員,並設定預設載入的資料表與成員類別,可以對集合的成員進行Update的動作。

Generic Attribute Collection

image 

繼承Generic Collection,並將Generic Attribute Object作為成員。叫做Attribute的原因是通常這種集合是附屬於某個主物件底下,作為額外的屬性。例如Annotation會有很多額外的feature(特徵),而這種屬性都會附帶有「type_id」,然後還有一些特性。

Generic Association Collection

image

繼承Generic Collection,並預先載入指定資料表中關連的資料表的資料,並且能夠修改指定資料表的關聯內容。


Benchmark Fever!

image

如果眼睛很尖的人,應該發現到開頭那張Unit Test的擷圖中多了一個項「Benchmark Time」。Benchmark是測試速度或是評分時常用的技術,CodeIgniter有著強大的Benchmark功能,可以記錄任何程式執行時所耗費的時間。因此我把它結合到CodeIgniter的Unit Testing當中,以便分析每一項測試所需要耗費的時間。當耗費時間過久時,該項測試可能就有些問題囉。

image

再搭配CodeIgniter的Application效能分析,就可以自動捕捉到多項細節資訊。包括URI字串、使用類別/方法、記憶體使用狀況、基準測試(benchmarks)、GET資料、POST資料、以及資料庫查詢的各種語法。特別是資料庫查詢的細節,光靠這個就能找到許多無效或錯誤的查詢,而修改許多錯誤。

由於之前寫到Annotation_scope_collection時,發現效能異常地慢,於是試著把Benchmark加入Unit Test,並從中找出最有問題的測試點來改善,最後才抓到不能一直依賴CI->load->library()來當做include_once讀取類別這個問題。改善之後我可以看到執行速度大幅縮短,然後我又試著加入Cache的機制,結果速度又縮短了0.x秒,實在讓人很開心。於是一不小心就會沉迷在改進程式以縮短執行速度這個挑戰極限的樂趣中。

現在幾乎每種測試都能在1秒之內跑完,其實不要慢得太誇張,差個0.x秒也就沒什麼大礙了。


本來想草草地寫,結果也寫了好一段時間。那這次就這樣啦,詳細進度可以追蹤我的噗浪,來繼續寫下一階段。

(more...)

論文進度報告(2010/7/2)

布丁布丁吃布丁

論文進度報告(2010/7/2)

image .

這次進度報告又隔了兩個禮拜,由於到最近才有比較明顯的成果出來,是也就沒有急於每週定期報告。

實際進度一張表就可以講完了:

類別 應完成 已完成 已完成百分比
Model 100 19 19%
View 73 0 0%
Controller 9 0 0%
總計 183 19 10.3%

這是到Coding D13的今天為止的進度。

以下是其他話題閒聊XD


完整的物件導向?還是兼容PHP 4.3?

我使用CodeIgniter 1.7.2這個PHP Framework來建置系統,而CodeIgniter是兼容於PHP 4.3為目的來設計,在CodeIgniter的PHP寫作風格指南裡面也提到說,除非特別說明,否則程式應該能夠相容於PHP 4.3版以上。

PHP 4跟PHP 5的物件導向寫作有很大的不同。PHP 5比較像是Java這種嚴謹的物件導向,有public private abstract final等好用的功能可以使用,而PHP 4則比較像是單純的變數跟函數綁在一起的物件。

image

在繪製UML時,物件中成員變數與方法的開放程度都會是考量的範圍內,但是PHP4並不支援,而CodeIgniter只有在Controller中有提供此方法,那就是private(私有)方法的名稱前加入「_」,例如「_filter_id($id)」。

本來我也是想用這種方法去兼容PHP 4.3,但是寫一寫忽然發現這還是有些問題。這樣作法會無法善用完整的物件導向概念,儘管實作上PHP是很自由的,但是從學習的角度來說,還是盡量地嚴謹一點會比較好。因此我中途決定改以較完整的方法來撰寫PHP程式碼,不僅讓物件導向較為漂亮,NetBeans的導覽視窗(Naigator)跟自動完成功能也能提供比較完善的支援。

image

這是我在撰寫Generic Object時,NetBeans的導覽視窗,有上鎖的表示private私有方法,而黃色菱形的則是PHP 5的魔術方法__construct()建構子。看到NetBeans能夠更正確地解讀我的程式,也就覺得用完整的物件導向也挺不錯的感覺。

也許以後實務工作時我會從簡來做,但現在我仍在學習中,就好好地確實地寫好每一支程式吧。

很好上手,卻也很難抉擇的PHP

儘管PHP有提供物件導向功能,但原本他是程序導向的程式。而CodeIgniter雖然是物件導向程序,但是他卻有自己的一套作法。雖然高度自由的PHP讓我可以選擇各種作法,但這也是頗難抉擇的一件事情。

CodeIgniter會希望程式設計師以CI_Base物件為主體,在Contoller、Model裡面已經先預載了CI_Base,而Library或其他地方則是要呼叫「CI =& get_instance()」。如果要使用CodeIgniter豐富的Library或Helper的話,就非得使用CI_Base才行。

然而CodeIgniter裡面的如果要用繼承、介面等物件導向功能,就不應該使用它的Model,而是用Library才是。這也跟原本我在UML中規劃的方式有所不同。Library並不會預先載入CI_Base,都必須另外呼叫才行,

因為CodeIgniter寫作方式與我預先認知有所差異,所以實作時遇到了很多難以抉擇的困擾。到底要用物件導向的繼承?還是要用Helper的function?以前寫PHP時,很依賴function來提供模組化的作法。但現在程式開發的技術進步了,是否能夠改用物件導向的繼承來實作呢?

這些問題並不只會在一開始困擾著我,在系統持續發展的時候,也會不斷地修正我的作法,以求得更好、更佳的程式開發方法吧。


迷上了Unit Test 單元測試

自從之前看了極致軟體製程(eXtreme Programming,簡稱XP)的介紹之後,我就把單元測試這個概念深深地記在腦海當中。而在開發系統時,我也開始學著依賴單元測試,並且到最後迷上了它。也許有人會在噗浪上看不懂我在念著測試測試到底是什麼,其實就是指單元測試(Unit Test)。

相符或不相符的檢查

單元測試是軟體測試的小型版本。軟體測試的概念很簡單,就是看看系統產出的實際輸出與我們希望的預期輸出是否吻合。我製作了meeting時報告用的投影片,不過我認為節圖出來用文字來說明應該會更好懂:

image

這是單元測試的一個示意圖。程式設計師撰寫出程式給電腦,然後要求電腦執行該程式,而程式設計師也自己想一個預期成果,並把它們相互比對。這支程式輸入兩個整數參數,並把它們彼此相加再輸出。輸入test(1, 2)的話,輸出結果應該是3。如果正確地符合程式設計師的預期,那麼測試就算通過(Passed)。

image

反過來說,當程式跑出來的結果並不是3的時候,可能就是該程式出現問題了。上面示意圖中則是測試沒通過的樣子,因為程式裡漏掉了參數,導致結果輸出不如預期,這時候就是要回頭去debug了。

單元測試與程式開發

image

單元測試本身是一種黑盒測試,它只注重輸出結果,並不看程式內部的細節。但由於他檢測的程式通常都是非常小的一塊,而不是整個系統的運作,所以用來檢查錯誤非常方便。

單元測試提供了一個模擬環境供程式運作,它可以讓程式重複地進行測試,並輸出一張簡單明確的報告,讓你知道哪些測試通過、哪些沒通過。由於單元測試執行速度快、簡單,因此只要程式有任何修改,都可以馬上回頭以單元測試進行檢查。久而久之程式設計的動作就會變得很單純:寫完、測試、通過就繼續寫,沒通過就回頭修改。

image

在極致軟體製程中,單元測試也是相當重要的一環。當系統分析做完之後、要開始撰寫程式之時,程式設計師應該先只寫程式的大綱,像是成員變數的宣告、私有公有方法的宣告(但是裡面都是空空如也),很快地把整個程式的大綱寫出來即可,內容細節或是能不能運作,稍後再說。

有了程式大綱之後,就開始製作單元測試檔案。這個測試檔模擬該程式使用的情境,包括輸入的參數、預期輸出的結果。在嚴謹的單元測試當中,會將程式裡每一個方法一一去測試,但我在實作上只有測試幾個重要的項目而已。其實這也不是什麼大問題,只要後續想到什麼情境還可以拿來測試,隨時都可以加入單元測試檔,這也是XP告訴我們的方法。

測試檔完成之後,就拿程式大綱來測試。理所當然地,測試會失敗。接著程式設計師再繼續把程式細節一一地補上,並隨時利用單元測試檔來檢測自己的進度。直到所有測試都通過,那麼這支程式就算完成了。

單元測試Framework:PHPUnit

就像Java的單元測試框架JUnit一樣,PHP也有單元測試的框架:PHPUint。它是由純PHP程式碼寫成的輕量級測試框架,具有自動產生規範好的測試檔格式功能,能提供嚴謹的單元測試。除此之外,它也可以結合Xdebug分析程式碼覆蓋率,或是支援Phing部屬測試與Selenium做大型自動化集合測試。

image

在IDE中也會提供PHPUnit的支援,像是上圖就是NetBeans的測試功能。

但由於CodeIgniter框架運作方式與單純的PHP不同,難以使用PHPUnit來做測試,所以我並沒有使用這個強大的工具來進行單元測試,而是使用CodeIgniter提供的簡易版單元測試功能而已。

通過測試的程式令人安心

我現在也學著以測試導向作為程式建置的方法。儘管有人會覺得這個測試檔的製作很多餘,但習慣時候,看到測試通過的程式反而更令人安心。

程式設計最大的樂趣,我認為莫過於看到程式順利運作的時候。但在大型系統中,我們不得不將程式分割成細小的部分,就像MVC中切割成三大責任一樣。系統運作缺一不可,但是要等到全部做完才看到成果,也未免太令人不安。就像我現在在開發Model這一塊,正常情況下它是沒辦法獨立運作,而更不知道它到底能不能順利地運作。這時候使用單元測試,就可以簡單、迅速地知道這支程式在預期的情況下正不正常,並依此來修改程式。

雖然看到測試沒通過時,會覺得有點難過,但也總比系統寫得超複雜時還要回頭偵錯好的多。反過來說,看到每個單元測試都通過時,那種感覺真是非常地快樂。於是不知不覺,人心就變得單純了XD


我在這次報告中還有敘述Generic Object跟Lazy Loading的概念。Generic Object我還要再作一些修改,而它也實作了Lazy Loading這個程式設計的小技巧(儘管它很重要XD),所以留待之後有機會再一起講吧。

本週的論文進度報告就到此為止。因為有雜務丟下來了,所以又得一段時間沒辦法寫論文。就認命吧。

(more...)

論文進度報告(2010/6/20)

布丁布丁吃布丁

論文進度報告(2010/6/20)

2010-06-20_211446 進度報告

本週的進度報告很準時,這可能是最近大有進展、多到值得拿出來一說的樣子,那就一件一件地慢慢來聊聊吧。


越畫越複雜的Sequence Diagram

繼上週說的Sequence Diagram (循序圖),這次已經把該階段的作業完成。原本規劃是要畫4個流程,但後來畫到內嵌登入時,發現許多傳送參數與執行程序都可以重複使用,於是就把兩者和一。目前完成了「建立新增標註的過程」、「接受建議並修改標註」、「內嵌&手動登入」三種Sequence Diagram,詳細請看KALS Wiki

image

其中,第三張登入的複雜度,甚至已經分割成14張圖來表示,而且我還已經省略了View元件的初始化細節。這是由於KALS在初始化時需要經過很多步驟,登入取得參數、建立Domain與Webpage物件等工作都會在此時完成。換句話說,畫完此圖之後,大致上程式最根本的問題就差不多釐清,接下來就是程式寫作上的問題了。

多虧了Sequence Diagram的大整理,讓我回頭把Model跟Controller修了不少東西。一想到之後程式實作時,這些項目可能還會再改,我就沒有急著將之更新到KALS Wiki。事後也的確陸陸續續地修改了很多次。


KALS的程式實作計畫

完成了Sequence Diagram之後,接下來就可以開始進行程式實作了。但這次我也遵循著「工欲善其事、必先利其器」的態度,先來摸熟撰寫程式的各種工具。

KALS系統本身是採用PHP+PostgreSQL,使用CodeIgniter框架來撰寫。

PHP是大家耳熟能詳的網頁伺服器端程式語言,就普及性及開放性來說,我認為是時下首選。

PostgreSQL則是開放原始碼當中性能最強大的資料庫。儘管不如MySQL知名,但同樣能夠跨平台、更靈活的授權條款,而效能上也更為強大,其中全文檢索也是我垂涎已久的功能之一。儘管後來研究他全文檢索功能時,發現MySQL也有提供類似的功能。但我不喜歡MySQL編碼與無法商業用途的限制,所以仍堅持以PostgreSQL來實作KALS系統。

以上兩個其實都是很基本的程式語言與資料庫而已,但如果要讓自己的程式設計等級更上一層,就必須熟悉「框架」與「IDE」才行。

CodeIgniter Framework (框架)

image

CodeIgniter (簡稱CI)可能對學校剛出來的程式初學者來說比較陌生,但Ruby on Rails這名字沒聽過的話,你對網頁程式設計業界的了解程度可能不太夠喔。CodeIgniter是類似Ruby on Rails的框架,基於MVC架構,強調簡單、具有邏輯的結構、並提供豐富的函式庫。此外,CI背後有著EllisLab公司的支援,以確保這個開放原始碼計畫跟得上時代,而各種語言(包括正體中文喔!)的使用手冊也十分完備,在各種PHP Framework的效能評比中,CI也是數一數二的強喔!

雖然我沒有用過Ruby來寫程式,但看一看介紹,感覺上CodeIgniter就像是PHP版的Ruby on Rails差不多。事實上,CodeIgniter並不是學起來很「簡單」,而是撰寫程式時會讓它看起來很「簡潔」的一種框架。由於他有著許多固有的系統邏輯,除了MVC主要概念之外,還有libraray、helper、config等等各種細節需要去熟悉。就算是強大的資料庫控管功能Active Record Class,也跟PHP單純的mysql_query()有著不小的距離。要使用Framework,就必須先學習如何使用Framework,而這總是比純PHP還要複雜的一項額外作業。

另一個問題就是程式寫作的習慣。傳統的PHP是程序導向(procedure-oriented),到PHP4時逐漸有物件導向(Object-oriented)的功能,而PHP5時物件導向才大致完備。CodeIgniter則是用於PHP 4.3以上,相容PHP5的物件導向概念,這讓寫了兩年Java的我感到非常地不適應(還包括前一段講得那些架構,也都不太是單純的物件導向)。儘管CI這種方法是講求簡潔、快速,而我也承認Java純物件導向太過消磨程式設計師的耐性,但習慣這東西仍然不是一時能改得回來的。

更何況我學PHP時也是停留在程序導向的時代。當時function寫一堆,但遇到class裡面要用「$this」跟「->」就一整個不習慣。Java是使用「.」作為屬性或是方法的連接符號,而PHP是使用「->」;Java不太用「this」(儘管this有用處,但大多時候會省略),而PHP則是強制使用「$this」。而CI為了支援PHP 4.3,建構子仍然使用Class的名字,而非PHP的__constructor()之類的用法,這又跟我之前從書中所學有些不同。

請原諒我上面用了些程式設計師才看得懂的敘述來描述這些挫折,但我想這種無奈的感覺,大概也真的只有這個領域的人才能體會吧。總而言之,這一切的一切,都註定了我在實作前期必須要做好四處碰壁的心理準備。換句話說,不管怎麼寫,應該有八成都是錯誤的。

進階程式人員的利器:IDE

撰寫網頁程式的工具很多,有些人推崇使用具有所見即得功能的編輯器來快速設計網頁介面,包括DreamweaverNVU (這是開放原始碼的工具喔),但這是屬於前端介面的設計;有人也會用純文字編輯器Notepad++EmEditor (雖然對我來說,Dreamweaver也同樣是純文字編輯器就是),但是面對高度複雜的大型專案來說,使用單純的純文字編輯器可能就難以發揮良好效益了。

為什麼純文字編輯器效益不足呢?我簡單地舉出幾個理由:

  1. 沒有自動完成(auto-complete)的辭典:如果你寫程式時需要努力地翻找許多函式庫的使用手冊,你才能知道各種功能的參數及輸出型態的話,那你應該試著找尋具備自動完成的工具。儘管努力是件好事,但效率也太低了。沒有辭典的配合,也很難避免手殘寫錯函式名稱的情況發生。
  2. 沒有DOM或程式架構的導覽器HTML的Document Object Model或物件導向架構都是很有邏輯且方便的架構,但是在純文字編輯器當中是很難一目了然。我作過追蹤壓縮過的JavaScript程式碼的事情,那真是場惡夢,到最後也沒有什麼收穫。
  3. 追蹤專案中的程式:我以前使用EmEditor或是Dreamweaver的全文搜尋來找尋專案當中某個程式的方法,但我後來才知道,原來IDE早就能夠幫你把所有程式作連結、比較,這絕對比你搜尋字串還來得方便許多!

上述的功能都是現代整合開發環境IDE(Integrated Development Environment)中常見的基本功能。目前最知名的IDE應該是以Java為主要對象的Eclipse或是VB專用的Virtual Basic。其中,開放原始碼Eclipse具備的靈活架構,讓它可以整合PHP作為編輯對象,而具體呈現就是PHP開發工具計畫PDT。知名的PHP專用IDE商業軟體的Zend Studio也在5.5版本後推出了基於PDT的平台,可惜這是要付費的軟體,所以我並沒有使用。

一開始我安裝以Eclipse為基礎的PDTApatana,雖然他們都是很強大的IDE工具,但很遺憾的卻跟CodeIgniter不太和。如前面所述,我猜想這可能是歸咎於CI的物件導向沒這麼正規的緣故。不過還好,另一個知名的IDE NetBeans,則可以透過PHP Documentor來提供CI的支援!

IDE for PHP: NetBeans

image

感謝昇陽公司,原本商業發行的NerBeans現在也成為開放原始碼IDE的選擇。NetBeans主要用於Java,但跟Eclipse一樣地可以擴充支援PHP。另外它還支援以PHP Documentor撰寫的註解,讓我們只需要增加幾行註解,就能夠讓NetBeans解讀CodeIgniter的架構!

image

上圖就是NetBeans在能夠剖析CI架構之後所提供的自動完成功能。當你輸入方法名稱開頭幾個字時,NetBeans已經幫你帶出了CI相關的方法,並且基於PHP Documentor的註解格式,提供了包涵用途、參數、資料型態、回傳資料等說明。

由於NetBeans與PHP Documentor搭配是如此良好,撰寫專業風格的註解不再只是讓人看了自我感覺良好的工具,而是真的可以派得上用場的實用資訊!因此我現在也是一邊參考PHP Documentor的寫法,一邊為複雜的程式加上註解。

當然,NetBeans的自動完成提示不僅包括PHP,連JavaScript(包括jQuery,只要NetBeans看得懂)、CSS、還有PHP Documentor的格式都能夠聰明地告訴你喔!在此讓我誇張地來形容一下從純文字編輯器跳到NetBeans的差異,就像是從費力地騎腳踏車變成開賓士輕鬆出遊的爽快啊!


滿頭包的程式實作

在畫完Sequence Diagram之後,我稍微地統計了一下Model、WebApp部份的View跟Controller,看看它總共需要幾支類別。答案是總共182支。而從三天前開始程式實作到現在,我確實地完成的程式,只有2支。

除了上述提到的理由之外,我也嘗試熟悉PHP Doucmentor並製作NetBeans的樣板,以加速後面的開發作業。這次我也試著應用從極致軟體開發eXtreme Programming學到的「單元測試」精神,利用CI內建的單元測試類別來撰寫對應的測試工具。

2010-06-19_114940 unit test

上圖是單元測試的結果畫面。單元測試是一種最簡單的測試方法,輸入程式運算出來的結果,以及你預期應該要有的結果,如果兩者相符(甚至是資料類型相符),那麼測試就Passed,否則就是Failed。而我把每支程式比較難以確定正確性的功能都設計對應的單元測試,只要單元測試All Passed,那麼我也就可以差不多確定這支程式沒有問題了!

儘管一開始困難重重,許多的不熟悉帶來了巨大的挫折感,但同時「學習新事物」的新鮮感卻也讓我對這種挫敗甘之如飴。與之前程式寫作的經驗比起來,我感覺到自己明顯地逐步成長中,而這種成長的體驗也是讓我擁有在這個世界上活著的依據。

就讓我繼續在困境中狼狽地掙扎、跟絕望快樂地相處、然後繼續走到走不動為止吧。


專案進度與報告投影片

image

這次的專案進度中,我加入了幾個查核點,包括「可展示系統完成」、「可開始配置實驗資料」、還有「預官入伍(1/17)」(汗)等。預定本階段系統實作(coding)的時間會到7/12(一)。那時候好像是有些學弟妹的口試時間,我想我還是會去聽聽他們口試的。詳細的專案進度,請看KALS Wiki吧!

而本週報告的投影片也非常精簡,這是顧及了學弟妹需要報告實驗分析結果所作的取捨,所以只是簡單地報告我大概作什麼事情,以及進度規劃而已。


(SkyDrive下載)

自從昨天寫程式寫到整個Windows XP終於壞到無法正常進入Explorer之後,我毅然決然地改用學校提供的Windows 7。在經過一整天的兵荒馬亂,到了今天晚上才把整個Windows 7設定大致抵定。儘管Windows 7的使用體驗也是有很多值得聊的,但我赫然發現這篇寫到現在已經破三千字了。想看一看我在用Windows 7時發生什麼事情的朋友,只好請你們去看看噗浪這一篇吧。

經過一個月枯燥乏味地畫圖,能開始撰寫程式之後,從上面這一長串就可以看得到我到底有多麼地為此感到開心。

本篇從昨天九點半寫到現在也四個多小時了,也差不多到此為止吧。下次有些進度再來跟大家聊聊囉!

(more...)

論文進度報告(2010/6/13)

布丁布丁吃布丁

論文進度報告(2010/6/13)

1-1 CreateAnnotationScopeCollection

距離上次進度報告大概10天的時間,現在就開始這次的進度報告。

上次將Webpage Application的網站草圖(Website Wireframe)畫完之後,陸陸續續地也把Controller做完了,詳情請看KALS Wiki的資料。在畫Controller時,其實我並沒有很仔細地去構思到底該怎麼運作。在AJAX的架構中,View所在的JavaScript同時扮演了View跟Controller的角色,伺服器端的Controller反而像是提供資料的角色而已。

原本計畫完成Controller之後,我就開始進行程式撰寫的作業。目前把ERD (關聯式資料庫的實體關聯圖)畫得差不多,還再次複習了CodeIgniter使用手冊。但基於對Controller太過潦草的不安,我決定還是插入Sequence Diagram(循序圖)的任務,打算好好地檢視資料在物件之間流動的情況。特別是以下這四種情況:

  1. 建立新增標註的過程(包含計算分數、推薦標註與提示等細節)
  2. 接受建議並修改標註位置
  3. 自動登入
  4. 手動登入

由上而下的規劃方式

1 CreateAnnotation main

由於對於Sequence Diagram的不熟悉,我花了很多時間在畫建立新增標註的過程。由於StarUML跟書上寫的功能有些許不同,書上對Sequence Diagram的介紹也不是很清楚,於是我只好自己試著建立起屬於自己的表示方式。除了將上面的這張主要流程切割成其他7個小部份,對於參數傳遞與回傳值等也稍微跟標準的劃法不太一樣。目前已經完成了建立新增標註的過程的八張圖請看KALS Wiki

經過Sequence Diagram的檢視,赫然發現標註在模糊分數計算、推薦與提示上出現了很大的問題。這讓我回頭去修改了Model的Annotation、Fuzzy跟Recommend等Class。

在之前的進度報告中,我在繪製View、網站草圖時,也常常提到回頭修改這件事情。每次回頭修改的感覺都頗令人絕望,但值得慶幸的是,我回頭只是改圖,而不是修改那數千行的程式碼。我想,這就是一種由上而下的規劃方式吧。儘管目前仍沒有實際可以把玩的程式給大家看,但這些分析與規劃的確是一步一步地讓這個系統更為穩健。


專案進度:加入Sequence Diagram

image

如上圖所示,跟上週比起來,加入了Sequence Diagram的工作,並將之規劃為9天的工作天,因此排擠到後面程式撰寫與可展示系統的查核點。很不幸的,如果專案如期進行,大概七月初才能將系統展示給大家看吧。詳細的專案進度,請到KALS Wiki下載


老實說,一直畫圖,太久沒寫程式,實在是讓我覺得有點無聊。所以這次中間有幾天都跑去修改布丁布丁吃?的版面(遮臉)。那時的自己並不會使用JavaScript的callback技巧,我還蠻驚訝的。在不知不覺時,自己的程設等級似乎又無形中上升了,而這在修改以前寫的程式中也有所映證。

除此之外,老師對我在畫UML這件事情也覺得還不錯。儘管UML分析的過程枯燥乏味又無法立竿見影,急於完成論文的學生大多時候並不會選擇採用這種方式。但對於大型系統與多人合作團隊的情境之下,UML仍是一項很有力的工具。

反正我已經多留了很多時間了,也不差讓我再多用一些時間繼續繞繞遠路,學些新的玩意兒。

我也不知道這究竟是好事還是壞事。從好的角度看來像是求知欲強烈,從壞的角度來看則是拖台錢(找理由延畢)。不管怎樣,我只知道我還挺無聊的就是XD

(more...)

布丁布丁吃? 速度優化改版

布丁布丁吃布丁

布丁布丁吃? 速度優化改版

image

由於昨晚在幫朋友修改自動摘要功能,一時興起,就一起把整個Blog的功能都整理了一下。「布丁布丁吃?」的讀取速度緩慢,一直是為朋友所詬病的問題。連我自己都不太常直接開啟「布丁布丁吃?」,而是用Google閱讀器來找之前的文章。

這次整理有幾項改變:

  • 為JavaScript加入了callback的程式設計技巧,讓網頁中的元件依序處理、顯示,而不是一口氣擠在一起處理、導致瀏覽器看起來就像當掉一樣。
  • 修正自動摘要、側欄列、最新回應的一些小問題。 自動摘要變很多……但效率一樣低落XD 所以遇到讀很多篇的頁面,我會把右側導覽列的部份功能關掉。
  • 修正已經被轉移的Google Page Creator網址,改用hostes網站空間,以為JavaScript跟CSS提供快取(cache)功能。
  • 將相關文章改成LinkWithin的「您或許對這些文章有興趣:」:原本相關文章是抓取同樣Label隨機選取的,作法簡單。現在越來越多人用LinkWithin了,我也跟著潮流用用看。
  • 加入Facebook的「讚」跟addThis的share按鈕:因為我也開始用Facebook啦。雖然只是上去玩玩遊戲、把噗浪轉過去而已。

最後使用GTmetrix來分析網站的效能(電腦玩物有詳細的介紹),發現布丁布丁吃?的效能卡在Google Friends Connect (簡稱GFC)的顯示上。然而到目前為止,我實際使用GFC的機會微乎其微,因此我在考慮是否要改成Facebook的社群外掛元件?稍微摸了一下,好像很複雜orz 所以暫時還是保持原樣吧。

下次整裡的時候,預定會把Cbox換掉,改成由Blogger的回應來實作。概念上就是把其中一篇Blog當作訪客留言板,利用張貼意見的RSS來顯示留言,輔以張貼意見的按鈕,然後模仿Cbox的留言板介面,感覺就會像是一個小型聊天室。這樣的好處是留言板的資料會保留,而且讀取速度也會比外來的Cbox還快。但是開發這種外掛似乎也是一件大工程,等我哪天想不開時,再來使用吧。


雖然篇名寫說是速度優化改版,但其實好像也沒多快…… OTL

(more...)

把可攜式瀏覽器作為您的預設瀏覽器:Default Portable Browser

布丁布丁吃布丁

把可攜式瀏覽器作為您的預設瀏覽器:Default Portable Browser

image


發展緣由

網頁瀏覽器的種類百百種,其中我最常碰觸的是IEFirefoxGoogle瀏覽器(Google Chrome)。但是基於硬碟備份策略,我不喜歡把瀏覽器以及瀏覽器的各種資料裝在C分割區,而是喜歡用Portable可攜式綠色軟體的瀏覽器,將之擺在其他的分割區中。除了IE沒有可攜式版本之外,Firefox跟Google瀏覽器都有不少人致力於此,諸如:

儘管可攜式瀏覽器讓您可以將資料帶著走,但它們的問題在於,要將它作為「預設瀏覽器」的動作卻十分麻煩。以往我是使用DefaultBrowser,但不知為何,我的Windows XP現在並不允許我使用這個套件,我推測是跟.NET Framework的更新有關係。

於是我只好參考How can I configure the default Internet Browser?Using Firefox Portable as your default browser!這兩篇文章,直接去修改登錄檔。修改登錄檔的手續較為複雜,所以我又用AutoIT來簡化這個程序,而撰寫成了Default Portable Browser這隻小程式,以方便有相同需求的人使用。

由於我目前只使用Firefox、Google瀏覽器跟IE,所以Default Portable Browser也只支援這三種。IE雖然不是可攜式瀏覽器,但是既然文章寫了方法,那我也就順勢地加入了這個功能。

(more...)