استورد سلوكًا، واربطه ببياناتك، وغيّر ما يحق لموضع الاستدعاء تغييره. تبقى آلة الحالات ملكًا للسلوك.
معظم برنامج Orb مركَّب لا مكتوب. يُستورد سلوك من المكتبة القياسية (أو من وحداتك الخاصة) بـ uses، ثم يُشار إليه سمةً سمة أو كمداريّ كامل. تربطه بكيانك وتضبط مفاتيحه، وتبقى حالاته وانتقالاته كما عرّفها السلوك تمامًا.
1uses Browse from "std/behaviors/std-browse"
2
3trait BookShelf = Browse.traits.BrowseItemBrowse -> Book {
4 config {
5 browseLook: feed
6 fields: [{ name: "name", label: "Title", variant: h4 }]
7 }
8}Alias.traits.Name -> Entity يأخذ السمة ويعيد ربطها بكيانك. ولا يمس الجسم إلا سطح الاستدعاء:
| التعديل | أثره |
|---|---|
config { key: value } | يضبط المفاتيح التي تعلنها السمة |
events { OLD: NEW } | يعيد تسمية مفاتيح الأحداث في كل الآلة |
fields { old: new } | يعيد تسمية حقول الكيان التي تقرؤها السمة وتكتبها |
listens { … } | يستبدل استماعات السمة كلها |
emitsScope internal | يبقي كل بث داخل المداريّ |
لا سبيل إلى إضافة حالة أو حذف انتقال أو تغيير تأثيرات انتقال عند موضع الاستدعاء. لتتفاعل بشكل مختلف، أضف سمة شقيقة تستمع إلى أحداث السلوك. هذه القاعدة هي ما يجعل البرنامج المركَّب قابلًا للتحقق كالبرنامج المكتوب يدويًا.
هنا سلوكان قياسيان مرتبطان بكيان Book محلي، دون كتابة آلة حالات يدويًا:
LibraryPage
on LibraryView · states: 1 · transitions: 0BookShelf
on Book · states: 3 · transitions: 9BookFacts
on LibraryView · states: 1 · transitions: 0MasterListView
on Book · states: 1 · transitions: 1books
on loan
Abelson and Sussman
Hoare
Knuth
البرنامج أعلاه كآلات حالات، واحدة لكل سمة: كل مربع حالة، وكل سهم حدث ينقلها، والأيقونات على السهم هي التأثيرات التي يشغّلها ذلك الحدث. الرمز ◇ على السهم شرط حارس؛ مرّر المؤشر فوقه لتقرأ الشرط. كيف تقرأ AVL
1app std-orb-docex-library "1.0.0"
2"std-orb-docex-library — composition: two standard behaviors bound to a local entity and configured at the call site, with no state machine written by hand."
3orbital LibraryOrbital {
4 uses Browse from "std/behaviors/std-browse"
5 uses StatBand from "std/behaviors/std-stat-band"
6
7 entity Book [persistent: docex_books, local] {
8 id : string!
9 name : string!
10 author : string = ""
11 status : "active" | "pending" | "inactive" = active
12 instances [
13 { id: "B-1", name: "Structure and Interpretation", author: "Abelson and Sussman", status: active },
14 { id: "B-2", name: "Communicating Sequential Processes", author: "Hoare", status: pending },
15 { id: "B-3", name: "The Art of Computer Programming", author: "Knuth", status: active }
16 ]
17 }
18
19 entity LibraryView [runtime] {
20 id : string!
21 }
22
23 trait LibraryPage -> LibraryView [interaction, instance] {
24 initial: idle
25
26 state idle {
27 INIT -> idle
28 (render-ui main { type: stack, direction: vertical, gap: lg, children: [@trait.BookFacts, @trait.BookShelf] })
29 }
30 }
31
32 trait BookShelf = Browse.traits.BrowseItemBrowse -> Book {
33 config {
34 browseLook: feed
35 bodySearch: false
36 fields: [{ name: "name", label: "Title", variant: h4 }, { name: "author", label: "Author", variant: caption }, { name: "status", label: "Status", variant: badge, labels: { active: "On the shelf", pending: "On loan", inactive: "Lost" } }]
37 }
38 }
39
40 trait BookFacts = StatBand.traits.StatBandRender -> LibraryView {
41 config {
42 heading: "The shelf at a glance"
43 items: [{ value: "3", label: "books" }, { value: "1", label: "on loan" }]
44 }
45 }
46
47 page "/library" -> LibraryPage
48}1uses Board from "std/behaviors/std-board"
2
3orbital Hiring = Board.orbitals.BoardOrbital {
4 entity Candidate
5 fields { title: name }
6 extend { referredBy : string = "" }
7 pages { "/board": "/hiring" }
8}يجلب مرجع المداريّ الكيانَ وكل سمة وكل صفحة. يستطيع جسمه إعادة ربط الكيان، وإعادة تسمية الحقول، وإضافة حقول جديدة بـ extend، وإعادة تعيين المسارات، وتقليص السمات بـ omit أو only، وضبط المفاتيح المعلنة للمداريّ بـ config. تُسبَق الأسماء المستوردة باسم مداريّك، فلا يتصادم استيرادان للسلوك نفسه أبدًا.
تعيش المفاتيح على السمة (trait.config)، وعلى المداريّ (المفاتيح التي ينشرها عبر سماته)، وعلى التطبيق. تنشر السمة مفتاح مداريّ أو تطبيق لنفسها بجعل القيمة الافتراضية لمفتاحها @config.<knob>، ويسير الحل من موضع الاستدعاء إلى المداريّ إلى التطبيق. المفتاح المعلن الذي لا تمرره أي سمة خطأ، وكذلك تعديل مفتاح لم يُعلَن.
1uses lazy Guide from "./guide"
2
3orbital GuideIntro = Guide.orbitals.GuidePage {
4 pages { "/guide": "/guide/intro" }
5}السلوك المستورد بـ uses lazy يُترجم إلى ملف خاص به ولا يُحمَّل إلا حين تُفتح إحدى صفحاته، فلا يرسل الموقع الكبير كل أقسامه مقدمًا. لا يُستخدم الاسم المستورد بهذه الطريقة إلا كمداريّ كامل له صفحات. صفحات هذا التوثيق نفسها سلوكيات تُحمَّل عند الحاجة.
تصفّح المتاح في المكتبة القياسية ومرجعها.