記一次ORM的權衡和取捨

面對ORM的選型,有些人是根據自己熟悉程度來評判,有些人是根據他人的推薦來抉擇,有些人覺得都差不多,隨便了。當自己要真正做選擇的時候,以上的這些依據都無法真正說服自己,因爲不同的業務需求,不同的團隊構成都會造成選型的差異,而且特別大,這裏談一談自己的選型。

1.1需求背景介紹

  • 我所在的公司是做互聯網產品,對性能有着極致的要求
  • 後臺人數也不算多,儘量人盡其用,技術水平呈梯度分佈
  • 因爲產品需要長期維護,所以對代碼質量要求非常高,必須做評審和單元測試
  • 對技術的可維護性,可擴展性要求很高,因爲資源有限;
  • 因爲資源有限,所以在生產力和性能之間需要做一個平衡

1.2需求分析

難點

  我們知道沒有完美的技術,魚和熊掌無法兼得,所以我們必須擇優錄取,這裏的複雜度在於你要對所選擇的技術優缺點有一個360度的環評,最好能展示各自優缺點對比一覽圖,最後依據數據來證明你的選擇對的,是對團隊和業務負責的。

現狀

  不知道你有沒有呆過這樣的團隊:

  • 選什麼技術從不討論,大夥各自悶聲幹,等幹出來你才知道原來對方是用的IBatis.NET。
  • 你是後面入職的,你只能在前人的基礎上做維護,儘管你覺得這個技術不是最優的,但是你也無法瞭解當初爲什麼做這樣的選擇。
  • 在入職後,沒有規範的技術培訓和規範,你一邊Google一邊編碼一邊罵娘。

  所以對需求的分析和選型在前期特別的重要,沒有對比的選擇,感覺活得有點不明不白,你無法說服自己,更無法說服團隊和領導。

分析

  根據互聯網業務特點和團隊結構,我們的選擇有幾個重要的關鍵詞:

  • 高性能
  • 易使用
  • 可擴展

  高性能就不用說了,互聯網產品,毫秒必爭!

  易用性和易維護相似,希望能在後續運維過程中不要給團隊造成維護的困難,同時也遵循簡單原則,高級的東西都有簡單的特點。

  可擴展面對的是產品的變更,很難想象高性能,易使用但是擴展性很差的產品,這種瑕疵會造成代碼的臃腫和腐朽。

  所以,這個權衡的標準就出來了,性能、易用、擴展

1.3備選方案

  這裏的備選方案由於精力和時間的關係,根據經驗和評論只羅列EF CoreDapperSmartSql三種,另外一個原因是這三種設計理念完全是不一樣的,差異性很大。另外有些人也會偏愛NHibernate Core(和EF雷同,不做考慮)或者SqlSuger等,不在本文討論範圍。

備選方案1:EF Core

優點

  • 強類型帶來維護的安全感,一旦數據庫有修改或者字段變更,編譯帶來的BUG提示,可用極大提升維護效率。
  • EF Core的Code first和自動遷移功能,對面向DDD的設計十分友好,對DB遷移的高效帶來的體驗也非常棒。
  • 領域優先的設計理念,在和業務人員溝通的過程中,優勢也相對明顯。
  • 喜歡寫SQL的同學,不要忘記EF本身兼容原生腳本,包括存儲過程,不過不是優先的選擇。
  • 支持多種數據庫。

缺點

  • 入門容易,精通比較難,其知識體系有點複雜,學習曲線會比較陡峭!
  • 生成的SQL需要調試和跟蹤,面對多表聯合查詢,性能就不用說了。
  • 需要藉助性能檢測工具比如MiniProfiler來進行性能分析和監控。
  • “我想好了Sql怎麼寫,然後再來寫Linq,完了可能還要再查看一下Linq輸出的Sql是什麼樣的“。這是非常糟糕的體驗。

適用場景

  在性能和生產力之間可以做很好的平衡,比如企業管理系統、個人站點或者外包項目等。

  對EF Core來說如果用的好,性能是完全可以做到非常高的,雖然不是極致的效果,但是在開發效率和性能之間可以做一個很好的平衡。

備選方案2:Dapper

  Dapper是.NET的一款輕量級ORM工具(GitHub),也可稱爲簡單對象映射器。在速度方面擁有微型ORM之王的稱號。它是半自動的,也就是說實體類和SQL語句都要自己寫,但它提供自動對象映射。是通過對IDbConnection接口的擴展來操作數據庫的。

優點

  • 輕量,只有一個文件
  • 性能高,Dapper的速度接近與IDataReader,取列表的數據超過了DataTable。
  • 支持多種數據庫。Dapper可以在所有Ado.net Providers下工作,包括sqlite, sqlce, firebird, oracle, MySQL, PostgreSQL and SQL Server
  • 使用Dapper可以自動進行對象映射,通過Emit反射IDataReader的序列隊列,來快速的得到和產生對象

缺點

  • 代碼裏邊充斥着 SQL 和各種判斷分支,這些將會使代碼維護難以閱讀和維護,更談不上Linq的優雅。
  • 和EF相比,手寫SQL 當修改表結構不易發現bug。
  • 習慣了EF後再來使用Dapper,會很難適應那種沒有了強類型的安全感。

適用場景

  對性能有着極限的追求,同時能寫一手很好的SQL(對數據庫能達到DBA的水準更好),懷念SQL的感覺,習慣SQL的體驗的同學。

  在可維護這塊有做單元測試,很好的規避後期維護的困難。

備選方案3:SmartSql

  爲什麼這邊沒有選擇NHibernate-Core?是因爲這傢伙和EF Core太像了,在人氣上來看,完全沒有必要去做選型,當然如果你的團隊有NHibernate情節,對NH玩得風生水起例外。

  爲什麼是SmartSql而不是MyBatis?主要是Mybatis在跨平臺上找到不到開源方案,幾乎沒有更新,更不用說跨平臺了。而且SmartSql的設計理念就是借鑑的Mybatis,同時又增加了不少強大的功能,比如支持緩存、CQRS等乾貨,看官宣SmartSql就一句話:

MyBatis .NET Core+ Cache(Memory | Redis) + R/W Splitting +Dynamic Repository + Diagnostics 

優點

  • 因爲SQL自擼,所以性能和Dapper不相上下,非常的高。
  • SmartSql 借鑑了 MyBatis 的思想,使用 XML 來管理 SQL ,並且提供了若干個篩選器標籤來消除代碼層面的各種 if/else 的判斷分支。
  • SmartSql將管理你的 SQL ,並且通過篩選標籤來維護本來你在代碼層面的各種條件判斷,使你的代碼更加優美,你再也不用看到到處充斥的SQL了,對代碼優雅有着極限追求的人會有點受不了。
  • 支持多種數據庫

缺點

  • 易排查:排查性和維護性對新人來說,個人感覺不是十分友好,寫SQL會考驗你的細心。
  • 使用 XML 來管理 SQL個人覺得是優點也是缺點,因爲代碼優雅了,但是有些人並不是很感冒這種方式,特別是在XML裏面的if/else的邏輯判斷,不親切。
  • 穩定性有待提升,雖然官宣對Dapper有很好的提升,但是從人氣來看,成熟度需要進一步觀察。

適用場景

  喜歡Dapper的性能,但是不喜歡到處充斥的SQL腳本,追求極致優雅,同時又對SmartSql的特性和效率特別欣賞。但是從人氣和成熟度來看,如果對源碼沒有很好的掌控能力,碰到坑就不好搞了。

1.4備選方案評估和選擇

  在評估和最終選型的時候,建議做360度環評,架構人員、開發人員、運維人員、測試人員不妨都請過來參與一下。

  架構人員首先給出自己的備選方案,然後舉行備選方案評估會議,再根據會議結論修改備選方案文檔。

  有些團隊主管或者叫技術經理一人就包辦了需求分析、方案選型等工作,雖然這種方式效率很高,但是對團隊開發的推進和向上彙報其實是很不利的。首先團隊會覺得你大包大攬,黑箱操作;領導會覺得你做事沒有章法和原則,萬一你離職了,你留下的後遺症和黑鍋需要你來背,也許你會覺得我都離職了,關我上面事!

  我覺得你的技術牌子首先就砸了,你的影響力和同事的相處能力也消減了,你的分享能力和做事風格也就丟分了,這些無形的資產會在將來某一個時刻帶你帶來晦氣。

  由於精力有限,我沒有對這些ORM進行很好的壓測和提供壓測數據,所以提供的是網友的壓測結果,由於壓測和環境配置以及框架本身版本息息相關,所以這裏的數據僅供參考:

圖片來源

結論:Dapper+擴展

  根據人氣、性能和易用性,我選擇了Dapper。EF Core的性能和精通的門檻是我拋棄它的原因,而SmartSql儘管設計理念是我的最愛,但他的人氣和坑是我擔心的點。因爲無法魚和熊掌兼得,所以只能根據自己的情況進行取捨,但是你無法開懷,因爲你要包容Dapper帶給你的不足,而這些不足,我個人選擇單元測試來彌補;同時對Dapper的進一步封裝和優化也是接下來很重要的工作:比如AOP攔截代替到處都在的Transaction等等,正式的工作纔剛剛開始……

 

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