Dynamic Object Handler

Doh.js is a JavaScript application ecosystem built on multiple inheritance.

The industry has proven that multiple inheritance is terrible and hard.

But what if...

...it didn't have to be?

Scroll...

The Diamond Problem

The classic example that revealed why multiple inheritance is genuinely hard.

Animal
↙ ↘
Bird Horse
↘ ↙
Pegasus

The Real Problem

move() → "flying"
move() → "galloping"

// Which one gets inherted?
pegasus.move() → ???

Just running both methods isn't enough. What's the return value? The execution order? How do they share state?

Why "Just Combine Them" Fails

Ordering

Should validation run before or after logging? Base before derived? Context matters.

Return Values

One method returns altitude, another returns speed. Do you pick one? Average them? Create a tuple?

Hooking

Need setup before methods run? Cleanup after? Simple stacking can't handle lifecycle hooks.

Language Chaos

Every language invented different rules. C++ uses virtual inheritance. Python has MRO linearization. Scala has trait linearization.

The complexity exploded. Developers couldn't predict behavior. Debugging became a nightmare.

The Great Retreat

Java banned it. C# followed. JavaScript never had it. Go rejected it from the start.

The mantra became universal: "Composition over inheritance."

The diamond problem has two core challenges:

1. Inheritance Order

Which parent comes first? How do you traverse complex hierarchies predictably?

2. Conflict Resolution

When multiple parents define the same property, which wins? How do you combine them?

Methods make this exponentially harder—functions can't just "merge" like objects or arrays can.

Composition Through Inheritance

We didn't abandon multiple inheritance. We gave it explicit composition rules.

Solution 1: Resolution Order Algorithm

Transform any inheritance graph into a predictable ordered list.

Diamond Graph

Animal
↙ ↘
Bird Horse
↘ ↙
Pegasus

Ordered List

1. Animal
2. Bird
3. Horse
4. Pegasus

Four phases make this more powerful than this simple example shows: source identification, recursive expansion, deterministic flattening, and conditional evaluation. But the gist is: flatten the graph.

Solution 2: Melded Object Composition (MOC)

MOC is our type AND merge system in one—when multiple patterns define the same property, explicit rules determine how they combine.

Pattern('Animal', {
    moc: { 
        config: 'object', 
        classes: 'array' , 
        move: 'method'
    },
    config: { habitat: 'land' }, 
    classes: ['animal']
    move() { console.log('Animal is moving'); },
});

Pattern('Bird', 'Animal', {
    name: 'Bird', // Simple override (no moc rule needed)
    config: { wings: 2 }, 
    classes: ['flying']
    move() { console.log('Flying at 1000ft'); },
});

Pattern('Horse', 'Animal', {
    name: 'Horse', 
    config: { legs: 4 }, 
    classes: ['galloping']
    move() { console.log('Galloping at 40mph'); },
});

Pattern('Pegasus', ['Bird', 'Horse'], { name: 'Pegasus' });

Results:

  • String overrides: name: 'Pegasus'
  • Objects merge: config: {habitat:'land', wings:2, legs:4}
  • Arrays combine: classes: ['animal','flying','galloping']
  • Methods collaborate:
Animal is moving
Flying at 1000ft
Galloping at 40mph

This shows simple method stacking, but doesn't address ordering control, return value blending, or hooking (pre_move, post_move) that melded methods provide.

The Method Strategy Matrix

Method stacking is just the beginning. Real composition needs control over ordering, return handling, and lifecycle hooks.

Each combination of data flow + execution order + async support creates a specialized method composition pattern:

Core Patterns
Method / This_Blender
Blend returns onto `this` object using intelligent type-aware merging
Chain
Sequential pipeline where each result becomes input to next method
Blender
Uses Doh.blend() - respects MOC rules on target object
Execution Order Variants (+ _Funnel)
This_Funnel
Reverse order Method (Derived → Base)
Chain_Funnel
Reverse order Chain pipeline
Funnel
Reverse order Blender enhancement
Async Variants (Async_ prefix)
Async_Method, Async_This_Funnel
Promise-aware `this` blending
Async_Chain, Async_Chain_Funnel
Awaitable pipeline transformations
Async_Blender, Async_Funnel
Promise-aware target enhancement
Special Purpose
Phase
Lifecycle stage handling during object construction
Super
ES6-style explicit inheritance calls

