اجعل الانتقال مشروطًا بالكيان أو الحمولة أو الزائر، واحتفظ بكل قاعدة في مكان واحد.
الشرط تعبير بعد when. إن كان خاطئًا يُرفض الحدث: لا تغيّر في الحالة ولا تأثيرات. الشروط هي موطن قواعد العمل.
APPROVE -> approved when (<= @entity.amount 500)
(set @entity.note "Approved")PAY -> paid when (> ?amount 0)
(set @entity.total ?amount)?amount حقل من الحدث الوارد. يجب إعلانه، إما في emits الخاصة بالسمة الباثّة أو في مدخل listens محلي، ليتحقق المدقق من نوعه.
هنا ترفض صفحة الدفع مبلغًا صفريًا، ولا سبيل لشحن طلب غير مدفوع:
Checkout
on Order · states: 3 · transitions: 41app std-orb-sample-checkout "1.0.0"
2"std-orb-sample-checkout — the checkout program shown on orb.almadar.io's home page, running: an order that cannot ship before it is paid. The page shows this file as code beside the running trait, and each move is reported (MOVED) so its state machine can follow along."
3orbital Orders {
4 entity Order [runtime] {
5 id : string!
6 total : number
7 }
8
9 trait Checkout -> Order [interaction, instance] {
10 initial: pending
11
12 state pending {
13 INIT -> pending
14 (render-ui main { type: stack, gap: sm, children: [
15 { type: typography, content: "Unpaid", variant: h4 },
16 { type: button, label: "Pay 40", action: PAY, actionPayload: { amount: 40 } }
17 ] })
18 PAY -> paid when (> ?amount 0)
19 (set @entity.total ?amount)
20 (emit MOVED { event: "PAY" })
21 (render-ui main { type: stack, gap: sm, children: [
22 { type: typography, content: "Paid 40", variant: h4 },
23 { type: button, label: "Ship", action: SHIP }
24 ] })
25 }
26
27 state paid {
28 SHIP -> shipped
29 (emit MOVED { event: "SHIP" })
30 (render-ui main { type: stack, gap: sm, children: [
31 { type: typography, content: "Shipped", variant: h4 },
32 { type: button, label: "New order", action: NEW_ORDER }
33 ] })
34 }
35
36 state shipped {
37 NEW_ORDER -> pending
38 (emit MOVED { event: "NEW_ORDER" })
39 (render-ui main { type: stack, gap: sm, children: [
40 { type: typography, content: "Unpaid", variant: h4 },
41 { type: button, label: "Pay 40", action: PAY, actionPayload: { amount: 40 } }
42 ] })
43 }
44
45 emits {
46 PAY {
47 amount : number!
48 }
49 MOVED -> external {
50 event : string!
51 }
52 @description "Each move names the event it took, so a diagram beside the order can follow it."
53 }
54 }
55
56 page "/checkout" -> Checkout
57}ما الذي يحدث عندما يقع الحدث PAY:
(> @payload.amount 0)(set @entity.total @payload.amount)APPROVE -> approved when (= @user.role "manager")
(set @entity.approvedBy @user.id)@user هو الزائر المسجّل. أعلن شكله مرة واحدة بكيان [identity]، فيرفض المدقق أي دور خارج المفردات:
▼entity Person [persistent: people, identity] {
id : string! @key
role : "employee" | "manager" = employee
}(and …) و(or …) و(not …) تدمج الشروط. حين ينبغي لحدث أن يفعل أشياء مختلفة بحسب قيمة، اكتب انتقالًا لكل حالة بشروط متنافية، أو دع match يكتبها لك:
▼REVIEW -> reviewed match @entity.priority {
"high" -> (notify warning "Escalated")
_ -> (notify info "Queued")
}الشرط يرفض الحدث ولا يخفي الزر الذي يرسله. إن كان الزر لا ينبغي أن يظهر فقل ذلك في الشاشة: when في إجراء الصف، أو (if …) حول العقدة. لا شيء يُخفى ضمنيًا، فيُقرأ البرنامج كما يعمل تمامًا.
الأحداث بين المداريّات تصل بين مداريّات منفصلة.