文檔代碼化

文檔代碼化,將文檔以類代碼的領域特定語言的方式編寫,並借鑑軟件開發的方式(如源碼管理、部署)進行管理。它能夠藉助於特定的工具進行編輯、預覽、查看,又或者是經過專屬的系統部署到服務器上。面向非技術人員的文檔代碼化的一種常見架構模式是: 編輯-發佈-開發分離』,

最近一個月裏,我在開發一個基於 Git + Markdown 的全新文檔系統。我定製了一個基於 markdown 的標記語言,以支持起雷達圖、條形統計圖、思惟導圖等圖表的文檔系統。這個系統將在將來幾個月內發佈。固然了,視進度而看,也多是月底。git

過去的幾年裏,咱們一直在討論各類各樣的代碼化,基礎設施代碼化、設計代碼化、需求代碼化……。在個人那一篇《雲研發:研發即代碼》中,設計了一個徹底代碼化的軟件開發流程。而今天咱們將討論另一個有趣的存在:文檔。程序員

在《架構金字塔》中,我將文檔定義爲支撐五層架構模型的一種存在。由於文檔在一個系統中是很是重要的存在,咱們用它來指導開發工做,用它來記錄問題,用它來寫下規範……。總而言之,它很重要,因此咱們從新討論一下這個話題。github

引子 1:架構決策記錄:格式化文檔

三年前,當我第一次接觸到『架構決策記錄』的概念時,我被它的理念所吸引:web

  • 使用輕量級文本格式化語言描述重大決策
  • 跟隨代碼一塊兒版本化
  • 使用某種特定的文檔格式(標題、上下文、決策、狀態、後果)

隨後,我使用 Node.js + TypeScript 寫了一個 ADR 工具。如今,在個人大部分開源薦中,我都會使用它來管理一些技術決策。由於基於這個理論設計的這個文檔系統真很是棒,我能夠查詢到:數據庫

  • 一個技術決策發生的時間和架構改變,對應的修改人
  • 回溯全部的技術決策,從中整理出架構發展過程
  • 全部的決策都是記錄在版本控制系統中,可恢復
  • 易於管理和維護

對於一個長期開發的系統來講,它真的很是有用。npm

引子 2:靜態站點生成:數據代碼化

靜態站點生成是一種混合式的 Web 開發方法,它經過部署預先構建的靜態文件進行部署,來讓開發者在本地構建基於服務器的網站。

當 GitHub Pages 成爲了程序員首選的 博客/內容/文檔 服務器時,他/她也採用了靜態站點生成這一項技術。靜態站點生成有各類各樣的優勢:編程

  • 可靠性、安全性、穩定性、可用性等更好
  • 可版本控制
  • 易於測試
  • 易於實踐持續部署。提交便可上線
  • 靈活,易於定製

而事實上,靜態站點生成所作的最主要的一件事是:將數據庫中的數據進行代碼化。採用諸如 Wordpress 這樣的 CMS 時,咱們是將數據存儲在數據庫中,以實現對於數據的 CRUD。一篇文章變爲數據庫二進制文件中的一個片斷。安全

隨後,靜態站點生成工具作了第二件事情即是將文本內容可視化出來,便於人們閱讀。這樣一來,咱們便實現了發佈-開發分離。服務器

引子 3:定製的標記語言:擴充

將數據代碼化時,咱們面臨了一個很是大的挑戰:易於編寫、閱讀的標記語言(如 markdown)只設計了內容的形式,缺乏了內容相關的其它信息,諸如於建立時間、做者、修改時間等等。markdown

因而各個靜態站點生成器定製了本身的 markdown,添加了一些額外的信息,如 hexo 採用 :year-:month-:day-:title.md 的形式來管理文章的日期和標題等。這樣一來講,就不須要經過讀取這個文章的 Git 信息來構建出整個信息。

咱們所熟悉的 GitHub Flavored Markdown 也是如此,經過不明顯破壞內容格式的兼容模式來擴展 markdown 數據字段。

除此,咱們能夠定製基於 markdown 數據的圖表、思惟導圖等內容。

引子 4:編輯-發佈-開發分離:面向非技術人員

面向非技術人員設計是代碼文檔化的一大挑戰。做爲一個程序員,咱們以爲 markdown 語法再簡單不過了,可是對於非技術人員來講並不是如此。他/她須要:一個易於上手的可視化編程器。而要實現這樣一個目的,咱們須要在架構上作一些轉變,咱們能夠嘗試使用 『編輯-發佈-開發分離』 模式來解決這個問題。

即,咱們將過程拆爲了三步:

  • 編輯人員,可使用經常使用的編輯器或者是定製的編輯器
  • 開發人員,編寫內容的展現
  • 發佈的時候,集成這兩部分代碼

咱們依舊能夠選擇用源碼管理的方式來管理內容。只須要將數據庫接口,轉變爲 Git 服務器接口便可 —— 固然它們是稍有不一樣的。不過呢,把本地的 Git 轉換爲 Git remote 那就基本一致了。

如此一來,最後咱們的成本就落在改造出一個基於 Git 的 markdown 編輯器。

文檔代碼化

完美,我又一次在引子裏,把中心思想表達完了。

爲何你須要將文檔代碼化?

主要緣由有:文檔不代碼化,就沒有重構的可能性。

