- Use PascalCase for classes, interfaces, methods, properties, and public members
- Prefix interfaces with
I(e.g.,IAIService,INavigationService) - Suffix async methods with
Async(e.g.,InitializeAsync,LoadDataAsync) - Use descriptive, self-documenting names
- Use singular nouns for classes (e.g.,
TaskScheduler, notTaskSchedulers)
- Use abbreviations unless widely understood (e.g.,
ctxis acceptable,mgris not) - Use Hungarian notation (e.g.,
strName,intCount) - Use underscores in public identifiers (private fields may use
_prefix)
- Prefer lightweight, modular, and future-proof architecture
- Separate concerns: Core (interfaces), Infrastructure (implementations), UI (presentation)
- Use Dependency Injection for all service dependencies
- Design for extensibility: modules should auto-discover and register themselves
- Keep Core layer dependency-free (interfaces and models only)
- Use interfaces for all services to enable testing and swapping implementations
- Create "God Objects" that do everything (e.g., avoid monolithic
IMnemoAPI) - Hard-code module registration in startup code
- Mix business logic with UI code
- Create circular dependencies between layers
- Group related functionality into namespaces:
Mnemo.Core.Servicesfor service interfacesMnemo.Core.Modelsfor data modelsMnemo.Infrastructurefor implementationsMnemo.UI.Componentsfor reusable UI components
- Keep files focused: one class/interface per file
- Use
partialclasses only when necessary (e.g., code-behind files)
- Put implementations in the Core layer
- Mix UI components with business logic
- Create deep namespace hierarchies (max 3-4 levels)
- Use
async/awaitfor all I/O operations - Return
TaskorTask<T>from async methods - Use
CancellationTokenparameters in long-running operations - Use
ConfigureAwait(false)in library code when appropriate
- Block async code with
.Resultor.Wait() - Mix async and sync code without careful consideration
- Ignore cancellation tokens
- Use exceptions for exceptional circumstances
- Return
Result<T>orboolfor expected failure cases - Log errors with context (use structured logging when possible)
- Handle exceptions at appropriate boundaries (UI, service boundaries)
- Swallow exceptions silently
- Use exceptions for control flow
- Catch
Exceptionwithout re-throwing or logging
- Use MVVM pattern: ViewModels contain logic, Views are declarative
- Bind to ViewModels, not directly to services
- Use Avalonia's built-in controls when possible
- Create custom controls only when adding new functionality (not just styling)
- Use styles/themes for visual customization, not subclassing controls
- Put business logic in code-behind files
- Create custom controls just to change colors/borders (use styles instead)
- Hard-code strings in UI (use localization)
- Block the UI thread with long-running operations
- Use SQLite for runtime data
- Use
.mnemoZIP format for portable exports - Separate runtime storage from packaged storage
- Version your data schemas
- Store large binary data in SQLite (use file system with references)
- Mix runtime and packaged data without clear boundaries
- Create storage without migration paths
- Implement
IModuleinterface for auto-discovery - Register services, routes, and tools in module initialization
- Use
IFunctionRegistryfor AI tool registration - Design APIs that extensions can consume
- Require manual registration of modules
- Create tight coupling between modules
- Expose internal implementation details to extensions
- Profile before optimizing
- Use lazy loading for heavy resources
- Cache expensive computations
- Use appropriate data structures (e.g.,
ConcurrentDictionaryfor thread-safe lookups)
- Prematurely optimize
- Load all data at startup
- Create memory leaks (unsubscribe from events, dispose resources)
- Write unit tests for business logic
- Mock dependencies using interfaces
- Test edge cases and error conditions
- Test implementation details
- Create tests that depend on external resources without mocking
- Skip testing error paths
- Add XML documentation comments for public APIs
- Document complex algorithms and business rules
- Keep README files updated
- Document obvious code (e.g.,
// Sets the name) - Leave TODO comments without tracking issues
- Write documentation that duplicates the code