Apple Questions

Design and implement a thread-safe observable/reactive data binding system.

HardTechnicalDesign Patterns25-30 minutes

Model Answer

A reactive data binding system notifies observers when data changes. Thread safety means concurrent reads and writes don't corrupt state, and observer notifications are consistent. The core pattern: Observable wraps a value, maintains a list of observer callbacks, and notifies them on value changes. Thread safety is achieved through a locking mechanism.

Approaches

Observable with Copy-on-Notify

Copy the observers list before notifying to prevent concurrent modification issues. Use closure-based unsubscribe for clean cleanup.

class Observable {
  constructor(initialValue) {
    this._value = initialValue;
    this._observers = [];
  }

  get value() {
    return this._value;
  }

  set value(newValue) {
    const oldValue = this._value;
    this._value = newValue;
    // Copy observers to prevent issues if observers are added/removed during notification
    const snapshot = [...this._observers];
    for (const observer of snapshot) {
      try {
        observer(newValue, oldValue);
      } catch (e) {
        console.error('Observer error:', e);
      }
    }
  }

  subscribe(observer) {
    this._observers.push(observer);
    // Return unsubscribe function
    return () => {
      const index = this._observers.indexOf(observer);
      if (index > -1) this._observers.splice(index, 1);
    };
  }
}

// Usage:
const name = new Observable('Alice');
const unsub = name.subscribe((newVal, oldVal) => {
  console.log(oldVal, '->', newVal);
});
name.value = 'Bob'; // logs: Alice -> Bob
unsub(); // clean up
Time: O(n) per update where n is observer countSpace: O(n) for observer list

Common Mistakes

  • 1.Not copying the observer list before iterating (concurrent modification during notification)
  • 2.Not providing an unsubscribe mechanism (memory leak)
  • 3.Using synchronous notification that blocks the writer
  • 4.Not handling the case where an observer throws an exception during notification

Follow-up Questions

  • How would you implement computed/derived observables?
  • How would you batch multiple rapid changes into a single notification?
  • How would you prevent memory leaks from observers that forget to unsubscribe?