2007年08月31日
[PHP] PHP 5.2.4 發佈
-
主要是修正了很多 Bug , 我想等一陣子再更新好了。
-
獵人261 連載再開!!!! 富樫義博 終於要畫 HunterXhunter 261了!!!
富奸終於要畫新的獵人了~~真是太感動了!!! ( TT__TT )
什麼?這跟網站製作沒關係喔?因為我太高興了嗎...
2007年08月30日
[Web] 連結分享
Ruby on Rails
-
Ruby on Rails vs PHP - railsenvy.com Commercial #6
這是 Neo 給我看的連結;真人對話好像很流行的樣子,這次是 RoR vs PHP 。還故意找個胖子和瘦子來對比...
唉...看來 PHP 社群真的很被看不起...雖然我不討厭 RoR (只是不喜歡 Ruby 那種跟 Perl 有得拼的天書語法) ,也欣賞它的架構;但是 PHP 能做的比你想像得多呀! RoR !
註:我以為我找不到 #1 和 #5 ,原來 #1 是 Java , #5 是 .NET 。
-
Ruby on Rails vs Java - RailsEnvy.com Commerical
當然也有 RoR vs Java 。
-
Ruby on Rails vs .NET - railsenvy.com Commercial #5
.NET 免不了也被拿來比一比,不過說實在的,我真的很討厭這種看不起人的行銷手法,好像這世界只有 RoR 才是王道。
JavaScript
-
把 array 中沒有意義的項目移除,或是保留指定的項目。
-
Cross-browser XML and JavaScript
消除各家瀏覽器在 XML Parser 之間的差異。
2007年08月27日
[PHP] 連結分享
-
Zend 自己出的 IDE 終於要推出 6.0 了,其實它就是 Eclipse + PDT 。最大的特色就是可以新增一個 Zend Framework 的專案,然後會幫你把相關的目錄結構給建好。
試用了一下,發現裝了一堆套件的 Eclipse 執行速度真的是很慢很慢,我自己手動安裝的還快點...
註:我不曉得能不能給下載連結,因為這是 Mark 給的,它好像要申請測試才能試用的樣子。不過電腦等級不是最高檔的話就別試了,保證慢到你會想扁人。
-
Setting up Zend Framework applications with Phing
用 Phing (簡體中文介紹 by Hick) 來設定 Zend Framework 應用程式的建構與佈署,我想在上面的 Neon 還沒正式推出之前,也可以考慮採用這個方法。
不過目前在我們的實際開發上,我覺得這樣的方式還是有點複雜與麻煩,「 SVN 加複製貼上可能還比較有搞頭」;當然這是我們的狀況,也許其他地方很適用也說不定。
2007年08月24日
[JavaScript] jQuery 推出 1.1.4 版
jQuery 1.1.4: Faster, More Tests, Ready for 1.2
還沒看到阿土伯的介紹,所以我先貼一下好了。
Updated: 阿土伯也寫介紹囉~~是篇很精采的技術分析,請看 Racklin's 阿土伯程式大觀園::jQuery 1.1.4 Release 。
jQuery 推出了 1.1.4 版,速度變得更快了。如果我沒看錯的話,某些狀況有快到 16 倍之譜,不過不曉得是不是把一些功能分離出去或直接拿掉的關係。
jQuery 也可以用以下的方式來與其他 JavaScript Library 結合:
// With the Dojo Toolkit
dojo.jquery = jQuery.noConflict(true);
dojo.jquery("#elem div").slideDown("slow");
// or with Yahoo UI
YAHOO.query = jQuery.noConflict(true);
YAHOO.query("span.hidden").removeClass("hidden");
另外 jQuery 也多了幾個新函式,並移除幾個不常用的功能;這些我想都是因應使用者的回應,並且準備導向 1.2 版所作的決定。
註:不過如果有 plugin 用到這些廢除功能的話就慘了,看來我得再持續關心後續的發展。
總之 jQuery 越來越令人欣賞了,不過我還是等看看 1.1.4.1 會不會馬上蹦出來好了。
[PHP] 該用 Abstract Class 還是 Interface ?
這裡把自己對 Abstract Class (抽象類別) 和 Interface (介面) 的理解記一下,如果有錯請指正我 :)
Abstract Class 與 Interface 的宣告方式
Abstract Class 和 Interface 本身都無法用來建構一個 object (物件實體) ,它們必須透過其他類別以 extends (繼承) 或 implements (實作) 來完成目的。在 PHP 中,我們可以用以下的方式來宣告一個 Abstract Class :
abstract class Test
{
// ... code ...
}
然後其 sub class 必須用 extends 來繼承它:
class ClassA extends Test
{
// ... code ...
}
而 Interface 則是用以下的方式宣告:
interface Testable
{
// ... code ...
}
然後 sub class 類別便可以 implements 關鍵字來實作該介面:
class ClassB implements Testable
{
// ... code ...
}
註:同人老大說實作 Interface 的類別不能稱為 sub class ,不過我實在也想不出什麼好名詞,歡迎大家提供意見。
另外比較特別的是, Interface 可以繼承衍生自另一個 Interface :
interface A extends B
{
// ... code ...
}
這裡本來用繼承一詞,經同人老大指點後,用衍生一詞會比較精準。
但是除了語法上的不同,它們本身所代表的意義是什麼呢?
Abstract Class
當整個類別繼承體系有一致的行為時,我們通常會將這些行為抽離到上一層的 super class 去。如果這些行為的程式碼不在 super class 中定義的話,那麼會使得其 sub class 必須重覆地出現相同的程式片段,導致了壞味道的發生。然而有時我們並不打算讓這些 super class 可以被建構成物件實體,那麼它們就是所謂的 Abstract Class 。
在 Abstract Class 中, method 的定義方式有兩種,以下是有實作的 method :
public function method1()
{
// ... code ...
}
值得注意的是,就算大括號中沒有程式碼,也算是有實作的 method ,我稱之為空實作。
另一種是抽象方法,只要在 function 前加上 abstract 關鍵字,再拿掉大括號並加上分號:
abstract public function method2();
這樣的抽象方法,就會要求 sub class 在繼承之後要實作該方法的細節。
Interface
在我們確定了物件之間的溝通方式及規格,卻未能確定其實作細節時,就是利用 Interface 的時機。 Interface 能保證 Client 在操作物件上有一致的方式,而具體的表現方式則是讓實作的類別來決定。因此這些類別都必須實作在 Interface 裡定義的 method ,否則將會出現錯誤。在 Interface 中所有方法都是 abstract 的,定義方式和 Abstract Class 的抽象方法一樣,但是不用加上 abstract 關鍵字,例如:
public function method3();
顯然地,當 Abstract Class 所擁有的方法都是 abstract method 時,它就退化成了一個 Interface 。不過還是要小心以下兩點:
-
一個 Class 可以實作多個 Interface ,但只能繼承一個 Abstract Class ;這即是所謂的單一繼承體系,也就是子類別只能繼承一個父類別;但是一個父類別則可以被多個子類別所繼承。
-
在 Abstract Class 中可以宣告屬性成員 (attribute) 而 Interface 是不可以的,但兩者都能有常數成員 (constant) 。
範例
假設我們有兩個裝置 (Device) ,一個是鍵盤 (Keyboard) ,一個是滑鼠 (Mouse) ;而這兩種裝置都支援 USB 和 PS/2 兩種接頭 (Adapter) 讓使用者可以自行選擇,不過一次只能選擇一種接頭。
註:這個範例舉得不是很好,只是為了說明而已。
上面文字明白指出了我們可能會有 Device 和 Adapter 兩個 Abstract Class (或 Interface ) ,不過問題是哪一個應該用 Abstract Class ?而哪一個該用 Interface 呢?
為了簡化說明,我們把原來的問題重新定義為以下的規格:
-
Device 有 inputData (輸入資料) 及 getStatus (取得狀態) 等兩個方法。
-
Adapter 有 send (傳送) 和 receive (接收) 兩個方法。
-
Device 必須透過 Adapter 來傳送或接收資料,
我們從規格的第三點可以得知,無論 Device 的類型為何,都會需要透過 Adapter 來收送資料,這就是一種抽象行為。也因此我們必須為 Device 提供一個 Adapter 類型的 $_adapter 屬性成員,從這點就可以看出 Device 應該是個 Abstract Class 。
而因為有 $_adapter 屬性,但我們又不想讓外界直接改變它,所以我們將它的 scope 設置為 private (私有屬性) ;然而要設定 private attribute 我們就要借重一個規格外的方法,這裡我將它命名為 setAdapter ;所以當我們在呼叫 setAdapter 時就必須傳入一個 Adapter 物件來指定給 $_adapter 屬性,這樣就能防止 Device 在使用 $_adapter 時的錯誤。
public function setAdapter(Adapter $adapter)
{
$this->_adapter = $adapter;
}
然後 Device 的 inputData 和 getStatus 就會委託 Adapter 物件的 send 及 receive 來收送資料:
public function inputData($data)
{
echo $this->_deviceName, ' input data:';
$this->_adapter->send($data);
}
public function getStatus()
{
echo $this->_deviceName, ' get status:';
echo $this->_adapter->receive();
}
註:以上程式還是有一些潛在的小問題,這裡就留給各位自行判斷囉。
對 Device 的 sub class 來說,以上的行為都是可以共用,也因此不必再實作一次了。完整的 Device 類別體系如下:
<?php
abstract class Device
{
private $_adapter = null;
protected $_deviceName = '';
public function setAdapter(Adapter $adapter)
{
$this->_adapter = $adapter;
}
public function inputData($data)
{
echo $this->_deviceName, ' input data:';
$this->_adapter->send($data);
}
public function getStatus()
{
echo $this->_deviceName, ' get status:';
echo $this->_adapter->receive();
}
}
class Device_Keyboard extends Device
{
protected $_deviceName = 'Keyboard';
}
class Device_Mouse extends Device
{
protected $_deviceName = 'Mouse';
}
接著再看 Adapter ,因為 USB 和 PS/2 在規格實作上是有所差異的,因此我們無法在 Adapter 中直接去定義像 Device 中 inputData 及 getStatus 這樣共用的行為方法。所以在這裡我們就能將 Adapter 視為是一個 Interface ,讓其下的 Class 去實作 send 和 receive 兩個方法的細節。所以整個 Adapter 的類別體系如下:
<?php
interface Adapter
{
public function send($data);
public function receive();
}
class Adapter_Ps2 implements Adapter
{
public function send($data)
{
echo $data, ' by PS2.', "\n";
}
public function receive()
{
return rand(100, 200) . ' by PS2.' . "\n";
}
}
class Adapter_Usb implements Adapter
{
public function send($data)
{
echo $data, ' by USB.', "\n";
}
public function receive()
{
return rand(300, 400) . ' by USB.' . "\n";
}
}
註:為了說明方便,所以我簡化了 USB 和 PS/2 的兩個方法的實作方式。
當然 Adapter 也不一定要是 Interface 才行,這得看整個程式架構上的設計來判斷。如果在 Adpater 在設計上會有共用的行為或屬性時,那麼 Abstract Class 就是比較好的選擇;只是在這個範例裡,我為了說明 Interface 的緣故,就大幅簡化了 Adapter 的設計。
整個設計用 UML 來表示的話,就是以下這樣子:

