State Machine Là Gì

     

Giới thiệu Finite State Machine

Finite State Machine (FSM) giới thiệu khái niệm về tâm trạng (state) và lịch sử hoạt động của nó. FSM bao hàm hữu hạn những trạng thái của hệ thống, lưu trữ cách hệ thống đi mang lại trạng thái đó thế nào và có các cách xử lý các dữ liệu đầu vào (input) không giống nhau dựa trên trạng thái hiện tại. FSM tất cả thể thay đổi trạng thái dựa vào input, sự biến hóa này điện thoại tư vấn là transition.Bạn vẫn xem: Finite state machine là gì

(Wagner, Schmuki, Wagner và Wolstenholme, 2006)

FSM được tư tưởng trong khối hệ thống bởi một số trong những hữu hạn các trạng thái, trạng thái bắt đầu và điều kiện để đổi khác giữa các trạng thái.

Bạn đang xem: State machine là gì

Để cho dễ hiểu thì ta có thể tham khảo thứ thị sau

*

(Nystrom, 2014)

Đồ thị trên bộc lộ sơ cỗ về một FSM, với 4 tinh thần là Standing, Ducking, Jumping với Diving, trạng thái bắt đầu có thể phát âm là Standing (trong game, nhân vật dụng lúc nào cũng đứng yên ổn chờ tín đồ chơi ấn nút) và những điều khiếu nại để chuyển đổi từ tinh thần này thanh lịch trạng thái khác (với các nút bấm).

Công dụng của Finite State Machine

Điều tuyệt vời nhất của FSM là bọn họ luôn có một thiết bị thị khớp ứng với thiết kế, giúp họ hình dung các trạng thái của khối hệ thống một cách dễ dàng. Chúng ta luôn biết hữu hạn những trạng thái cơ mà hệ thống hoàn toàn có thể đạt được phụ thuộc vào thiết kế của FSM mà không lo ngại bỏ sót, đồng thời bài toán thêm hoặc sút trạng thái rất solo giản.

Ví dụ ở vật thị làm việc trên, muốn nhân vật dụng vừa ngồi vừa dash như Rockman Zero, ta chỉ việc thêm tinh thần Low Dashing cạnh Ducking cùng thêm dòng mũi tên từ Ducking sang Low Dashing với đk Press Y.


*

Áp dụng vào web

Lý thuyết là vậy, với ví dụ thì cũng về game, vậy với web thì sao? thực chất với dân frontend thì ngày ngày vẫn thao tác làm việc với một dạng của FSM, đó là router (ví dụ React Router). Vì sao router lại là 1 trong FSM?

Theo như tư tưởng ở trên, router gồm 1 số hữu hạn các routes và những handlers của nó, route khởi chế tác (thường là root xuất xắc home) và các links hoặc actions để đi trường đoản cú route này sang trọng route khác. Bởi thế với mỗi cặp route và handler, ta hoàn toàn có thể hiệu đó là một trạng thái của hệ thống; ráng mỗi cặp đó bởi state ta sẽ sở hữu router đó là FSM. Ko tin chúng ta có thể sử dụng đúng quan niệm của FSM với tự implement một router cho bạn (cho React chẳng hạn), nó trọn vẹn không khó khăn và xứng đáng để thử.

Xem thêm: Chưa Chuyển Dạ Uống Nước Lá Tía To Có Tác Dụng Gì Cho Bà Bầu

Để dễ dàng hiểu hơn nữa thì ta đem một ví dụ nó trong thực tiễn hơn một chút. Lấy ví dụ như ta có một hệ thống bài viết, bài viết mới tạo thành sẽ luôn là Draft, muốn được published lên trang nhất, thứ nhất ta yêu cầu đi từ Draft cho In Review, rồi chờ những bác editors vote xem bao gồm nên chuyển lên trang tuyệt nhất không In Votes rồi new được lên thành Published. Giả dụ tạch 1 trong 2 bước In reviews hoặc In Votes, bài viết lại được trả về địa phương để Draft tiếp. Cùng với naive implementation, code nó sẽ là một trong rổ flags như sau:

interface Post uid: number; title: string; isDraft: boolean; isInReview: boolean; isInVote: boolean; isPublished: boolean; voteCount: number;enum Status Draft, InReview, InVote, Publish const throwUpdateError = () => ;const updateStatus = (post: Post, status: Status) => if (post.isDraft) if (status === Status.InReview) post.isDraft = false; post.isInReview = true; console.log("Wait for review"); return; else throwUpdateError(); return; if (post.isInReview) if (status === Status.Draft) post.isDraft = true; post.isInReview = false; console.log("Rejected from review"); return; if (status === Status.InVote) post.isInReview = false; post.isInVote = true; console.log("Wait for vote"); return; throwUpdateError(); ...;Vì loại updateStatus nó quá nhiều năm và tinh vi trong trường phù hợp này nên nội dung bài viết chỉ viết đến trường hợp nội dung bài viết đang hóng được reviews In Review. Vụ việc của viên code ngơi nghỉ trên là nó vượt dài, không ít flags và khó khăn để thêm giảm trạng thái, chưa tính nếu thêm vài cái flags vào nữa thì việc sót ngôi trường hợp là vấn đề thường gặp, dẫn đến xúc tích đi sai phía (ví dụ thoải mái và tự nhiên từ Draft nhảy lên Published luôn thì rõ là tai hại).

Để số đông thứ đơn giản dễ dàng hơn, ta rất có thể thay gò flags loằng ngoằng trên bằng một field tuyệt nhất là state cùng với type là enum State:

enum State Draft, InReview, InVote, Published/** * Post structure. */interface Post uid: number; title: string; voteCount: number; state: State;/** * Proceed action in FSM */const proceedPost = (post: Post) => { if (post.state === State.Draft) post.state = State.InReview; return if (post.state === State.InReview) post.state = State.InVote; return if (post.state === State.InVote) if (post.voteCount /* same as above */;/** * Delegate action for FSM */const updatePost = (post: Post, action: "proceed" ;/** * Published State in Post FSM */const publishedState: State = proceed: (post: Post) => console.warn("Published cannot be processed anymore"); return publishedState; , reject: (post: Post) => console.warn("Go khổng lồ draft again."); return draftState; ;/** * Proceed action in FSM */const proceedPost = (post: Post) => post.state = post.state.proceed(post);;/** * Reject kích hoạt in FSM */const rejectPost = (post: Post) => post.state = post.state.reject(post);;/** * Delegate kích hoạt for FSM */const updatePost = (post: Post, action: "proceed" | "reject") => if (action === "proceed") proceedPost(post); if (action === "reject") rejectPost(post); ;Mọi thứ gần như hoàn hảo, dẫu vậy nếu ta mong có local state cho các State trên thì sao? Ở bên trên ta chỉ tất cả một instance độc nhất của State và đổi qua thay đổi lại, nếu có khá nhiều Post cùng thực hiện thì local state ở chỗ này không hoạt động. Vậy ta cần một cái constructor để tạo thành State cùng local state của nó:

const makePublishedState: State = () => const timer = ; /* use a real timer here */ return proceed: (post: Post) => timer.start(() => ); /* implement real timeout function */ return makeAnotherState(); , reject: (post: Post) => console.warn("Go to lớn draft again."); return makeDraftState(); Như vậy với mỗi trạng thái thì ta sẽ sở hữu một object implement State trait (ở phía trên ta hiểu là States mang lại Post FSM), với FSM này đã nhận và cách xử trí 2 hành động đó là Proceed cùng Reject. Hệ thống mỗi lần nhận 1 trong 2 hành động này vẫn delegate mang đến State bây giờ để cách xử trí đồng thời trả lại State mới. Bởi vậy ta không cần thiết phải kiểm tra hàng loạt flags nữa, đồng thời ao ước thêm một trạng thái new cho bài viết, lấy ví dụ Archive - trạng thái mang đến các bài viết đã published và quá cũ, ta chỉ cần thêm 1 object implement State trait và điều chỉnh action handlers cho publishedState, điều đó giúp ta trọn vẹn không đề xuất động vào các states còn lại, đảm bảo an toàn tính đúng chuẩn của hệ thống.

Nếu mong muốn chuyển object Post làm việc trên thành dạng flatten, tương thích cho trình lên service, ta rất có thể thêm method getStatus(): string đến State trait, states vẫn trả lại status khớp ứng cho post.

Xem thêm: Tại Sao Lại Ăn Chè Đậu Đỏ Vào Ngày Thất Tịch, Ngày Thất Tịch Là Gì

Kết

với State, ta rất có thể thêm các method vào như transition(), start() hoặc end() để cách xử trí giữa việc biến hóa các trạng thái dễ dàng hơn. FSM giúp decouple những trạng thái, bớt tối đa khả năng chạm mặt lỗi khi đổi khác trạng thái của app. Với Finite States, ta sẽ sở hữu Finite Actions. Tức là sẽ không có chuyện một kích hoạt lạ hoắc kỳ lạ huơ làm sao nhẩy vào hệ thống của chúng ta biến hóa trạng thái lung tung.

Tham khảo

Other notes