Declarative design patterns programming paradigm
posted on 31 Jan 2026 under category programming
| Date | Language | Author | Description |
|---|---|---|---|
| 31.01.2026 | English | Claus Prüfer (Chief Prüfer) | Declarative Design Patterns: Modern OOP Pattern for Configuration-as-Model |



Important: This article clarifies a widely misunderstood concept. Declarative Design Patterns are NOT related to functional programming or generic declarative configuration. They are a modern OOP-based design pattern that modifies configuration structures (JSON/XML) directly into internal runtime OOP models which enables a so-called Configuration-as-Model approach.
Before diving deep, it is critical to clarify terminology that has been confused in the programming community:
The term “Declarative Design Patterns” serves as an umbrella term for a collection of related patterns that share a common principle: using configuration structures AS the runtime object model, not just as input (configuration) to create separate domain objects. This fundamentally changes how we think about the relationship between configuration and code.
Declarative configurations used in combination with non OOP based languages (Go) or non-OOP paradigms like typical JavaScript frameworks (React, Vue) or TypeScript that rely on functional/reactive patterns rather than true OOP do not benefit from these patterns in the same way—they may even increase programming complexity. However, JavaScript frameworks that embrace true OOP principles (such as the x0 Framework) can successfully implement declarative design patterns.
Using this “Declarative Design Pattern” approach in combination with modern storage technologies, e.g. ODM - JSON Object Document Mapping (MongoDB), and especially runtime class abstraction / mapping (see: python-micro-esb PKI Management Example), inherits many new sub-patterns which altogether form the base of “Declarative Design Patterns”.
The most powerful aspect of Declarative Design Patterns is runtime class abstraction / mapping. This technique allows:
This creates a system where configuration structures directly drive object instantiation, property assignment, and method invocation at runtime—eliminating the traditional separation between configuration and domain objects.
The key benefits (especially in large code bases):
Declarative Design Patterns are a new class of OOP-based design patterns that leverage structured configuration data (JSON, XML, YAML) as the primary mechanism for building complex object hierarchies. The fundamental principle is:
Configuration structures become the internal object model directly, passed as references/pointers to sub-modules, drastically reducing programming logic and code lines.
What Declarative Design Patterns are NOT:
What Declarative Design Patterns ARE:
A comprehensive implementation of the Declarative Design Pattern in Python is demonstrated in the python-micro-esb PKI Management Example. This example showcases runtime class abstraction / mapping—the most advanced form of declarative design patterns.
Step 1: Define Class Reference Hierarchies
# class_reference.py
class_reference_server = {
'CertServer': {
'property_ref': 'Cert',
'children': {
'Smartcard': {
'property_ref': 'Smartcard',
'children': {
'SmartcardContainer': {
'property_ref': 'SmartcardContainer'
}
}
},
'CertCA': {
'property_ref': 'Cert',
'children': {
'Smartcard': {
'property_ref': 'Smartcard',
'children': {
'SmartcardContainer': {
'property_ref': 'SmartcardContainer'
}
}
}
}
}
}
}
}
The hierarchical structure declares relationships between classes—CertServer contains both a Smartcard and references a CertCA, each with their own nested structures.
Step 2: Implement Classes with Abstract Base
# service_implementation.py
import abc
from microesb import microesb
class Cert(microesb.ClassHandler, metaclass=abc.ABCMeta):
def __init__(self):
super().__init__()
self.register_property('cert_data', {
'type': 'str',
'default': None,
'required': False,
'description': 'Generated Certificate Base64 encoded'
})
@abc.abstractmethod
def _load_ref_cert_data(self):
""" Load referenced certificate data. """
@abc.abstractmethod
def _gen_openssl_cert(self):
""" Generate certificate using OpenSSL. """
def gen_cert(self):
self._load_ref_cert_data()
if getattr(self, 'Smartcard') is not None:
self._hsm_gen_keypair()
self._gen_openssl_cert()
self._store_cert_data()
class CertServer(Cert):
def __init__(self):
self.type = 'server'
super().__init__()
def _load_ref_cert_data(self):
# access child object directly - populated from configuration
self.CertCA._get_cert_data_by_id()
def _gen_openssl_cert(self):
# both current object and child object properties are available
srv_metadata = {
"CertServer": self.property_dict,
"CertCA": self.CertCA.property_dict
}
self.cert_data = generate_cert(srv_metadata)
Step 3: Execute with Runtime Class Mapping
# 00-main-ca.py
from microesb import microesb
from class_reference import class_reference_ca as class_reference
from service_properties import service_properties
from class_mapping import class_mapping
from service_call_metadata import service_metadata_ca as service_metadata
from pymongo import MongoClient
# MongoDB connection for ODM integration
client = MongoClient('mongodb://127.0.0.1/')
mongodb = client.get_database('microesb')
# runtime class mapper - the heart of declarative design patterns
class_mapper = microesb.ClassMapper(
class_references=class_reference,
class_mappings=class_mapping,
class_properties=service_properties
)
# execute service - classes instantiated and methods called based on configuration
res = microesb.ServiceExecuter().execute_get_hierarchy(
class_mapper=class_mapper,
service_data=service_metadata
)
# store complete object hierarchy to MongoDB
root_object = res[0]['CertCA']['object_instance']
mongodb.cert_hierarchy.insert_one(root_object.json_dict)
Note on ODM Hierarchy Storage: The true potential of hierarchical ODM (Object Document Mapping) storage with MongoDB becomes evident in the
02-main-client.pyexample, where complex parent-child certificate relationships are stored and retrieved as nested JSON documents. This demonstrates how declarative design patterns combined with document databases eliminate the impedance mismatch between object hierarchies and data storage.
Note on Runnable Examples: The python-micro-esb framework ships with complete runnable examples inside a Docker container that includes MongoDB and all dependencies pre-configured. This allows developers to immediately experiment with the declarative design pattern approach without complex setup.
Step 4: Define Class Aliasing
# class_mapping.py
class_mapping = {
'CertCA': 'CertCA',
'CertServer': 'CertServer',
'CertClient': 'CertClient',
'Smartcard': 'Smartcard',
'SmartcardContainer': 'SmartcardContainer'
}
This mapping enables the framework to instantiate classes based on configuration identifiers—a key feature of runtime class abstraction.
Note on Configuration Structure: The example uses a “flat” 1:1 class mapping model. The real power of this pattern emerges when using mapped “aliases”—where a single configuration identifier can represent different class implementations based on context, enabling polymorphic behavior through declarative configuration rather than code.
Step 5: Finally, Call Service With Service Metadata (Configuration as Behavior)
# service_call_metadata.py
service_metadata_server = {
'SYSServiceID': 'generateCertServer',
'data': [
{
'SYSBackendMethod': { 'CertServer': 'gen_cert' },
'CertServer': {
'id': 'test-server1',
'CertCA': {
'id': 'test-ca1'
},
'Smartcard': {
'label': 'smartcard_customer1',
'user_pin': 'pin2',
'SmartcardContainer': {
'label': 'testserver1_keypair'
}
},
'country': 'DE',
'state': 'Berlin',
'locality': 'Berlin',
'org': 'WEBcodeX',
'org_unit': 'Security',
'common_name': 'testserver@domain.com',
'email': 'pki@webcodex.de',
'valid_days': 365
}
}
]
}
Notice how SYSBackendMethod declares which method to call on which class—the configuration drives not just data but behavior.
Traditional OOP approaches require:
With Declarative Design Patterns using Runtime Class Mapping:
Code Reduction Example: A complete PKI management system that might require 3000+ lines of traditional OOP code (classes, builders, factories, parsers, hierarchy management) can be reduced to ~500 lines of declarative configuration plus clean, focused implementation classes.
These concepts are fundamentally different:
| Aspect | Declarative Configuration | Declarative Design Patterns |
|---|---|---|
| Purpose | Provide settings to an application | Model complex object hierarchies |
| Implementation | Config files read at startup | Config structures become runtime objects |
| Code Impact | Minimal - just reads values | Massive reduction - replaces OOP boilerplate |
| Language Requirement | Any language | OOP languages (Python, C++, Java) |
| Data Flow | Config → Code reads values | Config → ClassMapper → Objects → Methods |
| Hierarchy | Flat key-value pairs | Complex tree structures |
Why Declarative Design Patterns don’t work:
Note: This does NOT mean these languages cannot have good configuration. It means the specific Declarative Design Pattern (config-as-model with runtime class mapping) doesn’t translate well.
When the pattern is overkill:
Limitations in performance scenarios:
Performance Counterpoint: The above limitations are based on traditional implementation approaches, but AI analysis suggests this is not necessarily true when declarative design patterns are used correctly. By employing smart “static class-instance pre-loading” strategies—remember, the system is fundamentally based on references/pointers—performance can actually be superior. Consider a modified nlohmann::json implementation (similar to Apache Spark’s memory-resident dataset concept) where the complete object model resides in continuous, huge-page-assisted RAM. In such an architecture, the declarative approach eliminates object instantiation overhead entirely, and reference-based access to pre-loaded instances can outperform traditional object creation patterns. The key is architectural design that leverages the reference-based nature of the pattern.
While the Python examples above demonstrate runtime class mapping, C++ provides another powerful implementation of Declarative Design Patterns through the nlohmann/json library. The http-1.2 Project serves as a reference implementation demonstrating these concepts in production-grade C++ code.
C++ is inherently suited for generic programming through templates and STL containers. With nlohmann::json, the language gains STL-like JSON access that enables the same configuration-as-model approach seen in Python, but with compile-time type safety and zero-overhead abstractions.
From the http-1.2 project (full configuration file):
{
"global": {
"path": { "base": "/var/www" },
"tcp": { "cork": false, "nodelay": true }
},
"server": {
"runas": { "user": "x0-http", "group": "x0-http" },
"connection": {
"timeout": "600",
"ipv4": { "address": "127.0.0.1", "port": 80 }
},
"mimetypes": ["html", "js", "json", "css", "png", "jpg", "svg", "woff2"]
}
}
The nlohmann::json library enables intuitive, chainable syntax for accessing nested configuration:
#include <nlohmann/json.hpp>
#include <fstream>
using json = nlohmann::json;
try {
std::ifstream configFile(CONFIG_FILE);
json jsonData = json::parse(configFile);
const auto& runAsUser = jsonData["server"]["runas"]["user"];
const auto& runAsGroup = jsonData["server"]["runas"]["group"];
const auto& basePath = jsonData["global"]["path"]["base"];
const auto& serverAddr = jsonData["server"]["connection"]["ipv4"]["address"];
const auto& serverPort = jsonData["server"]["connection"]["ipv4"]["port"];
const auto& mimeTypes = jsonData["server"]["mimetypes"];
}
catch (const std::exception& e) {
std::cerr << "Config file error: " << e.what() << std::endl;
std::exit(EXIT_FAILURE);
}
C++ move semantics enable efficient transfer of configuration structures directly into object instances:
struct NamespaceProps {
nlohmann::json jsonConfig;
std::shared_ptr<Filesystem> fsRef;
};
std::map<std::string, NamespaceProps> namespaces;
for (const auto& nsItem : jsonData["namespaces"]) {
NamespaceProps props;
props.jsonConfig = std::move(nsItem);
props.fsRef = nullptr;
namespaces.emplace(nsItem["hostname"], std::move(props));
}
With nlohmann::json, configuration structures are moved directly into object constructors, embodying the configuration-as-model principle:
// objects accept nlohmann::json rvalue references in their constructors
std::unique_ptr<MyObject1> objInstance1;
std::unique_ptr<MyObject2> objInstance2;
// configuration members can be defined as immutable (const)
objInstance1.reset(new MyObject1(std::move(jsonData["confgroup1"][0])));
objInstance2.reset(new MyObject2(std::move(jsonData["confgroup1"][1])));
std::move enables efficient transfer of configuration hierarchiesstd::vector, std::map, and modern iterationThe http-1.2 implementation demonstrates how these patterns reduce code complexity while maintaining C++’s performance characteristics. The full implementation can be studied at WEBcodeX1/http-1.2/Configuration.cpp.
The x0 Framework demonstrates how Declarative Design Patterns can be applied to JavaScript UI development. Unlike typical React/Vue applications that rely on functional/reactive patterns, x0 embraces true object-oriented principles with proper class hierarchies and object instantiation from configuration. This is what distinguishes it from mainstream JavaScript frameworks and enables the declarative design pattern approach.
Key Features:
The x0 framework shows that Declarative Design Patterns can extend beyond backend services to frontend UI development when the framework architecture is built on true OOP foundations rather than functional/reactive paradigms.
Upcoming Feature: A soon-to-be-released feature for x0 will enable direct hierarchical ODM (MongoDB) backend object mapping to UI elements, which in comparison to other frameworks will lead to a complete elimination of transformation layers between backend and frontend (currently multiple serialization/deserialization steps exist) and a dramatic reduction in overhead and complexity. Specifically, this will allow MongoDB document hierarchies to flow directly into UI component hierarchies, creating a truly unified full-stack declarative design pattern where configuration-as-model extends seamlessly from database to display.