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

5.9 KiB

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:

  • 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