Every method call follows the same blending intelligence that governs object construction—MOC rules applied at runtime. The composition strategy itself becomes part of your domain modeling.

How One Matrix Fixed Functions

The Method Strategy Matrix doesn't just organize patterns—it systematically addresses every multiple inheritance challenge:

1
Ordering

Add _Funnel to reverse any strategy. Chain_Funnel, Method_Funnel, Async_Funnel—direction matches purpose.

2
Return Values

Returns follow same MOC rules as construction. Method blends onto `this`, Chain pipes results, Blender respects type-aware merging.

3
Hooking

Every method gets pre_ and post_ hooks automatically. Setup, teardown, validation—lifecycle control built-in.

Building Up, Not Mixing In

MOC definitions themselves are inherited. Define behavior rules once, they cascade through your entire inheritance chain.

Traditional Mixins

// Each mixin is isolated
const LoggerMixin = {
    log() { /* self-contained */ }
};
const ValidatorMixin = {
    validate() { /* separate */ }
};

Doh Patterns

// Define rules once
Pattern('Base', {
    moc: { process: 'Chain' }
});
// All descendants inherit the rule
Pattern('Child', 'Base', {
    process(data) { /* adds to chain */ }
});

Inheritance Becomes Composition

// Not "IS-A" or "HAS-A" but "DOES-ALL"
const component = New(['Draggable', 'Resizable', 'Clickable']);

// All behaviors are active and collaborative
// No conflicts, no ambiguity, no choosing sides

Maybe multiple inheritance can work?

Testing the Theory

We had a solution for multiple inheritance. But where were its limits? We kept looking for places where these core principles would break down.

Long before ESM existed, we had script tags executing immediately on parse. No dependency resolution, no guaranteed order. Testing our pattern system was impossible when you couldn't control execution flow.

Simple extension: jQuery's $(document).ready(callback) let you wait for DOM. Why not wait for other callbacks?

The realization: Modules are Objects

Doh.Module(name, deps, callback) was born—dependency-aware document.ready().

Each piece unlocked the next logical problem. As web standards matured, we leveraged what we could—JSON, Node.js, ESM. But the core insight remained: dependency-aware execution flow transforms everything it touches.

→ Auto-Packager emerges

We wanted to inject args into callbacks by name, and move modules around from file to file without updating anything. AST parsing scanned source code to understand what each module needed, built dependency graphs, generated manifests.

→ Packages before package.json

Long before package.json or even JSON itself, we needed to group things under names. Doh.Package() let you organize without file/folder ceremony—just object literals and what we'd now call JSONP.

→ DohPath emerges

Moving modules around broke assets. We needed path resolution that worked regardless of where files lived. DohPath let you reference files relative to project root (/), module context (^/), or packages (^:pkg/).

→ Pod system emerges later

As systems matured, modules needed configuration defaults. Not massive config files—sparse YAML that inherited and layered. Doh.Pod() compiled settings into type-safe runtime config.

→ Express middleware layer

When Node.js came, Express was perfect—we just needed it to work with our module system. Thin compatibility layer for middleware integration, file-based routing, pod-driven configuration. No rebuilding for the sake of it.

→ Load DSL and Doh.load()

Modules needed richer dependency syntax: 'async module', 'await file.json', 'browser?? dom_utils'. Environment branching, async control, conditional loading—all declarative.

And this only scratches the surface. Modules and Patterns became the foundation for security systems, data pipelines, development tools, cloud orchestration—we ended up making a...

Complete Ecosystem

After 16 years of building with these patterns, we assumed that at some point we would find a requirement or pattern that we couldn't map a strategy to. Instead we cultivated the following surprisingly large collection of our attempts to find those edges.

Core Infrastructure

Load System & Auto-Packager

Universal dependency loading with Doh.load() across all environments. The Auto-Packager performs compiler-grade analysis to generate manifests that make runtime execution instant.

Key Features: Cross-environment compatibility, automatic NPM installation, build-time optimization, manifest generation

