microsoft / microsoft/FluidFramework

Duplicate Code: sequence field codec mark encode/decode loops (V2 vs V3)

Open
#26,856 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
TypeScript
Stars
4.9k
Forks
586
Avg merge
1d 15h
Merged PRs (30d)
146

Description

🔍 Duplicate Code Detected: Sequence field codec mark encode/decode loops

Analysis of commit 0350e0deb1b4ad2e1a060a7c65fded411de6882c

Assignee: @copilot

Summary

The sequence-field codecs for format V2 and V3 contain a largely duplicated encode/decode loop that walks the marks array and maps common fields (count, effect, cellId, changes). This duplication is >10 lines and increases maintenance risk when evolving the wire format or adding mark fields.

Duplication Details

Pattern: Encode/decode loops for Changeset marks
  • Severity: Medium

  • Occurrences: 2

  • Locations:

    • packages/dds/tree/src/feature-libraries/sequence-field/sequenceFieldCodecV2.ts (lines 283-345)
    • packages/dds/tree/src/feature-libraries/sequence-field/sequenceFieldCodecV3.ts (lines 93-141)
  • Code Sample (duplicated structure):

    V2 (excerpt):

    const jsonMarks: Encoded.Changeset(NodeChangeSchema) = [];
    for (const mark of changeset) {
      const encodedMark: Encoded.Mark(NodeChangeSchema) = { count: mark.count };
      if (!isNoopMark(mark)) {
        encodedMark.effect = markEffectCodec.encode(mark, context.baseContext);
      }
      if (mark.cellId !== undefined) {
        encodedMark.cellId = changeAtomIdCodec.encode(mark.cellId, context.baseContext);
      }
      if (mark.changes !== undefined) {
        encodedMark.changes = context.encodeNode(mark.changes);
      }
      jsonMarks.push(encodedMark);
    }
    

    V3 (excerpt):

    const jsonMarks: Encoded.Changeset(NodeChangeSchema) = [];
    for (const mark of changeset) {
      const encodedMark: Encoded.Mark(NodeChangeSchema) = { count: mark.count };
      if (!isNoopMark(mark)) {
        encodedMark.effect = markEffectCodec.encode(mark, context.baseContext);
      }
      if (mark.cellId !== undefined) {
        encodedMark.cellId = atomIdCodec.encode(mark.cellId, context.baseContext);
      }
      if (mark.changes !== undefined) {
        encodedMark.changes = context.encodeNode(mark.changes);
      }
      jsonMarks.push(encodedMark);
    }
    

Impact Analysis

  • Maintainability: Changes to shared mark encoding/decoding rules must be duplicated across V2 and V3, increasing the chance of drift.
  • Bug Risk: Fixes in one version (e.g., handling of optional fields or future mark metadata) can be missed in the other.
  • Code Bloat: Duplicated boilerplate obscures the actual differences between V2 and V3.

Refactoring Recommendations

  1. Extract shared mark-loop helpers

    • Extract to something like packages/dds/tree/src/feature-libraries/sequence-field/sequenceFieldCodecHelpers.ts (or export helpers from sequenceFieldCodecV2.ts).
    • Suggested split:
      • encodeMarks(changeset, context, { effectCodec, atomIdCodec })
      • decodeMarks(encoded, context, { effectCodec, atomIdCodec, postprocessDecodedMark? })
    • Estimated effort: Medium (2–4 hours)
    • Benefits: Single point of truth for common fields; V2 can keep its rename-normalization postprocess while V3 can omit it.
  2. Make version differences explicit

    • Keep V2/V3-specific logic limited to effect codec differences and any version-specific postprocessing.
    • Benefits: Easier to reason about format deltas when adding new versions.

Implementation Checklist

  • Extract shared encode/decode loops into helpers
  • Update V2 and V3 codecs to use helpers
  • Ensure V2’s rename normalization behavior is preserved (postprocess hook)
  • Run existing unit tests for sequence-field codecs

Analysis Metadata

  • Analyzed Files: 2
  • Detection Method: Serena semantic code analysis + manual verification
  • Commit: 0350e0deb1b4ad2e1a060a7c65fded411de6882c
  • Analysis Date: 2026-03-26T21:46:55.817Z

Generated by Duplicate Code Detector ·

To install this agentic workflow, run

gh aw add github/gh-aw/.github/workflows/duplicate-code-detector.md@94662b1dee8ce96c876ba9f33b3ab8be32de82a4

Contributor guide

Open the contributing guide

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.

Research direction

Start with the encode/decode loops in packages/dds/tree/src/feature-libraries/sequence-field/sequenceFieldCodecV2.ts and sequenceFieldCodecV3.ts, then inspect the existing sequence-field codec unit tests. Extract shared helpers while keeping the V2 rename-normalization postprocess and version-specific codecs distinct. Done means both codecs use the helpers and the existing codec tests pass.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
distributed-systems
Issue type
Refactor
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
64/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.