為什么不推崇復雜的ORM


      上一篇文章寫完,回復的人很多,有的說的很中肯,有的貌似只是看到文章的標題就進來寫評論的!還有人問為什么我要屏蔽掉【反對】按鈕,因為誰寫文章都是為了分享,都在說出自己的心得體會。不過由於大家遇到的項目,做的東西,見過技術各有差異,很難讓每個人都向一種意見靠攏。所以你可以不喜歡,但是請不要作惡!

      評論中*深海, lindping說的是通用的ORM可以為通用產品帶來部署的便利!dax.net深藍醫生路過秋天說的是ORM一個很關鍵的作用就是可以加快開發速度!還有些屬於性能控,對SQL比較推崇。還有些沒有明白表達的意圖,語文是音樂老師教的!實在抱歉!

     先說下部署這個問題,如果是做通用產品的話,考慮到各種數據庫的兼容確實能帶來很多好處。這一點我很認同,不過從業開始但現在,接觸過的項目基本上都是屬於定制類的,所以這一點沒能感同身受。有過一次,不過不是換數據庫這么簡單,而是換整個部署方案,從WINDOW平台換到LINUX上,數據庫從MSSQL換成ORACLE。沒用ORM,用的SQLSHOP+存儲過程的方式來做的系統,前后一個星期全部完工。因為SQLSHOP的SQL都是可以人工干涉的,存儲過程這一類的調用也是放在SQLSHOP里面,所以我們基本上沒有動一行代碼,都是通過機器生產和人工的方式來修改存在XML里面的SQL,效果還可以。也是因為這次的經歷,我才發現原來MSSQL和ORACLE其實差不了多少,存儲過程,SQL函數,調用的語法,性能等等.Mono加JEXUS,有時比IIS還給力。

      開發效率是評論中比較讓我糾結的。因為我不是說我不用ORM,而是我覺得ORM設計的太復雜,沒有什么太大的意義(原文第四句哈)!

      主流的數據庫,其增【INSERT INTO . (.,.)VALUES(.,.)】,刪【DELETE FROM . WHERE ...】,改【UPDATE . SET .=. WHERE .=.】的語法都一樣,這部分可以抽象,做出一個支持CUD(沒有R)的系統。

      但是查詢就不是那么簡單了,人們對數據的關注點不一樣,所以需要的查詢語句就不相同。不是所有主流數據庫都有一個相同的查詢系統,所以這一部分很難抽象。

      所以沒有一套ORM能很完美的處理了查詢問題。

      1.語法上,沒法做到比SQL更簡潔。

      2.語義上,各庫SQL方言的差異很大。你需要為每個主流數據庫寫一套不同的SQL方言系統,你需要了解各種庫SQL的特點。

      3.語用上,你需要動態生成符合當前情景的SQL。比如你做分頁,每種庫純SQL的分頁方言就有很多,每種分頁在不同的分頁情景下效率是不同的,最優的情況是你可以動態去判斷情景。

      上述三點,不說第三點。前兩個弄得很好的ORM,開源的NHibernate沒有做到,微軟自己的EF沒有做到,商用的LightSpeed也沒有做到。目前的ORM都是在1和2上下功夫。3很難,而且對需求如此苛刻的也不會使用ORM了。所以,我倒是覺得與其活生生的坑在這三點上,倒不如從以下幾個方面好好考慮一下,數據庫支持,功能支持,語法支持,映射支持等。比如:

       1.考慮下NOSQL吧,可以做完整單表映射或NOSQL數據的對象映射。

             怎么支持RavenDB,STSdb,MongoDB,Cassandra等?

       2.考慮下DDD吧。功能齊全的CUD系統,能否很好的支持CQRS中C?

             怎樣快速從數據庫中映射出運行時對象?反射,EMIT,表達式?

             怎么提高緩存的命中?支持Memcached,還是使用自己實現的?

       3.考慮下支持OO原生特性,因為需要拿ORM來表達業務流程,是站在OO的角度考慮問題而不是數據庫。那么你的ORM就需要考慮一些數據庫問題了。

            怎樣為有繼承關系的對象設計表?共享同一張表,還是分開,然后使用字段關聯?

            怎樣選擇更新時的充血或貧血?充血和貧血都有優缺點,怎樣選擇?

            業務對象是可以用戶實例化的還是只能由ORM實例化?用戶實例化和ORM實例化各有各的好處,選擇哪個?

            可否為對象及對象的屬性添加攔截?能夠知道系統中最熱對象是哪個,最熱屬性是哪個,由此可以得出一些很有意思的信息在,怎么設計?

             ......

            這實在是太多了,不管是細節還是宏觀上,都太多了。

       4.考慮下支持從數據庫直接映射成XML或JSON吧,或把XML或JSON直接轉換為SQL吧,雖然XML和JSON不是對象,但是越來越多的地方使用XML或JSON來做對象容器。

           

      說完查詢SQL生成的復雜,再說業務邏輯的問題。把復雜邏輯放在代碼,還是放在數據庫里面。其實這個也很讓人糾結。站在數據庫的角度想,在離數據越近的地方處理數據越快,所以放在數據庫里面吧。但是站在代碼的角度考慮,各種對象組合在一個表達了一套完整的業務流程,用OO的方式去考慮這個流程遠比使用數據庫表結構去表達要好很多,所以放在代碼里面吧!......評論中地獄門神的評論很直接,我也很想這么做。但是有時候,完全使用代碼去完成一套業務流程是不靠譜的。使用存儲過程的時候,一切都是在數據庫中,少了從數據庫表到運行時對象的轉換,肯定會快很多。而且業務流程越復雜,這一點體現的越明顯。如果你的系統中有個部分是和很多表關聯的,比如權限模塊,你用ADO.NET到OBJECT,再處理OBJECT,再使用OBJECT和ADO.NET獲取新的OBJECT的這種串行化的方式處理業務流程,當表的關聯到達一定程度的時候,那個速度是完完全全不能忍受的。這個時候就需要使用存儲過程了。

    所以根據以往的經驗,使用存儲過程的地方主要是兩點。

    1.如果有部分的業務變化比較頻繁並且有一些性能要求,使用存儲過程吧,這樣在系統運行時就能輕松的修復一些問題。

    2.如果一個流程關聯的表比較多(多於3張以上的表),而且每個表的數據都超過1W,那么也用存儲過程吧。

    如果對性能要求不高,表關聯也不多,業務流程很簡單,那就可以使用代碼的方式來表達業務流程了。

 

    所以,想想吧!

    復雜查詢SQL,就算是再復雜的ORM也玩不來的,與其如此,倒不如設計的簡單易用些。

    不要再為ORM考慮怎么全部的CURD都是對象操作,怎么全部的查詢SQL都是自動生成,怎么設計支持多表關聯了。

    作為程序員,何必活的那么復雜,大道至簡! 

 

   補加一段我下午5點的評論(評論31樓)!

現在所有的ORM都是以解決對象的CURD為目標的!

但是!
數據庫集群的時候,讀寫分離!
CQRS中把C和Q會分開!
所以!
原本R和CUD就不是一類,但是非要用ORM來動態生成!
生成的結果又也不一定好,也不能充分體現每種數據庫自己的優勢!
與其如此,倒不如把CUD做好,把R外置出去,做到可以人為干涉!
因為我自己一直在做ORM,也希望做的完美!
C#寫的ORM,我用過的不一定你都用過!
用的越多,自己做的時間越長就越覺得R和CUD不是一類!
所以就希望把R從ORM中外置除去,做到所有生成的SQL可以手動干涉!
開發效率不會比你直接調ORM的SQL慢,但是效率絕對不比你慢,修改絕對比內置在ORM內部要方便,覺得那個SQL生成的不好,還可以手動去改!
這就是把R和CUD分出去的好處!
現在的ORM,那個能做到這么靈活!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM