Initial project setup with documentation
- Add project requirements document (01_requirements.md) - Add technical specification (02_technical_specification.md) - Add architecture decisions (03_architecture_decisions.md) - Add README with project overview - Add .gitignore for Python projects
This commit is contained in:
189
docs/03_architecture_decisions.md
Normal file
189
docs/03_architecture_decisions.md
Normal file
@@ -0,0 +1,189 @@
|
||||
# Architecture Decision Record
|
||||
## ThermalATE: Technical Architecture Decisions
|
||||
|
||||
| Document ID | ARD-001 |
|
||||
|-------------|---------|
|
||||
| Version | 1.1.0 |
|
||||
| Status | Draft |
|
||||
| Author | Kai Chappell |
|
||||
| Created | 2025-12-01 |
|
||||
| Last Updated | 2025-12-01 |
|
||||
|
||||
---
|
||||
|
||||
## Purpose
|
||||
|
||||
This document captures the **rationale** behind architectural decisions. It explains **why** certain approaches were chosen over alternatives.
|
||||
|
||||
For **what** the system must do, see `01_requirements.md`.
|
||||
For **how** to implement the system, see `02_technical_specification.md`.
|
||||
|
||||
---
|
||||
|
||||
## Related Documents
|
||||
|
||||
| Document | Purpose |
|
||||
|----------|---------|
|
||||
| `01_requirements.md` | Defines **what** the system must do |
|
||||
| `02_technical_specification.md` | Specifies **how** to implement the system |
|
||||
| `03_architecture_decisions.md` | Explains **why** decisions were made (this document) |
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Guiding Principles](#1-guiding-principles)
|
||||
2. [Decision Log](#2-decision-log)
|
||||
|
||||
---
|
||||
|
||||
## 1. Guiding Principles
|
||||
|
||||
These principles guided all architectural decisions:
|
||||
|
||||
| Principle | Rationale |
|
||||
|-----------|-----------|
|
||||
| **Single Responsibility** | Reduces coupling; each module changes for one reason only |
|
||||
| **Dependency Inversion** | Enables testing and hardware swapping without code changes |
|
||||
| **Explicit Dependencies** | Makes code predictable; no hidden global state |
|
||||
| **Fail Fast** | Problems surface immediately rather than propagating |
|
||||
| **Configuration over Code** | Runtime behaviour changes without recompilation |
|
||||
| **Engineering Efficiency** | Prioritise development velocity using appropriate tools |
|
||||
|
||||
---
|
||||
|
||||
## 2. Decision Log
|
||||
|
||||
### ADR-001: Programming Language
|
||||
|
||||
| Aspect | Content |
|
||||
|--------|---------|
|
||||
| **Context** | Need to choose primary implementation language for a DVT automation platform |
|
||||
| **Decision** | Python 3.11+ |
|
||||
| **Why This Choice** | Python is the industry standard for test automation. Hiring managers for DVT roles expect Python proficiency. The ecosystem (NumPy, SciPy, PyVISA) directly supports the problem domain. A single language reduces context-switching and demonstrates depth over breadth. |
|
||||
| **Trade-offs Accepted** | Slower execution than compiled languages (acceptable for 100Hz simulation). Dynamic typing requires discipline (mitigated with type hints and mypy). |
|
||||
| **Alternatives Rejected** | LabVIEW (proprietary, not demonstrable in portfolio), C++ (slower development velocity), TypeScript (not standard in ATE domain) |
|
||||
|
||||
---
|
||||
|
||||
### ADR-002: Frontend Approach
|
||||
|
||||
| Aspect | Content |
|
||||
|--------|---------|
|
||||
| **Context** | Need user interface for test execution and monitoring. Must balance effort against target role (DVT/Backend, not Frontend). Must demonstrate engineering efficiency. |
|
||||
| **Decision** | CLI-first with Streamlit dashboard |
|
||||
| **Why This Choice** | CLI demonstrates core functionality without UI overhead. Streamlit enables rapid iteration on dashboard UI using pure Python—no JavaScript, CSS, or complex state management required. This demonstrates 'Engineering Efficiency': building effective internal tools quickly using appropriate technology. Real ATE tools at hardware companies are often CLI or simple Python GUIs, not React SPAs. |
|
||||
| **Trade-offs Accepted** | Streamlit has limitations for complex interactivity. Less customisable than React. Re-runs script on interaction (mitigated with caching). |
|
||||
| **Alternatives Rejected** | React (wrong skill signal for DVT roles, major time investment, JavaScript required), Panel (more powerful but steeper learning curve, slower iteration), PyQt (higher complexity, dated appearance) |
|
||||
|
||||
---
|
||||
|
||||
### ADR-003: Data Persistence Strategy
|
||||
|
||||
| Aspect | Content |
|
||||
|--------|---------|
|
||||
| **Context** | Need to persist test metadata and high-frequency measurement data |
|
||||
| **Decision** | SQLite for metadata + Parquet for time-series measurements |
|
||||
| **Why This Choice** | SQLite requires no server process—the entire system remains self-contained. Parquet is columnar and optimised for analytical queries on measurement data. Both are file-based, making projects portable and easy to share. Standard library (sqlite3) and well-supported (PyArrow) tools demonstrate effective use of established technologies before reaching for external dependencies. |
|
||||
| **Trade-offs Accepted** | Single-user only (acceptable for portfolio project). No real-time replication. Query capabilities limited to pandas/SQL without additional tools. |
|
||||
| **Alternatives Rejected** | PostgreSQL (requires server, adds infrastructure complexity), InfluxDB (another service to manage), DuckDB (additional dependency not strictly necessary for single-user simulator) |
|
||||
|
||||
---
|
||||
|
||||
### ADR-004: Instrument Communication Protocol
|
||||
|
||||
| Aspect | Content |
|
||||
|--------|---------|
|
||||
| **Context** | Need protocol for test application to communicate with simulated instruments |
|
||||
| **Decision** | SCPI over TCP/IP sockets |
|
||||
| **Why This Choice** | SCPI is the industry standard for programmable instruments (IEEE 488.2). Using the real protocol means the same drivers work with real hardware. TCP/IP enables process separation and future network deployment. Demonstrates domain knowledge to reviewers. |
|
||||
| **Trade-offs Accepted** | Must implement SCPI parser. Network overhead (negligible on localhost). |
|
||||
| **Alternatives Rejected** | Direct function calls (wouldn't demonstrate real-world architecture), gRPC (not industry standard for instruments), REST API (not SCPI-compliant, wouldn't transfer to real hardware) |
|
||||
|
||||
---
|
||||
|
||||
### ADR-005: Process Architecture
|
||||
|
||||
| Aspect | Content |
|
||||
|--------|---------|
|
||||
| **Context** | Need to decide if physics simulation runs in-process or separately |
|
||||
| **Decision** | Simulation server runs as separate process |
|
||||
| **Why This Choice** | Mimics real hardware architecture where instruments are separate devices. Forces clean network boundaries that translate to real deployments. Enables Docker containerisation with proper service separation. The same test code works whether talking to simulation or real instruments over network. |
|
||||
| **Trade-offs Accepted** | Process management complexity. Inter-process communication overhead. |
|
||||
| **Alternatives Rejected** | In-process simulation (wouldn't demonstrate production architecture, wouldn't prove hardware abstraction works) |
|
||||
|
||||
---
|
||||
|
||||
### ADR-006: Hardware Abstraction Mechanism
|
||||
|
||||
| Aspect | Content |
|
||||
|--------|---------|
|
||||
| **Context** | Need to swap between simulated and real instruments without changing test code |
|
||||
| **Decision** | Python Protocol classes (structural typing) with Factory pattern |
|
||||
| **Why This Choice** | Protocols enable interface-based programming without inheritance coupling. Factory centralises the simulator-vs-real decision to configuration. No heavy DI framework needed—Python's simplicity is sufficient. Demonstrates understanding of SOLID principles and dependency injection. |
|
||||
| **Trade-offs Accepted** | Manual wiring in factory (acceptable at this scale). Protocols require Python 3.8+. |
|
||||
| **Alternatives Rejected** | Abstract Base Classes only (less flexible than Protocols), DI framework like dependency-injector (over-engineering for this scale), No abstraction (would couple test code to simulator) |
|
||||
|
||||
---
|
||||
|
||||
### ADR-007: Concurrency Model
|
||||
|
||||
| Aspect | Content |
|
||||
|--------|---------|
|
||||
| **Context** | Need to handle concurrent instrument connections and real-time physics updates |
|
||||
| **Decision** | asyncio for simulation server; synchronous-first for test code |
|
||||
| **Why This Choice** | Server must handle multiple simultaneous connections efficiently—asyncio is Python's standard solution. Test code is inherently sequential (set voltage, wait, measure), so forcing async everywhere adds complexity without benefit. Clear boundary at transport layer. |
|
||||
| **Trade-offs Accepted** | Two patterns to understand. Must be careful about blocking calls in async context. |
|
||||
| **Alternatives Rejected** | Threading everywhere (GIL limitations, harder to reason about), Full async in test code (unnecessary complexity, test sequences are sequential) |
|
||||
|
||||
---
|
||||
|
||||
### ADR-008: Configuration Format
|
||||
|
||||
| Aspect | Content |
|
||||
|--------|---------|
|
||||
| **Context** | Need human-readable, version-controllable configuration |
|
||||
| **Decision** | YAML files validated with Pydantic |
|
||||
| **Why This Choice** | YAML supports comments (unlike JSON), making configs self-documenting. Pydantic provides type-safe parsing with clear error messages. Configs can be version-controlled alongside code. |
|
||||
| **Trade-offs Accepted** | YAML has some parsing quirks (Norway problem). Pydantic v2 has breaking changes from v1. |
|
||||
| **Alternatives Rejected** | JSON (no comments), TOML (less common in Python data ecosystem), Environment variables only (not structured enough for complex config) |
|
||||
|
||||
---
|
||||
|
||||
### ADR-009: Testing Philosophy
|
||||
|
||||
| Aspect | Content |
|
||||
|--------|---------|
|
||||
| **Context** | Need automated testing strategy for quality assurance |
|
||||
| **Decision** | pytest with dependency injection via fixtures; 80% coverage target on core modules |
|
||||
| **Why This Choice** | pytest is the Python community standard. Fixtures align with DI pattern—inject mocks at test boundaries. 80% coverage balances thoroughness with pragmatism. Demonstrates professional engineering practices expected at senior level. |
|
||||
| **Trade-offs Accepted** | Must design for testability from the start. Some integration tests require running simulation server. |
|
||||
| **Alternatives Rejected** | No tests (unacceptable for portfolio demonstrating senior-level work), unittest (less ergonomic than pytest), 100% coverage target (diminishing returns, encourages testing trivial code) |
|
||||
|
||||
---
|
||||
|
||||
### ADR-010: Project Structure
|
||||
|
||||
| Aspect | Content |
|
||||
|--------|---------|
|
||||
| **Context** | Need to organise code for clarity and maintainability |
|
||||
| **Decision** | Monorepo with src layout and package-per-concern |
|
||||
| **Why This Choice** | Single repository simplifies development for a solo developer. Src layout is Python packaging best practice (prevents import confusion). Package-per-concern makes dependencies explicit and enforceable. |
|
||||
| **Trade-offs Accepted** | Must configure editable installs for development. All code in one repo (acceptable at this scale). |
|
||||
| **Alternatives Rejected** | Flat structure (poor for larger codebases), Multi-repo (overhead for single developer), Package-per-layer only (too coarse-grained) |
|
||||
|
||||
---
|
||||
|
||||
### ADR-011: Development Phasing Strategy
|
||||
|
||||
| Aspect | Content |
|
||||
|--------|---------|
|
||||
| **Context** | Need to prioritise features for efficient delivery of portfolio-quality project |
|
||||
| **Decision** | Vertical Slice approach: deliver end-to-end functionality (Physics → HAL → Driver → UI) before adding horizontal features (reporting, API) |
|
||||
| **Why This Choice** | A working "Virtual Lab Bench" demonstrates the core value proposition immediately. Vertical slices reduce integration risk—problems surface early. Defers low-value work (PDF formatting) until core is proven. Enables meaningful demos at every phase. |
|
||||
| **Trade-offs Accepted** | Some infrastructure (reporting) delayed. May need refactoring when adding phases. |
|
||||
| **Alternatives Rejected** | Horizontal layers first (delays integration, hides problems), Feature-complete phases (too long between demos), MVP without UI (harder to demonstrate value) |
|
||||
|
||||
---
|
||||
|
||||
**End of Architecture Decision Record**
|
||||
Reference in New Issue
Block a user