forked from NationTech/harmony
		
	adr: proposal serde for score data representation and UI rendering
Decouples score definitions from UI implementations by mandating `serde::Serialize` and `serde::Deserialize` for all `Score` structs. UIs will interact with scores via their serialized representation, enabling scalability and reducing complexity for score authors. This approach: - Scales better with new score types and UI targets. - Simplifies score authoring by removing the need for UI-specific display traits. - Leverages the `serde` ecosystem for robust data handling. Adding new field types requires updates to all UIs, a trade-off acknowledged in the ADR.
This commit is contained in:
		
							parent
							
								
									b4cc5cff4f
								
							
						
					
					
						commit
						1cbf4de2a1
					
				
							
								
								
									
										62
									
								
								adr/008-score-display-formatting.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								adr/008-score-display-formatting.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,62 @@ | |||||||
|  | ## Architecture Decision Record: Data Representation and UI Rendering for Score Types | ||||||
|  | 
 | ||||||
|  | **Status:** Proposed | ||||||
|  | 
 | ||||||
|  | **TL;DR:** `Score` types will be serialized (using `serde`) for presentation in UIs. This decouples data definition from presentation, improving scalability and reducing complexity for developers defining `Score` types. New UI types only need to handle existing field types, and new `Score` types don’t require UI changes as long as they use existing field types.  Adding a new field type *does* require updates to all UIs. | ||||||
|  | 
 | ||||||
|  | **Key benefits:** Scalability, reduced complexity for `Score` authors, decoupling of data and presentation. | ||||||
|  | 
 | ||||||
|  | **Key trade-off:** Adding new field types requires updating all UIs. | ||||||
|  | 
 | ||||||
|  | --- | ||||||
|  | 
 | ||||||
|  | **Context:** | ||||||
|  | 
 | ||||||
|  | Harmony is a pure Rust infrastructure orchestrator focused on compile-time safety and providing a developer-friendly, Ansible-module-like experience for defining infrastructure configurations via "Scores". These Scores (e.g., `LAMPScore`) are Rust structs composed of specific, strongly-typed fields (e.g., `VersionField`, `UrlField`, `PathField`) which are validated at compile-time using macros (`Version!`, `Url!`, etc.). | ||||||
|  | 
 | ||||||
|  | A key requirement is displaying the configuration defined in these Scores across various user interfaces (Web UI, TUI, potentially Mobile UI, etc.) in a consistent and type-safe manner. As the number of Score types is expected to grow significantly (hundreds or thousands), we need a scalable approach for rendering their data that avoids tightly coupling Score definitions to specific UI implementations. | ||||||
|  | 
 | ||||||
|  | The primary challenge is preventing the need for every `Score` struct author to implement multiple display traits (e.g., `Display`, `WebDisplay`, `TuiDisplay`) for every potential UI target. This would create an N x M complexity problem (N Scores * M UI types) and place an unreasonable burden on Score developers, hindering scalability and maintainability. | ||||||
|  | 
 | ||||||
|  | **Decision:** | ||||||
|  | 
 | ||||||
|  | 1.  **Mandatory Serialization:** All `Score` structs *must* implement `serde::Serialize` and `serde::Deserialize`. They *will not* be required to implement `std::fmt::Display` or any custom UI-specific display traits (e.g., `WebDisplay`, `TuiDisplay`). | ||||||
|  | 2.  **Field-Level Rendering:** Responsibility for rendering data will reside within the UI components. Each UI (Web, TUI, etc.) will implement logic to display *individual field types* (e.g., `UrlField`, `VersionField`, `IpAddressField`, `SecretField`). | ||||||
|  | 3.  **Data Access via Serialization:** UIs will primarily interact with `Score` data through its serialized representation (e.g., JSON obtained via `serde_json`). This provides a standardized interface for UIs to consume the data structure agnostic of the specific `Score` type. Alternatively, UIs *could* potentially use reflection or specific visitor patterns on the `Score` struct itself, but serialization is the preferred decoupling mechanism. | ||||||
|  | 
 | ||||||
