一次成功的重構實踐3 - 抽象的藝術

一次成功的重構實踐3 - 抽象的藝術

黃國強 2019/2/7

       抽象能力的培養非常重要。所謂抽象即抓住事物的本質規律,透過現象看本質。一個程序員工作多年,寫代碼的技術都會掌握。但是如果想做架構,缺乏抽象能力是不行的。
       這就好比工匠和藝術家,前者只能做到是技藝純熟,不斷重複自己。藝術家往往可以表達人類普遍情感,探索客觀世界的規律。比如,物理學上補色原理就是印象派畫家最先發現並運用到他們的作品中。
       回到編程,看一個具體的例子。
       設備裏用到了多種IO控制卡,控制卡負責讀取傳感器輸入信號並輸出信號控制設備動作。下面分別是三個控制卡的API。

// 控制卡1的輸入輸出函數
EXPORTS void   CALLBACK PIODIO_OutputWord(DWORD wPortAddress, DWORD wOutData);
EXPORTS void   CALLBACK PIODIO_OutputByte(DWORD wPortAddr, WORD bOutputValue);
EXPORTS DWORD  CALLBACK PIODIO_InputWord(DWORD wPortAddress);
EXPORTS WORD   CALLBACK PIODIO_InputByte(DWORD wPortAddr);
// 控制卡2的輸入輸出函數
EXPORTS WORD   CALLBACK FRB_SendSA(WORD wPort, WORD SAn, WORD wOutputData);
EXPORTS WORD   CALLBACK FRB_ReceiveRA(WORD wPort, WORD RAn, WORD *wInputData);
EXPORTS WORD   CALLBACK FRB_ReadRAStatus(WORD wPort,BYTE *bRAStatus);
// 控制卡3的輸入輸出函數
short __stdcall ps400_get_FRnet_DI
    (
    BYTE bCardID,			/* the specific Card ID that is configured by onboard DIP-switch */
		WORD wSA,				/* Group Address FRNET_SA8 ~ FRNET_SA15 */
		WORD *pStatus,			/* the pointer to the FRnet DI status */
		WORD wEnableDirectAccess = FRNET_ENABLE_DIRECT_ACCESS /* FRNET_ENABLE_DIRECT_ACCESS/FRNET_DISABLE_DIRECT_ACCESS, access the DI module directly, or read the stored status in driver */
		);

short __stdcall ps400_set_FRnet_DO
    (
    BYTE bCardID,			/* the specific Card ID that is configured by onboard DIP-switch */
		WORD wRA,				/* Group Address FRNET_RA0 ~ FRNET_RA7 */
		WORD wDOData			/* the data to DO module */
		);

       很明顯,三個API完全不同,任何其他模塊如果用到IO,並直接使用這些API的話,將不可避免地導致這些代碼不可移植,換IO卡必須重寫這些代碼,這很無聊。而且類似模塊如果很多的話,工作量也很大。
       因而這裏我們需要抽象,我們認爲世界上只有標準的IO卡,這個IO卡包含下面幾個函數。

// 從衆多不同的IO卡提煉出以下三個基本函數成爲類成員
    void BitOn(const WORD, const WORD, const WORD, const BOOL);     // 輸出ON信號
    void BitOff(const WORD, const WORD, const WORD, const BOOL);    // 輸出OFF信號
    bool Bits(const WORD, const WORD, const WORD, const BOOL);      // 查詢當前IO狀態

       問題來了,這些函數怎麼獲得呢?這裏加重點:要從軟件用戶的角度,獲得得到這些函數。以氣缸爲例,對於用戶來說,客戶只關心如何打開氣缸、如何關閉氣缸以及當前是關還是開的狀態。所以這個IO卡抽象出這個三個函數是正確的。如果站錯了角度,你抽象出的函數根本就是不對的。
       我們把真實的IO卡適配到這個標準卡,達到設計模式裏所提到到的“抽象與實現分離”的目的。架構師的工作就是不斷髮掘系統裏形形色色的類和函數,把抽象出一個又一個與具體實現無關的類放到領域層中。那麼領域層到底是什麼?賣個關子,以後再寫。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章