feat(rules): add shared development and security rules
This commit is contained in:
@@ -0,0 +1,375 @@
|
||||
# WPF Code Guidelines
|
||||
|
||||
* Use modern C# and current .NET/WPF conventions.
|
||||
* Keep UI, application logic and domain logic clearly separated.
|
||||
* Prefer MVVM for non-trivial views.
|
||||
* Keep code-behind minimal.
|
||||
* Use code-behind only for view-specific behavior that does not belong in the ViewModel.
|
||||
* Avoid business logic in views.
|
||||
* Avoid direct service access from controls.
|
||||
* Keep dependencies explicit and testable.
|
||||
* Prefer composition over inheritance.
|
||||
* Avoid unnecessary abstractions and framework wrappers.
|
||||
* Follow the existing project architecture unless there is a strong reason to change it.
|
||||
|
||||
## MVVM
|
||||
|
||||
* Keep ViewModels focused on presentation state and commands.
|
||||
* Do not put UI element references into ViewModels.
|
||||
* Do not access `Window`, `UserControl`, `DispatcherObject` or visual tree elements from ViewModels.
|
||||
* Avoid direct navigation, dialogs or message boxes from ViewModels without an abstraction when testability matters.
|
||||
* Prefer explicit application services for navigation, dialogs and external interactions.
|
||||
* Keep domain logic outside ViewModels.
|
||||
* Do not use ViewModels as general-purpose service containers.
|
||||
* Keep ViewModel dependencies minimal.
|
||||
* Prefer immutable or readonly state where practical.
|
||||
* Avoid duplicated derived state.
|
||||
* Keep state transitions predictable.
|
||||
|
||||
## Data Binding
|
||||
|
||||
* Prefer data binding over manual UI synchronization.
|
||||
* Use strongly typed properties.
|
||||
* Use appropriate binding modes.
|
||||
* Prefer `OneWay` when two-way updates are not required.
|
||||
* Use `TwoWay` only when the UI must modify the source.
|
||||
* Avoid unnecessary `UpdateSourceTrigger=PropertyChanged` for expensive operations.
|
||||
* Keep binding paths simple and stable.
|
||||
* Avoid deeply nested binding paths.
|
||||
* Do not hide broken bindings.
|
||||
* Treat binding errors as real defects.
|
||||
* Use `FallbackValue` and `TargetNullValue` only when they reflect intended behavior.
|
||||
* Avoid excessive converters.
|
||||
* Prefer exposing correctly shaped state from the ViewModel over complex converter logic.
|
||||
* Avoid `MultiBinding` when simpler state modeling is clearer.
|
||||
* Do not put business logic into converters.
|
||||
|
||||
## Property Change Notifications
|
||||
|
||||
* Implement property change notifications consistently.
|
||||
* Avoid raising `PropertyChanged` unnecessarily.
|
||||
* Raise notifications only when values actually change.
|
||||
* Keep dependent property notifications explicit.
|
||||
* Avoid hidden notification chains that are difficult to reason about.
|
||||
* Prefer reusable base implementations only when they reduce duplication without obscuring behavior.
|
||||
* Do not use reflection-based notification mechanisms unless there is a concrete benefit.
|
||||
|
||||
## Commands
|
||||
|
||||
* Prefer commands over click handlers for ViewModel-driven actions.
|
||||
* Keep command execution focused.
|
||||
* Avoid putting large workflows directly inside command implementations.
|
||||
* Keep `CanExecute` logic cheap.
|
||||
* Refresh command availability only when relevant state changes.
|
||||
* Avoid command implementations with hidden side effects.
|
||||
* Handle async commands safely.
|
||||
* Prevent accidental duplicate execution when an async action must not run concurrently.
|
||||
* Never use `async void` except for true event handlers.
|
||||
|
||||
## Async and Threading
|
||||
|
||||
* Keep async operations asynchronous throughout the call chain.
|
||||
* Avoid `.Result`, `.Wait()` and other synchronous blocking of async work.
|
||||
* Do not block the UI thread.
|
||||
* Run I/O asynchronously.
|
||||
* Move expensive CPU work off the UI thread only when necessary.
|
||||
* Marshal UI updates back to the UI thread when required.
|
||||
* Keep Dispatcher usage minimal and explicit.
|
||||
* Do not use the Dispatcher to hide incorrect threading design.
|
||||
* Support `CancellationToken` for cancellable long-running operations.
|
||||
* Cancel obsolete work when views or selections change.
|
||||
* Prevent race conditions caused by overlapping async operations.
|
||||
* Handle exceptions from background operations explicitly.
|
||||
|
||||
## UI Thread
|
||||
|
||||
* Treat the UI thread as a scarce resource.
|
||||
* Avoid expensive loops, parsing, serialization, database access or network calls on the UI thread.
|
||||
* Avoid excessive Dispatcher invocations.
|
||||
* Batch UI updates where practical.
|
||||
* Do not update UI-bound collections excessively in tight loops.
|
||||
* Avoid synchronous waits on background work.
|
||||
* Keep rendering-related callbacks lightweight.
|
||||
|
||||
## Collections
|
||||
|
||||
* Use `ObservableCollection<T>` only when collection change notifications are required.
|
||||
* Do not use `ObservableCollection<T>` as a general-purpose collection.
|
||||
* Use `List<T>` or other suitable collections for non-observable internal data.
|
||||
* Avoid replacing entire observable collections when incremental updates are sufficient.
|
||||
* Avoid thousands of individual collection notifications when a bulk update is more appropriate.
|
||||
* Keep collection mutations on the correct thread.
|
||||
* Avoid exposing mutable internal collections unnecessarily.
|
||||
* Prefer read-only views where consumers should not modify data.
|
||||
|
||||
## XAML
|
||||
|
||||
* Keep XAML readable and focused.
|
||||
* Avoid excessively large view files.
|
||||
* Split complex views into focused controls when it improves maintainability.
|
||||
* Use resources for repeated values and styles.
|
||||
* Avoid magic numbers in XAML.
|
||||
* Keep styles and templates consistent.
|
||||
* Avoid excessive inline styling.
|
||||
* Prefer reusable resources over duplicated markup.
|
||||
* Avoid deeply nested panels.
|
||||
* Keep visual trees as shallow as practical.
|
||||
* Use semantic control choices.
|
||||
* Avoid unnecessary containers.
|
||||
* Do not overuse triggers when simpler state representation is possible.
|
||||
* Keep templates understandable.
|
||||
* Avoid XAML tricks that make behavior hard to discover.
|
||||
|
||||
## Layout
|
||||
|
||||
* Prefer `Grid` for structured layouts.
|
||||
* Use `StackPanel` only where its layout behavior is actually appropriate.
|
||||
* Avoid unnecessary nested panels.
|
||||
* Avoid fixed sizes unless the design requires them.
|
||||
* Prefer responsive sizing with `Auto` and `*`.
|
||||
* Avoid layout configurations that cause excessive measure/arrange passes.
|
||||
* Be careful with large visual trees inside scrolling containers.
|
||||
* Avoid disabling virtualization accidentally.
|
||||
|
||||
## Virtualization
|
||||
|
||||
* Keep UI virtualization enabled for large collections.
|
||||
* Do not use container layouts that disable virtualization without a reason.
|
||||
* Avoid wrapping large virtualized item lists in additional scrolling containers.
|
||||
* Use virtualizing panels where appropriate.
|
||||
* Verify virtualization when displaying large data sets.
|
||||
* Avoid rendering thousands of controls simultaneously.
|
||||
* Prefer paging, incremental loading or virtualization for very large data sets.
|
||||
|
||||
## Resources and Styles
|
||||
|
||||
* Use shared resources for repeated styles, brushes, templates and dimensions.
|
||||
* Keep resource dictionaries focused.
|
||||
* Avoid giant global resource dictionaries.
|
||||
* Prefer feature-level resources when styles are not truly global.
|
||||
* Use `StaticResource` by default.
|
||||
* Use `DynamicResource` only when runtime resource replacement is required.
|
||||
* Avoid excessive dynamic resource lookups.
|
||||
* Keep theme resources separated from application logic.
|
||||
* Avoid hardcoded colors and dimensions when design tokens or resources already exist.
|
||||
|
||||
## Dependency Properties
|
||||
|
||||
* Use dependency properties only when WPF property-system behavior is required.
|
||||
* Do not use dependency properties as a replacement for normal CLR properties.
|
||||
* Keep metadata and callbacks lightweight.
|
||||
* Avoid expensive work in property-changed callbacks.
|
||||
* Avoid callbacks with hidden side effects.
|
||||
* Validate or coerce values only when the control contract requires it.
|
||||
* Do not expose mutable default values in dependency property metadata.
|
||||
|
||||
## Attached Properties and Behaviors
|
||||
|
||||
* Use attached properties and behaviors for reusable view-specific behavior.
|
||||
* Do not use them to hide business logic.
|
||||
* Keep behaviors focused and predictable.
|
||||
* Clean up event handlers when behaviors are detached.
|
||||
* Avoid global attached-property state.
|
||||
* Prefer explicit behavior over complex XAML hacks.
|
||||
|
||||
## Events
|
||||
|
||||
* Avoid unnecessary event subscriptions.
|
||||
* Unsubscribe from long-lived publishers when required.
|
||||
* Prevent memory leaks from event handlers.
|
||||
* Prefer weak events where publisher lifetime significantly exceeds subscriber lifetime.
|
||||
* Keep event handlers small.
|
||||
* Do not use events as hidden global communication channels.
|
||||
* Avoid excessive event chaining.
|
||||
|
||||
## Memory Management
|
||||
|
||||
* Watch for memory leaks caused by:
|
||||
|
||||
* Event subscriptions
|
||||
* Timers
|
||||
* Static references
|
||||
* Long-lived services
|
||||
* Cached views
|
||||
* Closures
|
||||
* Collection views
|
||||
* Binding-related references
|
||||
* Dispose resources correctly.
|
||||
* Stop timers and background work when no longer needed.
|
||||
* Avoid retaining closed windows or unloaded views.
|
||||
* Do not keep unnecessary references to visual elements.
|
||||
* Profile memory when long-running applications continuously grow.
|
||||
|
||||
## Windows and Dialogs
|
||||
|
||||
* Keep window lifecycle explicit.
|
||||
* Avoid creating duplicate windows unintentionally.
|
||||
* Do not keep hidden windows alive without a reason.
|
||||
* Separate dialog logic from business logic.
|
||||
* Prefer dialog services when ViewModels need to request user interaction.
|
||||
* Keep ownership relationships explicit.
|
||||
* Avoid application shutdown behavior that depends on accidental window lifetime.
|
||||
|
||||
## Navigation
|
||||
|
||||
* Keep navigation state explicit.
|
||||
* Avoid coupling ViewModels directly to concrete views.
|
||||
* Avoid service locator patterns for view resolution.
|
||||
* Keep navigation history intentional.
|
||||
* Dispose or release navigation targets when they are no longer required.
|
||||
* Do not retain entire navigation graphs unnecessarily.
|
||||
|
||||
## Validation
|
||||
|
||||
* Validate user input at the appropriate boundary.
|
||||
* Keep validation logic out of XAML when it becomes complex.
|
||||
* Prefer reusable validation rules or ViewModel validation for non-trivial cases.
|
||||
* Display validation errors consistently.
|
||||
* Do not rely on UI validation as a security boundary.
|
||||
* Validate again at backend or domain boundaries when required.
|
||||
* Preserve user input on recoverable errors.
|
||||
|
||||
## Performance
|
||||
|
||||
* Keep the UI thread responsive.
|
||||
* Minimize visual tree depth.
|
||||
* Keep virtualization enabled.
|
||||
* Avoid unnecessary bindings.
|
||||
* Avoid unnecessary converters.
|
||||
* Avoid unnecessary resource lookups.
|
||||
* Avoid unnecessary property change notifications.
|
||||
* Avoid frequent full collection refreshes.
|
||||
* Avoid loading large datasets eagerly.
|
||||
* Avoid loading large images at full resolution when unnecessary.
|
||||
* Freeze `Freezable` objects where practical.
|
||||
* Reuse immutable resources where appropriate.
|
||||
* Avoid unnecessary animations.
|
||||
* Avoid high-frequency timers on the UI thread.
|
||||
* Measure startup time, UI responsiveness, memory usage and rendering performance before micro-optimizing.
|
||||
|
||||
## Images and Media
|
||||
|
||||
* Load images at an appropriate resolution.
|
||||
* Avoid decoding images significantly larger than their displayed size.
|
||||
* Release streams and file handles correctly.
|
||||
* Avoid locking image files unintentionally.
|
||||
* Cache images only when there is a clear memory strategy.
|
||||
* Avoid keeping large bitmaps alive unnecessarily.
|
||||
* Prefer frozen image resources when they are immutable.
|
||||
|
||||
## Security
|
||||
|
||||
* Treat all external input as untrusted.
|
||||
* Never expose secrets, credentials or tokens in UI code.
|
||||
* Do not store secrets in configuration files committed to source control.
|
||||
* Avoid leaking sensitive information through logs, dialogs or exception messages.
|
||||
* Validate file paths and external resources.
|
||||
* Do not execute external processes or files without explicit validation.
|
||||
* Avoid insecure deserialization.
|
||||
* Do not weaken TLS, authentication or certificate validation.
|
||||
* Prefer secure defaults.
|
||||
* Never disable security controls for convenience.
|
||||
|
||||
## File and Process Access
|
||||
|
||||
* Validate file paths before use.
|
||||
* Avoid assuming files or directories exist.
|
||||
* Handle permissions and locked files gracefully.
|
||||
* Avoid arbitrary shell execution.
|
||||
* Quote and validate process arguments safely.
|
||||
* Do not concatenate untrusted input into shell commands.
|
||||
* Avoid elevated privileges unless explicitly required.
|
||||
* Clean up temporary files when appropriate.
|
||||
|
||||
## Error Handling
|
||||
|
||||
* Handle expected errors explicitly.
|
||||
* Do not swallow exceptions.
|
||||
* Preserve useful exception context.
|
||||
* Avoid showing raw technical exceptions directly to end users.
|
||||
* Log enough information for diagnosis without exposing sensitive data.
|
||||
* Keep user-facing error messages clear and actionable.
|
||||
* Avoid using exceptions for normal control flow.
|
||||
* Ensure background exceptions are observed.
|
||||
|
||||
## Logging
|
||||
|
||||
* Use structured logging.
|
||||
* Avoid excessive logging on the UI thread.
|
||||
* Do not log every property change or binding update.
|
||||
* Never log secrets, tokens, credentials or sensitive user data.
|
||||
* Include relevant context for operational failures.
|
||||
* Avoid logging the same exception repeatedly at multiple layers.
|
||||
|
||||
## Architecture
|
||||
|
||||
* Keep presentation, application, domain and infrastructure concerns separated.
|
||||
* Avoid direct database access from views or ViewModels.
|
||||
* Avoid direct HTTP access from controls.
|
||||
* Keep external integrations behind focused services.
|
||||
* Avoid circular dependencies.
|
||||
* Keep feature boundaries clear.
|
||||
* Do not create shared utility classes for unrelated functionality.
|
||||
* Keep shared code genuinely reusable.
|
||||
* Minimize global state.
|
||||
* Avoid static service access.
|
||||
|
||||
## Dependency Injection
|
||||
|
||||
* Use dependency injection where lifecycle management, substitution or testability benefits from it.
|
||||
* Avoid service locator patterns.
|
||||
* Keep constructor dependencies minimal.
|
||||
* Do not inject dependencies that are not used.
|
||||
* Choose service lifetimes intentionally.
|
||||
* Do not make stateful services global without a concrete reason.
|
||||
* Avoid introducing interfaces solely for dependency injection when no abstraction is needed.
|
||||
|
||||
## Testing
|
||||
|
||||
* Keep ViewModels testable without a UI thread where practical.
|
||||
* Test behavior rather than implementation details.
|
||||
* Test domain and application logic independently from WPF.
|
||||
* Avoid brittle tests coupled to XAML structure.
|
||||
* Keep UI automation tests focused on critical flows.
|
||||
* Mock external boundaries rather than internal details.
|
||||
* Keep tests deterministic.
|
||||
* Avoid real network, database or filesystem dependencies in unit tests unless explicitly intended.
|
||||
|
||||
## Code Quality
|
||||
|
||||
* Use nullable reference types.
|
||||
* Prefer modern, readable C# syntax.
|
||||
* Avoid unnecessary interfaces and abstractions.
|
||||
* Prefer concrete types where no abstraction is required.
|
||||
* Use descriptive names.
|
||||
* Remove dead code.
|
||||
* Remove commented-out code.
|
||||
* Do not add comments unless the user explicitly requests them.
|
||||
* Treat compiler, analyzer and binding warnings seriously.
|
||||
* Do not suppress warnings without a concrete reason.
|
||||
* Prefer correctness, responsiveness, security and maintainability over cleverness.
|
||||
|
||||
## Performance Priority
|
||||
|
||||
Prioritize WPF performance work in this order:
|
||||
|
||||
* UI architecture
|
||||
* UI thread blocking
|
||||
* Data loading and I/O
|
||||
* Virtualization
|
||||
* Visual tree complexity
|
||||
* Binding and notification frequency
|
||||
* Rendering and images
|
||||
* Memory retention and leaks
|
||||
* Allocations
|
||||
* CPU micro-optimizations
|
||||
|
||||
Never optimize based purely on assumptions.
|
||||
|
||||
## Safety Rule
|
||||
|
||||
* The UI must remain responsive.
|
||||
* Do not block the UI thread with I/O or expensive CPU work.
|
||||
* Do not bypass validation or security controls for convenience.
|
||||
* Do not introduce hidden cross-thread access.
|
||||
* Prefer predictable, explicit and testable UI behavior.
|
||||
Reference in New Issue
Block a user