nc_program_manager/.paul/codebase/ARCHITECTURE.md
dtrentin dabcf989d9 docs: map existing codebase
- STACK.md - Technologies and dependencies (.NET 4.7.2, NuGet, Costura.Fody)
- ARCHITECTURE.md - Layered CLI with ICncMachine factory pattern
- STRUCTURE.md - Directory layout and where to add new code
- CONVENTIONS.md - C# style, naming, result wrapper pattern
- TESTING.md - NUnit 3 + Moq, stubs, ignored FOCAS tests
- INTEGRATIONS.md - FOCAS, LSV2, FTP, RSA licensing
- CONCERNS.md - Blocking async, silent catch, no logging, Windows-only

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 22:48:20 +02:00

156 lines
5.9 KiB
Markdown

# Architecture
**Analysis Date:** 2026-05-18
## Pattern Overview
**Overall:** Layered CLI console application with abstract machine interface, factory dispatch, and offline license gate.
**Key Characteristics:**
- Single Windows EXE (all dependencies embedded via Costura.Fody)
- Polymorphic multi-vendor CNC support via `ICncMachine` interface
- Factory pattern for manufacturer selection at runtime
- Async/await throughout (Task-based), but blocked at CLI boundary via `.GetAwaiter().GetResult()`
- Result-wrapper pattern (`CncResult<T>`) instead of exceptions for CNC operations
- RSA license validation gate on every startup
## Layers
**CLI Entry Layer:**
- Purpose: Parse args, validate license, dispatch to action (Scarica/Invia)
- Contains: `Program.cs` (main orchestration), `ArgParser.cs` (regex arg parsing), `InputArgs.cs` (config object)
- Depends on: Licensing layer, CNC abstraction layer
- Error output: Negative exit codes (-100 to -208) mapped to Italian user messages
**Licensing Layer:**
- Purpose: Prevent execution on unlicensed machines
- Contains: `Licensing/LicenseValidator.cs`, `Licensing/MachineFingerprint.cs`, `Licensing/LicenseFile.cs`
- Depends on: WMI (System.Management), RSA crypto
- Used by: CLI entry layer (startup check only)
**CNC Abstraction Layer:**
- Purpose: Uniform interface over 4 different CNC protocols
- Contains: `Cnc/ICncMachine.cs`, `Cnc/IFanucMachine.cs`, `Cnc/CncMachineFactory.cs`, `Cnc/Models/`
- Key types: `CncResult<T>`, `CncError`, `CncManufacturer`, `ConnectionState`, `CncProgram`
- Used by: CLI entry layer
**Manufacturer Implementations:**
- Purpose: Protocol-specific CNC communication
- Contains: `Cnc/Fanuc/`, `Cnc/Heidenhain/`, `Cnc/Siemens/`, `Cnc/Mitsubishi/`
- Each implements `ICncMachine` (Fanuc also implements `IFanucMachine`)
- Depends on: Protocol libraries (FOCAS DLL, TCP socket, FtpWebRequest)
**Validation Layer:**
- Purpose: Pre-upload NC program syntax checking
- Contains: `Cnc/INcProgramValidator.cs`, `Cnc/NcProgramValidator.cs`
- Injected into machine implementations; upload blocked on Error severity
- Depends on: Nothing external
**NC Program Parsing:**
- Purpose: Parse/format Fanuc composite NC file format
- Contains: `FanucProgram.cs` (program + tooloffset + workzero sections)
- Used by: CLI entry layer post-download
## Data Flow
**Scarica (Download from CNC):**
```
CLI args
→ ArgParser.Parse() → InputArgs
→ LicenseValidator.Validate() [exit -1xx on failure]
→ CncMachineFactory.Create(InputArgs) → ICncMachine
→ machine.ConnectAsync() → CncResult<bool>
→ machine.ReadProgramAsync(path) → CncResult<string>
→ [IFanucMachine cast] ReadToolDataAsync / ReadWorkZeroDataAsync
→ FanucProgram.Format() → composite file string
→ File.WriteAllText(localPath)
```
**Invia (Upload to CNC):**
```
CLI args
→ ArgParser.Parse() → InputArgs
→ LicenseValidator.Validate() [exit -1xx on failure]
→ CncMachineFactory.Create(InputArgs) → ICncMachine
→ File.ReadAllText(localPath)
→ NcProgramValidator.Validate() [exit on Error severity]
→ machine.ConnectAsync()
→ machine.WriteProgramAsync(path, content) → CncResult<bool>
```
**State Management:**
- No persistent in-memory state between invocations (each run is independent)
- Machine state tracked per-instance: `ConnectionState` enum + `StateChanged` event
- Thread safety: `SemaphoreSlim` gate per machine instance
## Key Abstractions
**ICncMachine:**
- Purpose: Uniform contract for all CNC machines
- Location: `Cnc/ICncMachine.cs`
- Methods: `ConnectAsync`, `DisconnectAsync`, `ReadProgramAsync`, `WriteProgramAsync`, `ReadAsync`, `DeleteProgramAsync`, `ReadActiveProgramAsync`, `SelectMainProgramAsync`
- Pattern: Interface + factory dispatch
**IFanucMachine:**
- Purpose: Fanuc-specific extensions (tool offsets, work zero)
- Location: `Cnc/IFanucMachine.cs`
- Extends: `ICncMachine`
- Pattern: Interface specialization
**CncResult<T>:**
- Purpose: Typed result wrapper replaces exception-based control flow
- Location: `Cnc/Models/CncResult.cs`
- Factories: `Ok()`, `Fail()`, `Cancelled()`, `OkWithWarnings()`
- Properties: `Success`, `Errors`, `WasCancelled`, `Value`
**IFocasDialect:**
- Purpose: Abstract FOCAS version differences (Legacy vs Modern API)
- Location: `Cnc/Fanuc/IFocasDialect.cs`
- Implementations: `LegacyFocasDialect.cs`, `ModernFocasDialect.cs`
- Detection: `FanucDialectDetector.cs` at connect time
**CncMachineFactory:**
- Purpose: Create correct ICncMachine from InputArgs
- Location: `Cnc/CncMachineFactory.cs`
- Dispatches on: `CncManufacturer` enum (Fanuc, Heidenhain, Siemens, Mitsubishi)
## Entry Points
**CLI Entry:**
- Location: `Program.cs` (Main method)
- Triggers: Process execution from command line or calling application
- Responsibilities: Arg parsing → license check → machine factory → action dispatch → exit code
**Argument Parser:**
- Location: `ArgParser.cs` (static `Parse(string[])`)
- Returns: `InputArgs` with all 16 CLI parameters normalized
## Error Handling
**Strategy:** Result wrapper at CNC layer, exit codes at CLI boundary, ArgumentNullException for null guards
**Patterns:**
- `CncResult<T>.Fail(errors)` for CNC operation failures
- `ArgumentNullException` for constructor null guards (`Cnc/Fanuc/FanucMachine.cs`)
- Exit codes -100 to -208 in `Program.cs` for user-facing errors
- `try/finally` with `connected` flag for connection leak prevention (`Program.cs`)
- `catch { }` (silent) on disconnect cleanup paths — known weakness (see CONCERNS.md)
## Cross-Cutting Concerns
**Logging:**
- `Console.WriteLine` only — no structured logging framework
- Debug mode (`-debug=` arg): keeps terminal open after operation
**Validation:**
- `NcProgramValidator` injected into machine constructors
- Runs before upload; blocked on `ValidationSeverity.Error`
**Cancellation:**
- `CancellationToken` passed through all async methods
- CLI does not currently expose cancellation to user
---
*Architecture analysis: 2026-05-18*
*Update when major patterns change*