以下是測試的程式:
<?php
require_once 'Device.php';
require_once 'Adapter.php';
$keyboard = new Device_Keyboard();
$mouse = new Device_Mouse();
echo "\n";
$keyboard->setAdapter(new Adapter_Ps2());
$keyboard->inputData('abc');
$keyboard->getStatus();
echo "\n";
$mouse->setAdapter(new Adapter_Ps2());
$mouse->inputData('def');
$mouse->getStatus();
echo "\n";
$keyboard->setAdapter(new Adapter_Usb());
$keyboard->inputData('abc');
$keyboard->getStatus();
echo "\n";
$mouse->setAdapter(new Adapter_Usb());
$mouse->inputData('def');
$mouse->getStatus();
/*
程式執行結果:
====================================================
Keyboard input data:abc by PS2.
Keyboard get status:130 by PS2.
Mouse input data:def by PS2.
Mouse get status:165 by PS2.
Keyboard input data:abc by USB.
Keyboard get status:360 by USB.
Mouse input data:def by USB.
Mouse get status:353 by USB.
====================================================
*/
結論
很多時候我們常會搞不清楚該用 Abstract Class 還是 Interface ,其實這在設計階段是常有的事情。所以掌握以下的重點,就會比較容易看出兩者的使用時機:
-
當類別有共同的行為或屬性時,可以考慮使用 Abstract Class 。
-
當類別有共同的操作介面,但是實作上卻有所差異時,可以考慮使用 Interface 。
不過當我們發現整個類別體系用錯 Abstract Class 或 Interface 時也不用過於煩惱,這時「 Refactoring (重構) 」就是我們會需要的好幫手。更詳細的 Refactoring 說明可以參考以下書籍:
-
Refactoring by Martin Fowler (中譯本:重構 by 侯捷、熊節)
-
Refactoring To Patterns by Joshua Kerievsky
2007年08月23日
[PHP-ZF] Zend_Cache
記一下剛剛看懂的 Zend_Cache 說明:
- Frontend
-
指的是要快取的對象。
- Backend
-
指的是儲存快取的容器。
然後 Zend_Cache 目前提供的 Frontend 及 Backend 相關資源如下:

