架構之路(五):忘記數據庫

 

前面寫了這麼多,很大程度上就是爲了這一章作準備。面向對象或者領域驅動,最重要的一點就是要忘記數據庫!我花了很長很長的時間,才理解了這一點,從而真正的邁向一個嶄新的天地;然後,我又花了很長很長的時間,才勉強作到這一點;我但願,有一天,這將再也不是一個問題,我不須要考慮這一點……html

 

爲何業務層這麼薄

 

三層架構流行起來以後,咱們很清楚的知道UI層負責頁面交互並調用下一層,也知道DAL層就是和數據庫打交道。但BLL層?什麼纔算是「業務邏輯」?有各類各樣的解釋,但這些不都是sql作的麼?對於絕大多數的應用系統而言,除了對數據庫進行「增刪改查」之外,實在不知道還能作些什麼?更況且,不是還有超級強大的存儲過程麼!mysql

因此,不少系統,即便勉強弄出一個業務層,也「薄」得不像話,像一層塑料薄膜同樣,讓人有一種把它當即撕掉的強烈的衝動。sql

 

爲何會是這樣呢?數據庫

 

這得從.NET陣營從歷史提及。.NET陣營的同窗知道三層架構,多半是從PetShop開始,這被奉爲三層架構的經典,不少項目甚至是直接複製其架構。在當時,它是一種了不得的進步。那時候,仍是從ASP向ASP.NET轉型的過程,不少asp項目,sql代碼都仍是寫在html裏面的!因此,UI和DAL的分離,無疑具備明細的示範效應。session

但微軟的步子,不大不小,恰好扯着蛋。數據結構

步子小一點,作成兩層架構,估計一點問題都沒有,你們都能接受;步子再大一點,就得上ORM,惋惜微軟當時還沒條件支持。因此就搞出了這麼個不明不白稀裏糊塗的概念出來,折磨了我很久很久……架構

長期以來,.NET的陣營,在應用級層面,實際上是「面向數據庫」的。從DataSet、DataGrid、DataSourceBinder之類的,均可以看出來。即便是Entity Framework,最開始也是從數據庫的表向.NET的類進行映射。這些,都極大的制約了.NET陣營同窗面向對象的思惟拓展。oracle

 

好在我終於跳出來了。nosql

 

面向數據庫

 

爲了說明,咱們舉一個最簡單的例子。工具

需求是:記錄文章(Article)的瀏覽數(ViewCount)。每當文章被閱讀(View)一次,瀏覽數加一。

看到這個需求,你首先想到的是什麼?是否是:

Update Article set ViewCount = ViewCount + 1;

若是是這樣的話,恭喜你,你還緊緊的守住了「面向數據庫」的陣地。

 

/*

面向數據庫並非不可接受的,面向對象也並不必定比面向數據庫「高級」。
這只是兩條道路的選擇,若是你願意看一看另一條路的風景,就請繼續;不然,就此打住吧。

*/

 

 

面向對象

 

那麼,面向對象或者領域驅動應該是怎麼作的呢?

        public void View()
        {
            //從數據庫中取出Article
            Article article = session.Load<Article>(articleId);
            
            //改變Article的ViewCount屬性
            article.ViewCount += 1;

            //將改變後的Article再存入數據庫
            session.Save(article);
        }

有什麼感受?眼前一亮,仍是難以想象?想得更深一點的,是否是以爲這是畫蛇添足,一句sql就能解決的問題,搞得這麼複雜?

 

我當年,考慮最多的,最不能接受的,是性能問題。

  1. 這必須利用ORM,即便不考慮ORM生成的sql高不高效,就這生成sql的開銷,應該就不低吧?
  2. 這樣作,取數據,打開一次數據庫鏈接;存數據,又打開一次數據庫鏈接。就算有鏈接池,但能省一點就省一點不是更好?

因此,若是你也和我同樣,倒回去看我以前的博客吧!

 

這樣作,還有其餘不少具體的技術問題,咱們後續博客會逐一展開說明。

 

爲何

 

咱們仍是回到大方向上來,爲何要這麼作?換言之,「面向數據庫」有什麼問題,或者說「面向對象」有什麼好處?

 

我以爲,「抽象」、「解耦」、「複用」之類的說法,都尚未觸及根本。最根本的緣由,還在於咱們的大腦,咱們的大腦不適應於把這個世界抽象成一張一張的表,而更適應於一個一個的對象。隨着系統日趨複雜,這種現象就表現得越明顯。

