configuration/principle/data/pattern.behavioral.data.json
configuration/principle/data/pattern.behavioral.data.json is a file in GovLab Context. 437 lines of code and 0 definitions.
{
"category": "Behavioral Patterns",
"check": {
"population": "every module whose behavior varies by mode, state, request kind or traversal",
"freshness": "a verdict stands until the module's branching or its state model changes",
"refusal": "the review or the complexity threshold rejects the change that reintroduces the branching the pattern removes",
"observation": "conditional complexity and dispatch counts read from source, and the recorded design review",
"evidence": "none: the catalog states this check as a class, so a watched run belongs to each system that adopts it",
"authority": "the pattern's dispatch structure, which a change to the module's branching is compared against"
},
"records": [
{
"id": "strategy-pattern",
"distinctFrom": [
{
"id": "architecture:decorator-pattern",
"reason": "A strategy replaces behavior behind one interface, while a decorator adds behavior by wrapping an object in the same interface."
}
],
"name": "Strategy Pattern",
"aliases": ["Policy Pattern"],
"definition": "A design pattern that puts each interchangeable algorithm behind one interface, so the caller selects behavior by passing an object.",
"type": "pattern",
"scope": [
"algorithm",
"policy",
"behavior"
],
"requires": ["Interchangeable Algorithms"],
"reinforces": [
"OCP",
"Polymorphism"
],
"enables": ["Runtime Behavior Selection"],
"conflicts_with": ["Large Conditional Logic"],
"tensions_with": ["Class Count"],
"violated_by": ["lexicon:large-conditional-logic"],
"detected_by": ["conditional strategy selection with duplicated behavior"],
"measured_by": ["conditional complexity"],
"refactored_by": [],
"enforced_by": [
"complexity thresholds",
"review"
],
"severity": "recommended",
"exemplar": {
"before": "function priceFoo(kind: string, value: number) {\n if (kind === \"standard\") return value;\n if (kind === \"double\") return value * 2;\n return 0;\n}",
"after": "interface FooPricing { price(value: number): number; }\nconst standard: FooPricing = { price: value => value };\nconst doubled: FooPricing = { price: value => value * 2 };\nfunction priceFoo(strategy: FooPricing, value: number) { return strategy.price(value); }",
"lang": "ts"
}
},
{
"id": "template-method-pattern",
"name": "Template Method Pattern",
"definition": "A design pattern that fixes the steps of an algorithm in a base class and lets subclasses supply the steps that vary.",
"type": "pattern",
"scope": [
"workflow",
"framework"
],
"requires": ["Stable Algorithm Skeleton"],
"reinforces": ["Framework Reuse"],
"enables": ["Controlled Variation"],
"conflicts_with": ["Duplicated Workflow"],
"tensions_with": ["Inheritance Coupling"],
"violated_by": ["lexicon:duplicated-workflow"],
"detected_by": ["duplicated method sequences"],
"measured_by": ["workflow duplication"],
"refactored_by": [],
"enforced_by": ["design review"],
"severity": "contextual",
"exemplar": {
"before": "function importJsonFoo(raw: string) { validateJson(raw); return saveFoo(parseJson(raw)); }\nfunction importCsvFoo(raw: string) { validateCsv(raw); return saveFoo(parseCsv(raw)); }",
"after": "abstract class FooImporter {\n import(raw: string) { this.validate(raw); return saveFoo(this.parse(raw)); }\n protected abstract validate(raw: string): void;\n protected abstract parse(raw: string): Foo;\n}",
"lang": "ts"
}
},
{
"id": "observer-pattern",
"name": "Observer Pattern",
"definition": "A design pattern in which a subject publishes events to subscribers it does not know by name.",
"type": "pattern",
"scope": [
"event notification",
"runtime"
],
"requires": ["Subject/Subscriber Contract"],
"reinforces": ["Event-Driven Architecture"],
"enables": ["Decoupled Notification"],
"conflicts_with": ["Direct Callback Coupling"],
"tensions_with": [
"Ordering",
"Debuggability"
],
"violated_by": ["lexicon:direct-callback-coupling"],
"detected_by": ["direct calls to multiple listeners"],
"measured_by": ["subscriber coupling count"],
"refactored_by": [],
"enforced_by": ["event contract tests"],
"severity": "recommended",
"exemplar": {
"before": "class FooEditor {\n save(foo: Foo) {\n fooStore.save(foo);\n refreshFooView(foo);\n sendFooEmail(foo);\n }\n}",
"after": "class FooEvents {\n #listeners = new Set<(event: FooEvent) => void>();\n subscribe(listener: (event: FooEvent) => void) { this.#listeners.add(listener); }\n publish(event: FooEvent) { this.#listeners.forEach(listener => listener(event)); }\n}\nclass FooEditor {\n constructor(private readonly events: FooEvents) {}\n save(foo: Foo) {\n fooStore.save(foo);\n this.events.publish({ type: \"FooSaved\", foo });\n }\n}\nfooEvents.subscribe(event => refreshFooView(event.foo));\nfooEvents.subscribe(event => sendFooEmail(event.foo));",
"lang": "ts"
}
},
{
"id": "mediator-pattern",
"name": "Mediator Pattern",
"definition": "A design pattern that routes the interactions between a set of objects through one coordinating object.",
"type": "pattern",
"scope": [
"object coordination",
"module"
],
"requires": ["Coordination Complexity"],
"reinforces": ["Low Coupling"],
"enables": ["Centralized Interaction Logic"],
"conflicts_with": ["Mesh Dependencies"],
"tensions_with": ["Mediator God Object"],
"violated_by": ["lexicon:mesh-dependencies"],
"detected_by": ["dense object dependency graph"],
"measured_by": ["interaction graph density"],
"refactored_by": [],
"enforced_by": ["dependency graph checks"],
"severity": "contextual",
"exemplar": {
"before": "fooEditor.notify(fooList, fooDetails, fooToolbar, foo);\nfooList.update(fooDetails, fooToolbar, foo);",
"after": "class FooMediator {\n constructor(private readonly list: FooList, private readonly details: FooDetails) {}\n handle(event: FooEvent) {\n this.list.apply(event);\n this.details.apply(event);\n }\n}",
"lang": "ts"
}
},
{
"id": "command-pattern",
"name": "Command Pattern",
"aliases": ["Action Pattern"],
"definition": "A design pattern that wraps a request in an object, so it can be queued, deferred or undone.",
"type": "pattern",
"scope": [
"behavior",
"invocation",
"workflow"
],
"requires": ["Encapsulation"],
"reinforces": [
"OCP",
"Single Responsibility Principle (SRP)"
],
"enables": [
"Undo/Redo",
"Deferred Execution",
"Request Queuing"
],
"conflicts_with": ["Direct Method Invocation"],
"tensions_with": ["Simplicity"],
"violated_by": ["lexicon:direct-method-invocation"],
"detected_by": ["switch/if chains selecting an operation to run"],
"measured_by": ["dispatch-branch count per action site"],
"refactored_by": [],
"enforced_by": ["design review"],
"severity": "recommended",
"exemplar": {
"before": "button.onClick = () => fooEditor.delete(foo.id);",
"after": "interface FooCommand { execute(): void; undo(): void; }\nclass DeleteFooCommand implements FooCommand {\n constructor(private readonly id: FooId) {}\n execute() { fooStore.delete(this.id); }\n undo() { fooStore.restore(this.id); }\n}\nhistory.run(new DeleteFooCommand(foo.id));",
"lang": "ts"
}
},
{
"id": "state-pattern",
"name": "State Pattern",
"definition": "A design pattern that gives each state of an object its own class, so behavior and legal transitions change with the state.",
"type": "pattern",
"scope": [
"behavior",
"state machine",
"lifecycle"
],
"requires": ["Explicit State Model"],
"reinforces": [
"OCP",
"Polymorphism"
],
"enables": [
"State-Local Behavior",
"Legal-Transition Enforcement"
],
"conflicts_with": ["Boolean Flag Soup"],
"tensions_with": ["Class Proliferation"],
"violated_by": ["lexicon:boolean-flag-soup"],
"detected_by": ["repeated conditionals on a status field"],
"measured_by": ["status-conditional density"],
"refactored_by": [],
"enforced_by": ["design review"],
"severity": "recommended",
"exemplar": {
"before": "function handleFoo(foo: Foo, event: string) {\n if (foo.status === \"draft\" && event === \"submit\") foo.status = \"review\";\n if (foo.status === \"review\" && event === \"approve\") foo.status = \"published\";\n}",
"after": "interface FooState { submit(): FooState; approve(): FooState; }\nconst published: FooState = { submit: () => published, approve: () => published };\nconst review: FooState = { submit: () => review, approve: () => published };\nconst draft: FooState = { submit: () => review, approve: () => draft };\nclass Foo {\n constructor(private state: FooState = draft) {}\n submit() { this.state = this.state.submit(); }\n approve() { this.state = this.state.approve(); }\n}",
"lang": "ts"
}
},
{
"id": "chain-of-responsibility-pattern",
"name": "Chain of Responsibility Pattern",
"definition": "A design pattern that passes a request along an ordered list of handlers until one of them handles it.",
"type": "pattern",
"scope": [
"behavior",
"request handling",
"pipeline"
],
"requires": ["Uniform Handler Interface"],
"reinforces": [
"OCP",
"Single Responsibility Principle (SRP)"
],
"enables": [
"Pluggable Handling",
"Ordered Fallthrough"
],
"conflicts_with": ["Monolithic Handler"],
"tensions_with": ["Traceability"],
"violated_by": ["lexicon:monolithic-handler"],
"detected_by": ["long if/else ladders handling heterogeneous requests"],
"measured_by": ["handler cyclomatic complexity"],
"refactored_by": [],
"enforced_by": ["design review"],
"severity": "recommended",
"exemplar": {
"before": "function handleFoo(request: FooRequest) {\n if (request.size > MAX_SIZE) return reject(request);\n if (!request.authorized) return deny(request);\n return process(request);\n}",
"after": "type FooHandler = (request: FooRequest, next: () => FooResult) => FooResult;\nconst enforceSize: FooHandler = (request, next) => request.size > MAX_SIZE ? reject(request) : next();\nconst enforceAuth: FooHandler = (request, next) => request.authorized ? next() : deny(request);\nconst chain = composeHandlers([enforceSize, enforceAuth, () => process(request)]);\nchain(request);",
"lang": "ts"
}
},
{
"id": "iterator-pattern",
"name": "Iterator Pattern",
"aliases": ["Cursor"],
"definition": "A design pattern that lets callers traverse a collection without seeing how it is stored.",
"type": "pattern",
"scope": [
"behavior",
"traversal",
"collection"
],
"requires": ["Uniform Traversal Interface"],
"reinforces": [
"Encapsulation",
"Single Responsibility Principle (SRP)"
],
"enables": [
"Structure-Agnostic Iteration",
"Lazy Traversal"
],
"conflicts_with": ["Exposed Internal Representation"],
"tensions_with": ["Simplicity"],
"violated_by": ["lexicon:exposed-internal-representation"],
"detected_by": ["index/pointer traversal of another type's internals"],
"measured_by": ["internal-structure access count"],
"refactored_by": [],
"enforced_by": ["design review"],
"severity": "contextual",
"exemplar": {
"before": "for (let i = 0; i < fooTree.nodes.length; i += 1) visit(fooTree.nodes[i]);",
"after": "class FooTree {\n #roots: FooNode[] = [];\n *[Symbol.iterator](): Iterator<Foo> {\n for (const node of this.#roots) yield* this.walk(node);\n }\n}\nfor (const foo of fooTree) visit(foo);",
"lang": "ts"
}
},
{
"id": "visitor-pattern",
"name": "Visitor Pattern",
"definition": "A design pattern that places each operation over a type hierarchy in its own visitor, so an operation is added without editing the element types.",
"type": "pattern",
"scope": [
"behavior",
"operation",
"type hierarchy"
],
"requires": ["Stable Element Hierarchy"],
"reinforces": [
"OCP",
"Separation of Concerns"
],
"enables": ["Operation Extension Without Element Change"],
"conflicts_with": ["Type Switching"],
"tensions_with": ["Element Stability"],
"violated_by": ["lexicon:type-switching"],
"detected_by": ["type-tag switches repeated per operation"],
"measured_by": ["type-switch duplication across operations"],
"refactored_by": [],
"enforced_by": ["design review"],
"severity": "contextual",
"exemplar": {
"before": "function renderFoo(node: FooNode) {\n if (node.kind === \"text\") return node.value;\n if (node.kind === \"group\") return node.children.map(renderFoo).join(\"\");\n}",
"after": "interface FooVisitor<T> { text(node: TextNode): T; group(node: GroupNode): T; }\nclass RenderFooVisitor implements FooVisitor<string> {\n text(node: TextNode) { return node.value; }\n group(node: GroupNode) { return node.children.map(child => child.accept(this)).join(\"\"); }\n}",
"lang": "ts"
}
},
{
"id": "memento-pattern",
"name": "Memento Pattern",
"definition": "A design pattern in which an object captures its own state in an opaque snapshot it can later restore.",
"type": "pattern",
"scope": [
"behavior",
"state capture",
"history"
],
"requires": ["Encapsulation"],
"reinforces": ["Information Hiding"],
"enables": [
"Undo/Redo",
"Snapshot/Restore"
],
"conflicts_with": ["External State Reach-In"],
"tensions_with": ["Memory Footprint"],
"violated_by": ["lexicon:external-state-reach-in"],
"detected_by": ["external code reconstructing internal state"],
"measured_by": ["private-field external access count"],
"refactored_by": [],
"enforced_by": ["design review"],
"severity": "contextual",
"exemplar": {
"before": "const backupName = foo.name;\nconst backupTags = [...foo.tags];\nfoo.rename(newName);\nif (canceled) { foo.name = backupName; foo.tags = backupTags; }",
"after": "class FooMemento { constructor(readonly snapshot: Readonly<Foo>) {} }\nconst memento = foo.save();\nfoo.rename(newName);\nif (canceled) foo.restore(memento);",
"lang": "ts"
}
},
{
"id": "null-object-pattern",
"name": "Null Object Pattern",
"aliases": ["Null Object"],
"definition": "A design pattern that represents absence with an object implementing the expected interface as a no-op.",
"type": "pattern",
"scope": [
"behavior",
"absence",
"default"
],
"requires": ["Shared Behavioral Interface"],
"reinforces": [
"Polymorphism",
"Fail-Safe Defaults"
],
"enables": ["Null-Check Elimination"],
"conflicts_with": ["Null Semantics Drift"],
"tensions_with": ["Silent No-Op Risk"],
"violated_by": ["lexicon:scattered-null-guards"],
"detected_by": ["repeated null checks before the same operation"],
"measured_by": ["null-guard density"],
"refactored_by": [],
"enforced_by": ["design review"],
"severity": "contextual",
"exemplar": {
"before": "const logger = config.logger;\nif (logger) logger.info(\"foo saved\");",
"after": "interface FooLogger { info(message: string): void; }\nconst NoopFooLogger: FooLogger = { info() {} };\nconst logger = config.logger ?? NoopFooLogger;\nlogger.info(\"foo saved\");",
"lang": "ts"
}
},
{
"id": "finite-state-machine",
"name": "Finite State Machine",
"aliases": [
"FSM",
"State Machine"
],
"definition": "A conceptual representation of behavior as a closed set of states and the events that move between them.",
"type": "model",
"scope": [
"behavior",
"state modeling",
"control flow"
],
"requires": ["Explicit State Set"],
"reinforces": [
"State Pattern",
"Correctness"
],
"enables": [
"Legal-Transition Enforcement",
"Exhaustive State Reasoning"
],
"conflicts_with": ["Boolean Flag Soup"],
"tensions_with": ["State Explosion"],
"violated_by": ["lexicon:boolean-flag-soup"],
"detected_by": ["impossible or contradictory state combinations reachable at runtime"],
"measured_by": ["count of representable-but-illegal states"],
"refactored_by": [],
"enforced_by": ["state model review"],
"severity": "recommended",
"exemplar": {
"before": "let isOpen = false, isLoading = false, isError = false;\nfunction onClick() { isLoading = true; if (isOpen) isOpen = false; }",
"after": "type FooState = \"closed\" | \"loading\" | \"open\" | \"error\";\nconst transitions: Record<FooState, Partial<Record<FooEvent, FooState>>> = {\n closed: { open: \"loading\" },\n loading: { ready: \"open\", fail: \"error\" },\n open: { close: \"closed\" },\n error: { retry: \"loading\" },\n};\nfunction next(state: FooState, event: FooEvent): FooState { return transitions[state][event] ?? state; }",
"lang": "ts"
}
},
{
"id": "statecharts",
"distinctFrom": [
{
"id": "architecture:finite-state-machine",
"reason": "A finite state machine is flat states and events, while statecharts add nested states and parallel regions to it."
}
],
"name": "Statecharts",
"definition": "A conceptual representation of a state machine extended with nested states and parallel regions.",
"type": "model",
"scope": [
"behavior",
"state modeling",
"hierarchy"
],
"requires": ["Finite State Machine"],
"reinforces": [
"Finite State Machine",
"Separation of Concerns"
],
"enables": [
"Hierarchical States",
"Parallel Regions",
"Guarded Transitions"
],
"conflicts_with": ["Flat State Explosion"],
"tensions_with": ["Tooling Complexity"],
"violated_by": ["lexicon:flat-state-explosion"],
"detected_by": ["combinatorial state growth from independent concerns modeled in one flat machine"],
"measured_by": ["transition duplication across sibling states"],
"refactored_by": [],
"enforced_by": ["state model review"],
"severity": "contextual",
"exemplar": {
"before": "type S = \"idleMuted\" | \"idleLoud\" | \"playingMuted\" | \"playingLoud\";",
"after": "const fooChart = {\n initial: \"idle\",\n states: { idle: {}, playing: {} },\n parallel: { volume: { states: { muted: {}, loud: {} } } },\n};",
"lang": "ts"
}
}
]
}