Wednesday, February 17, 2016

A DOM Chain of Responsibility


A major theme of the forthcoming Design Patterns in Dart is that design patterns are more useful for describing how systems are already designed, not for designing systems in the first place. The implications and applicability of patterns then aid programmers to understand how systems can evolve, once patterns are recognized in them.

With that in mind... consider a <div> with ID of "bottom" inside a <div> with ID of "middle" inside a <div> with ID of "top":



There are three Dart element objects:
  var bottom = query('#bottom'),
    middle = query('#middle'),
    top = query('#top');
If the bottom-most sees a request in the form of a click without modifier key, then it handles the request, preventing successors from seeing the request:
  bottom.onClick.listen((e){
    if (e.ctrlKey) return;
    if (e.shiftKey) return;

    bottom.style.border =
      bottom.style.border.contains('green') ?
        '' : '3px green dashed';
    e.stopPropagation();
  });
But if modifier key (shift or control) is held down while clicking in the middle of the "bottom" <div>, the request passes along to the successor. The next element object in line here is the "middle" <div>. If the request is received by this object with the shift key depressed, it handles the request, preventing successor from seeing the request:
  middle.onClick.listen((e){
    if (e.ctrlKey) return;

    middle.style.border =
      middle.style.border.contains('blue') ?
        '' : '3px blue dashed';
    e.stopPropagation();
  });
Finally, if it is not the control key, but the shift key that is depressed while clicking the "bottom" element, the request passes through both the bottom handler and the middle handler—both of which opt not to handle the request. In this case, the request is finally handled by top:
  top.onClick.listen((_){
    top.style.border =
      top.style.border.contains('orange') ?
        '' : '3px orange dotted';
  });
So is this a chain of responsibility pattern? Of course! There are concrete handler objects all of the same type. They all declare the same method to process a request object. The method may be in the form of an event listener instead of a pure method, but the overall intent and structure is the same. This is a chain of responsibility—and one that just about every web developer implemented at some point without thinking about the pattern.

And the implications and applicability? Well, that's a tale for another day.

Play with the code on DartPad: https://dartpad.dartlang.org/12bf7fa9c76c6d16fe5f.


Day #98

1 comment: