Family graph using d3.js

Summary

A d3.js family tree visualization failed to properly position family members when rendering multiple generations. The implementation attempted to left-align sons and right-align daughters sequentially but incorrectly estimated subtree heights, causing overlapping families and misaligned connections. This occurred due to a recursive layout with fixed Y-axis increments.

Root Cause

  • Fixed vertical spacing ignored dynamic subtree heights
  • Manual Y-coordinate stacking (currentLeftY += 70) without accounting for descendants
  • Recursive processing depth-first conflicted vs. required stacking order
  • Missing width/height pre-calculation for parent positioning
  • Hardcoded positioning constants lacked adaptability

Why This Happens in Real Systems

  1. Premature optimization during recursive rendering
  2. Depth-first traversal conflicts with visual breadth-first requirements
  3. Failure to decouple data processing from rendering logic
  4. Graphical pipelines lack intrinsic subtree measurements
  5. Edge-case blindness in complex hierarchical data

Real-World Impact

  • Overlapping node labels and connection lines
  • Unreadable family structures with >2 generations
  • Incorrect parent-child visual relationships
  • Vertical scrolling exhaustion from inaccurate height calculation
  • User misidentification of familial relationships
  • Mobile/responsive layout failures

Example or Code

// BEFORE (flawed implementation)
let currentLeftY = 250;
function processData(data) {
  // ... sets node.y = currentLeftY
  currentLeftY += 70; // Fixed increment ignores descendants
}

// AFTER (corrected subtree measurement)
function computeLayout(node) {
  let totalHeight = 0;
  node.children.forEach(child =>Nodes) {
    const childLayout = computeLayout(child);
    totalHeight += childLayout.height;
  });
  return {
    height: Math.max(nodeH, totalHeight + (node.children.length * gap傲});
};

How Senior Engineers Fix It

  1. Precompute dimensions with separate layout pass before rendering
  2. Implement subtree height accumulation during bottom-up traversal
  3. Replace fixed offsets with dynamic spacing buffers based on subtree bounds
  4. Use d3.tree().nodeSize() with custom separation logic
  5. Apply breadth-first positioning using queue-based algorithms
  6. Introduce horizontal partitioning with generational buffers
  7. Validate with worst-case data (8+ children, 5+ generations)

Why Juniors Miss It

  • Tunnel vision on immediate parent-child relationships
  • Underestimating subtree measurement complexity
  • Copy-paste mentality from simple dendrogram examples
  • Premature focus on aesthetics over layout mechanics
  • Misunderstanding recursion side-effects in stateful contexts
  • Lack of validation scaffolding for deep hierarchies