跳到主要內容

【程式語言 - Go】使用簡易的「工廠方法」來相容DB不同版本的API

 

zoomable

圖片來源...

在進入主題之前建議先行閱讀「【程式語言 - Go】來認識Google開發的程式語言…」,初步認識一下Go語言是什麼? 容不容易學習? 才能夠更快的體會此篇章的目的。

當我們在進行軟體開發時,常常會需要有背後的資料庫系統來儲存我們的資料,而資料庫系統也會隨著時代的演進,進行大幅度的更新,那在這樣的時空背景之下,我們究竟要如何設計才能對於未來升級時較無痛的改動呢? 因為我們都知道一但程式架構需要大幅度的改動時就是開發人員噩夢的開始了…,為了我們美好的未來,只好認真學習一下軟體的設計模式了,避免沒日沒夜的工作消磨掉應有的生活品質。

雖然我們也可以使用別人開發好的Library來補上這一塊,我們只要注意版本的差異即可,But…理想的狀況之下,作者願意持續維護該套件,甚至是有著官方的支持,才能有持續更新的版本,否則一但失去了維護的狀況之下,要嘛就是自己接手過來修改,不然就是另外尋找替代方案來進行替換,但這些都是成本啊,要用什麼方法,就好好的審慎評估了,並不代表說自己設計一定最好,通常事情都是這樣的,有正就有反,沒有最好,只有最適合的一種策略。

那我們也知道平常使用資料庫時,無非就是新增、修改、刪除、查詢這四大方法為一個基礎,而後才會衍生各式各樣的統計啊…等的進階應用,那麼假設我們的系統非常的單純,只需要設計資料庫的基本方法時,我們可以這樣做…

那在進入主題之前不免俗的在傳教一下什麼是「工廠方法」,所謂工廠方法我們就想像成汽車工廠,一台汽車基本上要能夠「驅動」,因此「驅動」是所有車型最基本需要的實作方式,那汽車工廠只要設計好「驅動」的介面規格即可,至於子公司要生產什麼車都沒關係,只要將「驅動」的功能給時做出來就可以了。

zoomable

圖片來源...

這樣有什麼好處呢? 嗯….,一開始確實感受不到什麼好處,甚至設計時不斷懷疑自己是不是大砲打小鳥的感覺,但當有一天資料庫的API大改版時,我們就會慶幸當初做了這樣的設計,除了讓改動幅度傷害降到最低之外,測試的時候也能夠根據資料庫的版本切換不同的生產工廠,怎麼做呢? 就讓我們繼續的學習以下的實作細節。

這邊會以Elasticsearch資料庫搜尋引擎為例來進行示範,我們不需要包山包海的實作,只取其中的_searchGET document_update...等部份的API進行即可。

其實原理很簡單,假設我們今天要實現5.x跟7.x的步驟如下:

  1. 將使用到的ES API定義成介面。
  2. 基底類別實做上述的介面,並延伸實做一些各版本共用的方法。
  3. Es5繼承自基底類別。
  4. Es7繼承自基底類別。
  5. 開發者使用elasticsearch.New(endpoint)的時候, 就先判斷版本,然後告知工廠我要版本5或7的ES產線即可。
zoomable

實做部份

  1. 假設我們只會使用到Get及Update。
// default.go
// EsInterface 定義我們會使用到的es方法
type EsInterface interface {
Get(esIndex, esType, esID string) (*Response, error)
Update(esIndex, esType, esID string, data interface{}) (*Response, error)
}

  1. 基底類別實做Interface
// default.go
// EsDefault 基底類別,其他版本可以繼承自此
type EsDefault struct {
EsInterface
endpoint string
}

// Get get documnent
func (e *EsDefault) Get(esIndex, esType, esID string) (*Response, error) {
// 這邊實做預設的API, 假設以v2當基底,我們就實做v2的API, 可以用套件或者單純的http request來實做Elasticsearch的Get
return nil, nil
}

// Update document
func (e *EsDefault) Update(esIndex, esType, esID string, body interface{}) (*Response, error) {
// 這邊實做預設的API, 假設以v2當基底,我們就實做v2的API, 可以用套件或者單純的http request來實做Elasticsearch的Update
return nil, nil
}

  1. Es7繼承自基底類別
// es7.go
// Es7 v7.x
type Es7 struct {
*EsDefault
}

// Get get documnent
func (e *Es7) Get(esIndex, esType, esID string) (*Response, error) {
// 這裡實做ES7的API。
return &response, nil
}

