摘要:代碼只是狀態機圖的相關元素的一種表現形式,它與節點式或表格式的狀態機圖并無本質不同。如上,狀態機是防止代碼失控的一劑良藥,制備完善的狀態機圖就是防止代碼失控的一種有效手段。
前言
前幾天和某某同學吃飯席間,他聊到每當要修改老項目中自己寫的代碼時就痛苦不堪,問我是不是也有同感。我覺得這應該是不少程序猿的心聲,之所以會這樣,大致有兩個主因:
項目的整體設計很糟糕,只管往上堆砌各種功能、補丁,對于代碼質量和結構關系基本無暇顧及,最終積重難返滑向失控。
對技術缺乏必要的敬畏心,基礎不夠扎實、知識面較窄,不能(無法)進行合理的規劃,最終導致停留在低水平的代碼堆砌上,只求完成功能就萬事大吉。
程序猿飯桌上總少不了對產品經理的吐槽:“產品經理又對業務流程進行了瘋狂調整,我覺得這會導致狀態機無法支持了。”他的這個槽點讓我一時有些語塞,倒不是懷疑產品經理的腦洞還能大到把狀態機開到失控,只是詫異難道我們還有比狀態機更適合應對業務流程變更的武器嗎?
事實上狀態機對于軟件工程師來說應該是個很基礎的知識點,它原理簡單卻擁有強大的適應力并被廣泛應用(譬如:游戲開發、工作流、編譯器、正則表達式等解析器),掌握好它的原理和應用,能幫助我們從容應對很多棘手問題,它于程序猿應對復雜流程性問題,就好比醫生使用抗生素應對細菌感染一樣的最佳武器。同時,它還是防止代碼失控的一劑良藥。
基本概念狀態機一般泛指“有限狀態機(Finite State Machine)”,《離散數學》中有關于它的專門章節,以下謹為我對相關概念的形式上的非精準釋義,如有出入請以教科書或相關學術資料為準。
狀態:顧名思義表示某個時刻系統處于一個特定的階段。通常我們不考慮中間態,也可以把中間態進行退化處理。當狀態發生變更,就叫狀態轉換(Transfer)或狀態遷移(Transition)。
事件:驅動系統進行狀態轉換/遷移的源,提供這種源的也常被稱為“觸發器(Trigger)”。
行為:當系統進行狀態轉換時進行的響應處理,提供響應處理的程序也常被稱為“處理器(Handler)”。
有了上面的基本概念,我們來看一個最簡單的狀態圖:
你可能會奇怪這個圖怎么跟網上那些狀態機圖不一樣,連狀態轉換條件都沒有呢?這是因為,我覺得在了解狀態機之前,最好先確立以下兩種概念:
狀態驅動:狀態機負責根據輸入來驅動狀態流轉。
遷移判定:在狀態流轉過程中確定當前狀態是否需要進行轉換/遷移,以及轉換/遷移到哪個狀態中的判定機制。
所以,在常見的狀態機圖中標注的那些狀態轉換條件只是“遷移判定”的一種具體表現形式,它即可以由狀態機內置,也可以是獨立的判定器來處理,又或者由狀態圖預先定義好,如此等等。
建立“狀態驅動”和“遷移判定”這兩個被抽象化的概念,有助于我們深入理解狀態機的機理,并且對我們設計一個魯棒性和擴展性更好到狀態機有實際指導意義。
狀態機圖以下是表示一個‘簡陋’的 Email 地址格式的解析器狀態圖,狀態遷移條件采用正則表達式來表達,其中圖二又稱為“狀態遷移圖”。
圖一:節點式
圖二:表格式(紅色格表示拒絕或異常;灰色格表示忽略或無意義;其他格表示遷移條件)
代碼實現有了上面的狀態圖,就像建筑工人拿到了詳細的建筑設計圖紙;現在我們只需要對著狀態機圖,把它映射成代碼即可完成一個基本狀態機。狀態機圖越詳細,實現起來就越容易,同時代碼的可維護性也越好。
public class Email { public string Identifier { get; private set;} public string Host { get; private set; } public string Domain { get; private set; } private Email() {} public static Email Parse(string text) { if(string.IsNullOrEmpty(text)) return null; var state = State.None; /* The State-Driven */ for(int i=0; i上面的代碼雖然看起來沒什么技術含量,但它已經具備了一個狀態機最基本的三大要素了(狀態、狀態驅動、遷移判定),針對具體業務場景我們只需完善和優化它的程序結構,底層原理的基本要義其實就是這么簡單。
失控的大腦人腦是一個很神奇的存在,它很擅長處理抽象思維,對于邏輯推理也有很好的應對能力,但卻有個不擅長處理并發任務的Bug。比如當面臨很多個邏輯分支,各分支的判定條件彼此關聯,大腦很快就會陷入繁雜的狀態中無法自拔。
表現在解決復雜流程相關的任務時就是,寫著寫著你會發覺腦子好像不夠用了,而程序中的 Bug 卻像打地鼠游戲中的老鼠一樣層出不窮。不難想象,即使腦力過人的你在勉強寫完后的某天,產品經理帶著他的腦洞又來找你了,在他的威逼利誘下你打開了一個月前的代碼,忽然,覺得還是抱著產品經理同歸于盡算了……
這大概是某某同學,面對自己曾經的代碼時痛苦的根源所在,因為普通人面對復雜流程問題時,終歸受人腦算力所限。本質上這是人腦算力有限的一個困境,人類解決這個困境的一個行之有效的辦法就是“分而治之”,即將一個大問題或復雜問題不斷進行分解分化,直至達到人腦能相對輕松理解和處理的程度。
為什么說狀態機是解決此類問題的一劑良藥?
通過狀態機圖可以很容易的看到它天生具有“分解、分化”的特征,一個復雜的流程由多個流程節點組成,這些節點可以理解為對流程的分解,流程節點之間的轉移條件(遷移判定)可以看成是被分化后的邏輯分支,如果大腦直接處理整個流程很容易陷入紛擾的流程分支和各種細節中,但是,當我們把眼光聚焦在某個流程節點和它的轉移條件上的時候,大腦需要處理的信息量就變得非常少了。
所以,當我們直面一個繁雜的流程圖的時候,第一感覺就是復雜、腦闊痛,這其實是大腦的正常反應,當你把眼光聚焦到“Start”節點上,并順著它往下推,每個節點的信息量一定是大腦能輕松處理的量級,這種順藤摸瓜的方式反過來也正是流程設計的套路。我有時會被自己剛畫完的狀態機圖給驚訝到,怎么這么復雜?因為當我一點點把細節補充上去后,整體性自然會變得復雜了,但是局部依然是簡單的,而簡單就是可靠、魯棒、可維護性的同義詞。
代碼只是狀態機圖的相關元素的一種表現形式,它與“節點式”或“表格式”的狀態機圖并無本質不同。
另外,狀態機圖相對代碼而言,它更專注于流程本身,而代碼畢竟是具體實現層面的東西,除了流程本身還包括程序結構、業務代碼等與流程無關的代碼,這些額外的東西對我們解讀流程造成了干擾,因而相對純粹的狀態機圖就好比是代碼實現的“地圖”。
經過一段時間后,我們可能已經不記得實現細節了,這時看著狀態機圖來進行代碼解讀和修改將會大大提高效率和準確度,這就是提升代碼可維護性的有力手段。
如上,狀態機是防止代碼失控的一劑良藥,制備完善的狀態機圖就是防止代碼失控的一種有效手段。
課后作業試著脫離狀態機圖擼一個“成員訪問表達式”的解析器去體驗下失控的感受。下次,我們將一起來實現這個東西。
附注:成員訪問表達式:訪問對象方法、屬性、字段、索引器(包括字典、列表)這些成員的表達式,其中方法和索引器(包括字典、列表)的參數支持常量和成員表達式(即表達式遞歸)。詳細的文法請參考C#語言手冊。譬如:
PropertyA .ListProperty[100] .MethodA(PropertyB, "StringConstant for Arg2", 200, ["key"]) .Children["arg1", "arg2"]如果你覺得這次的文章對你有所幫助,又或者你覺得我們的開源項目做的還不錯,請為我們點贊并關注我們的公眾號。
提示本文可能會更新,請閱讀原文: https://zongsoft.github.io/blog/zh-cn/zongsoft/coding-outcontrol-statemachine-1,以避免因內容陳舊而導致的謬誤,同時亦有更好的閱讀體驗。
本作品采用?知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議 進行許可。歡迎轉載、使用、重新發布,但必須保留本文的署名 鐘峰(包含鏈接:http://zongsoft.github.io),不得用于商業目的,基于本文修改后的作品務必以相同的許可發布。如有任何疑問或授權方面的協商,請致信給我 (zongsoft@qq.com)。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/42154.html
摘要:希望引起大家這些安全問題的足夠重視。允許攻擊者在受害者的瀏覽器上執行腳本,從而劫持用戶會話危害網站或者將用戶轉向惡意網站。 雖然,JavaEE 內置了一些非常優秀的安全機制,但是它不能全面應對應用程序面臨的各種威脅,尤其許多最常見的攻擊:跨站攻擊(XSS),SQL 注入,Cross-Site Request Forgery (CSRF), 與 XML eXternal Entities...
摘要:但你是否知道分庫分表需要哪些要素拆分過程是復雜的,提前計劃,不要等真正開工,各種意外的工作接踵而至,以至失控。在實施分庫分表策略時,這些個性會造成策略過大不好維護。 更多文章關注微信公眾號《小姐姐味道》 https://mp.weixin.qq.com/s?__... 數據庫中間件之分庫分表 恭喜你,貴公司終于成長到一定規模,需要考慮高可用,甚至分庫分表了。但你是否知道分庫分表需要哪...
摘要:今天我將美團點評這幾年在運維方面做的一些工作,以及自己的思考與大家分享一下。所以在美團點評給自己的使命,就是要把美團點評的運維做到騰訊百度的水平,把缺失的過程成長的過程由自己做出來。美團點評的自動化工具講一下美團點評的自動化工具。 數人云當西方的SRE遇上東方的互聯網Meetup第一彈實錄來啦! 本次分享嘉賓是美團點評運維中心高級總監鐘紅軍,他向我們詳細介紹了美團點評近3年來在大規模運...
閱讀 1433·2021-11-09 09:45
閱讀 1797·2021-11-04 16:09
閱讀 1461·2021-10-14 09:43
閱讀 1829·2021-09-22 15:24
閱讀 1613·2021-09-07 10:06
閱讀 1607·2019-08-30 14:15
閱讀 997·2019-08-30 12:56
閱讀 1573·2019-08-29 17:22