Opinionated Configuration

Opinionated configuration means encoding project-specific rules and defaults once, then reusing them across all components that share those constraints. Instead of repeating the same parameter values or enforcing the same policy in every configuration script, you centralize the opinion in a dedicated class or function.

This page shows three patterns for applying opinionated configuration on top of the Forge facade API. Choose the pattern that best matches how your project is structured.

Pattern: Inheritance

Subclass an existing facade to provide a project-specific factory method. The subclass removes the choices that must not vary, exposes only the parameters that callers are allowed to customize, and enforces the rest internally.

This pattern is suitable when you want to replace the standard facade with a stricter type throughout your project.

from __future__ import annotations

from ves_socom.facades import ComDaemonFacade, LogLevel


class OpinionatedComDaemonFacade(ComDaemonFacade):
    """Project-specific facade that always enables IAM and IDSM."""

    @staticmethod
    def create_opinionated(name: str) -> OpinionatedComDaemonFacade:
        base = ComDaemonFacade.create(
            name,
            log_level=LogLevel.INFO,
            enable_console_log=False,
            iam_required=True,
            iam_config_file_path="./config/iam_cfg.json",
            idsm_enabled=True,
            telemetry_enabled=False,
        )
        return OpinionatedComDaemonFacade(base.name, base.data)


if __name__ == "__main__":
    daemon = OpinionatedComDaemonFacade.create_opinionated("my_comdaemon")
    # Continue building configuration as usual...

iam_required and idsm_enabled are no longer visible to callers—they are always True. The rest of the configuration workflow is identical to the standard facade.

Pattern: Strategy

Create a strategy object that applies a transformation to an already-built facade instance. The strategy operates on the facade after it has been constructed, normalizing or enforcing rules across its children.

This pattern is suitable when the opinion applies to content that is added incrementally (such as ports or subnets), or when you want to apply the same rule to facades you did not create yourself.

from ves_socom.facades import ComDaemonFacade, IpPortType, IpProtocol, LogLevel


class UdpMixedDataIpPortStrategy:
    """Normalizes all data IP ports to UDP + Mixed."""

    def apply(self, facade: ComDaemonFacade) -> None:
        for subnet in facade.get_subnet_iterator():
            for data_ip_port in subnet.get_data_ip_port_iterator():
                data_ip_port.protocol = IpProtocol.UDP
                data_ip_port.port_type = IpPortType.MIXED


if __name__ == "__main__":
    daemon = ComDaemonFacade.create("my_comdaemon", log_level=LogLevel.DEBUG, idsm_enabled=True)

    # ... add subnets and ports ...

    UdpMixedDataIpPortStrategy().apply(daemon)
    # All data IP ports are now UDP + Mixed regardless of how they were added.

Pattern: Configuration Object

Define a typed dataclass that holds all the opinion dimensions as fields with defaults. Pass an instance of this object to a factory function that creates the facade.

This pattern is suitable when the opinion has multiple independent dimensions that callers may need to vary independently, or when you want to make the opinion explicit and auditable in one place.

from dataclasses import dataclass

from ves_socom.facades import ComDaemonFacade, LogLevel


@dataclass(frozen=True)
class ComDaemonOpinionConfig:
    """Explicit opinion configuration for ComDaemon setup."""

    log_level: LogLevel = LogLevel.INFO
    enable_console_log: bool = False
    iam_required: bool = True
    iam_config_file: str = "./config/iam_cfg.json"
    idsm_enabled: bool = True
    telemetry_enabled: bool = False
    tcp_maximum_message_size_bytes: int = 1500


def create_with_opinion(name: str, config: ComDaemonOpinionConfig) -> ComDaemonFacade:
    return ComDaemonFacade.create(
        name,
        log_level=config.log_level,
        enable_console_log=config.enable_console_log,
        iam_required=config.iam_required,
        iam_config_file_path=config.iam_config_file,
        idsm_enabled=config.idsm_enabled,
        telemetry_enabled=config.telemetry_enabled,
        tcp_maximum_message_size_bytes=config.tcp_maximum_message_size_bytes,
    )


if __name__ == "__main__":
    # Use the defaults, or override individual fields as needed.
    daemon = create_with_opinion("my_comdaemon", ComDaemonOpinionConfig())
    # Continue building configuration as usual...

The dataclass instance can be stored in a shared constants module and imported wherever the same opinion is needed.