聊聊程序設(shè)計(jì)思想之面向數(shù)據(jù)驅(qū)動(dòng)編程

數(shù)據(jù)驅(qū)動(dòng)

數(shù)據(jù)驅(qū)動(dòng)是一種思想,數(shù)據(jù)驅(qū)動(dòng)型編程是一種編程范式?;跀?shù)據(jù)驅(qū)動(dòng)的編程,基于事件的編程,以及近幾年業(yè)界關(guān)注的響應(yīng)式編程,
本質(zhì)其實(shí)都是觀察者模型。數(shù)據(jù)驅(qū)動(dòng)定義了data和acton之間的關(guān)系,傳統(tǒng)的思維方式是從action開始,
一個(gè)action到新的action,不同的action里面可能會(huì)觸發(fā)data的修改。數(shù)據(jù)驅(qū)動(dòng)則是反其道而行之,以data的變化為起點(diǎn),
data的變化觸發(fā)新的action,action改變data之后再觸發(fā)另一個(gè)action。如果data觸發(fā)action的邏輯夠健壯,
編程的時(shí)候就只需要更多的去關(guān)注data的變化。思考問題的起點(diǎn)不同,效率和產(chǎn)出也不同。

把知識疊入數(shù)據(jù)以求邏輯質(zhì)樸而健壯

數(shù)據(jù)驅(qū)動(dòng)編程的核心:數(shù)據(jù)驅(qū)動(dòng)編程的核心出發(fā)點(diǎn)是相對于程序邏輯,人類更擅長于處理數(shù)據(jù)。數(shù)據(jù)比程序邏輯更容易駕馭,所以我們應(yīng)該盡可能的將設(shè)計(jì)的復(fù)雜度從程序代碼轉(zhuǎn)移至數(shù)據(jù)。

真的是這樣嗎?讓我們來看一個(gè)示例。

假設(shè)有一個(gè)程序,需要處理其他程序發(fā)送的消息,消息類型是字符串,
每個(gè)消息都需要一個(gè)函數(shù)進(jìn)行處理。第一印象,我們可能會(huì)這樣處理:
void msg_proc(const char *msg_type, const char *msg_buf)  
{  
    if (0 == strcmp(msg_type, "inivite"))  
    {  
        inivite_fun(msg_buf);  
    }  
    else if (0 == strcmp(msg_type, "tring_100"))  
    {  
        tring_fun(msg_buf);  
    }  
    else if (0 == strcmp(msg_type, "ring_180"))  
    {  
        ring_180_fun(msg_buf);  
    }  
    else if (0 == strcmp(msg_type, "ring_181"))  
    {  
        ring_181_fun(msg_buf);  
    }  
    else if (0 == strcmp(msg_type, "ring_182"))  
    {  
        ring_182_fun(msg_buf);  
    }  
    else if (0 == strcmp(msg_type, "ring_183"))  
    {  
        ring_183_fun(msg_buf);  
    }  
    else if (0 == strcmp(msg_type, "ok_200"))  
    {  
        ok_200_fun(msg_buf);  
    }  
    。。。。。。  
    else if (0 == strcmp(msg_type, "fail_486"))  
    {  
        fail_486_fun(msg_buf);  
    }  
    else  
    {  
        log("未識別的消息類型%s\n", msg_type);  
    }  
}  
上面的消息類型取自sip協(xié)議(不完全相同,sip協(xié)議借鑒了http協(xié)議),消息類型可能還會(huì)增加。
看著常常的流程可能有點(diǎn)累,檢測一下中間某個(gè)消息有沒有處理也比較費(fèi)勁,
而且,沒增加一個(gè)消息,就要增加一個(gè)流程分支。

按照數(shù)據(jù)驅(qū)動(dòng)編程的思路,可能會(huì)這樣設(shè)計(jì):

typedef void (*SIP_MSG_FUN)(const char *);  
  
typedef struct __msg_fun_st  
{  
    const char *msg_type;//消息類型  
    SIP_MSG_FUN fun_ptr;//函數(shù)指針  
}msg_fun_st;  
  
