Tuesday, February 2, 2016

In Which I Quarrel with Bridge Names

I confess that I find the names in the bridge pattern awkward.

Why are there "refined abstractions" instead of "concrete abstractions"? Why is it "concrete implementor" instead of "refined implementor"? Why did we settle on names like "abstraction" and "implementor" which closely mirror programming concepts like "abstract classes" and "interface implementation"?

Also, why does the Gang of Four book describe the pattern as decoupling "an abstraction from its implementation so that the two can vary independently" instead of "decoupling an abstraction from part of its implementation"? The pattern does not have the implementor implement all of the abstraction's functionality, just parts of it.

Consider the "refined abstraction" WebMessenger:
// Refined Abstraction
class WebMessenger extends Messenger {
  InputElement _messageElement;

  void updateStatus() {

  String get message => _messageElement.value;
Just about all of that is specific to the refined abstraction—obtaining a message from a web page input element. Only the updateStatus() method bridges between the abstraction and implementor.

I suppose the abstraction (as opposed to the refined abstraction) has more of its implementation performed by the implementor:
abstract class Messenger {
  Communication comm;
  Messenger() : comm = new Communication();

  void updateStatus();
In there, Communication is a factory that assigns a concrete (not refined) implementor, which is then used in updateStatus(). In this simple case, the bridge might implement the whole interface. In a more substantial example from the Wikipedia page, the Shape abstraction on has part of its implementation handled by the concrete implementor:
abstract class Shape {
  DrawingApi _drawingApi;
  void draw();                         // low-level

  void resizeByPercentage(double pct); // high-level
The more I think about it, the less I like any of the naming conventions used. But I do not have particularly good alternatives. And, given enough thought, I grudgingly admit that the names adopted by the Gang of Four are reasonable and might be the best possible.

The main player in the pattern is some abstract concept—a window, a shape, a messenger. The "abstraction" name also suggests more concrete versions of the abstractions, which are important parts of the pattern termed refined abstractions. The secondary character in the play is the implementor, which performs a specific task for the abstraction. In other words, the implementor implements specific tasks.

There is probably not much to be done with "abstraction." I might alternatively call it a "concept," "thing," or "object." "Concept" is just as vague a name as "abstraction," and lacks the suggestion of refined concepts. I like thing, but what is a refined thing? I can hardly talk about Thing #1 and Thing #2 without heading down a Seussian side-trail. And "object" is a ridiculous term to introduce to an object oriented discussion.

I also have to conclude that "refined abstraction" might be the best name. "Concrete abstraction" is too much a contradiction in terms like "heavy air." Sure it might make sense if you give it some thought, but best to use terms that do not require much thought—even if they do no carrying significant meaning.

I may recast "implementor" in some of Design Patterns in Dart. I cannot completely rename things in a little-old, self-published book. Also, I know my readers are smart enough to work this out for themselves. But perhaps when I introduce "implementor," I will call it a "glorified gofer" since the abstraction tells it to run certain tasks (errands) on demand.

So after all of that, I conclude what I suspected all along—the Gang of Four probably gave a decent amount of thought to names. And aside from a quibble over whether "its implementation" means all or part of the implementation, I think the Gang of Four have me convinced that their convention, though not ideal, is likely the best.

Day #83

No comments:

Post a Comment