// Update update document
func (e *Es7) Update(esIndex, esType, esID string, body interface{}) (*Response, error) {
// 這裡實做ES7的API。
return &response, nil
}

  1. 最後用版本 + 工廠方法來產生相對應的類別
// default.go
// New elasticsearch interface
func New(endpoint string) (EsInterface, error) {
es, err := factory(endpoint)
if err != nil {
return nil, err
}
return es, nil
}

// version 取得es版本
func version(endpoint string) (uint64, error) {
resp, err := http.Get(endpoint)
if err != nil {
return semver.SpecVersion.Major, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
var verInfo *VerInfo
json.Unmarshal(body, &verInfo)
v, err := semver.Make(verInfo.Version.Number)
if err != nil {
return semver.SpecVersion.Major, err
}
return v.Major, nil
}

// factory 工廠方法,根據版本來產生相對應的Es類別
func factory(endpoint string) (EsInterface, error) {
v, err := version(endpoint)
if err != nil {
return nil, err
}
glog.Infof("Elasticsearch version: %d", v)
esDefault := &EsDefault{endpoint: endpoint}
var instance EsInterface
switch v {
case 7:
instance = &Es7{EsDefault: esDefault}
default:
instance = esDefault
}
return instance, nil
}

結語

其實這樣的概念不只用於軟體設計,各產業也都非常的適合使用,透過一開始的彈性設計規劃,雖然初期成本高且無實質效益,但難保有一天業績蒸蒸日上,產線也需要隨之擴大時,如果沒有規劃好的話很容易打掉重練,浪費時間之外也浪費了許多成本在做重複的事情,當我們想要永續發展一個事業體時不妨好好的思考一下是不是一開始就設計好產線,未來只要稍做調整就能夠再變出一個新的產品產線,來擴大營收,永續發展…。

如果有任何問題或錯誤的話不妨底下留言,讓我們互相學習,共同成長,一起將知識內化成為我們最堅實的後盾與最尖銳的武器,迎向快速發展的知識時代。

喜歡撰寫文章的你,不妨來了解一下:

Web3.0時代下為創作者、閱讀者打造的專屬共贏平台 — 為什麼要加入?

歡迎加入一起練習寫作,賺取知識!

留言

這個網誌中的熱門文章

java西元民國轉換_各種不同格式

C#資料庫操作(新增、修改、刪除、查詢)

【Excel好好玩】 自己的資產自己管!善用Google Sheet來幫我們評估貸款

這次介紹的主題是關於Excel的貸款還款計畫試算,我們人生中總會遇到需要大筆金額的花費,但當資金不夠時就得進行貸款,而貸款之前如果我們能夠審慎評估,並分析自己的還款能力之後在進行凍作,相信風險會小很多,因此就自己動動手來使用Google Sheet進行試算吧! 基本資料 ● 貸款總額: 1000000 ● 貸款期數: 84月 ● 年利率: 2.11% ● 月利率: 0.18% P.S 月利率 = 年利率 / 12 重要函式 PMT : 這是Google Sheet內建的重要年金計算公式,我們可以善用這個公式來計算固定利率及期數的固定攤還本息。因為PMT函式計算出的結果為負數,所以前面加上-號轉成正數。 動手做 首先我們在Excel表上列出我們的基本資料 圖片來源 其中月利率的部分就使用公式「=B4/12」 接著我們填上第一列的期數跟餘額 圖片來源 =B2 =B3 使用關鍵PMT函數來計算本息的部分 因為PMT函式計算出的結果為負數,所以前面加上-號轉成正數。 -PMT(貸款利率(月利率), 貸款期數, 貸款總額) =-PMT($B$5,$B$3,$B$2) 圖片來源 計算利息 利息 = 貸款餘額 x 月利率 =B8*$B$5 圖片來源 計算本金 本金 = 本息 - 利息 =C8-D8 圖片來源 製作第二列餘額的部分 餘額的部分 = 上一期的餘額 - 上一期的本金 圖片來源 接著拖曳該兩列往下拉,即可查看每一期的利息與本金 圖片來源 結語 雖然市面上已經有很多貸款銀行都提供了試算功能,但如果我們想要進一步管理自己的資產時,就需要將每一期的金額給計算出來,因此才會將公式運用在Excel表,讓我們的資產管理表能夠結合負債,進一步評估我們理財行動的下一步,希望這樣的經驗可以幫助到正在理財道路上打拼的夥伴,讓我們透過有效的管理,幫助荷包長大吧! 喜歡撰寫文章的你,不妨來了解一下: Web3.0時代下為創作者、閱讀者打造的專屬共贏平台 — 為什麼要加入? 歡迎加入一起練習寫作,賺取知識,累積財富!