Skip to content

Commit d9d2c3c

Browse files
committed
docs(avalonia): add development guidelines with error handling principles
1 parent f7ab080 commit d9d2c3c

File tree

1 file changed

+138
-0
lines changed

1 file changed

+138
-0
lines changed

avalonia-gui/CLAUDE.md

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# Avalonia GUI - Development Guidelines
2+
3+
Cross-platform ARM emulator GUI built with Avalonia and .NET 10.
4+
5+
## Prerequisites
6+
7+
- .NET SDK 10.0+ ([https://dot.net](https://dot.net))
8+
- macOS 26.2 / Windows / Linux
9+
10+
## Architecture
11+
12+
- **Pattern:** MVVM with ReactiveUI
13+
- **Backend Connection:** HTTP REST API (port 8080) + WebSocket
14+
- **Language:** C# 13 with modern idioms
15+
16+
## Development Workflow
17+
18+
### Before Every Commit (MANDATORY)
19+
20+
```bash
21+
# 1. Format code
22+
dotnet format
23+
24+
# 2. Build (must succeed)
25+
dotnet build
26+
27+
# 3. Run tests (must pass)
28+
dotnet test
29+
```
30+
31+
**All three must complete successfully before committing.**
32+
33+
### Build & Run
34+
35+
```bash
36+
# Build
37+
dotnet build
38+
39+
# Run application
40+
dotnet run --project ARMEmulator
41+
42+
# Run tests
43+
dotnet test
44+
```
45+
46+
### Line Endings
47+
48+
**CRITICAL:** Always use LF (Unix) line endings, never CRLF.
49+
50+
- Configure your editor to use LF for this project
51+
- Git is configured to enforce this via `.gitattributes`
52+
53+
## Code Style
54+
55+
### Modern C# 13 Features (Use These)
56+
57+
- **Primary constructors** for dependency injection
58+
- **Collection expressions** `[item1, item2]` instead of `new List<T> { ... }`
59+
- **Records** for immutable data models
60+
- **Pattern matching** (switch expressions, property patterns)
61+
- **Immutable collections** (`ImmutableArray<T>`, `ImmutableList<T>`)
62+
- **File-scoped namespaces** (`namespace Foo;` not `namespace Foo { }`)
63+
- **Nullable reference types** (enabled, treat warnings as errors)
64+
- **Target-typed new** (`Thing x = new();`)
65+
66+
### Reactive Extensions (Rx)
67+
68+
Use ReactiveUI patterns:
69+
- `ObservableAsPropertyHelper<T>` for derived properties
70+
- `ReactiveCommand` for commands
71+
- `WhenAnyValue()` for property change subscriptions
72+
- Proper disposal of subscriptions
73+
74+
### Error Handling
75+
76+
Use **idiomatic .NET exception-based error handling** (not Result/Either monads):
77+
78+
- **Let exceptions propagate** - don't catch just to log and rethrow
79+
- **Catch only at boundaries** where you can meaningfully handle errors (ViewModels for UI feedback)
80+
- **Use domain-specific exceptions** (`ApiException`, `SessionNotFoundException`, etc.)
81+
- **Don't catch-and-wrap** without adding useful context
82+
- **Avoid anti-patterns:**
83+
-`catch (Exception) { return null; }` - hides failures
84+
-`catch (Exception ex) { Log(ex); throw; }` - noise
85+
- ❌ Pokemon exception handling (catch 'em all) at low levels
86+
87+
**See:** `../docs/AVALONIA_IMPLEMENTATION_PLAN.md` section "Exception Handling Philosophy" for detailed examples
88+
89+
### Naming Conventions
90+
91+
- **Public properties/methods:** PascalCase
92+
- **Private fields:** _camelCase with underscore
93+
- **Local variables:** camelCase
94+
- **Constants:** PascalCase
95+
- **Interfaces:** IPrefixed
96+
97+
### Code Organization
98+
99+
- **ViewModels:** One per view, inherit from `ViewModelBase`
100+
- **Services:** Stateless, injected via constructor
101+
- **Models:** Immutable records when possible
102+
- **Views:** XAML with code-behind minimal (logic in ViewModel)
103+
104+
## Backend API Integration
105+
106+
**⚠️ CRITICAL:** Backend API is shared with Swift GUI.
107+
108+
- **NO breaking changes** to API contracts
109+
- Only additive changes allowed
110+
- Coordinate any API modifications with Swift GUI team
111+
- Test against running Go backend (`make build && ./arm-emulator`)
112+
113+
### API Communication
114+
115+
- **REST API:** Synchronous operations (load program, step, reset)
116+
- **WebSocket:** Real-time updates (execution state, register changes)
117+
- **Base URL:** `http://localhost:8080`
118+
119+
## Testing
120+
121+
- Write tests for ViewModels and Services
122+
- Mock backend services for unit tests
123+
- Integration tests should use real WebSocket/HTTP (with backend running)
124+
- Aim for high coverage of business logic
125+
126+
## Common Pitfalls
127+
128+
- ❌ Don't forget to dispose subscriptions
129+
- ❌ Don't put logic in code-behind (use ViewModel)
130+
- ❌ Don't use CRLF line endings
131+
- ❌ Don't commit without running `dotnet format && dotnet build && dotnet test`
132+
- ❌ Don't make breaking API changes
133+
134+
## Additional Documentation
135+
136+
- **Implementation Plan:** `../docs/AVALONIA_IMPLEMENTATION_PLAN.md`
137+
- **API Reference:** See Go backend `api/` directory
138+
- **Main Project Docs:** `../CLAUDE.md`

0 commit comments

Comments
 (0)