diff --git a/docs/README.md b/docs/README.md index 9728d37..3079c9d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,19 +6,23 @@ A Flutter-based Android GUI wrapper for iperf3, the popular network performance ``` lib/ # Flutter/Dart application layer -├── main.dart # App entry point (MaterialApp) -├── domain/ # Business logic (platform-independent) +├── main.dart # Composition root: picks the Iperf3Runner impl +├── domain/ # Pure Dart — no Flutter import │ ├── models/ │ │ ├── test_configuration.dart # Server, port, duration, interval, parallel streams -│ │ └── iperf3_result.dart # Raw output + exit code -├── data/ +│ │ ├── iperf3_result.dart # Raw output, exit code, stopped flag +│ │ └── iperf3_event.dart # Parsed --json-stream reports │ └── services/ -│ └── iperf3_service.dart # Dart → MethodChannel bridge (async with Completer) -└── ui/ # Presentation layer +│ └── iperf3_runner.dart # The contract the UI depends on +├── data/ # Transport — flutter/services only +│ └── services/ +│ └── iperf3_service.dart # Iperf3Runner over MethodChannel → JNI +└── ui/ # Presentation └── features/ └── test_run/ - ├── test_run_screen.dart # Server/port inputs + GO button - └── test_run_view_model.dart # State machine: idle → running → completed/error + ├── test_run_screen.dart # Inputs, GO/STOP, live transcript + ├── test_run_view_model.dart # idle → running → completed/error + └── iperf3_event_formatter.dart # Events → iperf3-style text android/app/src/main/ ├── kotlin/ # Kotlin plugin layer @@ -48,6 +52,28 @@ User taps GO → On completion: Dart Completer resolves with Iperf3Result ``` +## Layering + +Dependencies point inward: `ui → domain ← data`, never the reverse. + +| Layer | May import | Holds | +|---|---|---| +| `domain` | nothing else in this package, no Flutter | models and the `Iperf3Runner` contract | +| `data` | `domain`, `package:flutter/services.dart` | the MethodChannel/JNI implementation | +| `ui` | `domain` | widgets, view model, formatting | +| `main.dart` | everything | the single place that picks an implementation | + +The UI depends on `Iperf3Runner`, not on `Iperf3Service`, so presentation names +no transport. That is what lets `test/widget_test.dart` drive the real widget +tree against an in-memory runner with no MethodChannel, native library or +device — and what keeps a test double at five stable members instead of +mirroring the transport's whole surface. + +`test/architecture_test.dart` enforces all of this by reading the actual +imports under `lib/`, including a check that no fourth layer directory has +appeared unnoticed. Change the layering there when the layering should change; +don't work around it. + ## Key Design Decisions ### JNI Over Process Execution