|  | **Rationale:** | ||||||
|  | 
 | ||||||
|  | 1.  **Decoupling Data from Presentation:** This decision cleanly separates the data definition (`Score` structs and their fields) from the presentation logic (UI rendering). `Score` authors can focus solely on defining the data and its structure, while UI developers focus on how to best present known data *types*. | ||||||
|  | 2.  **Scalability:** This approach scales significantly better than requiring display trait implementations on Scores: | ||||||
|  |     *   Adding a *new Score type* requires *no changes* to existing UI code, provided it uses existing field types. | ||||||
|  |     *   Adding a *new UI type* requires implementing rendering logic only for the defined set of *field types*, not for every individual `Score` type. This reduces the N x M complexity to N + M complexity (approximately). | ||||||
|  | 3.  **Simplicity for Score Authors:** Requiring only `serde::Serialize + Deserialize` (which can often be derived automatically with `#[derive(Serialize, Deserialize)]`) is a much lower burden than implementing custom rendering logic for multiple, potentially unknown, UI targets. | ||||||
|  | 4.  **Leverages Rust Ecosystem Standards:** `serde` is the de facto standard for serialization and deserialization in Rust. Relying on it aligns with common Rust practices and benefits from its robustness, performance, and extensive tooling. | ||||||
|  | 5.  **Consistency for UIs:** Serialization provides a consistent, structured format (like JSON) for UIs to consume data, regardless of the underlying `Score` struct's complexity or composition. | ||||||
|  | 6.  **Flexibility for UI Implementation:** UIs can choose the best way to render each field type based on their capabilities (e.g., a `UrlField` might be a clickable link in a Web UI, plain text in a TUI; a `SecretField` might be masked). | ||||||
|  | 
 | ||||||
|  | **Consequences:** | ||||||
|  | 
 | ||||||
|  | **Positive:** | ||||||
|  | 
 | ||||||
|  | *   Greatly improved scalability for adding new Score types and UI targets. | ||||||
|  | *   Strong separation of concerns between data definition and presentation. | ||||||
|  | *   Reduced implementation burden and complexity for Score authors. | ||||||
|  | *   Consistent mechanism for UIs to access and interpret Score data. | ||||||
|  | *   Aligns well with the Hexagonal Architecture (ADR-002) by treating UIs as adapters interacting with the application core via a defined port (the serialized data contract). | ||||||
|  | 
 | ||||||
|  | **Negative:** | ||||||
|  | 
 | ||||||
|  | *   Adding a *new field type* (e.g., `EmailField`) requires updates to *all* existing UI implementations to support rendering it. | ||||||
|  | *   UI components become dependent on the set of defined field types and need comprehensive logic to handle each one appropriately. | ||||||
|  | *   Potential minor overhead of serialization/deserialization compared to direct function calls (though likely negligible for UI purposes). | ||||||
|  | *   Requires careful design and management of the standard library of field types. | ||||||
|  | 
 | ||||||
|  | **Alternatives Considered:** | ||||||
|  | 
 | ||||||
|  | 1.  **`Score` Implements `std::fmt::Display`:** | ||||||
|  |     *   _Rejected:_ Too simplistic. Only suitable for basic text rendering, doesn't cater to structured UIs (Web, etc.), and doesn't allow type-specific rendering logic (e.g., masking secrets). Doesn't scale to multiple UI formats. | ||||||
|  | 2.  **`Score` Implements Multiple Custom Display Traits (`WebDisplay`, `TuiDisplay`, etc.):** | ||||||
|  |     *   _Rejected:_ Leads directly to the N x M complexity problem. Tightly couples Score definitions to specific UI implementations. Places an excessive burden on Score authors, hindering adoption and scalability. | ||||||
|  | 3.  **Generic Display Trait with Context (`Score` implements `DisplayWithContext<UIContext>`):** | ||||||
|  |     *   _Rejected:_ More flexible than multiple traits, but still requires Score authors to implement potentially complex rendering logic within the `Score` definition itself. The `Score` would still need awareness of different UI contexts, leading to undesirable coupling. Managing context types adds complexity. | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user