2007年08月31日

[PHP] PHP 5.2.4 發佈


Posted by jaceju at 14:07回應(6) PHP

2007年08月30日

[Web] 連結分享

Ruby on Rails

JavaScript


Posted by jaceju at 10:27回應(4)連結分享

2007年08月27日

[PHP] 連結分享

  • PHP IDE - Zend Studio Neon

    Zend 自己出的 IDE 終於要推出 6.0 了,其實它就是 Eclipse + PDT 。最大的特色就是可以新增一個 Zend Framework 的專案,然後會幫你把相關的目錄結構給建好。

    試用了一下,發現裝了一堆套件的 Eclipse 執行速度真的是很慢很慢,我自己手動安裝的還快點...

    註:我不曉得能不能給下載連結,因為這是 Mark 給的,它好像要申請測試才能試用的樣子。不過電腦等級不是最高檔的話就別試了,保證慢到你會想扁人。

  • Setting up Zend Framework applications with Phing

    Phing (簡體中文介紹 by Hick) 來設定 Zend Framework 應用程式的建構與佈署,我想在上面的 Neon 還沒正式推出之前,也可以考慮採用這個方法。

    不過目前在我們的實際開發上,我覺得這樣的方式還是有點複雜與麻煩,「 SVN 加複製貼上可能還比較有搞頭」;當然這是我們的狀況,也許其他地方很適用也說不定。


Posted by jaceju at 10:26回應(0)連結分享

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 會不會馬上蹦出來好了。


Posted by jaceju at 18:24回應(5)JavaScript

[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 。不過還是要小心以下兩點:

  1. 一個 Class 可以實作多個 Interface ,但只能繼承一個 Abstract Class ;這即是所謂的單一繼承體系,也就是子類別只能繼承一個父類別;但是一個父類別則可以被多個子類別所繼承。

  2. 在 Abstract Class 中可以宣告屬性成員 (attribute) 而 Interface 是不可以的,但兩者都能有常數成員 (constant) 。

範例

假設我們有兩個裝置 (Device) ,一個是鍵盤 (Keyboard) ,一個是滑鼠 (Mouse) ;而這兩種裝置都支援 USB 和 PS/2 兩種接頭 (Adapter) 讓使用者可以自行選擇,不過一次只能選擇一種接頭。

註:這個範例舉得不是很好,只是為了說明而已。

上面文字明白指出了我們可能會有 Device 和 Adapter 兩個 Abstract Class (或 Interface ) ,不過問題是哪一個應該用 Abstract Class ?而哪一個該用 Interface 呢?

為了簡化說明,我們把原來的問題重新定義為以下的規格:

  1. Device 有 inputData (輸入資料) 及 getStatus (取得狀態) 等兩個方法。

  2. Adapter 有 send (傳送) 和 receive (接收) 兩個方法。

  3. 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 來表示的話,就是以下這樣子:

Device and Adapter

以下是測試的程式:

<?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 ,其實這在設計階段是常有的事情。所以掌握以下的重點,就會比較容易看出兩者的使用時機:

  1. 當類別有共同的行為或屬性時,可以考慮使用 Abstract Class 。

  2. 當類別有共同的操作介面,但是實作上卻有所差異時,可以考慮使用 Interface 。

不過當我們發現整個類別體系用錯 Abstract Class 或 Interface 時也不用過於煩惱,這時「 Refactoring (重構) 」就是我們會需要的好幫手。更詳細的 Refactoring 說明可以參考以下書籍:


Posted by jaceju at 12:40回應(10)程式開發

2007年08月23日

[PHP-ZF] Zend_Cache

記一下剛剛看懂的 Zend_Cache 說明:

Frontend

指的是要快取的對象。

Backend

指的是儲存快取的容器。

然後 Zend_Cache 目前提供的 Frontend 及 Backend 相關資源如下:

Zend_Cache

而 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


Posted by jaceju at 20:02回應(0)Zend Framework

2007年08月21日

[轉載] 5 個加速 JavaScript 執行速度的方法

5 ways to speedup javascript

5 個加速 JavaScript 執行速度的方法,節錄如下:

  1. use a compressor (使用壓縮器,例如 JSMin ;據說對岸高手寫的 JSA 也不錯。)

  2. minimize the number of .js files (減少 JS 檔案的引入次數,因為會引發多次的 HTTP 要求。)

  3. use profiler and timer tools (用側錄及計時工具來分析效能,推薦使用 Firebug 。)

  4. asynchronize your code (以非同步來執行程式碼;大意是不要直接在頁面解析時就執行程式,而是利用 setTimeout 來背景執行。)

  5. cache DOM variables (快取 DOM 變數;簡單來說就是把類似 document.getElementById 取到的節點放在變數裡,而不是每次都要再執行一次。)


Posted by jaceju at 23:24回應(0)JavaScript

[PHP] 連結分享


Posted by jaceju at 19:41回應(0)連結分享

[PHP] 連結分享

最近一直在貼連結,不過我已經想不出來標題要怎麼下了。


Posted by jaceju at 10:45回應(0)連結分享

[Web] 連結分享

再分享幾個連結:

PHP

Database

電子商務


Posted by jaceju at 0:25回應(0)連結分享
 [1]  [2]  [3]  [最終頁]