本文基於面向基本公共衛生的業務系統設計經驗,抽象出一套適合大型ERP系統的表單業務數據模型,目標是最大限度保留系統彈性的同時,儘量下降系統複雜度和開發成本。enjoy~程序員
填寫表單應該是全部業務線條中最避免不了的環節,例如我所經歷的醫療項目:算法
以上面兩個例圖做爲示例,能夠看到姓名、性別、出生日期、血型等字段是徹底重複的,因爲業務場景的差別,表單被定義了不一樣的樣式和字段結構,此時將遭遇如下幾種問題:數據庫
居民健康檔案
中血型填寫爲A型,而在居民健康檔案信息卡
中填寫爲B型;傳統的區域化基本公共衛生系統正在經歷這樣的劇痛,固然其餘行業好比金融的部分業務一樣面臨相同問題(本人只經歷過這兩個行業,見諒),如何在紛繁複雜的業務環節中抽離出四兩撥千斤的數據模型,除了知足日益頻繁的業務調整外,還能將數據完整的、標準的存儲並利用起來,是後端產品經理的安身立命之本。做爲一個遊手好閒的產品經理,此次就從數據庫表結構設計上,介紹一套解決方案:結構化動態表單。後端
1.可覆蓋絕大部分表單業務場景。 2.表單樣式和字段可靈活調整,不影響歷史積累數據,不會形成數據庫和代碼層面的頻繁變動; 3.數據統計時可以快捷、準確、全面地獲取到想要的字段數據,不過分依賴文檔和程序員老員工;框架
全部表單中全部的字段都在屬性庫中定義,至關於表單字段的字典。定義的核心包含屬性的惟一標識、屬性名、屬性值取值規則和約束等信息。模塊化
由於我認爲全部的字段都是圍繞某個業務進行的,把這個業務抽象成對象,那麼這些表單的字段就是這個對象的屬性,因此命名爲屬性庫工具
若是用關係型數據庫表達屬性庫,根據以往的經驗能夠總結出以下兩個基礎表: 佈局
屬性分類,主要根據使用者需求對屬性進行分類,方便查找和後期的批量數據統計,好比健康管理把心率、瞳孔大小、脈搏等屬性規劃到生命體徵類,把身高、體重等屬性規劃到基本體徵類等等,所以僅須要定義惟一識別碼、名稱和分類說明便可。字體
屬性,這個表很是重要,是數據標準化的基礎表。惟一標識、名稱、說明,這是一個屬性最基礎的說明,不用解釋。優化
分類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次的節奏,等發出來商業機會已經涼了,所以每每會作一個後臺配置廣告頁的功能,使運營人員能夠自行配置廣告頁面,包含頁面元素、入口布局、外鏈引導、渠道埋點配置等等,這就是功能迭代。若是運營改一次廣告,產品即發一次版,這就是數據層迭代。每一次變動都將累積相應的數據,產品是生成這些數據的工具,產生數據是業務人員作的事情,產品和業務是冰淇淋機和賣冰淇淋的小姐姐的關係。
用戶永遠只能看到功能,只關心產品是否知足其需求,而產品經理永遠要從高低遠近多維視角看待和解構需求,不斷的整合、重組、拆分、概括,窮舉各類場景下的業務形態,在業務耦合和模塊化處理上達到平衡,本質上是優化效率,創造利潤,若是達不到這兩個目的,這個產品不能叫產品,只叫藝術品。
提早預判功能模塊的發展趨勢,在設計初期預留充分的擴展性和迭代方向,避免高頻率的推倒重來,固然若是是敏捷開發,請無視這條。
如下是隨意舉例的可能的功能擴展方向,僅做爲擴展閱讀
多屬性之間的邏輯約束和默認值
單屬性複用
屬性值字典 診斷、症狀字典數據可能依賴外部接口調取,而非本地屬性值字典庫