1. 程式人生 > 實用技巧 >OnRL: 基於線上強化學習的移動視訊傳輸優化

OnRL: 基於線上強化學習的移動視訊傳輸優化

在軟體開發中,研發效率永遠是開發人員不斷追求的主題之一。於公司而言,在競爭激烈的網際網路行業中,產出得快和慢也許就決定著公司的生死存亡;於個人而言,效率高了就可以少加班,多出時間去提升自己、發展愛好、陪伴家人,工作、生活兩不誤。

提升效率的途徑,無外乎就是「方法」和「工具」。以一個開發者的思維來想,就是將工作內容進行總結、歸納,從一組相似的工作內容中提煉共同點,抽象出解決這一類問題的方法,從而造出便於在今後的工作中更為快速解決這類問題的工具。這個「工具」可以是個函式、元件、中介軟體、外掛,也可以是 IDE、其他開發工具的擴充套件,甚至是語言。

面向元件

在現代前端開發中,如果去問一個業務前端開發:「如何提升團隊開發效率?」對方所回答的內容中,極有可能會出現「元件庫」。沒錯,在前端工程化趨近完善的今天,在近幾年react、vue等元件化庫/框架的影響下,面向元件開發的思維方式早已深入人心。

元件庫提效有限

現在,元件庫已經是一個前端團隊的必備設施了,長遠來看,團隊一定且必須要有自己的元件庫。開源的第三方元件庫再好,對於一家企業的前端團隊來說也只是短期用來充飢的,因為它們無法完全滿足一家公司的業務場景,並且出於多終端支援的考慮,必定要進行二次開發或者自研。

元件庫有了,團隊和公司中推廣的效果也不錯,絕大多數的人都在用。使用元件開發頁面相對 jQuery 時代要每塊功能區都得從 <span>、 <div>等html標籤碼起來說確實提升了效率,然而有限;要搞出頁面需要反覆去引入元件,然後組合拼裝出來,就像工廠流水線上的工人拼裝零件,仍然要去做很多重複動作。

只要覺得當前的開發方式重複的動作多了,就代表還能繼續提效,得想個法子減少重複無意義動作。

面向元件的開發方式,是現代前端頁面開發提效的初級階段,也是一個團隊所要必經的階段。

更高層面的提效

在之前寫的文章中有段話——

元件可以很簡單,也可以很複雜。按照複雜程度從小到大排的話,可以分為幾類:

  1. 基礎元件;
  2. 複合元件;
  3. 頁面;
  4. 應用。

對,不用揉眼睛,你沒有看錯!

站在更高的角度去看,「頁面」和「應用」也是一種「元件」,只不過它們更為複雜。在這裡我想要說的不是它們,而是「基礎元件」和「複合元件」。

文中提到了「頁面」和「應用」也可以看作是種「元件」。雖然與當時的想法有些差異,但本文的內容就是要在那篇文章的基礎上簡單聊聊在「頁面」層面的提效。

一般來說,「頁面」是使用者所能看到的最大、最完整的介面,如果能在這個層面有個很好的抽象方案,在做業務開發時與單純地面向元件開發相比,應該會有更大的提效效果。

GUI 發展了幾十年,人機互動的圖形元素及佈局方式已經相對固定,只要不是出現像 Google Glass 之類的革命性互動裝置,就不會發生重大改變。在業務開發中介面形式更是千篇一律,尤其是 web 頁面,尤其是中後臺系統的 web 頁面,一定可以通過什麼方式來將這種「千篇一律」進行抽象。

試著來回想下,自己所做過的中後臺系統的絕大部分頁面是不是我所描述的這樣——

頁面整體是上下或左右佈局。如果是上下佈局的話,上面是頁頭,下面的左側可能有帶頁面導航的側邊欄,或者沒有側邊欄直接將頁面導航全部集中在頁頭中,剩餘區域是頁面主體部分,承載著這個頁面的主要資料和功能;如果是左右佈局,左側毋庸置疑就是有頁面導航的側邊欄,頁頭跑到了右側上面,其餘是頁面主體。

