Skip to content

Module Concept

This document is work in progress and may contradict other parts of the documentation. Once reviewed, it will guide design and refactoring of the system.

A Module is the core unit of Functional Decomposition for Arda’s system. It contributes a set of cohesive capabilities and interacts with other modules in a controlled, well-defined manner.

Modules are grouped into Functional Domains that represent major areas of related product capabilities. The design aims for:

  • High cohesion within each Module
  • Low harmful coupling between Modules
  • High coherence of the artifacts a Module defines and implements

A Module encapsulates a portion of the system state accessible only through the Module’s Services. The minimum encapsulation requirement is at the Module level. Where modules support different services, further partitioning is strongly desired. Exceptions for performance (e.g., foreign keys between services within a module) must never break encapsulation at the Module level.

  • A Module is a basic unit of change and version control; all artifacts that define it or are generated from it are identified with the module version.
  • A Module is typically implemented within a single technology ecosystem (Kotlin/JVM, TypeScript/NodeJS).
  • Modules are deployed as part of Runtime Components that package them into deployable artifacts.

Modules interact through four well-defined mechanisms:

API Endpoints / Services : A module invokes Services exposed by other modules. Services are collections of typed, named operations that perform well-defined behavior.

References : A module may keep references to entities managed by other modules. A Reference at the system level must uniquely identify the entity and the instance of the module that manages it.

Data Types : For complex interactions, modules exchange structured information via Data Types. Data Types must have strict value semantics:

  1. Two instances are equal if and only if the information they contain is equal.
  2. Data Type instances are immutable — once created, they cannot be changed.

Bindings : The expression of a Module’s Data Types and Services in a particular technology, protocol, and address space. A Binding defines how a Module invokes operations using a specific protocol (e.g., REST over HTTP), data encoding (e.g., JSON on UTF-8), and base URL.

When modules share a technology ecosystem, sharing Data Types and Service Accessors via shared libraries avoids harmful duplication. Arda’s products are primarily implemented in:

  • Kotlin/JVM for backend modules
  • TypeScript/NodeJS/React for frontend modules

Interactions between modules use:

  • RESTful APIs over HTTP/1.1 with JSON for frontend-to-backend and external system access
  • gRPC over HTTP/2 with Protobuf for backend-to-backend access

A backend module may publish:

  1. OpenAPI specifications for RESTful APIs
  2. Protobuf IDL files for gRPC APIs
  3. A Kotlin library with ADT-like interfaces and data classes for the information the Module supports
  4. Binding libraries that bridge ADT types to wire representations
  5. Persistence mapping libraries for shared embedded types

A module may not publish all of the above. The minimum is to publish IDL specifications for the protocols it supports.

Data Types range in specificity:

LevelExamples
Primitive typesString, Int
Common technology typesURI, UUID, DateTime, Email
Common business conceptsAddress, Money, Length, GeoLocation
Industry-specific conceptsWorkOrder, BillOfMaterials
Module-specific conceptsUserAccount, KanbanCard

For intermediate types, placement options are: the module that first introduces the concept, a dedicated “sister” module, a domain-level shared module, or the system-level common-module. Placement may be promoted over time as usage becomes more widespread.

Cohesion : How closely related are the responsibilities and capabilities within a system element. Indicated by the number of unrelated primitives or workflows. Related to the quality of decomposition of the containing element.

Coherence : How consistent all artifacts contributing to a capability are. Indicated by exceptions, special cases, and different ways of doing things. Related to the design of the artifacts that support the capability.

Coupling : How interdependent two system elements are. Indicated by cross-references (explicit or implicit assumptions about behavior). The goal of good design is to minimize harmful coupling.

Encapsulation : A portion of system state accessible and modifiable only through a Service, which maintains the integrity of the encapsulated state.

Service / API Endpoint : A named collection of operations providing a self-contained business capability.

Operation : A typed, named signature within a Service. Has a unique name, a typed input parameter, and a typed output parameter.

Behavior : The observable effects and results of invoking an operation — changes to internal state, invocations of other Services, interactions with external systems, and output values.