fix: resolve code-review findings in binders and collections#120
Conversation
Fixes surfaced by the max-effort review of PR #25 (Aspid.MVVM 1.1.0): - CollectionViewModelBinder: rebuild positional views on Move (the sibling-index swap was wrong for moves of distance > 1) and guard the view array against out-of-range; dedup the four granular hooks into RebuildFromCollection. - ImageSpriteBinder/Mono: clear Image.sprite on unbind so it no longer references the destroyed generated sprite; share a CreateSprite helper. - RendererMaterialColorSwitcherBinder: cache the materials array to drop the per-value Material[] allocation. - OrCompositeCollectionFilter: an all-empty filter now passes all items (consistent with And), implemented allocation-free. - VirtualizedList: OnMove window check uses < (matching OnAdded/OnRemoved); window-gate batch add/remove instead of unconditional Refresh. - ToCultureStringExtensions: delegate the overloads to the existing ToCultureInfo helper. - ObservableListViewModelBinder twins: extract shared view-list bookkeeping into ObservableListViewModelBinderHelper. Authored without an in-Editor Unity compile; verify by compiling in Unity.
|
@claude once |
|
Claude finished @VPDPersonal's task in 2m 50s —— View job Code ReviewOverall, the changes are clean and well-targeted. The four-hook dedup, P1 — Bug introduced by this PR
protected override void OnUnbound()
{
_materials = null; // ← base.OnUnbound() is never called
}This override is new in this PR — the method didn't exist before. Before this change the base class's Fix: protected override void OnUnbound()
{
_materials = null;
base.OnUnbound();
}P2 — Pre-existing indexing hole worth closing now
protected override void OnReplace(IViewModel? oldItem, IViewModel? newItem, int newStartingIndex)
{
_views[newStartingIndex].Deinitialize(); // ← throws if newStartingIndex >= _views.Length
if (newItem is not null)
_views[newStartingIndex].Initialize(newItem);
}
protected override void OnReplace(IViewModel? oldItem, IViewModel? newItem, int newStartingIndex)
{
if (newStartingIndex >= _views.Length) return;
_views[newStartingIndex].Deinitialize();
if (newItem is not null)
_views[newStartingIndex].Initialize(newItem);
}P3 —
|
Address review feedback on this PR: - Move ObservableListViewModelBinderHelper and the sprite CreateSprite helper into their own files (ObservableListViewModelBinderHelper.cs, SpriteBinderHelper.cs) instead of living inside a binder class. - Call base.OnUnbound() in RendererMaterialColorSwitcherBinder — the override added earlier in this PR was silently dropping the base-class cleanup; also add it to ImageSpriteBinder/Mono to follow the codebase convention. - Guard CollectionViewModelBinder.OnReplace against an out-of-range index, mirroring the OnAdded guard. - Add missing trailing newlines on touched files.
Addressed review feedback —
|
Summary
Fixes from the max-effort code review of #25 (Aspid.MVVM 1.1.0). 12 of 13 findings addressed:
Move(the sibling-index swap displayed the wrong order for moves of distance > 1), guard the view array against out-of-range growth, and dedup the four granular hooks intoRebuildFromCollection().Image.spriteon unbind so it no longer references the destroyed generated sprite; share aCreateSpritehelper.Renderer.materialsarray to drop the per-valueMaterial[]allocation; clear on unbind.And), implemented allocation-free.OnMovewindow check uses<(matchingOnAdded/OnRemoved); window-gate the batchOnAdded/OnRemovedinstead of an unconditionalRefresh().ToCultureStringoverloads to the existingToCultureInfohelper.ObservableListViewModelBinderHelper.Notes for review
float→double(finding 5) — reverted:_valueis a[SerializeField], so the type change risks resetting the threshold on existing serialized assets. The edge case (threshold > 2^24) is not worth the migration risk.[SerializeReference]fields plus the Mono/non-MonogameObjectvisibility difference make a blind refactor unsafe).Linked issues
Refs #25