2012年,Nikita Volkov寫(xiě)了一個(gè)當(dāng)時(shí)很酷的Scala框架SORM;2024年,他開(kāi)源了pGenie——一個(gè)完全相反的東西。這中間發(fā)生了什么?
事件現(xiàn)場(chǎng):從"抽象SQL"到"擁抱SQL"的180度轉(zhuǎn)彎
![]()
2012年的某個(gè)深夜,Volkov在寫(xiě)SORM的最后一個(gè)模塊。這個(gè)對(duì)象關(guān)系映射(ORM)框架用不可變值替代可變對(duì)象,在當(dāng)時(shí)算得上新穎。PostgREST和IHP這些項(xiàng)目后來(lái)都在用他寫(xiě)的Haskell驅(qū)動(dòng)hasql,但SORM本身卻在2016年被他親手殺死。
14年后,他發(fā)布了pGenie——一個(gè)"SQL優(yōu)先"的代碼生成器。不是改進(jìn)ORM,而是徹底放棄ORM。
「抽象化SQL通常是個(gè)錯(cuò)誤」,這是他用四年時(shí)間得出的結(jié)論。
正方:ORM曾經(jīng)解決了真問(wèn)題
2012年的Web開(kāi)發(fā)是什么狀態(tài)?Volkov的描述很具體:CRUD就是全部需求,性能問(wèn)題留給"以后",部署靠ssh+git pull,數(shù)據(jù)庫(kù)遷移根本不存在。
在這種環(huán)境下,SORM的出現(xiàn)有其合理性。它把數(shù)據(jù)庫(kù)表映射成不可變的Scala對(duì)象,開(kāi)發(fā)者不用手寫(xiě)SQL就能完成基礎(chǔ)操作。框架獲得了社區(qū)關(guān)注,一度像是成功的方向。
ORM的核心承諾至今仍有吸引力:用熟悉的編程語(yǔ)言對(duì)象操作數(shù)據(jù),屏蔽SQL的復(fù)雜性,減少樣板代碼。對(duì)于快速迭代的初創(chuàng)團(tuán)隊(duì),這能顯著降低上手門(mén)檻。
但Volkov發(fā)現(xiàn),這個(gè)承諾有個(gè)隱藏成本——它建立在"數(shù)據(jù)庫(kù)結(jié)構(gòu)會(huì)穩(wěn)定映射到業(yè)務(wù)模型"的假設(shè)上。而現(xiàn)實(shí)是,查詢需求的變化速度遠(yuǎn)超表結(jié)構(gòu)。
反方:抽象層的裂縫從哪開(kāi)始
2014年,Volkov停止了SORM的開(kāi)發(fā)。兩年后,支持也徹底終止。轉(zhuǎn)折點(diǎn)來(lái)自一個(gè)觀察:業(yè)務(wù)模型、表行結(jié)構(gòu)、查詢結(jié)果,這三者看似相似,實(shí)則是獨(dú)立演化的實(shí)體。
他用了一個(gè)精確的判斷:「相似≠相同,看起來(lái)像≠身份一致」。
具體什么問(wèn)題?當(dāng)你在多個(gè)查詢中復(fù)用同一個(gè)"行類(lèi)型",修改一個(gè)查詢的參數(shù)或返回結(jié)構(gòu),另一個(gè)查詢可能無(wú)聲無(wú)息地崩潰。把領(lǐng)域模型直接綁定到數(shù)據(jù)庫(kù)實(shí)體,這個(gè)問(wèn)題會(huì)蔓延到整個(gè)應(yīng)用層。如果再耦合到API類(lèi)型,你將在"違反API契約"和"數(shù)據(jù)庫(kù)集成bug"之間二選一。
ORM試圖用統(tǒng)一的對(duì)象模型解決所有問(wèn)題,結(jié)果制造了隱藏的依賴網(wǎng)絡(luò)。Volkov沒(méi)有停留在批評(píng),而是尋找替代方案。
2014年的hasql是一個(gè)關(guān)鍵轉(zhuǎn)向:不再抽象SQL,而是讓原始SQL的集成盡可能安全和便捷。它成為Haskell生態(tài)中兩個(gè)主要PostgreSQL驅(qū)動(dòng)之一,也是效率最高的那個(gè)。
但hasql仍有缺口:用戶需要為每個(gè)查詢手寫(xiě)編解碼器(codec),SQL字符串本身缺乏驗(yàn)證。2019年的hasql-th解決了語(yǔ)法檢查——基于PostgreSQL解析器的移植,在編譯時(shí)捕獲SQL語(yǔ)法錯(cuò)誤。這還不夠,因?yàn)檎嬲娘L(fēng)險(xiǎn)來(lái)自schema變化。
業(yè)界有人嘗試在編譯時(shí)連接真實(shí)數(shù)據(jù)庫(kù)做驗(yàn)證,Volkov拒絕了這條路:「那總是感覺(jué)像hack,會(huì)讓構(gòu)建不可重現(xiàn)」。他要的是完全包含在代碼倉(cāng)庫(kù)里的解決方案,不依賴外部基礎(chǔ)設(shè)施。
我的判斷:pGenie的"查詢中心"架構(gòu)為什么重要
Volkov最終找到的集成點(diǎn)既不是業(yè)務(wù)模型,也不是表結(jié)構(gòu),而是查詢本身。
這個(gè)選擇有深層的技術(shù)邏輯。查詢天然決定了兩個(gè)東西:它需要什么參數(shù),它返回什么結(jié)構(gòu)。圍繞查詢生成的類(lèi)型,就是該查詢的專屬參數(shù)和結(jié)果類(lèi)型——它們不是表行,不是領(lǐng)域模型,只是這個(gè)查詢的契約。
pGenie的激進(jìn)之處在于:它把數(shù)據(jù)庫(kù)作為單一真相源(single source of truth),但不是在運(yùn)行時(shí),而是在代碼生成時(shí)。開(kāi)發(fā)者寫(xiě)SQL,工具生成類(lèi)型安全的代碼,編譯時(shí)就能發(fā)現(xiàn)schema不匹配。
這對(duì)25-40歲的技術(shù)從業(yè)者意味著什么?
第一,ORM的"生產(chǎn)力優(yōu)勢(shì)"在復(fù)雜場(chǎng)景下會(huì)反轉(zhuǎn)。當(dāng)你的查詢涉及多表關(guān)聯(lián)、聚合、窗口函數(shù)時(shí),ORM的抽象層要么暴露底層讓你寫(xiě)原生SQL( defeat the purpose),要么生成難以優(yōu)化的查詢計(jì)劃。
第二,類(lèi)型系統(tǒng)的價(jià)值被重新定位。不是用類(lèi)型描述數(shù)據(jù)庫(kù)結(jié)構(gòu),而是用類(lèi)型精確描述每個(gè)查詢的契約。這更符合現(xiàn)代類(lèi)型化語(yǔ)言的精神:編譯時(shí)捕獲錯(cuò)誤,而非運(yùn)行時(shí)調(diào)試。
第三,基礎(chǔ)設(shè)施的成熟改變了權(quán)衡。2012年需要ORM來(lái)填補(bǔ)的生態(tài)缺口——遷移工具、查詢分析器、連接池——現(xiàn)在已有成熟解決方案。pGenie這類(lèi)工具的出現(xiàn),說(shuō)明"SQL優(yōu)先"不再是"原始"的代名詞,而是一種經(jīng)過(guò)驗(yàn)證的工程設(shè)計(jì)選擇。
Volkov的14年路徑不是孤例。Prisma的遷移到客戶端查詢、EdgeDB的類(lèi)型安全查詢語(yǔ)言、甚至Supabase的TypeScript生成器,都在探索相似的方向:讓數(shù)據(jù)庫(kù)能力充分釋放,同時(shí)保持開(kāi)發(fā)體驗(yàn)的現(xiàn)代性。
區(qū)別只在于,pGenie選擇不做任何運(yùn)行時(shí)抽象,把全部復(fù)雜性留在代碼生成階段。這是一個(gè)更徹底的賭注——賭的是開(kāi)發(fā)者更愿意理解SQL本身,而不是學(xué)習(xí)另一套查詢DSL。
這個(gè)賭局的結(jié)果,將取決于下一代數(shù)據(jù)庫(kù)工具能否把"SQL優(yōu)先"的體驗(yàn)打磨到與ORM同等順滑。Volkov已經(jīng)押注了14年。
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.