Files
freemo d9e5668cec fix(skills): comprehensive final audit pass for programming-patterns skill
Fixes and improvements from exhaustive audit:

Consistency fixes in SKILL.md:
- 'Pipe & Filter' → 'Pipe and Filter' (one stray '&' found and corrected)
- 'Singleton for factory instance' → clarified to 'register factory as
  singleton-scoped via DI container' (less misleading wording)
- Documentation Format section updated with note that SKILL.md itself is the
  authoritative source for related-pattern combinations

Coverage fix — Related Patterns sections:
- Added '## Related Patterns' to ALL 94 pattern files (was 0/94)
- Each section lists 3–6 related patterns with relationship descriptions
- Covers: why they're related, when to prefer one vs the other,
  and which are often confused

SOLID principles → Creational → Structural → Behavioral → Architectural →
Concurrency → Functional → Resilience → Data Access → Messaging →
Testing → Error Handling → Microservice — all 13 categories covered

Code verification:
- Python: 0 failures (all 85 testable blocks pass)
- Go: 0 failures (all 76 testable blocks pass)
- JavaScript: 0 failures (all 78 testable blocks pass)
- All 239 code blocks verified correct after edits

Final skill state:
- 108 files, 36,524 lines across 13 reference categories
- 94/94 pattern files have Related Patterns sections
- 2,815-line SKILL.md with 67 decision trees, 23 scenarios,
  0 broken references, 0 naming inconsistencies
2026-04-15 13:22:13 -04:00

11 KiB

Microkernel (Plugin) Architecture Pattern

Problem

An application needs to support many optional features, extensions, or variations, but embedding all of them into the core creates a monolith that is hard to maintain, test, and deploy. Adding new features requires modifying and redeploying the entire system. Different customers need different feature sets.

Solution

The Microkernel pattern splits the system into two components:

  • Core System — Minimal functionality that defines the application's identity. Contains the plugin registry, lifecycle management, and core abstractions.
  • Plugins — Independent modules that extend the core with additional features. Each plugin implements a known interface and is registered with the core at startup or runtime.

The core is stable and rarely changes. New features are added by writing new plugins, not by modifying the core.

When to Use

  • Product-based applications that need per-customer customization.
  • IDEs, editors, browsers, and other tool platforms.
  • Workflow engines where processing steps vary.
  • Applications with a stable core but frequently changing peripheral features.

When to Avoid

  • When the "core" would be trivially small and most logic lives in plugins.
  • High-performance systems where plugin dispatch overhead matters.
  • When the plugin interface is unstable and changes frequently.

Pseudocode

INTERFACE Plugin:
    METHOD name() -> string
    METHOD execute(context) -> result

CLASS Core:
    plugins = {}

    METHOD register(plugin: Plugin):
        plugins[plugin.name()] = plugin

    METHOD execute(plugin_name, context):
        plugin = plugins[plugin_name]
        RETURN plugin.execute(context)

    METHOD list_plugins():
        RETURN KEYS(plugins)

Python

from abc import ABC, abstractmethod


class Plugin(ABC):
    @abstractmethod
    def name(self) -> str: ...

    @abstractmethod
    def execute(self, data: str) -> str: ...


class UpperCasePlugin(Plugin):
    def name(self) -> str:
        return "uppercase"

    def execute(self, data: str) -> str:
        return data.upper()


class ReversePlugin(Plugin):
    def name(self) -> str:
        return "reverse"

    def execute(self, data: str) -> str:
        return data[::-1]


class WordCountPlugin(Plugin):
    def name(self) -> str:
        return "wordcount"

    def execute(self, data: str) -> str:
        count = len(data.split())
        return f"Word count: {count}"


class CaesarCipherPlugin(Plugin):
    def __init__(self, shift: int = 3) -> None:
        self._shift = shift

    def name(self) -> str:
        return "caesar"

    def execute(self, data: str) -> str:
        result = []
        for ch in data:
            if ch.isalpha():
                base = ord("A") if ch.isupper() else ord("a")
                result.append(chr((ord(ch) - base + self._shift) % 26 + base))
            else:
                result.append(ch)
        return "".join(result)