剩下的緣由有:

  • 二進制的文檔難以進行版本管理。想象一下 2020-02-30.docx2020-02-31.docx
  • 沒法準確地知道誰是文檔的修改者,你們可能都是 admin,又或者是會議上的張三
  • 找不到哪一個是最新的文檔
  • 文檔寫得很爛,可是你沒辦法重構二進制文檔
  • 供應商綁定
  • ……

應該還有更多。

什麼是文檔代碼化?

回到正題上:

文檔代碼化,將文檔以類代碼的領域特定語言的方式編寫,並借鑑軟件開發的方式(如源碼管理、部署)進行管理。它能夠藉助於特定的工具進行編輯、預覽、查看,又或者是經過專屬的系統部署到服務器上。

它具有這麼一些特徵:

  • 使用標記語言編寫內容。如 markdown
  • 可經過版本控制系統進行版本控制。如 git
  • 與編程一致的編程體驗(除了內容寫不了測試)

而一個高效的文檔代碼化系統,還具有這麼一些特徵:

  • 持續部署,即修改完內容可自動發佈。
  • 與特定的形式組織內容索引。如以知識庫的形式來組織內容。
  • 特定的文本格式。如架構決策記錄、靜態內容生成,以用於以提供更好的用戶體驗
  • 可支持 REST API。以經過編輯器來修改內容
  • 能夠支持多種方式的輸出。如網站標準 HTML,又或者是 Docx、Latex 等
  • 支持編輯、校對工做流
  • 支持搜索
  • 多人協做

而事實上,大部分的團隊並不須要上述的高級功能,並且它們都已經有了成熟的方案。

如何設計一個文檔代碼化系統?

事實上,咱們在四個引子中標明瞭咱們所須要的要素:

  1. 使用格式化的文檔
  2. 藉助靜態站點生成技術來發布系統
  3. 經過定製標記語言擴充能力
  4. 面向非技術人員實現編輯器

設計一個標記語言及其擴展語法,而後實現它便可。

1. 確立關鍵因素

考慮到我和個人同事們最近實現了這麼一個系統,我仍是忍受一下手的痛楚,簡單說一下怎麼作這樣一個系統。咱們所考慮的主要因素是:

  • 圖表渲染
  • 流程圖渲染
  • 可視化展現

由於由 DSL 轉換成的圖表易於修改,而且能夠索引。因而乎,咱們:

  1. 經過 markdown 的 Code 語法來擴充這些能力
  2. 使用 markdown 的 table 和 list 來提供數據
  3. 使用 D3.js 來支持流程圖繪製
  4. 使用 Echarts 來進行圖表繪製
  5. 儘可能使用 SVG 圖片
  6. ……

2. 實現一個 MVP

咱們使用 Angular + GitHub,快速實現了一個 MVP:

  1. 咱們使用 Git 做爲數據庫.它就能夠實現多人協做的目的,而且能夠追蹤全部的變化
  2. 咱們使用 GitHub Pages 做爲服務器。只要一修改文檔或者代碼,就會部署最新的文檔。
  3. 咱們使用 marked.js,它可讓咱們快速擴展語法。
  4. 使用 textarea 結合 markdown 製做了一個簡易的編輯器。

隨後,咱們在這個基礎上進行了快速的迭代。

3. 擴展語法

咱們使用了 markdown 的 code 做爲圖表的 DSL,擴展了這麼一些語法:

  • echarts。直接渲染 Echarts 圖表
  • mindmap。Markdown List 轉爲思惟導圖
  • radar。Markdown List 轉爲雷達圖
  • process-table。帶流程的圖表
  • process-step。另一種帶流程的圖表
  • pyramid。金字塔圖形
  • quadrant。四象限圖
  • class。直接調用 CSS 的 class
  • graphviz。使用 Dot 渲染圖片
  • mermaid。使用 mermaid 可視化
  • webcomponents。調用 WebComponents 組件
  • toolset。調用 Toolset 相關的組件

    • slider。權衡滑塊
    • line-chart。表圖

因此,對於使用者來講,只須要編寫下面的代碼:

  • 質量成熟度評估模型

    • 質量內建: 3 -> 4
    • 優化業務價值: 2 -> 2
    • 質量統一,可視化: 1 -> 5
    • 全員參與: 3 -> 4
    • 快速交付: 4 -> 5
    • 測試做爲資產: 2 -> 3
    • 快速反饋: 5 -> 5

config: {"legend": ["當前", "將來"]}

就能夠生成對應的圖表:

image.png

又或者是用於製做技術雷達圖:

image.png

咱們還經過 config 來輸入 JSON,進行必定的懶惰化處理(不要累死本身)。

3.1 重寫 markdown 渲染器

咱們在這個過程當中,遇到的最大的挑戰是,隨着咱們對 markdown 語法的不斷擴充,相關的代碼已經變成了一坨大泥球。因此,咱們不得不重寫了這部分代碼:

  1. 藉助於 marked.js 的 lexer 解析出 token
  2. 根據 token 修改生成新的 token
  3. 遍歷新生成的 token,渲染出元素
  4. 結合虛擬滾動,解決性能問題

已經開源在 GitHub,併發布對應的 npm 包:@ledge-framework/render

4. 發佈這個項目

咱們已經在 GitHub 上發佈了這個文檔化系統,你能夠參與到其中的使用和開發。

GitHub:https://github.com/phodal/ledge

項目首頁:https://devops.phodal.com/

總結

而後,你就成爲了一個 Markdown 工程師,D3.js 設計師,Echart 配置管理員。

相關文章
相關標籤/搜索