2026/9/18 5:15:00

LikeC4 Dynamic Views 完全指南:用 DSL 绘制流程与时序图

LikeC4 Dynamic Views 完全指南:用 DSL 绘制流程与时序图 LikeC4 Dynamic Views 完全指南用 DSL 绘制流程与时序图【免费下载链接】likec4Visualize, collaborate, and evolve the software architecture with always actual and live diagrams from your code项目地址: https://gitcode.com/GitHub_Trending/li/likec4动态视图Dynamic View是 LikeC4 中用于表达元素之间时间性交互与调用流的视图类型。它把 C4 模型中的静态关系串成一条条带方向的步骤渲染为可动画的流程图Flow Diagram也可以切换为 UML 风格的时序图Sequence Diagram。本指南以 skills/likec4-dsl/references/dynamic-views.md 为骨架结合本仓库的语法定义、校验器与测试用例完整讲解 dynamic view 的语法、流程控制块、步骤属性、导航下钻、时序图变体与常见反模式读完即可在.c4文件中写出可编译、可校验的复杂动态视图。语法总览动态视图写在views { ... }块内以dynamic view name { ... }声明。与静态视图view不同动态视图的核心不是谓词过滤而是逐条显式书写的步骤stepviews { dynamic view name { variant sequence // 可选以 UML 时序图渲染 title Flow title description Flow description SOURCE - TARGET step title SOURCE - TARGET return flow // 流程控制块每个都可带可选标题可任意嵌套 parallel optional { // 也支持par、opt、loop、break SOURCE_1 - TARGET_1 parallel action 1 SOURCE_2 - TARGET_2 parallel action 2 } alt optional { // 互斥分支容器 when condition { SOURCE - TARGET } else { SOURCE - TARGET } } try optional { SOURCE - TARGET } catch optional { SOURCE - TARGET } finally optional { SOURCE - TARGET } } }从语法定义like-c4.langium可以看到DynamicView由dynamic view nameId组成其 body 是DynamicViewBody先是一些视图属性tags、title、description、variant 等随后混排stepsStepStatement与rulesDynamicViewRule如include、style、autoLayout。也就是说动态视图内部可以同时存在步骤序列与静态视图规则二者互相补充。基本步骤前向步骤用-表达从源到目标的调用/消息传递标题会显示在箭头上dynamic view checkout-flow { customer - frontend opens cart frontend - backend requests checkout backend - payment-service initiates payment payment-service - bank authorizes card }在语法层面单个步骤对应 StepsourceElementRef (- | - | -[rel]-) targetElementRef其中-是最常见的无类型箭头。注意元素引用既可以是简单名customer也可以是带层级限定名的引用cloud.ui.mobile后者在 e2e 用例 model.c4 中大量出现。返回步骤用-表示响应/返回流语义上是从目标流回源dynamic view checkout-flow { customer - frontend opens cart frontend - backend requests checkout frontend - backend payment result // 返回流 }-表示 response/return 流渲染为虚/点线箭头具体样式取决于主题语义上明确指出流向是回到源。语法中isBackward?-正是为它设计的标记位like-c4.langium。校验器对返回步骤还有一个约束stepSeries检查中若链式表达式的起点是一个 backward step会报Invalid chain after backward step见 validation/dynamic-view.ts。链式步骤把多次跳转写成一个复合表达式语义上更紧凑dynamic view multi-hop { customer - frontend request - backend forwards - db query }语法上这对应StepSeriessource - target1 - target2 ...每次跳转由(dotKind | - | -[kind]-)连接like-c4.langium。当提示词明确要求链式语法时应保持一整条链而不是拆成多个顶层独立步骤这也是文档 Quick anti-patterns 第一条。跳转局部属性体hop-local body可以把属性体{ ... }只挂在某一次跳转hop上dynamic view checkout-flow { customer - frontend - api { technology HTTPS navigateTo payment-detail } }关键点属性体只作用于它所在的那一次跳转。除非提示词允许否则不要把块整体上移到整条链上。流程控制块步骤可以被分组进流程控制块flow-control block。parallel只是其中一种并非特例。每个块在关键字后紧跟一个可选标题String然后包裹一个{ ... }步骤体可以任意深度嵌套——唯一的例外是parallel/par不能再嵌套在另一个parallel/par内。块关键字映射表块关键字含义并行parallel/par块内步骤并发执行可选opt可能被跳过的步骤组循环loop会重复执行的步骤组中断break打断外层流程如退出 loop分支容器alt一组互斥分支的容器分支alt 内when/if/elsealt的某一分支if是when的别名异常处理try/catch/finally正常路径 可选错误处理语法上这些块统一建模为SubflowStepkind: opt | par | parallel | loop | when | if | else | break见 like-c4.langium。try则是独立的TryStepTryBlock | CatchBlock | FinallyBlock通过FinallyBlock→CatchBlock→TryBlock的嵌套链实现try→catch?→finally?的固定顺序。Parallel ——parallel/par块内步骤并发执行常用于一个源扇出到多个目标dynamic view fan-out { backend - cache write to cache parallel { backend - db save record backend - audit-log log event backend - notification-service send notification } }par { ... }是parallel { ... }的完全别名渲染为时间对齐的水平布局不可嵌套parallel { parallel { ... } }或混用par是校验错误Nested parallel blocks are not allowed但parallel可以放在opt/loop/try/alt分支内部当一个提示词只要求一次扇出时把兄弟动作放在同一个parallel { ... }块里不要拆成多个单步块。这一限制在源码中有明确校验subflowStep检查器判断kind par || kind parallel且其容器同为并行块时直接报错validation/dynamic-view.ts对应的测试见 views-dynamic-blocks.spec.ts 与 views-dynamic.spec.ts。Optional ——opt一组可能被跳过的步骤opt if not cached { api - db load and cache }Loop ——loop一组会重复执行的步骤loop until success { api - auth retry authentication }Break ——break打断外层流程典型场景是退出looploop poll for result { api - db check status break when ready { api - web return result } }Alternatives ——alt与when/if/elsealt是互斥分支的容器其直接子节点必须是分支——when、if或else各自可带可选标题alt { when authorized { app - api requests data } else not authorized { app - customer shows login } }if是when的别名两者都是分支关键字when/if/else只能出现在alt内部。放在顶层或loop/parallel/opt内是校验错误when alternative branch must be inside alt把非分支块loop、opt、parallel、try作为alt的直接子节点也是校验错误loop can not be used as an alternative branch。需要嵌套时把这类块放进某个when/else分支内部。语法上AltSteps定义为alt title? { branchesSubflowStep* }而校验器通过isAltSteps(el.$container)判断分支是否处于alt中validation/dynamic-view.ts测试覆盖见 views-dynamic-blocks.spec.ts。Try / catch / finally建模正常路径 可选错误处理。catch与finally均可选但顺序固定try→catch?→finally?try { api - db query } catch on failure { api - web shows error } finally { api - api release resources }try单独、try { } catch { }、try { } finally { }、try { } catch { } finally { }都是合法组合没有前置try的catch或finally之后的catch都是校验错误try不能作为alt的直接子节点只有分支可以——请把它放进when/else分支内。上述四种合法组合在 views-dynamic-blocks.spec.ts 中有对应测试非法用例裸catch、catch置于finally之后、try直接放进alt也都用toBeInvalid断言验证。嵌套除了parallel不能套parallel其他块可以任意组合嵌套dynamic view resilient-sync { variant sequence loop until synced { try { alt { when online { web - api sync changes } else offline { opt { web - web queue locally } } } } finally { web - api ack } } }e2e 仓库中 views.c4 的flow-control-1视图是一个真实的综合样例alt内含when/elseelse里再套loop随后try { parallel { ... } } catch { ... } finally { ... }再接opt与链式返回步骤几乎用全了所有控制块。步骤属性Step Properties给步骤挂一个{ ... }body 可以附加更多元数据dynamic view with-notes { customer - frontend view product { title View Product Detail technology HTTPS description Customer opens product page } frontend - backend fetch product data { notes Includes: - Product info - Pricing - Available inventory } backend - db query { metadata { latency 50ms cached false } } }步骤体内可用属性title— 备用或更长的标题technology— 所用技术/协议description— 详细描述notes— Markdown 格式的注释metadata— 自定义键值对语法上步骤的customCustomRelationProperties?挂的是关系级属性集like-c4.langium其中包含navigateTo、字符串属性、notation、notes、关系样式属性与multiple。测试 views-dynamic.spec.ts 验证了步骤级description、color、notation、title、notes含多行 Markdown均合法。导航与下钻Navigation Drill-down从步骤链接到另一个视图dynamic view high-level { customer - frontend browse frontend - backend request data { navigateTo>dynamic view checkout-sequence { variant sequence // 切换到时序图渲染 customer - frontend click checkout frontend - backend POST /checkout backend - payment-service charge card payment-service - bank authorization backend - payment-service charge approved frontend - backend 200 OK customer - frontend show confirmation }variant sequence告诉 LikeC4 按时序图渲染时间线自上而下流动而不是流程图的自左向右参与者actor成为 lifeline返回箭头为虚线。语法上由DynamicViewDisplayVariantProperty: keyvariant valueDynamicViewDisplayVariantValue定义like-c4.langium且variant属性只能在动态视图内部出现——校验器dynamicViewDisplayVariant会检查其容器必须是DynamicViewBody且取值只能是diagram或sequencevalidation/dynamic-view.ts。e2e 中的 model.c4 有variant sequence的真实用例。流程图与时序图渲染对比维度流程图Flow Diagram时序图variant sequence布局自左向右或自上而下自上而下的 lifeline返回箭头样式随主题变化标准虚线并行的表现水平对齐基于时间、带间距最佳场景系统交互消息交换协议返回箭头模式Response Arrow Patterns当提示词要求返回箭头时优先用-步骤表达响应而不是凭空发明额外的前向步骤dynamic view checkout-flow { customer - frontend - api customer - frontend - api // 响应链优先用 - 保持对称 }不要写成dynamic view checkout-flow { customer - frontend - api api - frontend returns // 错误不是返回箭头缺少对称性 frontend - customer returns }常见模式扇出 返回dynamic view fan-out-return { backend - cache check backend - db if miss backend - db result backend - client send }顺序先发给多个目标再各自收集结果不同时响应。注意这里check 后 if miss 再 query如果目标是表达并发应改用parallel文档 dynamic-views.md 中with-cache示例展示了frontend - cache check/cache - backend if miss的缓存旁路写法。管道 / 分阶段流程dynamic view>dynamic view payment-decision { customer - frontend enter amount frontend - backend validate alt { when within limit { backend - payment-service charge backend - payment-service result } else over limit { backend - frontend rejected } } }需要无 else 的 if一组可跳过的步骤时用opt需要成功 vs 失败路径时用try/catch当不值得写一个完整分支块时步骤上的notes仍是记录决策逻辑的轻量方式。常见反模式反模式问题正确做法嵌套parallel { parallel { ... } }报Nested parallel blocks are not allowed把所有并发步骤放进一个parallel {}when/if/else出现在alt之外报alternative branch must be inside alt用alt { ... }包住分支loop/opt/parallel/try直接作为alt子节点报can not be used as an alternative branch把它们嵌套在when/else分支内部没有try就写catch或finally之后写catchtry/catch/finally 顺序非法保持try→catch?→finally?单个视图步骤过多图变得不可读用navigateTo拆分成子视图用-表达并列动作语义上暗示返回破坏时序语义用前向-或parallel分组需要 UML 时序图却忘了variant sequence渲染结果不对需要时序图时加上variant sequence动态视图中的谓词过滤动态视图不使用谓词来生成或过滤交互步骤——步骤必须逐条显式列出。但仍可以用普通的 include 谓词添加不参与步骤的上下文元素dynamic view critical-flow { frontend - api request api - db query include cloud.* where tag is #critical include cloud.* where metadata.region is eu } dynamic view with-cache { // 带缓存层的备选流程 frontend - cache check cache - backend if miss }语法上这对应DynamicViewIncludePredicate: include exprsExpressionslike-c4.langium与静态视图的include/exclude谓词规则ViewRulePredicate不同——动态视图只支持include方向。e2e 用例 model.c4 与 views.c4 中都有include 谓词/样式配合步骤使用的实例。典型应用场景文档 dynamic-views.md 列出的常见场景认证流程— customer → login → auth-service → databaseCQRS 模式— command → service → write-dbquery-handler → read-db 用parallelWebhook 回调— external-system → api内部parallel配合navigateTo service-webhook-handler下钻Pub/Sub 流— publisher → message-bus → consumer多个订阅者用parallel写作时的精确性要点提示词要求链式语法时保持一条复合链不要改写成多个顶层独立步骤提示词明确要求返回箭头时用-而不是前向箭头一次并行扇出只用一个parallel块不要拆成多个不要省略提示词要求的 hop 局部 token如technology、navigateTowhen/if/else只能直接放在alt内loop/opt/parallel/try不能作为alt的直接子节点parallel内不能再嵌套parallel唯一不可嵌套的块严格遵守try→catch?→finally?的顺序。底层实现参考想深入理解 dynamic view 的编译与校验链路可以在本仓库中继续阅读语法定义packages/language-server/src/like-c4.langiumDynamicView声明、L648-L812步骤与流程控制块语法校验逻辑packages/language-server/src/validation/dynamic-view.ts并行嵌套、alt 分支归属、try/catch/finally 顺序、variant 取值单元测试packages/language-server/src/tests/views-dynamic.spec.ts、views-dynamic-blocks.spec.ts视图计算packages/core/src/compute-view/dynamic-view/compute.ts 与 computeFlow.ts端到端样例e2e/src/likec4/model.c4含parallel、opt、variant sequence、navigateTo、e2e/src/likec4/views.c4alt/loop/try/parallel综合嵌套。掌握了这些语法、校验规则与反模式你就能在 LikeC4 中稳定地产出既符合语言规范、又能在编辑器LSP中零报错的动态视图与时序图。【免费下载链接】likec4Visualize, collaborate, and evolve the software architecture with always actual and live diagrams from your code项目地址: https://gitcode.com/GitHub_Trending/li/likec4创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考