邏輯管理:解決方案(二) – 組裝原子和原子共存,共建上層輸出邏輯
- 2019 年 10 月 10 日
- 筆記
閱讀tips
此文章是一個連續探索關於程序中的邏輯的如何管理的系列,在JavaScript中落地實踐,理論上思想適用任何語言,建議從頭看:
概念解釋
在新迭代之前,解釋下之前博客中所說的一些概念,因為在內部分享的時候,也讓很多人去疑惑。
關於原子邏輯概念
之前的理解是抽象到無法再繼續分割的程度的叫原子邏輯,在實施之後發現,當你真正細分到那個程度的時候,會帶來很多問題。
a. 是否真正需要細分到那麼細節?
b. 理想化的實踐會不會帶來更高的成本?
c. 解決方案的使用者是否更方便?
針對這個問題,思考了很久,太理想化的東西,願景是好的,但是真正落地的時候,會發現有很多的坑需要自己去踩。所以原子邏輯的概念需要進行變更:
過去:將原子拆分到無法拆分的步驟,保證一個方法或者屬性只做一件事或者只代表一個屬性
現在:內部形成邏輯閉環,或依賴更低維度的邏輯形成閉環,為組裝提供邏輯服務能力的稱為原子邏輯
關於該開源項目到底是做什麼的?
首先確定一點,該項目不是教使用者去怎麼抽象我們項目/業務中的邏輯,因為每個人的思維和角度不一樣,抽象的顆粒度也不一致。該項目只是做一個解決方案,對邏輯的一個統籌管理,組裝生產,以及最後的結果管理。這樣就可以對散落在整個鏈路的邏輯做強制管控,所有的邏輯從這裡出發,然後組裝,最後提供服務,一層層邏輯的流轉鏈路,清晰明了。
接手了很多項目,最大的痛點就是所有邏輯沒有管理而失控,畢竟失控就意味着,它將終究會在「 巨石應用 」的路上越走越近。
組裝原子的設計
在上一篇初步的探討中遺留了一個問題:組裝原子如何和原子共存,共建上層輸出邏輯?
什麼是組裝原子?
依賴更低層的原子,組裝而成,形成閉環,對外提供原子服務的,稱之為組裝原子
真實案例
完成簡單的功能:前端請求增加mock能力。可以直接打開demo,安裝好依賴後,通過npm run start進行配合閱讀
設計圖
原子類管理
1. 不依賴外部自閉環的邏輯 ==> config配置、mock數據
2. 依賴自閉環邏輯形成閉環的邏輯 ==> request模塊
組裝類管理:
1. 對外依賴request,組裝出測試代碼。
代碼工程結構
-mockDemo
|-atom –原子管理目錄
|-one –不依賴外部的自閉環原子邏輯
|-two –依賴基礎自閉環原子形成閉環的原子邏輯
|-package –組裝邏輯目錄
|-index –配置注入入口
one:config.js 和 mock.js
export default { name: 'config', assembly: { // 請求配置 requestConfig:{ testData:{ url: 'https://xxxx.com/get', mock: true } } } }
export default { name: 'mock', assembly: { testData: '我是mock獲取的數據' } }
two:request.js
import ajax from 'ajax-js' /* * do something * 請求配置,timeout,header,error等等 * */ export default { name: 'request', extend: ['mock', 'config'], assembly: { get(name) { // 判斷配置文件中是否存在請求配置 if (this.requestConfig[name]) { // 判斷是否開啟mock if (this.requestConfig[name].mock) { // 獲取mock中的邏輯 return Promise.resolve(this[name]) } else { // 不開啟mock,發送真實請求 return ajax.get(this.requestConfig[name].url) } } else { console.error('未檢測到合法請求,請核對配置文件') } } } }
package:index.js -組裝
export default { name: 'testFile', extends: ['request'], through: false, assembly: { testRequestFun() { this.get('testData') .then(x => { console.warn('測試mock功能結果:', x) }) } } }
index.js – 注入配置
import {injection, getMateriel} from '@fines/factory-js' import config from './atom/one/config' import mock from './atom/one/mock' import request from './atom/two/request' import test from './package/index' injection({ atom: [ [config, mock], [request] ], package: [test] }) export default getMateriel('testFile')
測試代碼:
import mockDemo from './mockDemo' // 測試組裝原子請求 mockDemo.testRequestFun('testData')
測試結果:
整個邏輯的數據流向如下圖:
這樣一層一層的單向數據流的好處歸納如下:
1. 邏輯數據流動方向可以跟蹤,流動單一,追查問題的時候可以更快捷。
2. 每個邏輯的管理(比如,config、mock、request等)就是對邏輯的切片,在當前的切片里可以做替換、灰度等等。
3. 抽象和歸納思維的增強,如何去抽象,如何去依賴設計,以達到最契合當前項目的架構。
4. 助力邏輯管理更加方便和統籌,對「 巨石應用 」說不。
更豐富能力
到這裡,有人肯定會問,那如果我有依賴第二層邏輯的原子做服務的原子呢,是否支持更高或無限層次的依賴原子呢?當然支持!
下面就是底層實現的設計思路:
設計之初就依據無限層原子依賴服務進行設計的,
正如設計思路圖左邊一樣,對於組裝原子的執行順序就是,先從最底層自閉環的原子開始注入系統,然後依賴一級的開始組裝注入原子系統,依次類推,最終到更高維度。
整個組裝的裝載設計流程是圖的右邊
1. 首先第一層是可注入原子,直接注入系統
2. 其次第二級別的組裝原子依賴第一層的原子,在生產系統中進行裝配組裝。
3. 產出可注入系統的原子,注入到原子系統中
4. 更高維度的依次類推,對已注入原子系統的原子可支配使用,依賴原子形成自己的閉環,然後對外提供服務。
注意:組裝原子可使用extend進行原子調用,但是不會進行through進行透傳所繼承的原子的,因為本身組裝完了大家都在原子系統中。
迭代變更:
injection原子注入參數變更
// 老方法 injection({ atom: [atom1, atom2], package: [package1, package2] }) // 新方法 injection({ atom: [ [config, mock], [request] ], package: [test] })
總結
其實為request增加mock功能,這個需求可以將配置和mock數據都放到一個js里,這樣的話,這個request的就形成了自閉環的最基礎的原子。但是本章節的demo的設計,將mock的數據和配置文件單獨拆開了。這就是這個解決方案的能力:本解決方案,只是為邏輯的管理提供了一個解決方案,並不會教你怎麼去抽象你的邏輯。其次,基於js的設計,脫離了任何前端的框架(vue,react,angular等),你可以集成到任何框架裏面。後面我們自己摸索,會提供一個合理的插件。
注意
該解決方案正在設計中,還沒產出正式方案,可能還會有變動,如果大家感興趣可以自己非核心項目使用。如果你認為該方案確實值得一試,也可以使用,但是開發中必須鎖版本,這樣為了防止版本升級影響當前存量的項目。如果你要手動升級版本,可能需要付出升級成本,如果有任何問題或者疑問可以直接給我發郵件[email protected],大家一起交流。
github
項目地址:https://github.com/GerryIsWarrior/factory-js
demo地址:https://github.com/GerryIsWarrior/factory-js/tree/master/demo
點個star,?一下作者,繼續為更美好前端做努力
npm
npm地址:https://www.npmjs.com/package/@fines/factory-js
當前包版本:0.0.7
下期迭代
1. 原子邏輯中相同name處理。
2. 在組裝邏輯中,透傳更細顆粒度的原子邏輯,而不透傳一整個原子的邏輯。
3. Vue插件使用。
後記
我可能沒有那麼大的能量去推動前端這個大浪潮的前進,但是我願意貢獻自己微薄的一份力量,做點對前端有價值的東西,讓前端變得更加美好,這就是我的小願望,一直砥礪前行着。
當然,如果有需要,我也可以幫你推薦一些公司的職位,比如:餓了么,阿里,閱文,位元組,小紅書,B站,拼多多,哈啰,虎撲,美團,攜程等等,坐標上海。如有需要,帶上你的簡歷和期望公司職位,發到我的郵箱:[email protected]。職位不限技術,各種都可以,我可以幫你去諮詢。
畢竟生活不易,特別在外拼的,能幫就幫一把。