【轉】前端開發與后台開發如何協作?


作者:小豬
鏈接:https://www.zhihu.com/question/27226086/answer/35811288
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

首先,

給出的兩種開發模式基本上就是我們所有的選擇了,后端提供api,完全前端渲染的開發模式如果可行的話,angular或者react都是不錯的選擇。但如果網站業務決定了必須seo友好而必須進行服務端渲染的話,如同 所述,現有的開發模式下,前端和后端人員的協作是很困難的。下面我來談談我對這個困境的看法以及我們正在實踐的一個非常棒的模型(最近我在好幾個問題下面都回答了類似的內容,會不會被當成spam。。。)。

 

首先,服務端渲染的前后端分離之所以困難,根本的原因不在於模板技術的復雜性上,而在於MVC模式本身是有問題的。本質上講,MVC是面向業務過程的,對於企業應用開發,MVC模式的確是無上利器,可以清晰的分離業務邏輯層次,讓程序員將精力集中在業務邏輯的整合上(其實,我覺得即使對於這一點,傳統的MVC模式也沒有做得足夠好,這里重點不討論MVC,就不展開了,有興趣的可以看看這個:Asta4D Framework User Guide,算是我對傳統MVC模式的一些思考),但是,MVC模式本身的重點在於M和C,而V只是一個附屬品,一個用來展現業務流程的可視化界面而已,因此,通常對前端工作的要求是很低的,能夠展示數據,能夠將業務流程向前推進,這就足夠了。

回過頭來,對於重點是展示內容並幫助用戶獲得有效信息為主的互聯網網站來說,MVC本身就是不合時宜的,常見的例子就是,比如淘寶的首頁,model是什么?再進一步的,淘寶的寶貝頁面,也許可以把當前寶貝作為model,問題是,邊欄之類的周邊信息怎么整合到這個model中去?當然,不是做不到,但就此帶來的復雜性,實際上已經宣告了MVC的軟弱。

我上知乎的時間不太長,很奇怪在知乎沒有看到過任何討論view first模式的帖子,這個模式是由lift(Lift :: Home)最先提出並實踐的,可以說,view first模式從根本上解決了內容展示型的網站的MVC困境,可以極大的提高開發效率。

(說到這里,還沒有說到前后端如何分離。。。我都有點着急了。。。)

view first的基本理念來說,就是視圖,view,才是整個系統的第一優先對象,所有的代碼結構,所有的邏輯,都要圍繞view來展開,傳統的MVC模型,一個url,要先映射到一個controller,然后controller構建model,最后導向一個view,但在view first下,一個url,就對應一個view,服務端接受到request,view就開始渲染了,在渲染過程中,不斷的取得需要的數據,並完成整個頁面,這個過程中不需要controller來控制,也就更不需要model來溝通controller和view,一切都是以視圖為基礎進行的。說到這里,其實很多人應該已經明白過來了,這不就是傳統的PHP開發模式嘛,先寫html,然后把php的動態代碼嵌進去,OK,搞定啦,是快呀,可這代碼沒法維護呀,前后端也沒法分離呀。。。別急,快了。。。

可以說,view first這個模型,其實就是傳統的php開發模式,lift的貢獻在於,首先明確並命名了這樣一個開發模式,從理論上解決了開發效率的問題並且將開發人員從MVC的迷思中解放出來,然后,lift更重要的貢獻是,從實踐上解決了view first模式下代碼不可維護與前后端分離的問題,提供了一個前后端完全分離的模板模型。這里多說兩句,lift本身是基於scala的,我們公司在用了兩年lift之后鑒於對scala的種種不爽,決定還是退回到java上,雖然lift本身也支持用java進行開發,但我們覺得一個pure java的方案會更舒服,而且lift本身也有一些細節我們覺得是有改進必要的,因此我們開發了自己的框架Asta4D(astamuse/asta4d · GitHub),雖然我們提供了很多不同於lift的功能,但單就view first和前后端分離的模板來說,基本上是一個95%拷貝加5%改良的lift,下面我就用我們自己的框架來舉例,相信java代碼大家看起來也會更舒服一點。

