RecipeMetadataRegistry: move combo-box provisioning to UI; route config defects through Result instead of constructor throws

Open
#111 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
38/100
Issue type
Refactor
Clarity
Mostly clear
Activity status
Quiet
Tech stack
csharp
Domain
backend, frontend

Research direction

Start with Recipes/RecipeMetadataRegistry.cs and Recipes/ComboBoxItemViewModel.cs, then trace the existing Core GetGroup/GetAllActions APIs and Configuration/Validation/CrossReferenceValidator and DefaultValueValidator. Check how ConfigFacade produces the report shown in ErrorWindow. Done means UI combo-box provisioning is outside Core, configuration defects flow through Result, and the inconsistent lazy cache is removed.

Written by the indexing model from the issue text.

Description

enhancement

Summary

The domain metadata registry carries UI presentation concerns and reports configuration defects inconsistently with the rest of the config pipeline. Three related findings in one class.

1. UI combo-box concerns live in Core

  • Recipes/ComboBoxItemViewModel.cs:3 — a type named and shaped for Avalonia ComboBox binding sits in the Core domain layer.
  • Recipes/RecipeMetadataRegistry.cs:21-24, 177-205GetComboBoxItems/GetActionComboBoxItems caches whose XML docs reason about "UI bindings (per-row dictionaries on RecipeRowViewModel)" and "the cell factory". The registry even bends its own error contract for the binding pipeline: "Diverges from the Result pattern ... so that UI bindings ... can hold an empty-but-valid reference" (172-176).

Core has no Avalonia reference (good), but the concept leaked: UI presentation changes force Core edits.

Fix: move ComboBoxItemViewModel and both cache methods into SemiStep.UI (e.g. a provider in RecipeGrid) built on the existing Core primitives GetGroup/GetAllActions. The registry keeps one consistent Result-based contract.

2. Config defects throw where the rest of the pipeline returns Result

RecipeMetadataRegistry.cs:81, 107, 224, 244, 257, 274 — six InvalidOperationException throws in the constructor path for configuration defects (unresolved column/property references, string max-length rules). The same class of defects is reported via Result by Configuration/Validation/*. A bad config slipping past validators crashes DI container resolution instead of producing the aggregated report shown in ErrorWindow.

Fix: move EnsureColumnPropertyReferencesResolve and ResolveStringMaxLength rules into CrossReferenceValidator/DefaultValueValidator so all verdicts flow through ConfigFacade; keep constructor throws only as assertions of already-validated input.

3. Inconsistent lazy-cache thread safety

RecipeMetadataRegistry.cs:21-24, 202_comboItemsByGroup is a ConcurrentDictionary with a comment justifying concurrent access, yet _actionComboBoxItems ??= ... two members later is a plain non-thread-safe lazy field. Benign race (worst case a duplicate list), but the class contradicts its own stated concurrency model. Disappears if finding 1 is fixed.

Dominant language
C#
Stars
3
Forks
1
PR merge metrics
No merged PRs in 30d

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from Semiteq/SemiStep

All issues in Semiteq/SemiStep

Similar issues

More C# issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.