<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                &emsp;&emsp;在日常的業務開發中,會包含許多的業務規則,一般就是用if-else硬編碼的方式實現,這樣就會增加邏輯的維護成本,若無注釋,可能都無法理解規則意圖。 &emsp;&emsp;因為一旦規則有所改變,那么就需要修改代碼再發布代碼,而在日常的開發中唯一不變的就是變化,修改規則是很常見的。 &emsp;&emsp;規則引擎的作用就是將決策邏輯從業務邏輯中抽離出來,使得兩者可以獨立于彼此,便于集中管理,減少硬編碼的成本和風險,在不重啟服務的情況下快速響應需求的變化。 &emsp;&emsp;規則本質上就是一個函數,包括n個輸入(決策因子),一個輸出(結果)和一段計算規則三部分。 ~~~ decision = rule(factor1, factor2, …, factorn) ~~~ &emsp;&emsp;計算規則包含LHS(Left Hand Side,條件分支邏輯)和RHS(Right Hand Side,執行邏輯)。換句話說就是如果XXX(規則),那么XXX(動作)。 &emsp;&emsp;LHS比較容易實現,就是判斷條件的組合,包括常規表達式(算數運算、關系運算等),簡單規則(數組索引等),業務定制規則(觀看直播時間等)。 &emsp;&emsp;而RHS就比較復雜了,場景眾多,可以是簡單的算數運,也可以是單表查詢,甚至是幾張表的數據聚合,并且它的抽象程度直接會左右規則引擎的受眾人員。 &emsp;&emsp;如果設計的規則引擎是給產品或運營,那么就不能加入過多的編程概念,給他們用的應該是比較傻瓜的那種。 &emsp;&emsp;如果是給開發人員用的,那么可以設計的更加自定義,并且還能添加編程語句進來。 &emsp;&emsp;增加了編程性,就降低了可用性;增加了可用性,就降低了擴展性。在權衡后,決定先封裝已經出現的執行邏輯,做成可配置的。 &emsp;&emsp;例如有個活動規則,如果觀看30分鐘,那么贈送3天會員,其中30和3就是可配置的參數。這樣就能保持一定程度的可擴展。 ## 一、界面 &emsp;&emsp;與產品溝通后,讓她給出些規則,在看到她的文檔后,大大超出我的預期。 &emsp;&emsp;她先分成了兩個角色:主播和觀眾,然后根據這兩種角色來設計動作,例如觀眾 - 觀看直播 - 時長滿XX。 :-: ![](https://img.kancloud.cn/39/4e/394ec91448441879e1eb1aeaf7f8ce97_506x484.png =300x) &emsp;&emsp;她還給出了統計粒度,分天、周、月和自定義,這也是我之前的盲點,獎勵形式就是會員和兌換幣。 &emsp;&emsp;經過她的拆解后,我界面的設計也明朗了。順帶便,將之前打榜活動的規則也移植到該配置系統中。 :-: ![](https://img.kancloud.cn/98/c0/98c0c2fdbcfb3a55200ccf82baae33c1_1612x1224.png =800x) &emsp;&emsp;在此界面中,規則和獎勵都是可以多條的,運算符就是大于、小于、等于等。 &emsp;&emsp;規則關系就是與和或,由于不想實現太復雜,所以就降低了操作友好度,得手寫關系。滿足這層關系后,才會發放獎勵或執行結果。 ## 二、Node.js &emsp;&emsp;核心邏輯就是運行規則,發放獎勵,這些配置信息都存儲在MongoDB中。 &emsp;&emsp;首先根據名稱找到這條配置,然后先解析統計粒度,按日、周、月或自定義,時間庫采用了[moment.js](https://momentjs.com/)。 ~~~ getInterval(type, start, end) { const date = {}; switch (type) { case 1: //每日 date.start = moment().startOf("day"); date.end = moment().endOf("day"); break; case 2: //每周 date.start = moment().startOf("isoWeek"); date.end = moment().endOf("isoWeek"); break; case 3: //每月 date.start = moment().startOf("month"); date.end = moment().endOf("month"); break; default: //自定義 date.start = moment(start); date.end = moment(end); break; } return { start: date.start.format("YYYY-MM-DD HH:mm:ss"), end: date.end.format("YYYY-MM-DD HH:mm:ss") }; } ~~~ &emsp;&emsp;然后是遍歷規則,每條規則會對應不同的方法,未來擴展就是擴展這些規則方法,得到的結果再由運算符計算。 ~~~ caculate(left, operator, right) { const hash = { lt: left < right, lte: left <= right, gt: left > right, gte: left >= right, equal: left == right, notEqual: left != right, allEqual: left === right, notAllEqual: left !== right }; return hash[operator]; } ~~~ &emsp;&emsp;接著將規則關系中的數字替換成那幾個運算結果,得到嘴周的規則結果。 ~~~ let expression;     //規則表達式結果,可能是布爾值,也可能是其他類型的值 if (!row.relation) { expression = operators[1]; } else { // 將匹配的數字替換成規則結果值 expression = row.relation.replace( /(\d+)/g, function (match, p1, index, input) { return operators[match]; } ); expression = eval(expression);   //執行字符串代碼 } ~~~ &emsp;&emsp;最后發放獎勵,方法中包含Switch分支,未來就是完成這些分支中的邏輯。 ~~~ async giveRewards(params, type, value, project) { switch (type) { case "vip": //會員 break; case "gold": //兌換幣 break; case "letter": //站內信 break; } } ~~~ &emsp;&emsp;完整的執行規則的邏輯如下所示。 ~~~ async runRule({ name, params }) { const row = await this.models.WebRule.findOne({ name }); if (!row) return false; const { project } = row;   //項目類型 const date = this.getInterval(row.statis_type, row.rule_start, row.rule_end); const operators = {};     //運算符 // 遍歷規則 for (let i = 0; i < row.rules.length; i++) { const rule = row.rules[i]; // 得到方法值 const result = await this[rule.role[1]](params, date, project, rule.value); // 計算規則值 operators[i + 1] = this.caculate(result, rule.operator, rule.value); } let expression;     //規則表達式結果,可能是布爾值,也可能是其他類型的值 if (!row.relation) { expression = operators[1]; } else { // 將匹配的數字替換成規則結果值 expression = row.relation.replace( /(\d+)/g, function (match, p1, index, input) { return operators[match]; } ); expression = eval(expression);   //執行字符串代碼 } if (!expression) { return false; } // 發放獎勵 for (const data of row.awards) { await this.giveRewards(params, data.award[2], data.value, project); } return expression; } ~~~ 參考資料: [從0到1:構建強大且易用的規則引擎](https://tech.meituan.com/2017/06/09/maze-framework.html) [手把手搭建業務規則引擎 Rule Engine](http://www.waylon.one/monthly-skills/rule-engine/) [規則引擎基礎知識](https://ld246.com/article/1627548055112) [URule Pro](http://www.bstek.com/resources/doc/4.0/) [規則引擎](https://juejin.cn/post/6989066814332354567) [從產品角度看物聯網平臺的規則引擎](http://www.woshipm.com/pd/4237660.html) [復雜風控場景下,如何打造一款高效的規則引擎](https://tech.meituan.com/2020/05/14/meituan-security-zeus.html) [動手擼一個規則引擎(二):方案解析](https://cloud.tencent.com/developer/article/1507807) ***** > 原文出處: [博客園-Node.js躬行記](https://www.cnblogs.com/strick/category/1688575.html) [知乎專欄-Node.js躬行記](https://zhuanlan.zhihu.com/pwnode) 已建立一個微信前端交流群,如要進群,請先加微信號freedom20180706或掃描下面的二維碼,請求中需注明“看云加群”,在通過請求后就會把你拉進來。還搜集整理了一套[面試資料](https://github.com/pwstrick/daily),歡迎閱讀。 ![](https://box.kancloud.cn/2e1f8ecf9512ecdd2fcaae8250e7d48a_430x430.jpg =200x200) 推薦一款前端監控腳本:[shin-monitor](https://github.com/pwstrick/shin-monitor),不僅能監控前端的錯誤、通信、打印等行為,還能計算各類性能參數,包括 FMP、LCP、FP 等。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看