關(guān)于數(shù)據(jù)庫(kù), 關(guān)于 MVC, 也關(guān)于 React的兩篇文章讀后感
兩篇文章
今天看了兩篇文章, 我覺(jué)得對(duì)我的影響會(huì)很大, 當(dāng)然, 都是 React 相關(guān)的:
一篇是 Martin Kleppmann 在 Strangeloop 2014 大會(huì)上的演講, 有視頻, 也有文字版, 關(guān)于數(shù)據(jù)庫(kù):
Turning the database inside-out with Apache Samza
http://www.confluent.io/blog/turning-the-database-inside-out-with-apac...
另一篇是 Christian Alfoni 關(guān)于 Flux 的文章, 從 Twitter 上看到的, 關(guān)于 MVC 架構(gòu):
Why we are doing MVC and FLUX wrong
http://www.christianalfoni.com/articles/2015_08_02_Why-we-are-doing-MV...
https://www.youtube.com/watch?v=xCIv4-Q2dtA
http://www.christianalfoni.com/todomvc/#/
來(lái)源
前面一篇是在 Redux 的文檔上看到的, 這文檔上有不少我關(guān)心的技術(shù):
http://gaearon.github.io/redux/index.html
- The Elm Architecture a great intro to modeling state updates with reducers;
- Turning the database inside-out for blowing my mind;
- Developing ClojureScript with Figwheel for convincing me that re-evaluation should "just work"
- Webpack for Hot Module Replacement;
- Flummox for teaching me to approach Flux without boilerplate or singletons;
- disto for a proof of concept of hot reloadable Stores;
- NuclearJS for proving this architecture can be performant;
- Om for popularizing the idea of a single state atom;
- Cycle for showing how often a function is the best tool;
- React for the pragmatic innovation.
Redux 的作者最近在 Twitter 上非常活躍, 總是在發(fā)各種 Redux 相關(guān)的消息
我的感覺(jué)是 Redux 一出來(lái), React 社區(qū)跟函數(shù)式編程, 跟未來(lái), 的距離又拉進(jìn)了一步, 一大步
包括 Clojure, Elm, PureScript 在 Twitter 上也非常地活躍... 當(dāng)然也因?yàn)槲谊P(guān)注多了這些人
然后我就常常在想, 函數(shù)式編程是真的在復(fù)興了對(duì)吧, 到處都出現(xiàn)了?
關(guān)于數(shù)據(jù)庫(kù)
***篇文章很難懂, 還好圖片多, 大致的意思就是重新思考一下數(shù)據(jù)庫(kù)
常用的數(shù)據(jù)庫(kù)都在基于上世紀(jì)的硬件條件設(shè)計(jì)的, 受到各種限制
如果我們重新思考一下數(shù)據(jù)庫(kù)的應(yīng)用, 應(yīng)該怎么考慮設(shè)計(jì)新的方案?
然后作者梳理了一下數(shù)據(jù)庫(kù)應(yīng)用當(dāng)中的幾個(gè)重要的點(diǎn):
Replication 數(shù)據(jù)庫(kù)同步
Secondary indexing 輔助索引
Cache 緩存
Materialized views 物化視圖
- We first discussed replication, i.e. keeping a copy of the same data on multiple machines. It generally works very well, so we’ll give it a green smiley. There are some operational quirks with some databases, and some of the tooling is a bit weird, but on the whole it’s mature, well-understood, and well-supported.
- Similarly, secondary indexing works very well. You can build a secondary index concurrently with processing write queries, and the database somehow manages to do this in a transactionally consistent way.
- On the other hand, application-level caching is a complete mess. Red frowny face.
- And materialized views are so-so: the idea is good, but the way they’re implemented is not what you’d want from a modern application development platform. Maintaining the materialized view puts additional load on the database, while actually the whole point of a cache is to reduce load on the database!
實(shí)際開(kāi)發(fā)的感受而言, 前兩者在數(shù)據(jù)庫(kù)內(nèi)部實(shí)現(xiàn)很高效, 也不需要太多操心
Cache 相對(duì)來(lái)說(shuō)就是一團(tuán)亂麻的實(shí)現(xiàn), 非常難管理
Materialized views 還不錯(cuò), 可是不適合編程, 靈活度低, 不能做太多事情
那么作者想, 如果反過(guò)來(lái), 把數(shù)據(jù)庫(kù)同步機(jī)制作為數(shù)據(jù)庫(kù)設(shè)計(jì)的核心, 能夠改善?
數(shù)據(jù)庫(kù)內(nèi)部通過(guò) Logical log 的形式, 將所有的數(shù)據(jù)保存下來(lái), 作為同步的手法
這里說(shuō)的是 Apache Kafka, 我似乎記得 MongoDB, Redux, Docker, Nix 都有類(lèi)似的做法
這里的 Log 有點(diǎn)像 Flux 當(dāng)中的 Action, 隨著時(shí)間就形成了 Stream, 用于同步數(shù)據(jù)
作者后來(lái)更加延伸一步, 覺(jué)得從數(shù)據(jù)庫(kù)到屏幕像素, 整個(gè)都是數(shù)據(jù)同步的一個(gè)過(guò)程
比如說(shuō)數(shù)據(jù)庫(kù)的一些查詢(xún)結(jié)果, 相當(dāng)于 Tables 的 Materialized views, 這樣一層抽象
那么, 緩存, HTML DOM, 界面像素, 其實(shí)就是后面緊跟的一層層抽象
編寫(xiě)應(yīng)用而言, 如果整個(gè)是 Reactive 的, 后面跟著前面自動(dòng)更新, 那將是非常高效的
考慮一下, HTML 是后端渲染的, 如果數(shù)據(jù)庫(kù)更新了, HTML 自動(dòng)局部更新多好
這樣就需要引入 Stream 的機(jī)制了. 只不過(guò), 前端的實(shí)現(xiàn)通常是發(fā)布/訂閱模式
現(xiàn)在的 Meteor 是個(gè)特別知名的例子. Meteor 用 MongoDB 的同步機(jī)制的話可能還更像
這篇文章指出類(lèi)似的方案已經(jīng)有很多人在貢獻(xiàn), 在開(kāi)發(fā)新的工具來(lái)實(shí)現(xiàn)了
而特別讓我在意的是, 整套思路至少在驗(yàn)證我用 Cumulo 探索的方案至少出發(fā)點(diǎn)很不錯(cuò)
實(shí)際上 Datomic, Redux 這些我在關(guān)注的技術(shù), 也是朝著類(lèi)似的方向前進(jìn)的
有不小的可能, 未來(lái)我們開(kāi)發(fā)應(yīng)用的方式, 整體是就是依照這套辦法做下去
關(guān)于 MVC
另一篇文章是在講 MVC 和 Flux 的問(wèn)題, ***拋出自己基于 React 寫(xiě)的 Cerebral
從文章的章節(jié)標(biāo)題可以看到具體的脈絡(luò),
MVC 在前端遇到什么問(wèn)題, Flux 怎么改進(jìn), 還能怎么改進(jìn):
- Traditional MVC
- Application state
- State in traditional MVC
- When we moved to the frontend
- The router is not a controller
- The view layer bypassed the controller layer
- No concept of a single state store
- State in the view layer
- What FLUX improved
- Fixing the problem
- A single state store
- A controller with middleware
- The views talk to the controller
- Just do the routing
- So what benefits do I really get?
- Summary
后端而言, 各個(gè) Part 之間隔離非常明顯, MVC 都有各自的程序和語(yǔ)言來(lái)抽象
在前端, 所有東西突然聚在了一起, 催生出特別多原來(lái)沒(méi)有的做法, 也面臨各種問(wèn)題
- Multiple views
- State also inside views
- Multiple models
- We bypass the view controller model flow
- The router is no longer the only entry point for state change
Flux 對(duì)問(wèn)題做了一些糾正, 避免了狀態(tài)分散在 View 當(dāng)中的狀況, 跟 MVC 更加貼近
然而其中一些 Part 的用法, 依然存在著問(wèn)題:
- The FLUX architecture uses multiple models (stores). With traditional MVC you only have one model, your database. Multiple stores quickly causes problems when a dispatch needs to reach more than one store and especially if one store needs to know about state in an other
- There is no concept of middleware like in a traditional controller. This quickly introduced the concept of action creators. They are much like a single middleware that is responsible for doing everything needed related to a request from the view layer, often doing multiple dispatches to the stores
- When the view layer wants to get some state they still do it directly from the model layer, making unnecessary complex dependencies in the views
作者也提出了具體的解決方案, 最主要的是數(shù)據(jù)和狀態(tài)要統(tǒng)一到 Model 當(dāng)中:
- We should have one model in our model layer
- All our state should be contained inside the model layer
- We should have one controller in our controller layer
- The view layer can only communicate with the controller layer
- Use a router that does not control the view layer
實(shí)際上最終作者得到的就是一個(gè)跟 Elm 類(lèi)似的, State 全部集中的幾個(gè)方案
同時(shí), 所有的操作也可以被收集, 跟 Elm 一樣, 可以用于重演和調(diào)試
這里的 Action 跟上面文章說(shuō)的 Logical log 在思路上也非常相似
也不多說(shuō)什么, 我總體上認(rèn)為這是整個(gè) React 社區(qū)未來(lái)的方向了
Big Picture
梳理一下 Time Travelling Debugger 開(kāi)發(fā)的歷程, 挺讓人感概
早在函數(shù)式編程理論方面的研究我不熟悉就展開(kāi)了
但實(shí)際上函數(shù)式編程, 不可變數(shù)據(jù), 幾乎是這一套方案得以實(shí)行的基礎(chǔ)
因?yàn)橛辛私y(tǒng)一的 State, 才能夠用一個(gè)調(diào)試工具重演整個(gè)狀態(tài)
而這些工具的進(jìn)展, 我印象比較深的有這樣一些時(shí)間點(diǎn):
2012年2月, Bret Victor 發(fā)表了演講 Inventing on Principle, 此后一再被引用
https://www.youtube.com/watch?v=PUv66718DII
同樣是2月, Chris Granger 開(kāi)始連載關(guān)于 Light Table 調(diào)試功能的一些文檔
http://www.chris-granger.com/2012/02/26/connecting-to-your-creation/
2014 年 5 月或者早一些, Elm 發(fā)布了關(guān)于 Time Travelling Debugger 的文章
http://wadler.blogspot.sg/2014/05/elms-time-travelling-debugger.html
5月的 WWDC, Swift 語(yǔ)言發(fā)布 Playground, 集成了部分 LightTable 當(dāng)中的調(diào)試功能
https://www.youtube.com/watch?v=oY6nQS3MiF8
7月初, 基于 Webpack 的代碼熱替換開(kāi)始在社區(qū)傳播, 也是后來(lái) Redux 的作者
https://gaearon.github.io/react-hot-loader/2014/07/23/integrating-jsx-...
2015年4月底 Bruce Hauman 在 Clojure Eroupe 上發(fā)布 Figwheel 類(lèi)似的時(shí)間調(diào)試功能
https://www.youtube.com/watch?v=j-kj2qwJa_E
6月初 React Eroupe 上 Redux 發(fā)布, 開(kāi)始做 React 的 Time Travelling Debugger
https://www.youtube.com/watch?v=xsSnOQynTHs
剛才的這個(gè) Cerebral, 大概上個(gè)月的事情, 也是基于 React 類(lèi)似的功能
http://www.christianalfoni.com/todomvc/#/
好多年了 Bret Victor 展示的方法, 我們?nèi)粘5拈_(kāi)發(fā)當(dāng)中還沒(méi)用上
好在主體的功能, 隨著 React 社區(qū)兩年來(lái)各種事情, 好像也就一步之遙了...