首先,無論是lift,還是我們的山寨Asta4D,前端工程師面對的都是pure html的模板,如下:

<section> <article> <div> <p id="name">name:<span>dummy name</span></p> <p id="age">age:<span>0</span></p> </article> </section> 

前端工程師可以自由的填入stub數據來調試他們想要的效果或者交互邏輯,在他們完成工作后,這個模板交給后端工程師的時候,后端工程師會在模板中嵌入一點代碼:

<section> <article afd:render="SomeSnippet:showProfile"> <p id="name">name:<span>dummy name</span></p> <p id="age">age:<span>0</span></p> </article> </section> 


好吧,這個時候想像一下,前端工程師發現了一點bug需要進一步修正,我們可以相信的一點是,在99%的情況下,后端工程師加入的那一行“afd:render”的代碼應該不會給前端工程師造成干擾,因此,這個時候,我們的前端和后端就已經可以開始同時工作了,先把前端的工作放在一邊,看看后端怎么填入真實數據:

 public Renderer showProfile() { Renderer render = Renderer.create(); render.add("p#name span", "asta4d"); render.add("p#age span", 20); return render; } 

后端用css selector來標定數據錨點並將真實數據填入,因此,在最簡單的情況下,只要數據錨點不變,無論前端工程師如何重構模板代碼,都不再需要后端工程師的介入了。當然,這里有一個顯而易見的問題,前端工程的重構並不能保證數據錨點不變,因此,我們在實踐中,引入了一個所謂的“X約定”,簡單的講,我們的后端工程師會在模板中再多加一點東西:

<section> <article> <div afd:render="SomeSnippet:showProfile"> <p id="name">name:<span class="x-name">dummy name</span></p> <p id="age">age:<span class="x-age">0</span></p> </article> </section> 

大家可以注意到,后端工程師在數據錨點上加入了以x開頭的偽類,這樣,后端的渲染代碼就變成下面這個樣子:

 public Renderer showProfile() { Renderer render = Renderer.create(); render.add(".x-name", "asta4d"); render.add(".x-age", 20); return render; } 

仍然是用css selector,只不過不再用tag而是用class來錨定數據,我們可以看到,class中加入的“x-”一方面不會對前端工程師的工作造成任何干擾,另一方面也起到hint的作用,前端工程師只要能夠將“x-”標記的數據錨點保持不變就可以放心大膽的重構代碼而不需要后端工程師的介入。

在我們的實踐中,一般的開發流程是前端先完成頁面,然后后端接手填入數據,這個中間通常不會進行交流,因為我們的前端和后端甚至是分開在兩個部門的,大家的交互就是redmine的ticket的轉交而已。當然,在某些時候,后端工程師無法理解前端的模板不知道應該將數據填在哪兒的時候,還是會有必要的交流,但這種交流真的很少發生,至少不需要他們非得坐在一起工作:)

更進一步的,某些時間很緊的開發任務,前后端甚至是同時開始工作的,后端會開一個debug頁面,在里面只用div和x-來標記數據錨點並完成后端的渲染邏輯,而同時前端會完成正式的html頁面代碼,最后,由后端將渲染邏輯合並到正式頁面即可。當然,這種情況下,前后端的交流會多一些,我們的前端mm擺脫后端猥瑣大叔們糾纏的辦法就是盡可能快的先完成基本的html骨架push上去,然后告訴他們,你們自己玩去吧,別來煩我了^_^

更為具體的一個我們的實踐的例子是,一個耗費前端兩個人月的頁面大規模重新設計和重構,在前端完成工作后30分鍾,我們的后端就完成了所有必要的修改並將代碼合並到主干准備進入release流程了。嗯,因為我們能做到這個,所以我們的前端和后端就一直是兩個部門沒人提合並的事情。

