<!-- META http-equiv="refresh" content="5;URL=http://somewhere.com" -->

<title>Template Page Title</title>

<!--<script   src="https://code.jquery.com/jquery-3.3.1.min.js"></script> -->
<!--link rel='stylesheet' type='text/css' href='css/main.css' /-->

<style type='text/css'><!--

	body {
		color:#4B92D1;
		font-family:sans-serif;
	}
	
--></style>
# /polyArch v2 - Self-Configuring Polymorphic Architecture

## Core Rules Summary (TL;DR for LLMs)

- **Module Locality is Key:** Everything for a module goes in the module.
- **Inject Shared Resources:** DB connections, etc., must be passed in.
- **Use Frozen `process.global` for Universals:** Only for `xLog`, `getConfig`, etc.
- **Use the Registry Pattern:** No `switch` statements in factories.
- **Formal Interfaces are Required:** Use TypeScript `interface` or JSDoc `@interface`.

---

## Overview

The Self-Configuring Polymorphic Architecture pattern (v2) creates robust, enterprise-grade applications by composing self-configuring components that present formal, uniform interfaces. This version refines the original pattern with clearer guidelines for dependency management, scalability, and safety.

## Fundamental Principle: Complete Module Locality

**To the maximum extent possible, all information, code, config, and resources needed to understand, debug, and extend a module should be present in that module.**

This remains the cornerstone of the architecture. Its goal is to enable a developer to open a single file and gain a complete understanding of that module's behavior and dependencies.

## Naming Principle: Descriptive and Searchable

**Never use common words (value, data, library, etc.) for names except for minimal local variables used within a few lines.**

This principle is critical for maintaining clarity in a system composed of many small modules. Names must be **descriptive**, **uniquely searchable**, and **specific**.

## Core Principles

### 1. Self-Configuration via a Global Context (The Exception)

While global state is generally an anti-pattern, a pragmatic exception can be made for a small, immutable set of truly universal utilities. Functions for **logging** and **configuration access** are candidates for this approach.

By placing these on `process.global`, they become available throughout the codebase without the need for repetitive dependency injection.

**Crucial Safety Guideline:** If using this pattern, the global object must be frozen at application startup to prevent accidental modification.

```javascript
// main.js - At startup
const { xLog, getConfig, commandLineParameters } = require('./lib/setup-env');

// Define the global context
process.global = { xLog, getConfig, commandLineParameters };

// Freeze it to prevent any modification
Object.freeze(process.global);

// Now any module can safely use it
const { xLog, getConfig } = process.global;
```

### 2. Self-Containment and Injected Shared Resources

Modules should instantiate their own stateless dependencies locally. However, any dependency that is stateful, expensive, or manages a shared resource pool **must be injected** by the orchestrator. This is the key distinction between a *shared resource* (like a DB connection) and a *global utility* (like a logger).

### 3. Formal, Polymorphic Interfaces

Components with varying implementations must adhere to a **formally defined interface**. This provides a strong contract for developers and allows the orchestrator to use components interchangeably.

In TypeScript, this should be enforced with `interface`:

```typescript
// /interfaces/DataExtractor.ts
export interface DataExtractor {
    extract(source: string): Array;
    getSourceType(): string;
    describe(): string;
}
```

In JavaScript, use JSDoc for static analysis. This provides type-checking hints to editors and documents the expected contract.

```javascript
/**
 * @interface DataExtractor
 * @property {function(string): Array} extract - Extracts data from a source string.
 * @property {function(): string} getSourceType - Returns the type of the source (e.g., 'json', 'csv').
 * @property {function(): string} describe - Provides a human-readable description of the extractor.
 */
```

### 4. Extensible Factories via The Registry Pattern

To avoid violating the Open/Closed Principle, use a **Registry Pattern** instead of a `switch` statement to select a component's implementation. This allows new implementations to be added without modifying the factory logic.

A typical directory structure for this pattern would be:

```
/fact-extractor
├── index.js         # The factory/registry
└── /extractors
    ├── json-extractor.js
    └── csv-extractor.js
```

The factory (`index.js`) dynamically selects the correct implementation:

```javascript
// /fact-extractor/index.js - The Factory using a Registry
const implementations = {
    json: require('./extractors/json-extractor'),
    csv: require('./extractors/csv-extractor')
    // To extend, add a new file and a new line here. No logic change needed.
};

const moduleFunction = (injectedDependencies) => {
    const { getConfig } = process.global;
    const localConfig = getConfig('fact-extractor');
    const extractionMode = localConfig.defaultExtractionMode;

    if (!implementations[extractionMode]) {
        throw new Error(`Unknown extraction mode: ${extractionMode}`);
    }

    // Return the configured implementation, passing through any injected resources
    return implementations[extractionMode](injectedDependencies);
};

module.exports = moduleFunction;
```

## Architectural Guideline: Resource Management

A dependency **must be externalized and injected** if it manages:

- A **persistent connection** (e.g., databases, message queues)
- A **limited resource pool** (e.g., file handles, sockets)
- **System-wide singleton state** (e.g., a metrics registry)

### Example: Database Connection vs. Logger

- **Logger**: Universal, stateless calls. A candidate for the frozen `process.global` context for convenience.
- **Database Handle**: Manages a limited pool of stateful connections. Must be created once by the orchestrator and **injected** into the modules that need it.

```javascript
// ✅ CORRECT: The orchestrator manages the shared resource.
// main.js
const db = require('better-sqlite3')(process.env.DB_PATH); // Create once
const reporter = require('./reporter')({ db }); // Inject resource

// reporter.js
const moduleFunction = ({ db }) => { // Receive shared DB handle
    const { getConfig, xLog } = process.global; // Use global utilities
    const localConfig = getConfig('reporter');

    const generateReport = (params) => {
        xLog.info(`Generating report with query: ${localConfig.query}`);
        const data = db.prepare(localConfig.query).all();
        // ...
    };
    return { generateReport };
};
```

## Anti-Patterns to Avoid

- **❌ Putting Business Logic or Mutable State on `process.global`**: The global context is *exclusively* for a small number of frozen, universal utilities. All other dependencies must be instantiated locally or injected.
- **❌ Using a `switch` statement factory**: This violates the Open/Closed principle. Use the Registry Pattern.
- **❌ Modules creating their own expensive/stateful resources**: This leads to resource exhaustion and is a major scalability anti-pattern. Inject these resources instead.
- **❌ Passing configuration blobs**: Modules should fetch their own configuration using the global `getConfig` utility.

## Summary

The Self-Configuring Polymorphic Architecture (v2) provides a robust framework for building clean, maintainable, and scalable applications by enforcing:

1. **Complete Module Locality**: Everything needed to understand a module is in one place.
2. **A Frozen Global Context**: A pragmatic exception for universal, immutable utilities like logging and configuration access.
3. **Strict Injection of Shared Resources**: Stateful or expensive dependencies are managed by the orchestrator and explicitly injected.
4. **Formal Polymorphic Interfaces**: Enforced contracts prevent architectural drift.
5. **Extensible Factories**: The Registry Pattern allows for safe and easy extension.

The key insight is refined: **A developer should be able to open a single file and understand everything about how that module works, knowing that its only hidden dependencies are a small, predictable set of frozen global utilities.**