
日期:2006-09-21 作者:喜騰小二 來源:PHPChina
一個關於 PHP/Oracle 開發模型如何在 Myers Internet
縮短應用程式生命週期的案例研究。
對於主要由應收款業務模型驅動的公司而言,其核心的業務功能之一是輸入、跟蹤和記錄訂單。在這方麵比較出色的公司可以伸縮它們的機構,並提高它們的利潤,而不會遇到基礎架構的限制。當訂單處理很麻煩、容易出錯或不一緻時,公司將因為直接的成本和降低的生產效率而蒙受經濟上的損失。
在我的公司 Myers Internet,核心的業務事項圍繞着建立客戶基礎,為 Myers
提供持續的服務並說明它在客戶問題出現時解決問題。公司正使用許多不同的係統來處理訂單輸入和實施週期的各個方麵。這些係統既不是彼此整合的,也不俱備確保每一份訂單都得到正確記帳的機制。
Myers 訂單跟蹤係統 (MOTS)
就像其它許多機構一樣,Myers
從一個小型公司成長為一個中型公司,同時在它的整個成長期間始終保留了相同的過程和係統。大多數這些過程在建立時,所有的事務處理都透過電子郵件、紙質記錄和實地拜訪來人工地完成。5
或 6 年前,Myers 的一個工程師利用 Allaire 的 Cold Fusion 和一個 Microsoft SQL Server
資料庫組裝了一個係統來跟蹤訂單實施,這個係統稱為 MOTS (Myers
訂單跟蹤係統),它允許銷售和帳目管理部門輸入訂單,然後由支援、工程、設計、資訊係統和會計部門實施這些訂單。雖然這個係統是嚮前邁進的重要的一步,但它仍然留有許多人工的步驟,並且沒有和任何其它的業務係統整合在一起。
大概在同一時間,還建立了一個係統,在這個係統中客戶和銷售代表可以線上訂購 Myers
網站的產品。這個係統可以建立新的 Web 站點,並計算提供的 Web 站點套裝程式的安裝和重複性費用的總和。然後它發送電子郵件給各個部門,各個部門可以將訂單輸入到
MOTS 中,並在帳目管理係統中建立記帳資訊。
體係結構障礙
這種類型的體係結構飽受幾種係統問題之苦。在
Myers,較明顯的問題之一包括啓動訂單跟蹤所需的人工資料輸入,以及作為這種人工過程的結果而產生的錯誤。另一個問題是公司中的訂單輸入、訂單跟蹤和記帳係統之間的脫節、訂單丟失、資訊遺漏和其導緻的錯誤。
另一個僅偶而出現的問題是 MOTS 係統本身有內在的缺陷。由於編寫 MOTS
的方式,可以輸入沒有部門分配資訊或者丟失了部門分配資訊的訂單。當這種情況發生時,訂單最終將在係統中丟失。當訂單丟失時,準確、及時的記帳就更難實現了。
隨着業務的成長,體係結構中的缺陷變得越來越明顯,並且隨着客戶和訂單數量的增加,丟失和錯誤輸入的訂單出現的頻率越來越高,從而給公司收入帶來了難於估量的影響。此外,人工輸入的資料的數量導緻了延遲和處理效率低下。
由於在實施機構內對收入的影響加大和效率降低,很明顯必須要有一個取代係統來將一切聯係起來,並提高效率和降低錯誤率。舊係統圖示如下。
![]() |
該圖顯示了需要人工資料輸入的所有區網域。由於這些係統都不是整合的,所以資料丟失或失真的可能性非常大。全域需求馬上變得明顯起來。
雖然一個好的訂單輸入和跟蹤係統可以說明降低成本,但它本身並不創造收入。
深入結構
在開始模式設計之前,需要解決一些基本的體係結構問題。第一個底層的技術需求是係統必須可配置,且無需額外的編碼。本質上,這意味着需要把工作流嵌入到資料庫中,而不是用解釋/處理程式碼來進行硬編碼。第二,資料庫需要包含足夠的資訊,以便能夠表現訂單輸入介麵的主要(和可變更)的方麵以及實施處理。
在努力解決上述問題的過程中,該係統逐漸適合於兩個部分 —
訂單輸入和訂單跟蹤,並在兩者之間提供了明確定義的聯係。訂單輸入係統需要知道如何用準確的產品程式碼、折扣和定價條款來表示訂單。訂單實施係統需要知道如何跟蹤各種類型的工作、相關的作業和各個部門,以處理和記錄每份訂單。最後,需要定期和可預測地把訂單轉化成實施作業。下圖顯示了目前存在的新係統的結構。
![]() |
該圖顯示了通嚮新的訂單係統的所有資訊路徑,新的訂單係統位於後端的入口管理站點。所有的初始資料輸入都僅一次性完成,並且隻需要每個小組在處理的各個階段驗證資料。透過引入從訂單係統到帳目管理係統的自動資料傳輸,至關重要的資料傳輸的另一個主要的領域也變為自動化。
依賴 PHP
在純技術的層麵上,早期決定使用 PHP 作為主要的開發語言和 Oracle
作為係統的資料資訊庫,這有幾個主要的原因。首先,Myers 現有的後端入口幾乎完全是用 PHP 根據一個現有的 Oracle
資料庫編寫的,這消除了一個產生不相容性的潛在來源。這還意味着要建立這個新的係統,Myers
可以利用自身的能力,這些能力建立了現有的後端入口。
第二,實驗測試顯示,與其它開發語言相比,PHP 提供了一個比較高的效能水平。因為 PHP
是作為一個動態載入的資料庫駐留在 Apache 伺服器內部的,所以每一次與係統連線都無需額外的啓動時間。此外,PHP 最佳化的改善(透過 Zend
項目)意味着在程式碼內部執行的一般操作不會明顯變慢。最後,為 PHP 編寫的 OCI 介麵模組是用 C 程式碼編譯和最佳化的,這使得訪問 Oracle
資料庫非常高效。
第三,我們瞭解到因為 PHP 程式碼將其自身嵌入到了 HTML
環境中,所以對於設計人員和編程人員而言,建立協作使用者介麵功能程式碼變得更加自然。雖然最後這個特性其它的伺服器端指令檔語言也俱備,但 Myers 發現 PHP
更不可能帶來開發人員和設計人員之間的衝突。此外,PHP 的語法和提供的程式碼庫意味着它可以做它需要做的所有事情。
最後,將所有程式碼嵌入到 HTML 程式碼中的另一個好處是,僅需要對標準文字檔案進行修改控制就可以控制源程式碼。我們用
CVS 作為它的標準修改控制係統。因為 PHP 程式碼不一定要用某一種方式進行編譯,所以建立係統的一次“編譯”僅涉及到從資訊庫中檢索文字源程式碼檔案,然後把它們放到
web 伺服器上。這意味着我們可以使用 CVS 中的控制機制為它的測試和生產環境發佈增量的 bug
補丁,而無需建立復雜的編譯係統。
設計模式來支援可重新配置性
下麵的基本模式示意圖顯示了訂單係統是如何建置的。兩種主要的模式都分為原型表和事務表。無論何時當業務情況發生變化時,原型表都允許重新配置係統,而無需重新編碼。事務表包含實際客戶訂單的訂單詳情和作業詳情。
![]() |
![]() |
這些模式示意圖看起來很復雜,當然,它們的確很復雜。不過,如果把它們分開,使得隻出現原型表(以 _def
結束的表),那麼該體係結構的基本結構就變得很清楚了。訂單由行組組成,這些行組包括詳細資訊、訂單行或兩者。訂單行可以隨意地建立作業,作業由一個工作序列組成,並且包含幾條詳細資訊。必需要為各種工作輸入這些詳細資訊。工作出現在不同的隊列中,這些隊列可以由不同部門的特定使用者進行訪問。
為了檢驗係統,策略是分階段將訂單係統原型化。係統要檢驗的第一部分是它單獨從訂單原型表中建立一份清楚的訂單的能力。一旦完成了最初的模式定義,訂單生成器就是原形化的係統的第一個可視部分。
為建置和配置這個係統而組成的小組除含受這個係統影響最大的各個部門的經理之外,還包括三個開發人員。開發人員的分工分別為:建置配置功能、顯示功能和事務處理功能。在整個最初的建置週期內,部門經理提供了關於介麵(這些介麵使使用者能夠輸入和處理資料)類型的有價值的回饋。
利用 PHP 繪制使用者介麵
要原型化的初始訂單是基本的 Web 站點訂單,在 webwiz.myersinternet.com/ 上提供。得到的訂單是由一個開發人員用 PHP
在三天的時間內建立的。如果訂單原型定義 — 依靠隻在資料庫和浏覽器之間的一層 PHP
程式碼,就能夠完全定義訂單輸入的外觀和行為,那麼在資料庫設計中需要一定程度的折衷。為此,諸如訂單行組之類的結構必須支援兩個用途:(1)
在輸入表單上提供視覺化的區分,以使類似的產品組可以繪制在一起 (2)
從功能上對類似的商品分組,比如說打了一定折扣的商品,或一個選項清單,從中可以作出唯一的選擇。
因為 PHP
是開發語言,所以原型組建相當快速,從而可以快速地完成模式所需的修改並且為表單生成器重新編碼(一前一後)。此外,因為模式是考慮了繪制的使用者介麵而設計的,所以當在原型建置過程中出現新的視覺化需求時,可以容易地進行模式修改和改編。生成的表單外觀與下圖相似:
![]() |
建立一個功能完全的係統
在提供訂單之後,需要使它變得功能完全。首先,係統需要儲存在訂單中輸入的用於事務處理的訂單資料。第二,填寫訂單的人需要能夠根據正在進行中的訂單資料來填寫訂單。第三,對於在提交時需要付款的訂單,一個支付過程是必需的。最後,提交的訂單需要建立必要的實施作業和它們的工作依賴性。
PHP
開發提供了快速周轉時間,允許在兩週的時間內,從外觀和功能上將係統的整個訂單輸入部分原型化。這使得對係統體係結構和它的實現可以作出快速回饋和反應。快速周轉意味着問題能夠在係統在每個人的腦海裡仍記憶猶新的時候得到解決。此外,因為在
UI 和後端(如中間層伺服器)之間沒有額外的程式碼層,所以建立原型的過程需要的開發步驟和開發人員更少。
一旦能夠從事務上建立作為訂單的結果的作業,訂單實施週期的各個方麵就能夠得到建立。作業實施過程主要集中在兩個 UI
螢幕上:工作分配和工作處理。工作分配页面包括檢視隊列中未分配的工作(使用者能夠訪問這些工作)以及顯示分配給使用者的工作(這些工作需要處理)。
開發週期中,對使整個係統保持一緻非常關鍵的一部分是搜尋可以提取到程式碼庫中的常用功能。存在幾種情況,在這些情況下特定的子功能和資料節點需要在多個页面上使用。無論何時當開發人員發現他們自己在一個介麵页面上執行的一係列步驟實質上和他們在先前的一個介麵页面上所執行的步驟相同時,就應該評估將這種功能提取到
PHP 程式碼庫中的好處。
工作處理页面需要顯示來自訂單的相關詳細資訊和作業的詳細資訊、以及由先前的使用者完成的工作和必須由當前使用者完成的工作。這個页面作為一個初始的原型被快速組裝起來,但在它真正變得對將要每天使用它的使用者有用之前,需要經過若乾次演進。
工作處理页面上的最復雜的操作與實現關閉工作的所有資料庫步驟有關:
雖然這種邏輯可能已經放在 PHP 程式碼中了,但因為 Perl
指令檔將用於一些自動工作處理,所以決定以一種通用的形式來執行這些操作。對於工作關閉過程,所有的操作都隻基於資料庫,因此用 PL/SQL
來編寫這個過程是合理的。這允許需要關閉工作的任意編程語言調用一個一緻的過程來執行所需的所有資料庫操作。
自動工作係統是用自動工作定義表作為配置和自動工作執行表作為事務表為各個自動工作而建立的。因為自動工作需要做諸如調用先前編寫的
CGI 指令檔等事情,所以我們確定 Perl 能夠實現所需的所有技術細節。可快速提供的 Perl
模組的巨大資料庫允許各種類型的操作,從而提供了所需的全部靈活性。係統本身包括一個伺服器處理序,該處理序駐留在一個每分鐘喚醒一次的係統上,以搜尋待處理的自動工作。如果找到了任意的待處理自動工作,就利用相關的工作詳細資訊和自動工作配置參數來執行它們。自動工作成功或失敗都將被記錄到資料庫中。當自動工作成功時,調用必要的
PL/SQL 過程來關閉工作。
將原型組裝在一起
一旦係統擁有了所有主要部分的功能原型,就可以和所需的所有訂單類型以及所有當前的商務實施週期配置在一起。訂單原型包括新客戶訂單、現有客戶訂單和特殊訂單。新客戶訂單一般由銷售代表來輸入新客戶的詳細資訊,並且通常要求預付安裝費用。現有客戶訂單涉及到從
Web 站點升級到完全和部分取消,再到服務和記帳修改的全部範圍。特殊訂單一般涉及到僅可由相對進階的人員訂購的產品。
隨着配置得到建立和係統開始成形,PHP
的快速開發時間的優勢再次證明瞭它們的價值。當這種需求(工作處理页面不僅需要顯示當前作業的詳細資訊,還需要顯示作為同一訂單一部分的所有其它作業的詳細資訊)出現時,在僅僅幾天的開發和測試之後就增加了那種功能。當需要一個新的自動工作,以使一個作業保持在休眠模式,直到一個特定的日期或直到一定的天數過去之後時,開發、測試和部署僅在一週內就完成了。
在係統配置開始之後變得明顯的另一個係統優勢是,工作依賴性配置以一種易於檢視和調整的方式清楚地顯示了當前的業務過程,特別是那些跨部門的業務過程。將資料庫依賴性資訊與一個來自
AT&T Research Graphviz 套裝程式(參見 www.graphviz.org)的名稱為 “dot”
的套裝程式結合意味着實施週期可以根據動態的配置資料進行圖形化顯示。下圖是安裝一個 Web
站點套裝程式所需的作業實施週期的一個簡單的範例圖。
![]() |
除事務處理页面之外,係統收集的各種量度允許生成更多的業務過程報表。在業務需求出現和變化時,可以建立和修改基於訂購的產品的收入報表和關於訂單周轉的實施報表。這些報表可以用
PHP 透過標準的 HTML 輸出來建立,或者用 Perl 來編寫,以按需要建立 Excel 電子資料表。利用 Oracle
的分析和分組功能建立概要視圖實現了報表的一緻性以及為資料庫管理員提供了一種容易的方法來執行最佳化。
項目時間表
係統開發從 2003 年 5 月開始。到 2003 年 6
月,主要的係統元件全部完成,係統最後的和完整的配置開始。到 2003 年 7 月底,係統全部完成配置,內部培訓開始。自 2003 年 8
月以來,係統一直處於生產模式,並且已經為大約 2,000 個客戶處理了 4,000 多份訂單,以及 6,000 多個實施作業和 20,000
個已完成的工作。自從係統建立以來,使用者能夠建立新的訂單和作業原型,而不需開發人員的介入。此外,現在將配置該係統來充當一個客戶故障單係統,且隻需新的配置,無需新的編碼。
一個靈活的體係結構與快速的開發周轉的結合使這個係統成為了一個成功的係統。雖然這個係統可以用幾種不同的方式來建立,但我們的選擇意味着可以用非常高的靈活性和非常低的開發成本來快速地建立這個係統。
下表顯示了建立每個元件和使它們進入生產設定所需的開發時間(以開發人員工時為單位)。此外,它還在適當的地方指出了建立被新訂單係統所取代的那個係統所花費的開發時間。
| 元件 | 新係統開發時間 | 舊係統 |
| Web 站點銷售訂單 | 32 個開發人員工時 7 個業務配置工時 | 200 個開發人員工時 |
| 升級訂單 | 35 個業務配置工時 | NA |
| 作業分配表單 | 12 個開發人員工時 | 40 個開發人員工時 |
| 作業處理表單 | 72 個開發人員工時 15 個業務配置工時 | 240 個開發人員工時 |
| 作業工作階段日誌表單 | 12 個開發人員工時 | NA |
| 每小時記帳跟蹤表單 | 8 個開發人員工時 | 24 個開發人員工時 |
| 生產效率報表 | 48 個開發人員工時 | NA |
| 委託報表 | 6 個開發人員工時 | NA |
| 收入報表 | 40 個開發人員工時 | NA |
| 銷售報表 | 24 個開發人員工時 | NA |
吸取的教訓
從這個係統的體係結構和實施中吸取的主要教訓是快速周轉在這幾個方麵 — 建立功能原型、建立 UI 配置和 UI
程式碼之間的緊密整合,以及保持這個係統盡可能多的部分是可配置的而不是需要編碼的 — 中的重要性。本文清楚地演示了在 PHP
開發模型的簡單性和係統中的靈活的原型配置之間的時間上的最短距離,以及最初的概念、功能原型和生產係統之間的相關內容。