最后,題外話,最近react.js突然吸引了很多人的目光,對於客戶端渲染真的是非常不錯的東西,而我們的框架Asta4D,同樣的提供了服務端渲染下的虛擬DOM組件模型。哦,這里就不贅述了,有興趣的可以自己去看我們的user guide。

大家看幾個我們的頁面吧

Detailed information of toushiba corp.

Publication number 225663) a nonvolatile memory device

Technology and business trends of Glass melting and manufacturing

我們的網站其實是日文的,這個英文網站是做給華爾街的大爺們看的一個簡裝版,相對內容要簡單些,但大家仍然可以看到,我們在前后端完全分離的模式下可以做得很漂亮。


============感謝

的評論,評論回復里面沒法回答太多,我把回復貼到這里=====

 

賀師俊
你的 showProfile 其實就是變相的 model,x-name 和 x-age 就是 model 的屬性。

這取決於你如何定義model。

從簡單的ORMAP的角度來說,我們必然有一個entity,對我們的這個架構來說,這個entity是一定存在的,從這個角度上說,這里的確有一個model,就是ormap中的entity。

但是從MVC模式的model來說,MVC的model並不是簡單的entity,而是一個包含了所有前端必須數據的container,從這個意義上講,我們沒有model。

最后,我上面的回答跟你指出的事實,其實有點不搭界,你的意思是,render的方法本身就是一個邏輯上的model,而x-就是model的屬性,老實說,這個觀點真的很有趣。

你指出的事實讓我陷入了長考,這里究竟有沒有model,從邏輯上講,你是對的,我思考了很長時間,這種邏輯上的model跟MVC的model的區別是什么?

我的理解是,首先,我們不需要在代碼中構建一個大雜燴的數據容器,而是在一個極小的范圍類定義了一個局部適用的小數據結構,從這一點說,跟傳統MVC比起來,我們做到了更細粒度的解耦。其次,從實現的角度講,我們鼓勵開發人員盡可能簡單的取得數據,我們近乎變態的盡可能的執行以一行為單位的無join查詢(性能依靠緩存保證, ),這絕對比傳統的MVC模式的開發效率和可維護性都高得多。進一步的,我在原文中已經強調過了,這里的“x-”約定,只是一個hint,對前端沒有任何強制的約束能力,前端不會因為破壞了這個約定而導致頁面崩潰出錯,反過來,前端在有必要的時候可以完全無視這個約定,數據的整合是由后端完成的,但頁面的邏輯,是前端主導的,開玩笑的說,“x-”約定是我們后端人員對前端大爺的哀求:“大爺啊,不要亂搞我好嗎。。。”。

所以,我們對前后端分離的開發模式的理解是,最重要的一點是,前端具有主導權,由前端決定開發的走向而不是后端,后端的職責是滿足並提供前端需要的數據,反過來,前端沒有義務和必要為了后端的各種技術上的理由而去學習或者說導入各種跟前端無關的技術(有任何前端開發人員會喜歡velocity之流的模板的嗎?),前端需要最大限度的自由度去完成創造性的工作,后端的職責是配合他們。進一步的,后端的技術意義在於,以更合理的后台架構,更方便,快捷的提供前端需要的數據,在這個層次上,我們需要緩存的設計,需要合理的api設計,需要后台存儲架構的各種變化,但是,在最終向前端提供數據這一個邏輯層次上,后端可以比前端開發人員寫出更有效率的利用現有API取得必要數據的邏輯,但后端不可能比前端知道如何更有效率的將數據展現給用戶,因此,我們對view這一層的分工的理解就是,前端負責數據如何展現,后端負責取得數據並提供給前端。

最后,無論那種模式,最終總有一個標記數據位置的參數,或者是MVC中model的屬性,或者是我們這里的css selector hint,或者是一個嵌入的變量名,從這個意義上講, 任何模式都有個model,都有個屬性,所以,即便我很同意你說的邏輯上showProfile就是個model,但我仍然認為,我們從本質上是anti-MVC的。


免責聲明!

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



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