This repository has been archived on 2026-08-08. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
DynaLab-V0/docs/architecture.md
T
2026-08-08 22:43:01 +01:00

3.6 KiB

DynaLab Architecture and Naming

Goals

DynaLab accepts live data from multiple connector implementations and presents it in a desktop UI. The architecture keeps transport code, application state, and Dear PyGui code independent so that adding a connector or UI feature does not require edits across unrelated modules.

Data Flow

connector session -> ConnectorEvent queue -> UI feature controller -> feature state -> view

The connector thread owns sockets, handshakes, and heartbeat bookkeeping. It communicates with the main thread only through immutable events. The main thread owns application state and all Dear PyGui calls.

Package Layout

src/dynalab/
  app.py                    composition, lifecycle, frame loop, shutdown
  state.py                  focused application, signal, and recording state
  connectors/
    events.py               typed connector-to-application events
    protocol_server.py      asyncio server and connector sessions
  ui/
    shell.py                top-level window, menus, and feature navigation
    loading/                loading view and tags
    errors/                 error modal view and tags
    live_data/              gauge view, event controller, and tags
    recording/              recording view, controller, presenter, and tags

Feature folders own their widgets, tags, callbacks, and model-to-widget synchronization. Avoid global tag collections and modules named after generic implementation techniques, such as windows, routines, or render.

Naming

  • build_* creates widgets once.
  • refresh_* synchronizes existing widgets from state.
  • on_* is a thin Dear PyGui callback.
  • handle_* processes an application event or user intent.
  • start_* and stop_* control service lifecycle.
  • load_* and save_* access persistent storage.
  • *_tag functions generate dynamic Dear PyGui identifiers.
  • *State holds mutable state owned by the main thread.
  • *Event is immutable communication across a boundary.

Tags are feature-qualified strings, for example recording.dialog and live_data.gauge.<uuid>. Display labels are never parsed to recover domain identifiers; features maintain explicit label-to-ID mappings.

Ownership Rules

  • Only the connector thread accesses streams, sessions, and heartbeat timestamps.
  • Only the main thread mutates ApplicationState and calls Dear PyGui.
  • app.py composes services and dispatches events; it does not build feature widgets.
  • Controllers translate intent or events into state changes and view operations.
  • Views construct widgets and contain no connector logic.
  • Presenters format state for existing widgets and contain no networking logic.

Adding a Connector

A connector adapts its transport into the event types in connectors/events.py. It must not mutate application state or invoke Dear PyGui. Connector-specific handshake and framing stay within its own server/session implementation.

Adding a UI Feature

Create a folder under ui/ containing only the pieces the feature needs. A typical feature has view.py, controller.py, presenter.py, and tags.py; small features may use fewer files. Register its top-level view in ui/shell.py and dispatch relevant events from the application loop.

Testing Boundaries

  • Test event and state behavior without importing Dear PyGui.
  • Test controllers with a stubbed gauge or Dear PyGui adapter.
  • Test connector sessions with local asyncio streams or protocol fakes.
  • Keep manual connector simulators under test/ or move them to tools/ when the automated integration suite is introduced.