class TextProcessorCore:
    """Core system with plugin registry."""

    def __init__(self) -> None:
        self._plugins: dict[str, Plugin] = {}

    def register(self, plugin: Plugin) -> None:
        self._plugins[plugin.name()] = plugin
        print(f"  [Core] Registered plugin: '{plugin.name()}'")

    def unregister(self, name: str) -> None:
        if name in self._plugins:
            del self._plugins[name]
            print(f"  [Core] Unregistered plugin: '{name}'")

    def list_plugins(self) -> list[str]:
        return list(self._plugins.keys())

    def execute(self, plugin_name: str, data: str) -> str:
        plugin = self._plugins.get(plugin_name)
        if not plugin:
            return f"  [Core] ERROR: Plugin '{plugin_name}' not found"
        result = plugin.execute(data)
        return result

    def execute_pipeline(self, plugin_names: list[str], data: str) -> str:
        """Run multiple plugins in sequence."""
        result = data
        for name in plugin_names:
            result = self.execute(name, result)
        return result


def main() -> None:
    core = TextProcessorCore()

    print("--- Register plugins ---")
    core.register(UpperCasePlugin())
    core.register(ReversePlugin())
    core.register(WordCountPlugin())
    core.register(CaesarCipherPlugin(3))

    print(f"\n--- Available plugins: {core.list_plugins()} ---")

    text = "Hello World from Microkernel"

    print(f"\n--- Execute individual plugins on: '{text}' ---")
    for name in core.list_plugins():
        result = core.execute(name, text)
        print(f"  {name}: {result}")

    print(f"\n--- Pipeline: uppercase -> reverse ---")
    result = core.execute_pipeline(["uppercase", "reverse"], text)
    print(f"  Result: {result}")

    print(f"\n--- Pipeline: caesar -> uppercase ---")
    result = core.execute_pipeline(["caesar", "uppercase"], text)
    print(f"  Result: {result}")

    print("\n--- Unregister 'reverse', try executing ---")
    core.unregister("reverse")
    print(core.execute("reverse", text))
    print(f"  Available: {core.list_plugins()}")


if __name__ == "__main__":
    main()

Output:

--- Register plugins ---
  [Core] Registered plugin: 'uppercase'
  [Core] Registered plugin: 'reverse'
  [Core] Registered plugin: 'wordcount'
  [Core] Registered plugin: 'caesar'

--- Available plugins: ['uppercase', 'reverse', 'wordcount', 'caesar'] ---

--- Execute individual plugins on: 'Hello World from Microkernel' ---
  uppercase: HELLO WORLD FROM MICROKERNEL
  reverse: lenrekorciM morf dlroW olleH
  wordcount: Word count: 4
  caesar: Khoor Zruog iurp Plfurnhuqho

--- Pipeline: uppercase -> reverse ---
  Result: LENREKORCIM MORF DLROW OLLEH

--- Pipeline: caesar -> uppercase ---
  Result: KHOOR ZRUOG IURP PLFURNHUQHO

--- Unregister 'reverse', try executing ---
  [Core] Unregistered plugin: 'reverse'
  [Core] ERROR: Plugin 'reverse' not found
  Available: ['uppercase', 'wordcount', 'caesar']

Go

package main

import (
	"fmt"
	"strings"
)

// --- Plugin interface ---

type Plugin interface {
	Name() string
	Execute(data string) string
}

// --- Plugins ---

type UpperCasePlugin struct{}

func (p *UpperCasePlugin) Name() string            { return "uppercase" }
func (p *UpperCasePlugin) Execute(data string) string { return strings.ToUpper(data) }

type ReversePlugin struct{}

func (p *ReversePlugin) Name() string { return "reverse" }
func (p *ReversePlugin) Execute(data string) string {
	runes := []rune(data)
	for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
		runes[i], runes[j] = runes[j], runes[i]
	}
	return string(runes)
}

type WordCountPlugin struct{}

func (p *WordCountPlugin) Name() string { return "wordcount" }
func (p *WordCountPlugin) Execute(data string) string {
	count := len(strings.Fields(data))
	return fmt.Sprintf("Word count: %d", count)
}

type CaesarCipherPlugin struct {
	Shift int
}

func (p *CaesarCipherPlugin) Name() string { return "caesar" }
func (p *CaesarCipherPlugin) Execute(data string) string {
	result := make([]rune, len([]rune(data)))
	for i, ch := range data {
		if ch >= 'A' && ch <= 'Z' {
			result[i] = rune((int(ch-'A')+p.Shift)%26) + 'A'
		} else if ch >= 'a' && ch <= 'z' {
			result[i] = rune((int(ch-'a')+p.Shift)%26) + 'a'
		} else {
			result[i] = ch
		}
	}
	return string(result)
}

