以下文章来源于雷达峰 ,作者Faye Chen
作者:陈雅菲——中兴通讯公司资深软件架构师资深敏捷教练。深耕软件领域20余年,拥有丰富的大型软件项目架构、设计与开发经验,在软件设计开发理论与实践上均有独到见解。 长期致力于敏捷技术实践指导与推广,多次获得公司十佳敏捷教练称号。目前研究方向是LLM辅助设计编码。
▼
告警屏蔽:
4.当d告警产生时,屏蔽掉e、f告警。
告警生成:
2.当e告警产生且f告警未产生时,生成h告警。
首先思考系统的输入和输出。根据问题描述,特别是告警生成描述中的第2点,不难想到,系统的输入是告警列表。系统的输出是规则应用结果,包括应用成功、应用失败和未应用。
分析清楚了系统的输入和输出,我们再来思考系统本身。显而易见的是系统里的各种规则。不那么显而易见的是规则之间的关系。
用一句话描述就是:设计实现一个告警规则功能,该系统接受一个告警列表,根据各种规则和规则之间的关系应用规则,输出规则应用结果。
在问题描述中,告警是一个高频出现的概念,与当前特定问题领域的核心需求密切相关。
告警的语义是系统产生的某种告警,例如告警a、告警b。通常系统告警会包含很多属性,但在当前特定问题领域,只需要能把各种告警区分开的属性就行,例如告警名称、告警码等。这里使用告警名称唯一标识某种告警,因此用告警名称作为告警的构造参数。
“告警a”可形式化表达为alarm(a),圆括号里的是构造参数,即告警名称。
在问题描述中,规则是一个非常明显的概念,与告警规则这个问题领域的核心需求密切相关。
规则的语义是系统遵循的某种规则,其输入是告警列表、输出是规则应用结果。规则包括原子规则和组合规则。
规则可形式化表达为rule: alarms -> { succeeded | failed | unapplied },箭头左边是输入、右边是输出,花括号里的内容表示多选一。
在问题描述中,屏蔽告警非常明显,但屏蔽告警规则却不那么明显。
屏蔽告警规则的语义是屏蔽某种告警的规则,例如屏蔽告警b规则、屏蔽告警c规则。被屏蔽的某种告警作为它的构造参数。屏蔽告警规则是一种原子规则。
“屏蔽告警b规则”可形式化表达为mask(alarm(b))。
提炼出屏蔽告警规则后,生成告警规则是类似的。
生成告警规则的语义是生成某种告警的规则,例如生成告警g规则、生成告警h规则。被生成的某种告警作为它的构造参数。生成告警规则是一种原子规则。
“生成告警g规则”可形式化表达为generate(alarm(g))。
在问题描述中,“当...时,...”的句式描述的是一种条件应用规则。
条件应用规则由条件和规则构成。它的语义是:接受一个告警列表,对其进行条件判断,如果满足条件就应用规则,输出规则应用结果;如果不满足条件,就不应用规则,输出规则未应用。条件应用规则是一种组合规则。
条件应用规则可形式化表达为whenThen(condition, rule)。
相比较条件应用规则,顺序应用规则就非常不明显了。在问题描述中,告警屏蔽的1、2、3、4点和告警生成的1、2点其实都是顺序应用规则。
顺序应用规则由子规则列表构成。它的语义是:按照给定的顺序依次应用多条规则,如果某条规则应用失败或未应用,继续应用下一条规则,无论是否有规则应用失败或未应用,最终始终输出规则应用成功。顺序应用规则是一种组合规则。
顺序应用规则可形式化表达为seq(rules)。
条件应用规则包含了条件这一核心概念。
条件的语义是告警列表需要满足的某种条件,其输入是告警列表、输出是boolean,告警列表满足条件时输出true、否则输出false。条件包括原子条件和组合条件。
条件可形式化表达为condition: alarms -> { true | false }。
包含条件也不太明显,以“当a告警产生时”为例,它的实际含义是告警列表是否包含告警a。
包含条件的语义是告警列表是否包含某种告警,被包含的某种告警作为它的构造参数。包含条件是原子条件。
“a告警产生”可形式化表达为contains(alarm(a))。
提炼出包含条件后,否条件看上去就比较明显了。
虽然寻找否条件这个核心概念看上去并不难,但提炼其概念语义并不一定容易。以“f告警未产生”为例,否条件的语义有两种提炼方式:方式一是告警列表是否不包含告警f;方式二是告警列表包含告警f、再取非。哪种方式更好?方式二,因为方式二提炼的概念语义组合性更强、更抽象。否条件需要一个子条件作为它的构造参数。否条件是组合条件。
否条件可形式化表达为not(condition)。“f告警未产生”可形式化表达为not(contains(alarm(f)))。
在问题描述中,或条件非常明显。
或条件的语义可以直接映射到布尔代数的OR。在做设计时,首先考虑是否能将问题领域映射到一个熟悉的同构领域。如果能,就可以借用那个领域的机制来表达问题领域的概念,而不是重新发明。能找到这样一个同构领域应该是一个最好的结果,实在找不到再自己发明。或条件由两个子条件构成,两个以上的子条件只是语法糖衣。或条件是组合条件。
或条件可形式化表达为or(condition1, condition2)。“a或b告警产生”可形式化表达为or(contains(alarm(a)), contains(alarm(b)))。
提炼出或条件后,与条件是类似的。
与条件的语义可以直接映射到布尔代数的AND。与条件由两个子条件构成。与条件是组合条件。
核心概念 | 概念语义 | 原子/组合 | 形式化表达 |
告警 | 系统产生的某种告警,用告警名称唯一标识 | / | alarm(a) |
规则 | 规则的输入是告警列表、输出是规则应用结果,有3种情况:应用成功、应用失败、未应用。 | / | rule: alarms -> { succeeded | failed | unapplied } |
屏蔽告警规则 | 屏蔽某种告警的规则 | 原子规则 | mask(alarm(b)) |
生成告警规则 | 生成某种告警的规则 | 原子规则 | generate(alarm(g)) |
条件应用规则 | 对告警列表进行条件判断,如果满足条件就应用规则,输出规则应用结果;如果不满足条件,就不应用规则,输出规则未应用 | 组合规则 | whenThen(condition, rule) |
顺序应用规则 | 按照给定的顺序依次应用多条规则,如果某条规则应用失败或未应用,继续应用下一条规则,无论是否有规则应用失败或未应用,最终始终输出规则应用成功 | 组合规则 | seq(rules) |
条件 | 条件的输入是告警列表、输出是boolean,告警列表满足条件时输出true、否则输出false | / | condition: alarms -> { true | false } |
包含条件 | 告警列表是否包含某种告警 | 原子条件 | contains(alarm(a)) |
否条件 | 布尔代数的非 | 组合条件 | not(condition) |
或条件 | 布尔代数的或 | 组合条件 | or(condition1, condition2) |
组合条件 | and(condition1, condition2) |
有了语义模型及其形式化表达,可以用DSL实现语义模型的形式化表达,可以用DSL写出针对告警规则这个特定问题领域的规格说明(Specification)。在写规格说明的时候,其实就是在用这套DSL编程。
这里选择用Java语言以面向对象的方式实现设计。也可以用其他编程语言或其他方式,例如函数式编程实现设计。一般来说,通过构建语义模型驱动出的设计与编程语言、编程范式没有必然联系。
这里展示一些关键代码。
Alarm类
RuleResult类
Condition接口及其实现类
Rule接口及其实现类
END 11月24-25日,一场聚焦于AI大语言模型的年度盛会,“AI+软件研发行业数字峰会(AiDD峰会)”即将于深圳举办。助你在人工智能的浪潮中乘风破浪。 双11特惠 好基友同行,第二人半价
点这里↓↓↓记得关注标星哦~
人才培养的专属成长地图,数字化转型的方法 + 智库。" data-from="2" data-is_biz_ban="0" data-origin_num="104" data-isban="0" data-biz_account_status="0" data-index="0" data-filtered="filtered" style="color: initial;font: initial;font-palette: initial;font-synthesis: initial;forced-color-adjust: initial;text-orientation: initial;text-rendering: initial;-webkit-font-smoothing: initial;-webkit-locale: initial;-webkit-text-orientation: initial;-webkit-writing-mode: initial;writing-mode: initial;zoom: initial;accent-color: initial;place-content: initial;place-items: initial;place-self: initial;alignment-baseline: initial;animation: initial;app-region: initial;appearance: initial;aspect-ratio: initial;backdrop-filter: initial;backface-visibility: initial;baseline-shift: initial;block-size: initial;border-block: initial;border: initial;border-radius: initial;border-collapse: initial;border-end-end-radius: initial;border-end-start-radius: initial;border-inline: initial;border-start-end-radius: initial;border-start-start-radius: initial;inset: initial;box-shadow: initial;break-after: initial;break-before: initial;break-inside: initial;buffered-rendering: initial;caption-side: initial;caret-color: initial;clear: initial;clip: initial;clip-path: initial;clip-rule: initial;color-interpolation: initial;color-interpolation-filters: initial;color-rendering: initial;color-scheme: initial;gap: initial;contain: initial;contain-intrinsic-block-size: initial;contain-intrinsic-size: initial;contain-intrinsic-inline-size: initial;container: initial;content: initial;content-visibility: initial;counter-increment: initial;counter-reset: initial;counter-set: initial;cursor: initial;cx: initial;cy: initial;d: initial;display: initial;dominant-baseline: initial;empty-cells: initial;fill: initial;fill-opacity: initial;fill-rule: initial;filter: initial;flex: initial;flex-flow: initial;float: initial;flood-color: initial;flood-opacity: initial;grid: initial;grid-area: initial;height: initial;hyphenate-character: initial;hyphens: initial;image-orientation: initial;image-rendering: initial;inline-size: initial;inset-block: initial;inset-inline: initial;isolation: initial;letter-spacing: initial;lighting-color: initial;list-style: initial;margin-block: initial;margin-inline: initial;marker: initial;mask: initial;mask-type: initial;max-block-size: initial;max-height: initial;max-inline-size: initial;max-width: 100%;min-block-size: initial;min-height: initial;min-inline-size: initial;min-width: initial;mix-blend-mode: initial;object-fit: initial;object-position: initial;object-view-box: initial;offset: initial;opacity: initial;order: initial;orphans: initial;outline: 0px;outline-offset: initial;overflow-anchor: initial;overflow-clip-margin: initial;overflow: initial;overscroll-behavior-block: initial;overscroll-behavior-inline: initial;overscroll-behavior: initial;padding-block: initial;padding: 0px;padding-inline: initial;page: initial;page-orientation: initial;paint-order: initial;perspective: initial;perspective-origin: initial;pointer-events: auto;position: initial;quotes: initial;r: initial;resize: initial;rotate: initial;rx: initial;ry: initial;scale: initial;scroll-behavior: initial;scroll-margin-block: initial;scroll-margin: initial;scroll-margin-inline: initial;scroll-padding-block: initial;scroll-padding: initial;scroll-padding-inline: initial;scroll-snap-align: initial;scroll-snap-stop: initial;scroll-snap-type: initial;scrollbar-gutter: initial;shape-image-threshold: initial;shape-margin: initial;shape-outside: initial;shape-rendering: initial;speak: initial;stop-color: initial;stop-opacity: initial;stroke: initial;stroke-dasharray: initial;stroke-dashoffset: initial;stroke-linecap: initial;stroke-linejoin: initial;stroke-miterlimit: initial;stroke-opacity: initial;stroke-width: initial;table-layout: initial;text-align: initial;text-align-last: initial;text-anchor: initial;text-combine-upright: initial;text-emphasis: initial;text-emphasis-position: initial;text-indent: initial;text-overflow: initial;text-shadow: initial;text-size-adjust: inherit;text-underline-offset: initial;text-underline-position: initial;touch-action: initial;transform: initial;transform-box: initial;transform-origin: initial;transform-style: initial;transition: initial;translate: initial;user-select: initial;vector-effect: initial;vertical-align: initial;visibility: initial;border-spacing: initial;-webkit-box-align: initial;-webkit-box-decoration-break: initial;-webkit-box-direction: initial;-webkit-box-flex: initial;-webkit-box-ordinal-group: initial;-webkit-box-orient: initial;-webkit-box-pack: initial;-webkit-box-reflect: initial;-webkit-highlight: initial;-webkit-line-break: initial;-webkit-line-clamp: initial;-webkit-mask-box-image: initial;-webkit-mask: initial;-webkit-mask-composite: initial;-webkit-print-color-adjust: initial;-webkit-rtl-ordering: initial;-webkit-ruby-position: initial;-webkit-tap-highlight-color: initial;-webkit-text-combine: initial;-webkit-text-decorations-in-effect: initial;-webkit-text-fill-color: initial;-webkit-text-security: initial;-webkit-text-stroke: initial;-webkit-user-drag: initial;-webkit-user-modify: initial;white-space: initial;widows: initial;width: initial;will-change: initial;word-spacing: initial;x: initial;y: initial;z-index: initial;box-sizing: border-box !important;overflow-wrap: break-word !important">中智凯灵中智凯灵(KeyLink)是国内领先的专业数字人才发展平台,面向科技研发型企业和组织提供数字化人才培养的专属成长地图,数字化转型的方法 + 智库。104篇原创内容公众号