中後臺系統的主要功能就是 CRUD,即業務資料的增刪改查,相對應的頁面展現及互動形式就是列表頁、表單頁和詳情頁。列表頁彙總了所有業務資料的簡要資訊,並提供了資料的增、刪、改和更多資訊檢視的入口;表單頁肩負著資料新增和修改的功能;詳情頁能夠看到一條業務資料記錄最完整的資訊。

每新增一個業務模組,就要又寫一遍列表頁、表單頁和詳情頁……反覆做這種事情有啥意思呢?既然這三種頁面會反覆出現,那乾脆封裝幾個頁面級別的元件好了,有新需求的時候就建幾個頁面入口檔案,裡面分別引入相應的頁面元件,傳入一些 props,完活兒!

這種方式看起來不錯,然而存在幾個問題:

  • 沒有描述出頁面內容的結構,已封裝好的頁面元件對於使用者來說算是個黑盒子,頁面內容是什麼結構不去看原始碼不得而知;
  • 如果新需求中雖然需要列表頁、表單頁和詳情頁,但與已封裝好的能夠覆蓋大部分場景的相關元件所支援的頁面有些差異,擴充套件性是個問題;
  • 每來新需求就要新建頁面入口檔案然後在裡面引入頁面元件,還是會有很多無意義重複動作和重複程式碼,時間長了還是覺得煩。

我需要一種既能看一眼就理解內容結構和關係,又具備較好擴充套件性,還能減少重複程式碼和無意義動作的方式——是的,兜了一個大圈子終於要進入正題了——面向模板開發。

面向模板

面向模板的前端開發有三大要素:模板;節點;控制元件。

富有表達力的模板

我所說的「模板」的主要作用是內容結構的描述以及頁面的配置,觀感上與 Xhtml相近。它主要具備以下幾個特徵:

  1. 字元全部小寫,多單詞用連線符「-」連線,無子孫的標籤直接閉合;
  2. 包含極少的具備抽象語義的標籤的標籤集;
  3. 以特定標籤的特定屬性的形式支援有限的輕邏輯。

為什麼不選擇用jsON 或jsX 來描述和配置頁面?因為模板更符合直覺,更易讀,並且中立。用模板的話,一眼就能幾乎不用思考得看出都有啥,以及層級關係;如果是 JSON 或 JSX,還得在腦中進行轉換,增加心智負擔,並且拼寫起來相對複雜。vue上手如此「簡單」的原因之一,就是它「符合直覺」的設計。

要使用模板去描述頁面的話,就得自定義一套具有抽象語義的標籤集。

頁面的整體佈局可以用如下模板結構去描述:

<layout>
  <header>
    <title>歐雷流</title>
    <navs />
  </header>
  <layout>
    <sidebar>
      <navs />
    </sidebar>
    <content>...</content>
  </layout>
  <footer>...</footer>
</layout>

看起來是不是跟 HTML 標籤很像?但它們並不是 HTML 標籤,也不會進行渲染,只是用來描述頁面的一段文字。

整體佈局可以描述了,但承載整個頁面的主要資料和功能的主體部分該如何去描述呢?

在上文中提到,我們習慣將中後臺系統中與資料的增刪改查相對應的頁面稱為「列表頁」、「表單頁」和「詳情頁」。雖然它們中都帶有「頁」,但真正有區別的只是整個頁面中的一部分割槽域,通常是頁面主體部分。它們可以被分別看成是一種檢視形式,所以可以將稱呼稍微改變一下——「列表檢視」、「表單檢視」和「詳情檢視」。一般情況下,表單檢視和詳情檢視長得基本一樣,就是一個能編輯一個不能,可以將它們合稱為「表單/詳情檢視」。

「檢視」只描述了一個數據的集合該展示成啥樣,並沒有也沒法去描述每個資料是什麼以及長啥樣,需要一個更小粒度的且能夠去描述每個資料單元的概念——「欄位」。這樣一來,用來描述資料的概念和模板標籤已經齊活兒了:

<view>
  <field name="name" label="姓名" />
  <field name="gender" label="性別" />
  <field name="age" label="年齡" />
  <field name="birthday" label="生日" />
</view>