我曾經參與過一個項目,它的數據庫結構打印出來,得用地圖那麼大一張紙(我不知道算A幾了),密密麻麻的全是表,各類線條交錯其中,我看着就頭皮發麻。部門裏面像個寶貝同樣把這張表供着,由於公司無法打印也無法複印啊!(我不知道他們最開始是怎麼得來的,估計確定麻煩)

 

若是你一邊讀一邊在想,就會發現,「不對呀,有多少表就有多少類,類圖不是同樣複雜嗎?」

是的,並且因爲抽象,類極可能比表還要多。可是,有於抽象,在咱們進行架構、設計、溝通的時候,能夠暫時的拋棄不少細節。好比,咱們能夠說,「文章被評論以後,文章做者的積分加10分」,這個時候,咱們就不考慮文章有不少種:博客、新聞、問答、評論……,也不考慮積分增長是直接改積分總分呢,仍是添加一條積分記錄,或者還要同步……。若是隻有表,你怎麼說?

固然,表的結構也能夠設計成相似於繼承的樣子(類的繼承關係也最終會映射成表結構),可是,在交流溝通中,你如何代表這種抽象關係呢?

 

單純從程序的角度上說,使用ORM,面向對象,還增長了系統的複雜性。畢竟多了一道工做,並且把對象映射到數據庫不是一件簡單的工做,尤爲是你還要考慮性能問題的時候。

那爲何咱們還要這樣作?委託,換言之,把複雜性往其餘地方推。我記得我反覆講過這一點,架構的一個重要工做,就是把複雜性進行拆分和推諉。拆分估計你們好理解,但「推諉」是個什麼意思,推給誰呢?管它呢,我只作我分類的事,其餘的,UI推給BLL,BLL推給DAL,DAL推給DBA,DBA推給採購部……

寫在這裏很搞笑,但事實就是這樣的。在性能篇,我說,你要寫高性能的代碼,你就是搶了人家的飯碗,就這個意思。UI都把DBA的活兒幹了,人家吃什麼?你代碼都寫成01001010101010二進制了,別說作彙編的,估計作CPU的都活不下去了。

咱們這裏,就是把複雜度推給了Map團隊、ORM工具開發商和DBA。

 

由於咱們要和客戶談需求啊,典型的是領域驅動,要和客戶/領域專家找到「共同的語言」,這共同的語言是什麼?是表結構?估計若是開發的是一個財務會計系統,這仍是可行的——估計早期的系統大多就是財務報表類系統?說不定還真是這樣。爲何面向對象從Java開始流行,Java是虛擬機,能夠用在微波爐報警器之類上面的,底層數據結構能夠徹底脫離數據庫啊!.NET作什麼起家的,就報表啊!呵呵。

 

總之,發展到今天,隨着系統複雜性的增長。在系統的架構設計中,咱們不得不將現實世界首先映射成一個一個能夠封裝、具備繼承多態特性的對象,而且將重心放在這些對象關係功能的維護上。

數據庫?就先無論它吧。

只有脫離了數據庫的束縛,咱們才能自由的翱翔在面向對象的世界裏!

 

忘不掉

 

「問題是我忘不掉啊!」

「我只要看到需求,腦子裏立刻就是數據庫就是表。」

「沒有數據庫,我都不知道怎麼開始寫代碼了。」

……

 

是的,忘掉數據庫是很難很難——尤爲是對於咱們這些老人來講。已經浸淫sql數十年的高手,你讓我忘掉它?你覺得寫小說啊,張無忌學太極啊?

 

我只能說說我是怎麼作到的,但願能給你一些參考。

我就假設個人系統不是用「關係數據庫」存儲數據,不是mysql,不是oracle;我用nosql,我用xml文件存儲,行不行?nosql,怎麼用?不知道啊,我十竅通了九竅。但我就要在我還不知道nosql怎麼用的時候,就開始構建個人BLL/領域層。並且我只設定幾個最簡單的假設:

  1. 全部的對象均可以直接從硬盤Load()出來
  2. 全部的對象均可以直接Save()到硬盤
  3. 對象之間用1:一、1:n、n:n創建關聯便可

究竟怎麼從硬盤裏存取(所謂的「持久化」),之後再說。我連用什麼進行持久化都不知道,如今怎麼考慮?但有一條,反正不會用關係數據庫,估計是用nosql吧……

 

最終的指望

 

真正的對象數據庫!快出來啊,求你了……

 

 

慣例說個人項目進展: 一、寫文檔寫到吐…… 二、重構累成了狗…… 本計劃發佈了新版本再寫這篇博客的,但實在不能再拖了。博客系列接下來,就進入項目的具體開發了,代碼還亂成一堆,啊……

相關文章
相關標籤/搜索