碎片數據收集利器:結構化動態表單設計思路
本文基于面向基本公共衛生的業務系統設計經驗,抽象出一套適合大型ERP系統的表單業務數據模型,目標是最大限度保留系統彈性的同時,盡可能降低系統復雜度和開發成本。enjoy~
背景
填寫表單應該是所有業務線條中最避免不了的環節,例如我所經歷的醫療項目:
以上面兩個例圖作為示例,可以看到姓名、性別、出生日期、血型等字段是完全重復的,由于業務場景的差異,表單被定義了不同的樣式和字段結構,此時將遭遇以下幾種問題:
- 同一用戶經歷了兩個不同場景時,不得不重復填寫相同的字段;
- 如果相同的字段在兩個表格中的值不同,基本無法判斷哪個為正確值,例如同一個人在
居民健康檔案
中血型填寫為A型,而在居民健康檔案信息卡
中填寫為B型; - 某些字段會重復出現在不同的表單中,隨著業務需要,將其串連起來查看其趨勢,如身高、體重、血壓、心率等等,以幫助醫生確診疾病,然而這些字段保存在各自的表單中,由于開發人員的變更、文檔的遺漏和產品的迭代,無法窮舉出所有的這些字段數據來源,即便能夠回溯所有的來源,本身也是一件十分消耗精力的事情;
- 因為政策或業務需要,要在原有的表單上做調整,新的標準導致表單字段產生變化,此時原有系統為保證其運行的穩定,難以從數據表和底層代碼中迭代,只能新增數據表做開發,當表單需求頻繁變化時,加劇數據碎片化的問題;
- 新增業務表單時,開發需要訂排期,用戶需要等待發版后才能使用,新增大量表單時影響原有開發計劃的同時,業務部門也難以快速開展系統業務。
- 做數據統計和分析時,由迭代造成的數據字段遺失或變更,無法統計出完整而準確的數據,做出的報告難以反映出真實的情況 ….
傳統的區域化基本公共衛生系統正在經歷這樣的劇痛,當然其他行業比如金融的部分業務同樣面臨相同問題(本人只經歷過這兩個行業,見諒),如何在紛繁復雜的業務環節中抽離出四兩撥千斤的數據模型,除了滿足日益頻繁的業務調整外,還能將數據完整的、標準的存儲并利用起來,是后端產品經理的安身立命之本。
作為一個不務正業的產品經理,這次就從數據庫表結構設計上,介紹一套解決方案:結構化動態表單。
場景和需求:
- 可覆蓋絕大部分表單業務場景;
- 表單樣式和字段可靈活調整,不影響歷史積累數據,不會造成數據庫和代碼層面的頻繁變更;
- 數據統計時能夠快捷、準確、全面地獲取到想要的字段數據,不過度依賴文檔和程序員老員工;
模塊介紹
屬性庫
所有表單中所有的字段都在屬性庫中定義,相當于表單字段的字典。定義的核心包含屬性的唯一標識、屬性名、屬性值取值規則和約束等信息。
因為我認為所有的字段都是圍繞某個業務進行的,把這個業務抽象成對象,那么這些表單的字段就是這個對象的屬性,所以命名為屬性庫。
如果用關系型數據庫表達屬性庫,根據以往的經驗可以總結出如下兩個基礎表:
屬性分類,主要根據使用者需求對屬性進行分類,方便查找和后期的批量數據統計,比如健康管理把心率、瞳孔大小、脈搏等屬性規劃到生命體征類,把身高、體重等屬性規劃到基本體征類等等,因此僅需要定義唯一識別碼、名稱和分類說明即可。
屬性,這個表非常重要,是數據標準化的基礎表。唯一標識、名稱、說明,這是一個屬性最基礎的說明,不用解釋。
- 分類ID字段可支持多個ID,表示一個屬性可劃分到多個分類下,這個可根據實際需求定義,我所經歷的場景是有這種情況的,比如心率,既可以是生命體征類屬性,也可以是臨床診斷類屬性,很難絕對界定。當然屬性和屬性分類也可以通過單獨建關系表來定義對應關系,方法有很多,各有優劣,看技術leader自行選型吧。
- 屬性類型,根據個人的經驗,總結出圖中的幾種類型,相信大家都認識,不用展開,其中單選框、多選框兩種類型因為還依賴對應的取值字典,因此還需要到屬性值字典中定義取值選項。另外
值單位
這個字段,方便做數據轉換和終端數據展示用,比如時長的值60,單位是分鐘,通過算法即可轉換該單位的值為1小時。
屬性值字典,主要用于配合屬性類型為單選框或多選框的取值,也是數據標準化的一部分。
例如定義一個屬性叫性別的屬性規劃到基礎信息分類中,此時會屬性庫的三個表中分別插入以下數據: 屬性分類表:ID=‘1’,分類名稱=‘基礎信息’,分類說明=‘用戶基本信息’ 屬性表:ID=2,分類ID=‘’,屬性名稱=‘性別’,屬性說明=‘用戶的性別’,屬性類型=‘單選下拉框’,值單位=空 屬性值字典:[ID=3,屬性ID=‘2’,字典值=‘男’],[ID=4,屬性ID=‘2’,字典值=‘女’],[ID=5,屬性ID=‘2’,字典值=‘未知’]
模版庫
所有的動態表單都是以模版的方式保存在數據庫中,表單模版中定義表單中填寫的字段、字段的默認值和表單樣式。
由于表單樣式的不可預見性,因此可以準備一套符合自家產品風格的視覺設計語言,限定表單視覺樣式的框架,包含前面提到的屬性類型呈現樣式,和細化到UI在手寫、PC端、移動端的字體大小、線條風格、交互方式、間距、縮進、比例、布局方式等參數,當然本篇由于篇幅限制不展開和視覺風格相關的討論,讀者可自行腦補。
既然是模版,肯定少不了控件,模版由控件組成,在這里把控件分為兩類:屬性組件和容器組件。
表單模版,是表單的字典表,用于定義表單的基礎信息如名稱、用途說明等,如果與業務銜接,還可以添加關聯的業務、填寫對象、觸發填寫的時間等,這部分信息由具體的業務場景決定,可根據實際需求設置字段。
容器組件,負責定義外觀樣式的組件,決定了屬性組件在表單中的呈現樣式,可根據不同布局需求細分更多容器組件,這里不展開細講。
- 順序號,在同級下的顯示排序,從左至右,從上至下的原則進行排列。
- 容器名稱,即表單中某方框的名稱,可不填
- 在終端顯示表單時,需要充分考慮各個組件在頁面上的默認布局參數和可變參數。通常前面提到的設計語言中會定義標準的內邊距外邊距、線粗和線色等視覺樣式,這些就是默認布局參數,但組件在表單中的顯示順序、嵌套關系和組件內的組件排列方式等參數多數時候是需要配置的,依據實際需求添加參數即可。
- 容器組件可嵌套,當遭遇多級層級關系時,用容器組件實現嵌套關系再好不過了,不建議屬性組件也支持嵌套,因為會提高屬性值的取值復雜度,除了開發和數據存儲邏輯復雜度高外,后期數據分析時也會進入邏輯黑洞,應盡量避免
- 是否支持累加數據,此字段用于控制組件內的元素,是否可以按照定義的字段多組生成,例如如:
在容器組件
主要用藥情況
中,屬性組件藥物名稱
、用法
、用量
、用藥時間
、服藥依從性
的值可以添加多次。 - 還可以添加跟多字段或子表,描述容器更多的視覺布局樣式,比如支持PC端、移動端、打印手寫的樣式定義。
屬性組件,來自于屬性庫中的屬性,決定了表單中填寫的字段信息。
- 容器ID,當前屬性組件放置在某個容器組件內,若值為null,表示直接放置在表單中
- 屬性別名,為適應部分個性化的需求,可以為屬性定義別名,比如身高,對嬰兒通常叫身長,對青少年或成年人叫身高。別名定義到模版中而不是在屬性庫的意義在于,用戶的個性化稱呼通常只會在自己所處的場景內使用,對于其他場景下的其他用戶并不一定通用。
- 屬性默認值,很好理解,沒用把這個字段放到屬性庫的理由和別名一樣,場景不同,默認值不一定通用。
- 是否必填,表單提交前判斷必填項的依據。
- 頁面區域,用于判斷當前組件出現在其父組件的位置,枚舉類型。
屬性組件還可以有更多可擴展特性,后面會提到一些。
業務數據庫
有了前面的屬性庫和表單模版庫的配置,即可配置出各式各樣的表單,而實際使用這些表單保存下來的數據格式是怎樣的呢?
表單主表,作為表單的索引表,主要是提供表單的填寫來源、時間戳和與業務相關的標記。
通常實際業務有很多附加的信息,圖中給出的是本人面臨的業務場景常見的字段。
容器明細表,這里保存了表單內負責樣式的容器數據,因為表單模版可能會變更,因此需要將其視覺樣式數據保存下來,以記錄當時呈現的樣式,避免因為模版變更而造成的布局樣式丟失。
屬性明細表,保存了所有表單的所有字段的值。
- 為了配合容器組件記錄其布局樣式,還添加了容器ID、順序號、組號、頁面區域,用于記錄保存表單時屬性在表單中的位置。
- 組號,當遇到屬性組件放置在允許累加數據的容器組件中時,標記出屬性值所在的組。
- 別名,若屬性在模版中配置了別名,則保存在這里,如果值為空,則顯示原屬性名。
- 修改時間,表單可能會遇到修改部分數據,因此標記字段的最后修改時間。如果有屬性值的操作日志,可以不要。
樣例
弊端
動態表單的存在,在一定程度上可以緩解產品迭代因業務變更帶來的壓力,但其開發復雜度較高,尤其表單模版,解析模版數據呈現到終端時,依賴遍歷算法,對程序員的要求不低,若整套產品的應用規模不大,不建議使用動態表單,或者根據需求開發簡配版。
由于表單依賴屬性庫和表單模版的配置,屬性和表單模版的維護質量決定了表單的數據質量,因此需要有高度責任心和專業能力的人員來進行屬性庫的維護,提高了使用門檻,但反過來講,羅馬不是一天建成的,如果有野心建立行業標準,本身也需要大力投入數據質控。
設計思想和基本原則
- 產品開發和業務運行盡可能的解耦。業務人員不必完全依賴產品業務功能的情況下才能運行相關業務(這個問題單獨靠動態表單無法完全解決,還需要依賴工作流,不過沒有動態表單時也可以勉強適應部分場景做業務試運行);
- 產品永遠做功能迭代,盡量避免數據迭代。常見的C端產品往往會有很多的營銷推廣廣告頁,這些廣告頁常常會頻繁變化,而且為了抓熱點往往需要即時響應跟進,如果按照每周發版1-2次的節奏,等發出來商業機會已經涼了,因此往往會做一個后臺配置廣告頁的功能,使運營人員可以自行配置廣告頁面,包含頁面元素、入口布局、外鏈引導、渠道埋點配置等等,這就是功能迭代。如果運營改一次廣告,產品即發一次版,這就是數據層迭代。每一次變更都將累積相應的數據,產品是生成這些數據的工具,產生數據是業務人員做的事情,產品和業務是冰淇淋機和賣冰淇淋的小姐姐的關系。
- 用戶永遠只能看到功能,只關心產品是否滿足其需求,而產品經理永遠要從高低遠近多維視角看待和解構需求,不斷的整合、重組、拆分、歸納,窮舉各種場景下的業務形態,在業務耦合和模塊化處理上達到平衡,本質上是優化效率,創造利潤,如果達不到這兩個目的,這個產品不能叫產品,只叫藝術品。
- 提前預判功能模塊的發展趨勢,在設計初期預留充分的擴展性和迭代方向,避免高頻率的推倒重來,當然如果是敏捷開發,請無視這條。
意義
- 屬性庫即數據規范,如果數據量在行業中足夠大,適用面足夠廣的情況下,具備發展為行業規范的潛力。
- 表單模版即數據接口標準,當多個系統需要進行數據對接時,最頭疼的往往是梳理數據對接標準,將需要對接的數據模版通過接口規范的方式導出給對接方,數據字段和取值規范一目了然,新老系統導數據也會用到。
- 數據利用更加便捷方便,需要查詢某項具體的屬性數據時,只需到屬性明細表中即可找到,無需遍歷其他業務表單
- 用戶可通過配置表單明確新需求,表單模版一定程度上提高了用戶需求和功能落地的溝通效率,一定程度上提高了產品的業務可擴展性
擴展性
以下是隨意舉例的可能的功能擴展方向,僅作為擴展閱讀。
屬性組件功能擴展
多屬性之間的邏輯約束和默認值:
- 性別為男時,診斷中不可出現婦科疾??;
- 年齡在18-21歲之間,職業默認值為大學生;
- 填寫了身份證號碼即可解析出籍貫、性別和出生日期。
單屬性復用:
姓名性別等字段用戶一旦填寫后,以后再次填寫有這些字段的表單即可自動填寫。
屬性值字典 診斷、癥狀字典數據可能依賴外部接口調取,而非本地屬性值字典庫。
容器組件擴展
- 可配置容器背景圖,視覺優化;
- 內部元素排列方式支持左對齊、右對齊、垂直排列、水平排列等;
- 可套用整體視覺設計的皮膚。
模版庫擴展
- 模版插入公用參數字段,如表單中的制表機構、填表人、所在科室等等;
- 表單中的字段可作為工作流業務環節控制字段,比如當支付方式為現金時,無需彈出支付二維碼。
操作日志
- 記錄所有用戶在業務表單上的操作記錄,包含操作人、時間戳、修改前屬性值;
- 記錄所有用戶在屬性庫和表單模版庫上的操作記錄。
本文由@魚丸 原創發布于人人都是產品經理。未經許可,禁止轉載
題圖來自Unsplash,基于CC0協議
看了你的第一條評論回復。你說提升要用機器學習和量化決策。那是數據分析和處理上的是吧?跟報表本身又是另一個層面的事情。
這個是個簡單共通的結構化動態表單思路實際應用更復雜,我做醫療信息化的產品經理,今年做的一個臨床科研數據采集系統的項目就是這樣,,要求更高劃分模塊更突出:數據集管理、表單設計配置工具、邏輯規則設計器、表單模板管理、數據源管理…….
臨床類的項目復雜度比公共衛生更高,劃分的模塊更細,不同的學科知識庫數據結構差異非常大,光靠這些可配置的數據采集器其實對業務本身提升并不大,個人認為可能需要往機器學習、量化策略等方向發展才可能有質的提升,但是這樣一來,門檻又更高了,但也變得更加有趣了
總結的很到位,動態表單的思路很清晰。
就像文中提到,羅馬不是一天建成的,如果有建羅馬的野心,就不要在在戰略層面偷懶。
另外,文中提到了敏捷開發,其實個人認為,敏捷開發與動態表單的設計理念并不矛盾。
就像作者提到,動態表單主要立足于建立統一的數據表結構規范,實現數據表層的動態管理,以適應碎片化的業務數據,避免因為業務表單變更新增而增加過多的數據表以及帶來的一系列問題;而敏捷開發更多的強調的是對業務需求的快速響應與快速實現與迭代,兩者的目標是一致的。
贊同,不過有時候敏捷開發在運營探路的過程中可能會發現其他商業機會,這種機會也可能會影響到戰略上的定位,動態表單在一些輕快的項目中太重了,三大模塊一個都不能少才能運行,有可能東西還沒做出來,因為試探不成功項目就擱置了,所以產品經理真的需要仔細權衡,到底是為了快速實現戰略目標搶占高地,還是為了用動態表單去做業務,殺雞焉用牛刀。
從大局來說動態表單確實可以覆蓋很多業務,在大戰略上可以當做整套平臺的基礎設施進行建設,以充分發揮其效能,所以個人認為這種較重的模塊適合在戰略目標長期明確的情況下瀑布式推進。