雖然資料能夠描述了,但還有些欠缺:表單/詳情檢視中想將欄位分組展示沒法描述;對資料的操作也沒有描述。為了解決這兩個問題,再引入「分組」和「動作」。這下,表單/詳情檢視的模板看起來會是這樣:

<view>
  <group title="基本資訊">
    <field name="name" label="姓名" />
    <field name="gender" label="性別" />
    <field name="age" label="年齡" />
    <field name="birthday" label="生日" />
  </group>
  <group title="寵物">
    <field name="dogs" label=":dog:" />
    <field name="cats" label=":cat:" />
  </group>
  <action ref="submit" text="提交" />
  <action ref="reset" text="重置" />
  <action ref="cancel" text="取消" />
</view>

模板很好地解決了內容結構描述和配置的問題,但如何去動態地調整結構和更改配置呢?在平常的業務頁面開發時也許不會太凸顯出問題,但碰到流程表單設計或頁面視覺化編輯這種靈活性很高的需求時,問題就會被暴露出來了。

佛山vi設計https://www.houdianzi.com/fsvi/ 豌豆資源搜尋大全https://55wd.com

充滿控制力的節點

在這裡,我要將定義好的標籤集所拼成的模板解析成節點樹,通過更改樹的結構和節點的屬性去影響頁面最終的呈現效果。每個節點都會有節點的基本資訊、對應標籤的屬性和一些節點操作方法:

{
  name: "field",
  tag: "field",
  attrs: {
    name: "name",
    label: "姓名"
  },
  parent: {},
  children: [],
  remove: function() {},
  insert: function() {}
}

在頁面模板化且節點化之後,理想情況下,頁面長啥樣已經不受如react、Vue 等執行時技術棧的束縛,控制權完全在解析模板所生成的節點樹上,要想改變頁面的視覺效果時只需更改節點即可。

極具表現力的控制元件

頁面內容的描述通過模板來表達了,頁面內容的控制權集中到節點樹中了,那麼頁面內容的呈現在這種體系下應該如何去做呢?負責這塊的,就是接下來要說的面向模板開發的第三大要素——控制元件。

「控制元件」這個詞不新鮮,但在我所說的這個面向模板開發的體系中的含義,需要被重新定義一下: 「控制元件」是一個可複用的,顯示的資訊排列可由使用者改變的,可以進行互動的 GUI 元素。

在這個面向模板開發的體系中,模板和節點樹完全是中立的,即不受執行時的技術棧所影響;而控制元件是建立在執行時技術棧的基礎之上,但不必限於同一個技術棧。也就是說,可以使用 React 元件,也可以用 Vue 元件。

每個控制元件在使用前都需要註冊,然後在模板中通過 widget屬性引用:

<view widget="form">
  <group title="基本資訊" widget="fieldset">
    <field name="name" label="姓名" widget="input" />
    <field name="gender" label="性別" widget="radio" />
    <field name="age" label="年齡" widget="number" />
    <field name="birthday" label="生日" widget="date-picker" />
  </group>
  <group title="寵物" widget="fieldset">
    <field name="dogs" label=":dog:" widget="select" />
    <field name="cats" label=":cat:" widget="select" />
  </group>
  <action ref="submit" text="提交" widget="button" />
  <action ref="reset" text="重置" widget="button" />
  <action ref="cancel" text="取消" widget="button" />
</view>

這樣,一個面向模板開發的普通表單頁出來了!

思想總結

面向模板的開發方式很好,能夠大幅度提高業務前端開發效率,一定程度上減少了業務系統的搭建速度;作為核心的模板和節點樹是保持中立的,大大降低了執行時技術棧的遷移成本,且能夠應對多端等場景。

面向模板的開發方式初期投入成本很高,標籤集、模板解析和控制元件註冊與呼叫機制等的設計和實現需要較多時間,並且這僅僅是檢視層,邏輯層也需要做出相應的變化,不能簡單地用 props和事件繫結進行處理了。

這個體系建成之後,在業務開發上會很簡單,但機制理解上會增加部分開發人員的心智負擔。

為了效率,一家公司裡的業務前端開發到最後一定是面向模板,而非面向元件。