DohPath & Resolution Order

Universal path resolution system and the foundational algorithm that governs all composition in Doh—from package dependencies to object inheritance to configuration cascading.

Key Features: Three coordinate systems, universal composition rules, predictable inheritance chains

Patterns & Modules

Powerful component architecture with multiple inheritance, lifecycle management, and Melded Object Composition (MOC). Build anything from simple utilities to complex applications.

Key Features: Multiple inheritance, lifecycle phases, property melding, sub-object building

Server & Networking

Express Router

Protocol-agnostic routing that unifies HTTP and WebSocket handling. The same route handles both protocols seamlessly, with file-based routing and automatic middleware integration.

Key Features: Unified HTTP/WebSocket API, file-based routing, middleware support, auto-SSL integration

Redbird Proxy & Greenlock SSL

Automated reverse proxy configuration and SSL certificate management. Multi-site deployment becomes point-and-click with automatic certificate issuance and renewal.

Key Features: Automatic proxy setup, SSL automation, multi-site management, zero-config deployment

Cloud Manager

Centralized orchestration of distributed Doh instances. Manage multiple servers, synchronize files bidirectionally, monitor logs, and control deployments from a unified dashboard.

Key Features: Multi-instance management, file synchronization, log aggregation, remote control

Data & Processing

Dataforge

Declarative data processing pipelines that work identically across server and browser. Transform data using command sequences with built-in database operations and templating.

Key Features: Cross-environment compatibility, declarative syntax, pipeline chaining, template integration

Database Integration

Unified database access using SQLite (server) and alasql (browser) with synchronous operations by default. Simple, consistent API across all environments.

Key Features: Cross-environment database API, synchronous by default, automatic connection management

Handlebars Integration

Template processing directly integrated into Dataforge pipelines. Generate dynamic content with live data injection and protocol handlers for file includes.

Key Features: Pipeline integration, dynamic variables, protocol handlers, live data binding

User Management & Security

User System

Complete authentication system with JWT tokens, email verification, multi-device sessions, and brute-force protection. Admin interfaces handle user management without custom tooling.

Key Features: JWT authentication, email verification, session management, admin dashboard

Permission System

Context-aware authorization with Doh.permit() for runtime object evaluation. Express complex rules like "users can only edit documents they own" with simple syntax.

Key Features: Runtime context evaluation, hierarchical groups, dynamic permissions, exploration tools

SSO & Federation

Single Sign-On server and client modules for distributed authentication. Create identity providers or anchor to existing ones with simple configuration.

Key Features: SSO server/client, distributed auth, identity federation, simple anchoring

Development & Deployment

Browser IDE

VS Code-compatible IDE running directly in browsers. File operations, terminal access via server-side PTY, and Git integration work with live filesystems across any Doh instance.

Key Features: Browser-based development, PTY terminals, Git integration, live filesystem access

MCP Server

Model Context Protocol server for AI assistants. AST-powered code search, documentation search, browser automation, and unified debugging make AI development partnerships seamless.

Key Features: AI assistant integration, code analysis, browser automation, development guidance

Export & Packaging

Create standalone HTML applications with Virtual File Systems, package modules as Dohballs for sharing, and export applications with all dependencies included.

Key Features: Single-file exports, virtual filesystems, module packaging, dependency bundling

Ready to Explore?

Start with the documentation and see how it all works it greater detail.

Explore the Complete Documentation

Try it!

Launch your first Doh application and gain access to the entire ecosystem—from basic web servers to sophisticated cloud-orchestrated applications.

1. Install Doh CLI

# Mac/Linux
curl -fsSL https://deploydoh.com/install | bash
# Windows
powershell -c "irm deploydoh.com/install.ps1 | iex"

> Requires Bun or Node.js for npm package management.
- If needed, we can even install those for you too: doh install bun or doh install node

2. Create Your App

mkdir my-doh-app
cd my-doh-app
doh init webserver

Scaffolds a new Doh project with a pre-configured web server.

3. Run & Develop

doh run

Your new project runs at http://localhost:3000 with live reloading.

Ready to dive deeper? Explore the Architecture.