而 Core 是預設的 Frontend ,可以儲存大部份能被 serialize 的資源。
以下是官方提供建立 Cache 物件的方式:
<?php
require 'Zend/Cache.php';
$backendName = 'File';
$frontendName = 'Core';
$frontendOptions = array([...]); // optional
$backendOptions = array([...]); // optional
$cache = Zend_Cache::factory($frontendName, $backendName, $frontendOptions, $backendOptions);
以上的關係理解後,看官方手冊就更容易了。
註:不知道是年紀大而導致理解力衰退,還是 Zend_Cache 參數命名不直覺的關係?這麼簡單的東西想了好久...Orz
2007年08月21日
[轉載] 5 個加速 JavaScript 執行速度的方法
5 個加速 JavaScript 執行速度的方法,節錄如下:
-
minimize the number of .js files (減少 JS 檔案的引入次數,因為會引發多次的 HTTP 要求。)
-
use profiler and timer tools (用側錄及計時工具來分析效能,推薦使用 Firebug 。)
-
asynchronize your code (以非同步來執行程式碼;大意是不要直接在頁面解析時就執行程式,而是利用 setTimeout 來背景執行。)
-
cache DOM variables (快取 DOM 變數;簡單來說就是把類似 document.getElementById 取到的節點放在變數裡,而不是每次都要再執行一次。)
[PHP] 連結分享
-
Zend Framework: Zend_Application Component Proposal
這個和我目前做的 Application 類別有異曲同工之妙,不過既然是官方的 Solution ,那麼我想我應該參考看看。
[PHP] 連結分享
最近一直在貼連結,不過我已經想不出來標題要怎麼下了。
-
15 Cool Things About PHP That Most People Overlook
大致介紹了一下 PHP5 的一些特點,還有傳統 PHP 就有的技巧。
-
12 Things You Should Dislike About PHP
跟上一篇剛好相反,這些是開發 PHP 的人很不喜歡的缺點;尤其是第一點的函式命名,一點也不統一,真希望 PHP未來的版本能做改進。
-
利用 debug_backtrace() 函式來完成 Event 的監聽,利用到了 Observer 模式。話說 debug_backtrace() 真的是一個滿有用的函式,它可以協助你瞭解程式執行時的來龍去脈。
[Web] 連結分享
再分享幾個連結:
PHP
-
Develop multitasking applications with PHP V5
用 stream_select() 函式實現多工,還滿有趣的一個技術。
-
Creating Image Streams from Existing Graphics with the GD Library in PHP
教你如何使用 GD 建立影像,這個雖然算是 GD 基礎,不過可以看看傳統函式如何與 PHP5 的 try-catch 機制搭配。
-
這篇是從 mikespook 那邊看到的,改天來試試用 MySQL 實作。
Database
-
Auto detecting referenced field
這個是 PEAR::MDB2 裡會用到的, PEAR::MDB2 是用來取代 PEAR::DB 的另一種資料庫抽象層。
-
How fast can you sort data with MySQL ?
微調 sort_buffer_size 來測試 MySQL 在排序上的效率。
電子商務
-
其實裡面有一些都有和 Neo 討論過了,尤其庫存這項在搶購出現時,的確是非常難解的一件事。
