EnglishGitHub
teilweisepackages/complex-compare/src

Complex Compare

@ralphschuler/complex-compare

Berechnet gerichtete Array-Differenzen und flache Änderungen eigener Objektschlüssel ohne globale Mutation.

diffobjectspure functions

01 · Problem

Wofür braucht man das?

Konfigurationen und Snapshots müssen häufig zeigen, welche Schlüssel hinzugefügt, entfernt oder verändert wurden.

02 · Denkmodell

Das mentale Modell

Ein Diff ist eine Menge adressierbarer Änderungen mit before und after. Die Vergleichstiefe und Gleichheitssemantik müssen Teil des Vertrags sein.

Im Repository

Berechnet gerichtete Array-Differenzen und flache Änderungen eigener Objektschlüssel ohne globale Mutation. Objektwerte werden per Identität verglichen; tiefer Strukturvergleich liegt außerhalb des Kerns.

03 · Kontrollfluss

Was passiert in welcher Reihenfolge?

  1. Vereinigung aller eigenen Schlüssel beider Objekte bilden.
  2. Werte mit einer festgelegten Gleichheitsfunktion vergleichen.
  3. Nur abweichende Paare als before/after erfassen.
  4. Array-Differenz über ein Set der ausgeschlossenen Werte berechnen.

04 · Bauteile

Die entscheidenden Verträge

arrayDifference(left, right)Liefert linke Werte, die rechts fehlen.
objectDifference(left, right)Liefert geänderte eigene Schlüssel als Alt/Neu-Tupel.

05 · Selbst bauen

Selbst implementieren

Pure Funktionen vermeiden Namenskollisionen, enumerable Prototype-Properties und überraschende Seiteneffekte beim Import.

  1. Nimm beide Werte explizit als Parameter statt native Prototypen zu patchen.
  2. Benutze Object.keys und Object.is für ein klares flaches Diff.
  3. Behandle Deep-Diff, Array-Mengenlogik und Patch-Erzeugung als getrennte Erweiterungen.
Konzeptskizze · kann ausgelassene Helfer verwenden
function objectDiff(
  left: Record<string, unknown>,
  right: Record<string, unknown>,
) {
  const keys = new Set([...Object.keys(left), ...Object.keys(right)]);
  const changes = new Map<string, { before: unknown; after: unknown }>();
  for (const key of keys) {
    if (!Object.is(left[key], right[key])) {
      changes.set(key, { before: left[key], after: right[key] });
    }
  }
  return changes;
}

06 · Verifizieren

Was solltest du testen?

  • Hinzugefügte, entfernte und auf undefined gesetzte Keys bleiben unterscheidbar.
  • NaN, -0 und Referenzobjekte folgen der dokumentierten Gleichheitssemantik.
  • Der Import verändert weder Array.prototype noch Object und Eingaben bleiben unverändert.

Selbst ausprobieren

Formuliere die erste Prüfaussage als fehlschlagenden Test, implementiere die kleinste Korrektur und ergänze einen Grenzfall.

Hinzugefügte, entfernte und auf undefined gesetzte Keys bleiben unterscheidbar.

Ansatz vergleichen

Dein Test sollte beim gezielten Verletzen der Invariante fehlschlagen und nach der Korrektur wieder bestehen. Halte den Aufbau deterministisch und prüfe ein beobachtbares Ergebnis.

07 · Grenzen

Kompromisse und Stolperfallen

  • Ein flaches Diff ist schnell, erkennt aber Änderungen innerhalb verschachtelter Objekte nicht.
  • Deep-Diffs benötigen Zyklenerkennung und eine definierte Behandlung von Map, Set und Klasseninstanzen.
Wichtig

Objektwerte werden per Identität verglichen; tiefer Strukturvergleich liegt außerhalb des Kerns.

08 · Weiterdenken

Quellcode und verwandte Ideen

yarn tsx packages/complex-compare/examples/basic.ts