msg_fun_st msg_flow[] =  
{  
        {"inivite", inivite_fun},  
        {"tring_100", tring_fun},  
        {"ring_180", ring_180_fun},  
        {"ring_181", ring_181_fun},  
        {"ring_182", ring_182_fun},  
        {"ring_183", ring_183_fun},  
        {"ok_200", ok_200_fun},  
  
        。。。。。。  
        {"fail_486", fail_486_fun}  
};  
  
void msg_proc(const char *msg_type, const char *msg_buf)  
{  
    int type_num = sizeof(msg_flow) / sizeof(msg_fun_st);  
    int i = 0;  
  
    for (i = 0; i < type_num; i++)  
    {  
        if (0 == strcmp(msg_flow[i].msg_type, msg_type))  
        {  
            msg_flow[i].fun_ptr(msg_buf);  
            return ;  
        }  
    }  
    log("未識別的消息類型%s\n", msg_type);  
}  

下面這種設(shè)計(jì)思路的優(yōu)勢:

1、可讀性更強(qiáng),消息處理流程一目了然。
2、更容易修改,要增加新的消息,只要修改數(shù)據(jù)即可,不需要修改流程。
3、重用,第一種方案的很多的else if其實(shí)只是消息類型和處理函數(shù)不同,但是邏輯是一樣的。下面的這種方案就是將這種相同的邏輯提取出來,而把容易發(fā)生變化的部分提到外面。

隱含在背后的思想

很多設(shè)計(jì)思路背后的原理其實(shí)都是相通的,隱含在數(shù)據(jù)驅(qū)動(dòng)編程背后的實(shí)現(xiàn)思想包括:

1、控制復(fù)雜度。通過把程序邏輯的復(fù)雜度轉(zhuǎn)移到人類更容易處理的數(shù)據(jù)中來,從而達(dá)到控制復(fù)雜度的目標(biāo)。

2、隔離變化。像上面的例子,每個(gè)消息處理的邏輯是不變的,但是消息可能是變化的,那就把容易變化的消息和不容易變化的邏輯分離。

3、機(jī)制和策略的分離。和第二點(diǎn)很像,本書中很多地方提到了機(jī)制和策略。上例中,我的理解,機(jī)制就是消息的處理邏輯,策略就是不同的消息處理。這和 UNIX 哲學(xué)之一「提供機(jī)制,而不是策略」是相吻合的,因?yàn)椴呗越?jīng)常改變,而機(jī)制相對固定,在數(shù)據(jù)驅(qū)動(dòng)編程中我們就可以使用數(shù)據(jù)來應(yīng)對「策略」的變化,而使用數(shù)據(jù)驅(qū)動(dòng)編程實(shí)現(xiàn)的程序就可以看做是我們所提供的「機(jī)制」。

小結(jié)

1.它不是一個(gè)全新的編程模型,它只是一種設(shè)計(jì)思路,而且歷史悠久,在unix社區(qū)應(yīng)用很多;
2、它不同于面向?qū)ο笤O(shè)計(jì)中的數(shù)據(jù):“數(shù)據(jù)驅(qū)動(dòng)編程中,數(shù)據(jù)不但表示了某個(gè)對象的狀態(tài),實(shí)際上還定義了程序的流程;
  OO看重的是封裝,而數(shù)據(jù)驅(qū)動(dòng)編程看重的是編寫盡可能少的代碼?!?
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 關(guān)于Mongodb的全面總結(jié) MongoDB的內(nèi)部構(gòu)造《MongoDB The Definitive Guide》...
    中v中閱讀 32,317評論 2 89
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,695評論 19 139
  • L/2016-5-19 我是一個(gè)臉盲,所以一個(gè)月的時(shí)間我還是認(rèn)不了中隊(duì)的所有人,也大概是因?yàn)橹静辉诖恕?手機(jī)會(huì)收到...
    MY林小妖閱讀 401評論 2 2

友情鏈接更多精彩內(nèi)容