// --- Core ---

type TextProcessorCore struct {
	plugins map[string]Plugin
	order   []string
}

func NewTextProcessorCore() *TextProcessorCore {
	return &TextProcessorCore{plugins: make(map[string]Plugin)}
}

func (c *TextProcessorCore) Register(p Plugin) {
	c.plugins[p.Name()] = p
	c.order = append(c.order, p.Name())
	fmt.Printf("  [Core] Registered plugin: '%s'\n", p.Name())
}

func (c *TextProcessorCore) Unregister(name string) {
	if _, ok := c.plugins[name]; ok {
		delete(c.plugins, name)
		var newOrder []string
		for _, n := range c.order {
			if n != name {
				newOrder = append(newOrder, n)
			}
		}
		c.order = newOrder
		fmt.Printf("  [Core] Unregistered plugin: '%s'\n", name)
	}
}

func (c *TextProcessorCore) ListPlugins() []string {
	return c.order
}

func (c *TextProcessorCore) Execute(name, data string) string {
	p, ok := c.plugins[name]
	if !ok {
		return fmt.Sprintf("  [Core] ERROR: Plugin '%s' not found", name)
	}
	return p.Execute(data)
}

func (c *TextProcessorCore) ExecutePipeline(names []string, data string) string {
	result := data
	for _, name := range names {
		result = c.Execute(name, result)
	}
	return result
}

func main() {
	core := NewTextProcessorCore()

	fmt.Println("--- Register plugins ---")
	core.Register(&UpperCasePlugin{})
	core.Register(&ReversePlugin{})
	core.Register(&WordCountPlugin{})
	core.Register(&CaesarCipherPlugin{Shift: 3})

	fmt.Printf("\n--- Available plugins: %v ---\n", core.ListPlugins())

	text := "Hello World from Microkernel"

	fmt.Printf("\n--- Execute individual plugins on: '%s' ---\n", text)
	for _, name := range core.ListPlugins() {
		result := core.Execute(name, text)
		fmt.Printf("  %s: %s\n", name, result)
	}

	fmt.Println("\n--- Pipeline: uppercase -> reverse ---")
	result := core.ExecutePipeline([]string{"uppercase", "reverse"}, text)
	fmt.Printf("  Result: %s\n", result)

	fmt.Println("\n--- Pipeline: caesar -> uppercase ---")
	result = core.ExecutePipeline([]string{"caesar", "uppercase"}, text)
	fmt.Printf("  Result: %s\n", result)

	fmt.Println("\n--- Unregister 'reverse', try executing ---")
	core.Unregister("reverse")
	fmt.Println(core.Execute("reverse", text))
	fmt.Printf("  Available: %v\n", core.ListPlugins())
}

Output:

--- Register plugins ---
  [Core] Registered plugin: 'uppercase'
  [Core] Registered plugin: 'reverse'
  [Core] Registered plugin: 'wordcount'
  [Core] Registered plugin: 'caesar'

--- Available plugins: [uppercase reverse wordcount caesar] ---

--- Execute individual plugins on: 'Hello World from Microkernel' ---
  uppercase: HELLO WORLD FROM MICROKERNEL
  reverse: lenrekorciM morf dlroW olleH
  wordcount: Word count: 4
  caesar: Khoor Zruog iurp Plfurnhuqho

--- Pipeline: uppercase -> reverse ---
  Result: LENREKORCIM MORF DLROW OLLEH

--- Pipeline: caesar -> uppercase ---
  Result: KHOOR ZRUOG IURP PLFURNHUQHO

--- Unregister 'reverse', try executing ---
  [Core] Unregistered plugin: 'reverse'
  [Core] ERROR: Plugin 'reverse' not found
  Available: [uppercase wordcount caesar]
  • Strategy — each plugin is a strategy; the core selects and executes the appropriate strategy for each operation.
  • Factory — a plugin factory or registry creates and manages plugin instances.
  • Observer — the core can notify plugins of lifecycle events via the observer pattern.
  • Pipe and Filter — microkernel is about pluggable features; pipe and filter is about sequential data transformation steps.