Showing posts with label bridge pattern. Show all posts
Showing posts with label bridge pattern. Show all posts

Wednesday, February 3, 2016

Degenerate Abstractions


What do you get when you remove all but one refined abstraction from the bridge pattern? I already looked into what happens when you only need one implementor. The Gang of Four book even included a discussion about one implementor, terming it a "degenerate case." What about the opposite?

The prime mover in the bridge pattern is given the seemingly vague name of "The Abstraction." There are two required characteristics for the abstraction. First, it needs to perform some action whose exact implementation can vary. Second, it needs to have subclasses—different specific types of the abstraction. These subclasses are called refined abstractions mostly because they had to call them something and "concrete abstraction" is a contradiction in terms.

The idea is that client code can use different refined abstractions with different implementations. Maybe the client chooses which implementation to use. Maybe the refined abstraction chooses. It doesn't matter. Each refined abstraction should work with each action implementation. Furthermore developers should be able to make changes to the implementation without requiring corresponding changes to the refined abstractions and vice versa.

When there is only one implementation, the Gang of Four book concludes that there is still value to the pattern. Even if only one implementation for the action is ever used, the separation of the implementation from abstraction still buys independent changes to each. So the same thing should be true of multiple implementations and a single abstraction, right?

Let's take a look at the web example that I have been using. The backend communication has two implementations, one to send messages over websockets and the other to send messages over plain-old HTTP. In Dart, this looks like:
abstract class Communication {
  void send(String message);
}

// Concrete Implementor 1
class HttpCommunication implements Communication {
  void send(message) {
    HttpRequest.postFormData('/status', {'message': message});
  }
}

// Concrete Implementor 2
class WebSocketCommunication implements Communication {
  WebSocket _socket;
  WebSocketCommunication() { _startSocket(); }

  _startSocket() async { /* ... */  }

  void send(message) {
    _socket.send("message=$message");
  }
}
My original intent (it's important that I use that specific word) is to have multiple Messenger refined abstractions will allow people to post status updates:
// Abstraction
abstract class Messenger {
  Communication comm;
  Messenger(this.comm);
  void updateStatus();
}
In this thought experiment, I am coding the web version while another team is building a mobile Messenger. The Messenger interface tells both teams how to build our classes. We will be communicating with some form of Communciation and we need an updateStatus() method to post messages over those communication channels.

But something happens. Just after we start, the company decides that it is web-only and fires the entire mobile team. Since I want to avoid premature generalization, I get rid of the Messenger interface and dump everything into WebMessenger:
// Degenerate Abstraction
class WebMessenger  {
  Communication comm;
  InputElement _messageElement;
  WebMessenger(this._messageElement) : comm = new HttpCommunication();

  void updateStatus() {
    comm.send(message);
  }

  String get message => _messageElement.value;
}
I still support the Communication implementor, defaulting to the HttpCommunication concrete implementation. I still support the updateStatus() method. I also have code specific to a web page, which grabs the message to post from an input element. But, despite the new web-specific code, the original intent is still the same. I want to be able to make changes to the communication implementation without affecting the WebMessenger abstraction. I still want to be able to assign different Communication objects, in this case at runtime when a different radio button is selected:
  queryAll('[name=implementor]').
    onChange.
    listen((e) {
      var input = e.target;
      if (!input.checked) return;

      if (input.value == 'http')
        message.comm = new HttpCommunication();
      else
        message.comm = new WebSocketCommunication();
    });
So the intent remains the same. And, maybe someday the company will come to its senses and rehire a mobile team. At that point, the abstraction interface can be pulled back out and I will have a true bridge. In the meantime, what do I have?

This sure looks like a simple strategy pattern to me:
class WebMessenger  {
  Communication comm;
  // ...
  void updateStatus() {
    comm.send(message);
  }
  // ...
}
In that sense, a WebMessenger has a Communication object. The specific implementation of Communication can vary depending on what strategy is chosen. So is it a strategy?

I think the answer is that it remains a bridge because of the intent—intent is big in patterns. Even though it winds up looking exactly like a strategy, the structure was originally chosen to support a multiple abstraction structure. Plus, it could easily be refactored to get back to an interface that makes the pattern more explicit.

What I find interesting, however, is what another developer might think should she come along 6 months from now. Without the interface, she should reasonably conclude that the intent is a simple strategy pattern. Under that assumption, she might very well make any number of subsequent design decisions that make it very hard to switch back to a bridge. So in that sense, who cares what the intent was? Unless the intent is made explicit in some form, it would seem that structure trumps intent.

And so, my final answer is that a degenerate abstraction in the bridge pattern does not guarantee that the pattern remains a bridge. More often than not, a degenerate abstraction in the bridge pattern means that it is a bridge pattern no more. In its place is a strategy pattern, intent be damned.


Day #84

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;
  WebMessenger(this._messageElement);

  void updateStatus() {
    comm.send(message);
  }

  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;
  Shape(this._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

Monday, February 1, 2016

Factory Bridges in Dart


I've constructed a bridge in a client. I've constructed a bridge in a constructor. So tonight, I construct a bridge in a factory.

I must investigate the factory and abstract factory in Dart. Mostly because I am unsure how much value the standard structure of the pattern is needed in a language with factory constructors baked right in. Since they are baked in, that's what I opt for tonight.

The abstraction in my bridge pattern example continues to be a Messenger:
abstract class Messenger {
  Communication comm;
  Messenger(this.comm);
  void updateStatus();
}
The purpose of classes implementing this interface is to simply facilitate status updates. There are a number of communication methods bridged from this abstraction: HTTP, websockets, etc. In last night's pass at the bridge pattern, the specific implementation was chosen in the abstraction's constructor (i.e. Messenger) and subsequently changed when certain thresholds were reached.

Tonight, I move the responsibility of choosing the implementation out of the abstraction and into a factory constructor. Because it make sense and is so darn easy, I declare a factory constructor in the Communication implementation:
import 'dart:math' show Random;

// Implementor
abstract class Communication {
  factory Communication() => new Random().nextBool() ?
    new WebSocketCommunication() : new HttpCommunication();
  void send(String message);
}
I continue to find it strange that an abstract class can declare a constructor—even if it is a factory constructor. Each time, I must remind myself that it works for just this kind of case: choosing a subclass implementation. In this case, I randomly choose between the WebSocketCommunication and HttpCommunication concrete implementations.

No changes are required to either of the concrete implementations. They both continue to establish their connections to the server and define the appropriate code to send messages. The Messenger abstraction and the subclass refined for use in web clients, WebMessenger do need to change slightly.

The subclass no longer needs to concern itself with the Communication implementation. The Messenger can do that. Instead, the subclass can worry only about web page related things, like the text input element from which it will obtain messages to send back to the server:
class WebMessenger extends Messenger {
  InputElement _messageElement;
  WebMessenger(this._messageElement);
  // ...
}
The Messenger abstraction needs to do a little more work now, but not much. In addition to declaring the Communication instance variable, it now assigns it in the constructor:
abstract class Messenger {
  Communication comm;
  Messenger() : comm = new Communication();

  void updateStatus();
}
On a sidenote, I remain skeptical of initializer lists in constructors like that. I am trying to use them to see if they grow on me, but I think it just makes things noisy (especially if a constructor body is added to the mix).

That pretty much does it. Through several page reloads, I find that the client does indeed randomly switch between implementations:
$ ./bin/server.dart
[WebSocket] message=asdf
[WebSocket] message=asdf
[WebSocket] message=asdf
[HTTP] message=asdf
[WebSocket] message=asdf
[HTTP] message=asdf
That was fairly straight-forward and low on the surprise scale. I note before concluding that none of this precludes me from setting the Communciation implementation in the client code. For example:
main() {
  var message = new WebMessenger(query('#message'))
    ..comm = new HttpCommunication();
  // ...
}
I also note that making more purposeful choices than the current random implementation selection is straight-forward. I can simply choose based on VM info, browser info, or any other bit of information on which one might opt between HTTP and websocket communication. Any or all of those choices would be right at home in the factory constructor. Or perhaps someday in an abstract factory constructor.

Code for the bridge client and the backend server are on the Design Patterns in Dart public repository.




Day #82

Sunday, January 31, 2016

When to Choose Your Own Implementation in the Bridge Pattern


At this rate, every pattern in Design Patterns in Dart is going to include a websocket. That is a little crazy considering that I do not use websockets all that often in actual client code, but they have the dual benefits of having an accessible API and being conceptually easy to understand. So who knows, maybe I will find a way to include them in every single pattern.

The pattern of current investigation is the bridge pattern. As I found last night, websockets can serve as a realistic alternative to vanilla HTTP for communication. The alternative implementations for communication make the situation well suited for the bridge pattern, which seeks to "bridge" between an abstraction and multiple implementations.

What I would like to examine tonight is creating the right implementor object. Last night, I made two quick decisions on when to create the Communication implementor. Perhaps I could have done that better.

The abstraction in this bridge pattern example remains a Messenger class. It could be a mobile app for posting status updates or sending direct messages. It could be a web form that does the same thing. Either way, a messenger needs a reference to a concrete implementation of Communication and it needs to know how to post updates. So the interface that refined Messenger classes will need to extend looks like:
// Abstraction
abstract class Messenger {
  Communication comm;
  Messenger(this.comm);
  void updateStatus();
}
The refined messenger class that I am using is a WebMessenger. Its constructor stores a text input element from which it can obtain messages to send:
class WebMessenger extends Messenger {
  InputElement _messageElement;
  WebMessenger(this._messageElement) :
    super(new HttpCommunication());
  // ...
}
The bit after the constructor is a redirection to the superclass constructor, which supplies a Communication implementation to the Messenger superclass. Here is where I make my first decision about when to construct a Communication implementation. By default, I opt to create an HttpCommunication implementation of the Communication interface. Since the superclass requires a Communication object in its constructor, I either had to create one right in the constructor as I have done here or I could have required client code to do so.

The choice of whether the client should provide the implementation or if it should be done in the refined abstraction comes down to the details of the code. To be perfectly honest, I did it this way because it was quickest. It probably was not the correct choice, however. Yesterday's implementation has the client choose when to switch between the websocket and HTTP concrete implementations. If the client code chose when to switch, it probably should determine initial state as well.

But let's move the choice of implementation from the client and instead put in into the WebMessenger. It makes sense to start with a low-overhead HttpCommunication object. Given that, the redirecting constructor can stay as-is. But, should the client find itself at the mercy of a power user who is updating status more often than 3 times a minute, then the WebMessenger should switch to a websocket.

So, after each message, I log the message along with a timestamp:
class WebMessenger extends Messenger {
  // ...
  List _history = [];
  // ...
  void updateStatus() {
    comm.send(message);
    _log(message);
  }

  void _log(message) {
    _history.add([new DateTime.now(), message]);
  }
  // ...
}
Then, after logging I do a simple calculation of the frequency with which this user is updating. If it is too often or too slow, I switch Communication implementations:
class WebMessenger extends Messenger {
  // ...
  void updateStatus() {
    comm.send(message);
    _log(message);
    _maybeChangeCommunication();
  }
  // ...
  _maybeChangeCommunication() {
    if (_history.length < 3) return;

    var last = _history.length - 1,
      dateOld = _history[last-2][0],
      dateNew = _history[last][0],
      diff = dateNew.difference(dateOld);

    if (diff.inSeconds < 60) {
      if (comm is! WebSocketCommunication)
        comm = new WebSocketCommunication();
    }
    else {
      if (comm is! HttpCommunication)
        comm = new HttpCommunication();
    }
  }
}
That does the trick. If I send the first 3 message updates out in quick succession, then WebMessenger upgrades the connection to the WebSocketCommunication implementation. The server sees the first three messages come in over HTTP, then the next few over websockets:
$ ./bin/server.dart
[HTTP] message=asdf+1
[HTTP] message=asdf+2
[HTTP] message=asdf+3
[WebSocket] message=asdf 4
[WebSocket] message=asdf 5
[WebSocket] message=asdf 6
[HTTP] message=asdf+7

I then wait a minute between messages 5 and 6, after which I have crossed the lower threshold and am again in the HttpCommunication implementation.

That seems a nice example of when it make sense for the refined abstraction to have responsibility for choosing the implementation—websockets come through again! I do think that some or all of the choice behavior could move into the abstraction itself. Whether that is a good idea depends on the variance in refined abstractions. If a mobile messenger wanted different thresholds or added a new implementation, then the choose-your-implementation behavior would need to continue to reside in the refined abstractions. But if the web and mobile (and other) refined abstractions could share the same choices, then the subclasses could be wonderfully brief.

Code for the bridge client and the backend server are on the Design Patterns in Dart public repository.

Day #81

Saturday, January 30, 2016

The Bridge Pattern with Websockets and HTTP


Design patterns don't tell us how to develop systems. Patterns are names applied to how we already develop. Knowing patterns well won't help us to implement them better in the future—we are already doing that very fine, thank you very much. Knowing a pattern is understanding its consequences and puts us in a better position to minimize or take advantage of those consequences.

That's all fine—if you recognize the pattern. When I first started playing with it, I could not think of an example in which I had used the bridge pattern. It took me some brain digging, but I think I finally excavated a real-world example of it.

Consider, if you will, a browser application that normally communicates with a server over websockets, but has to switch to plain-old HTTP under certain circumstances. The reason for switching might be an older client, a low-memory browser, or simply that this part of the application needs to talk to an HTTP-only server.

Whatever the reason, the web application should not change when the communication implementation changes. If the application is a simple form, then the web form and backing code should never change when switching between HTTP and websockets:



I need to suss out better names for the actors in this play, but I start by calling the web form a "messenger" and mechanism for talking "communication." They are kind of the same thing, so I need to work on that, but it will do for a start. The Messenger abstraction will require a Communication implementation of some kind and will need to know how to send messages with that communication channel. Expressed in Dart, that looks like:
abstract class Messenger {
  Communicator comm;
  Messenger(this.comm);
  void send();
}
The refined abstraction is a web form messenger that gets the message to send from a text element:
class FormMessenger extends Messenger {
  Element _messageElement;
  FormMessenger(this._messageElement) : super(new HttpCommunicator());

  void send() {
    comm.save(message);
  }

  String get message => _messageElement.value;
}
As can be seen from the send() method, the Communication class needs to support a save() method in order to save the message on the backend:
abstract class Communicator {
  void save(String message);
}
The HttpCommunicator is simple enough, thanks to the HttpRequest.postFormData() method:
class HttpCommunicator implements Communicator {
  void save(message) {
    HttpRequest.postFormData('/save', {'message': message});
  }
}
The second implementor, the WebsocketCommunicator class, takes a little more setup for websockets, but is still pretty straight forward:
class WebSocketCommunicator implements Communicator {
  WebSocket _socket;
  WebSocketCommunicator() { _startSocket(); }

  _startSocket() async {
    _socket = new WebSocket('ws://localhost:4040/ws');

    var _c = new Completer();
    _socket.onOpen.listen((_){ _c.complete(); });
    await _c.future;
  }

  void save(message) {
    _socket.send(message);
  }
}
And that pretty much does it. Aside from some better naming, this feels like a fairly accessible example.

One of the implications of the bridge pattern is that a code decision needs to be made as to where to assign the implementor. For a fist pass, I listen to the two radio buttons in the form and, based on which is selected, I assign a different Communicator:
  queryAll('[name=implementor]').
    onChange.
    listen((e) {
      var input = e.target;
      if (!input.checked) return;

      if (input.value == 'http')
        message.comm = new HttpCommunicator();
      else
        message.comm = new WebSocketCommunicator();
    });
With that, I can switch between implementors and send messages to the server however I like:
$ ./bin/server.dart
[HTTP] message=A+web+form+message%21
[WebSocket] A web form message!
[HTTP] message=A+web+form+message%21
[HTTP] message=A+web+form+message%21
[HTTP] message=A+web+form+message%21
Nice! Now all that is left is to come up with some better names.

Full code for the frontend and backend is located at: https://github.com/eee-c/design-patterns-in-dart/tree/master/bridge.


Day #80

Friday, January 29, 2016

Handle Body Reference Counting in Garbage Collected Dart


Oh, what the hell. I finished yesterday hand-waving over a particular implementation. Let's see if I can actually implement a reference counting handle body in Dart. There may be no practical application for this in a garbage collected language like Dart, but we'll see...

I continue to use Shape as the abstraction in my bridge pattern exploration. It will now serve double duty as the handle class, holding references to the body implementation. Well, it already did that (which is rather the point of the pattern), but now it needs to reference, dereference, and delete implementors as well.

The implementor is DrawingApi, which knows that subclasses will, among other things, know how to draw a circle:
abstract class DrawingApi {
  void drawCircle(double x, double y, double radius);
}
To maintain reference counts, DrawingApi needs a _refCount instance variable along with ref() and deref() methods to increase and decrease that counter:
abstract class DrawingApi {
  int _refCount = 0;
  void ref() {
    _refCount++;
    print('  $this Increased refcount to $_refCount');
  }
  void deref() {
    _refCount--;
    print('  $this Decreased refcount to $_refCount');
  }
  void drawCircle(double x, double y, double radius);
}
In client code, I can create an instance of two subclasses of DrawingApi:
main() {
  var api1 = new DrawingApi1(),
      api2 = new DrawingApi2();
  // ...
}
Then I initially set those as the "drawer" (the thing that draws, not a thing that holds stuff in desks) property for Circle instances:
main() {
  // ...
  var circle1 = new Circle(1.0, 2.0, 3.0)..drawer = api1,
      circle2 = new Circle(0.0, 6.0, 1.0)..drawer = api1,
      circle3 = new Circle(2.0, 2.0, 1.5)..drawer = api2;
  // ...
}
The Circle class is a concrete implementor of the Shape abstraction / handle class. So assigning api1 to two difference Circle instances needs to update the number of references to api1 accordingly.

I more or less copy the code from the handle / body example from the bridge pattern chapter in the Gang of Four book. The drawer() setter is responsible for noting the new reference, and noting the derefence for the existing object. If the reference count goes to zero, the handle class needs to delete the reference, which I do by assigning the _drawingApi instance variable to null:
abstract class Shape {
  DrawingApi _drawingApi;

  set drawer(DrawingApi other) {
    other.ref();
    if (_drawingApi != null) {
      _drawingApi.deref();
      if (_drawingApi._refCount == 0) {
        print('  ** Deleting no longer used $_drawingApi **');
        _drawingApi = null;
      }
    }
    _drawingApi = other;
  }
}
It is here that I finally realize that there is no point to doing any of this—at least not in this example. Even without explicitly setting _drawingApi to null, it gets assigned to a different value on the following line. Once that happens, Dart itself notes that there is one fewer references to the object and, if zero, schedules the object for garbage collection.

I don't know why I thought this might be necessary in some cases. I do get easily confused in the presence of C++.

Anyhow, back in my client code, I draw those circles with the mixture of api1 and api2, then update the drawers so that everyone is using api2:
main() {
  // ...
  circle1.draw();
  circle2.draw();
  circle3.draw();

  circle1.drawer = api2;
  circle2.drawer = api2;

  api1 = api2 = null;

  circle1.draw();
  circle2.draw();
  circle3.draw();
}
When I run this code, I get what I expect. The first time through a mixture of api1 and api2 drawers are used, when I switch to all-api2, the deletion of the api2 reference is noted, then api2 drawing commences:
./bin/draw.dart
  Instance of 'DrawingApi1' Increased refcount to 1
  Instance of 'DrawingApi1' Increased refcount to 2
  Instance of 'DrawingApi2' Increased refcount to 1
[DrawingApi1] circle at (1.0, 2.0) with radius 3.000
[DrawingApi1] circle at (0.0, 6.0) with radius 1.000
[DrawingApi2] circle at (2.0, 2.0) with radius 1.500
  Instance of 'DrawingApi2' Increased refcount to 2
  Instance of 'DrawingApi1' Decreased refcount to 1
  Instance of 'DrawingApi2' Increased refcount to 3
  Instance of 'DrawingApi1' Decreased refcount to 0
  ** Deleting no longer used Instance of 'DrawingApi1' **
[DrawingApi2] circle at (1.0, 2.0) with radius 3.000
[DrawingApi2] circle at (0.0, 6.0) with radius 1.000
[DrawingApi2] circle at (2.0, 2.0) with radius 1.500
So it works, but Dart already had me covered with garbage collection. The effort is not a complete waste. I did clear up whatever C++ confusion I was suffering. Potentially more important, I have client code that can demonstrate sharing implementors such that garbage collection will reclaim them when they go unused.

Play with the code on DartPad: https://dartpad.dartlang.org/43585b1f6e0f1403fc5a.


Day #79

Thursday, January 28, 2016

Sharing Implementors is Easy in the Bridge Pattern


Reference counting is something of a lost art. I, for one, hope it stays that way. If there was a way to mess up counting, I was more than up to the task of finding it. That's only a slight exaggeration.

So I very much appreciate garbage collected languages like Dart. Of course, garbage collection can only do so much—I promise you that it is still possible to build web applications that consume insane amounts of memory. In that vein, tonight I investigate sharing implementors in the bridge pattern.

The Gang of Four book describes Handle Body idiom for tackling this in C++. But that's for my old nemesis reference counting. In Dart, I have to think factory constructor singletons would be an easy way to tackle this. For example, consider the wildly memory intensive DrawingApi1 class:
class DrawingApi1 implements DrawingApi {
  void drawCircle(double x, double y, double radius) {
    print(
      "[DrawingApi1] "
      "circle at ($x, $y) with "
      "radius ${radius.toStringAsFixed(3)}"
    );
  }
}
Clearly, I do not want that class to instantiate new objects each time a Circle refined abstraction is created:
  List<Shape> shapes = [
    new Circle(1.0, 2.0, 3.0, new DrawingApi1()),
    new Circle(0.0, 6.0, 1.0, new DrawingApi1()),
    new Circle(2.0, 2.0, 1.5, new DrawingApi1()),
    new Circle(5.0, 7.0, 11.0, new DrawingApi2()),
    new Circle(1.0, 2.0, 3.0, new DrawingApi1()),
    new Circle(5.0, -7.0, 1.0, new DrawingApi2()),
    new Circle(-1.0, -2.0, 5.0, new DrawingApi1())
  ];
Even if DrawingApi2 is significantly more lightweight than DrawingApi1, enough of the latter will drag the browser / system to a halt. But a simple singleton factory constructor solves that neatly:
class DrawingApi1 implements DrawingApi {
  static final DrawingApi1 _drawingApi = new DrawingApi1._internal();
  factory DrawingApi1()=> _drawingApi;
  DrawingApi1._internal();

  void drawCircle(double x, double y, double radius) { /* ... */ }
}
The class variable _drawingApi is constructed once from a private constructor. The regular DrawingApi1() is a factory constructor that only returns that one _drawingApi reference. And the internal constructor is a simple, no-argument private constructor.

The only case that does not cover is when the number of references to a DrawingApi1 instance goes to zero. The start-at-zero case is handled automatically for me by Dart. The private _drawingApi class variable is not assigned until the constructor is invoked for the first time—that is just thanks to Dart's lazy instantiation. So no memory will be used unless and until the first DrawingApi1 shape is drawn.

If I really needed to reclaim memory, I might try a handle-body kind of thing. But I'd probably get it wrong. So instead I use mirrors (because mirrors are always easier than reference counting). If I switch to constructing shapes with the class name instead of an instance, the individual shapes might look like:
  List<Shape> shapes = [
    new Circle(1.0, 2.0, 3.0, DrawingApi1),
    new Circle(0.0, 6.0, 1.0, DrawingApi1),
    new Circle(2.0, 2.0, 1.5, DrawingApi1),
    new Circle(5.0, 7.0, 11.0, DrawingApi2),
    new Circle(1.0, 2.0, 3.0, DrawingApi1),
    new Circle(5.0, -7.0, 1.0, DrawingApi2),
    new Circle(-1.0, -2.0, 5.0, DrawingApi1)
  ];
The Circle constructor still redirects the last parameter, which is now a Type, to the abstraction superclass:
class Circle extends Shape {
  double _x, _y, _radius;
  Circle(this._x, this._y, this._radius, Type drawingApi) :
    super(drawingApi);
  // ...
}
Finally, the constructor in the Shape abstraction can putIfAbsent() on the cache:
import 'dart:mirrors' show reflectClass;
abstract class Shape {
  DrawingApi _drawingApi;
  static Map _drawingApiCache = {};

  Shape(Type drawingApi) {
    _drawingApi = _drawingApiCache.putIfAbsent(
      drawingApi,
      ()=> reflectClass(drawingApi).newInstance(new Symbol(''), []).reflectee
    );
  }
  // ...
}
If I want to clear that cache after all Shape instances have been removed, I can use a simple clear():
abstract class Shape {
  // ...
  void reset() { _drawingApiCache.clear(); }
  // ...
}
The rest remains unchanged from previous nights. The bridge between abstraction (shape) and implementor (a drawing API) is used in the draw() method in the refined abstraction:
class Circle extends Shape {
  // ...
  void draw() {
    _drawingApi.drawCircle(_x, _y, _radius);
  }
  // ...
}
I draw two conclusions from this. First, I enjoy mirrors far more than is healthy. A handle-body class would have involved counting, but might have solved the last reference removal just as well (and possibly clearer). Second, singletons seem to solve the reference count for nearly all use-cases.


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

Day #78

Wednesday, January 27, 2016

Bridge Mixins


Today I take a look at the bridge pattern with Dart mixins. The Gang of Four book includes a brief discussion on multiple inheritance and the bridge pattern. This has me curious about mixins, which can serve a similar purpose to multiple inheritance.

I continue to work with the shape drawing example from Wikipedia. In it, a Shape is the the abstraction in need of bridging to an implementation—drawing in this case. The abstract Shape class requires a drawing API object be supplied when constructing a concrete implementation, along with two methods that must be defined by that same subclass:
abstract class Shape {
  DrawingApi _drawingApi;

  Shape(this._drawingApi);

  void draw();                         // low-level
  void resizeByPercentage(double pct); // high-level
}
In a "refined abstraction," the low-level draw() is the method that needs the bridge to the implementor. For a Circle, the draw() method might invoke a drawCircle() method on a concrete drawing API object:
// Refined Abstraction
class Circle extends Shape {
  double _x, _y, _radius;
  Circle(this._x, this._y, this._radius, DrawingApi api) :
    super(api);

  // low-level i.e. Implementation specific
  void draw() {
    _drawingApi.drawCircle(_x, _y, _radius);
  }
  // ...
}
The client then create a concrete DrawingApi object (like DrawingApi1) to supply to Circle's constructor:
    new Circle(1.0, 2.0, 3.0, new DrawingApi1())
      ..draw();
That works great and is a nice example of a bridge pattern. But it is a hassle to have to construct a concrete DrawingApi class every time I construct a Circle. What's to prevent me from using DrawingApi1 (or DrawingApi2) as a mixin? The answer is nothing!

Since the abstraction no longer needs to track the implementor, it can be simplified to an interface requiring two methods:
abstract class Shape {
  void draw();                         
  void resizeByPercentage(double pct);
}
Then I mixin DrawingApi1 to Circle by extending Shape with DrawingApi1:
class Circle extends Shape with DrawingApi1 {
  double _x, _y, _radius;
  Circle(this._x, this._y, this._radius);
  void draw() { /* ... */  }
  void resizeByPercentage(double pct) { /* ... */ }
}
With access to the methods of DrawingApi1, I can now call drawCircle() directly from draw():
class Circle extends Shape with DrawingApi1 {
  // ...
  void draw() {
    drawCircle(_x, _y, _radius);
  }
  // ...
}
That in turn simplifies my client code since it longer needs to worry about creating the drawing API object:
    new Circle(1.0, 2.0, 3.0)
      ..draw();
When this code is, just as in the prior implementation, it produces the following output:
$ ./bin/draw.dart           
[DrawingApi1] circle at (1.0, 2.0) with radius 3.000
So it is possible to use mixins to implement the bridge pattern in Dart… except not quite.

This will work for the degenerate case explored last night in which there is only one concrete drawing implementor. Both the implementor and abstraction can vary independently, which is ultimately the goal of the pattern.

What does not work is the same thing that the Gang of Four mentions as a shortcoming of the multiple inheritance approach in C++. The binding between the abstraction and implementor are now permanent. If I needed to vary the implementation at runtime, I am out of luck. Even mirrors will not help—at least not until the mixin property of ClassMirror is read-write.

In the end, mixins in the bridge pattern are a fun experiment. They may even be a useful approach to use in degenerate, single implementor implementations. For a full featured bridge pattern, mixins will not serve as a legitimate solution.

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


Day #77


Tuesday, January 26, 2016

Degenerate Bridges


I enjoyed last night's example implementation of the bridge pattern, though it feels unfamiliar. The Gang of Four book mentions a degenerative case—that sounds right up my alley!

In last night's example, the "refined abstraction" in the pattern was a Circle (Shape being the abstraction). In addition to supporting position and size arguments, the constructor also accepted an instance of an implementation. The example uses drawing circles on the screen as the implementation being supported:
class Circle extends Shape {
  double _x, _y, _radius;
  Circle(this._x, this._y, this._radius, DrawingApi api) :
    super(api);
  // ...
}
The draw() method of Circle then delegates responsibility to the drawing API (it bridge the abstraction and implementation):
class Circle extends Shape {
  // ...
  void draw() {
    _drawingApi.drawCircle(_x, _y, _radius);
  }
  // ...
}
The degenerate case does not support multiple implementations. Last night's approach accepted a DrawingApi instance so that multiple types of DrawingApi objects could be used (e.g. one for the console, one for the browser, etc.). But if there is only one concrete implementor, then the abstraction itself can create that implementor:
abstract class Shape {
  DrawingApi1 _drawingApi = new DrawingApi1();

  void draw();                         
}
In this case, the Circle refined abstraction does not have to worry about creating or handling the DrawingApi, it can just do circle things:
class Circle extends Shape {
  double _x, _y, _radius;
  Circle(this._x, this._y, this._radius);

  void draw() {
    _drawingApi.drawCircle(_x, _y, _radius);
  }
}
The draw() method still works through the DrawingApi1 implementor, the only difference here is that the _drawingApi instance is created in the Shape abstraction class.

Since there is only one implementor, there is no need for an interface. The abstraction depends directly on the concrete DrawingApi1 implementor, which remains unchanged from yesterday's print-to-stdout barebones example:
class DrawingApi1 {
  void drawCircle(double x, double y, double radius) {
    print(
      "[DrawingApi] "
      "circle at ($x, $y) with "
      "radius ${radius.toStringAsFixed(3)}"
    );
  }
}
Client code can then create and draw a circle with something like:
    new Circle(1.0, 2.0, 3.0)
      ..draw();
That results in the desired, bridged output:
$ ./bin/draw.dart           
[DrawingApi] circle at (1.0, 2.0) with radius 3.075
The question is why would I want to do something like this instead of putting drawing code directly inside Circle's draw() method?

The Gang of Four suggest that a change in the drawing implementation should not force client code to recompile. Dart compilation does not work that way—any change anywhere necessitates that everything get recompiled. I would think the intent behind the Gang of Four's assertion was the single responsibility principle and that the point is still valid in Dart. Per the SRP, a class should only have one reason to change. If the drawing code existed directly inside the draw() method, then Circle would change whenever new features are added to describe a circle and whenever the manner in which drawing occurs changes.

I still do not recall ever having used even this simple case. That will mean a challenge coming up with a more real-world example for either this or the regular case. Still, it does seem worth noodling through.

Play with the code on DartPad: https://dartpad.dartlang.org/0ca4f1ac6ee8caad731e.

Day #76

Monday, January 25, 2016

The Bridge Pattern in Dart


The bridge pattern definition sounds like little more than a jargon generator seeded with object-oriented terms. From the Gang of Four book, the intent is to:
Decouple an abstraction from its implementation so that the two can vary independently.
Some day I hope to be able to reduce computer science-y terms with such whimsy. Until then, I'll settle for attempting to implement the pattern in Dart.

For my first pass, I borrow the Java implementation from the Wikipedia article. It is a nice example in which the abstraction is a shape and the implementation is a drawing API. Part of the abstraction's job is to maintain a reference to the implementation, so I start with the latter.

The implementor is DrawingApi:
abstract class DrawingApi {
  void drawCircle(double x, double y, double radius);
}
Obviously, what will vary between concrete implementors is that drawCircle() method. In this very simple string-based example, the only thing that changes is the first part of the string printed by drawCircle():
class DrawingApi1 implements DrawingApi {
  void drawCircle(double x, double y, double radius) {
    print(
      "[DrawingApi1] "
      "circle at ($x, $y) with "
      "radius ${radius.toStringAsFixed(3)}"
    );
  }
}

class DrawingApi2 implements DrawingApi {
  void drawCircle(double x, double y, double radius) {
    print(
      "[DrawingApi2] "
      "circle at ($x, $y) with "
      "radius ${radius.toStringAsFixed(3)}"
    );
  }
}
With that out of the way, it is time to check out the abstraction. Again, the abstraction maintains a reference to an implementor. It also defines the public-facing interface:
abstract class Shape {
  DrawingApi _drawingApi;

  Shape(this._drawingApi);

  void draw();                         // low-level
  void resizeByPercentage(double pct); // high-level
}
What I appreciate about this example is that it identifies where changes will occur. Implementator changes are low-level changes such as variations in the DrawingApi. Abstraction variations are considered "high-level" such as resizing the shape.

The refined abstraction for Shape is a Circle. It needs to store properties for a circle and supply the implementor to the Shape superclass:
class Circle extends Shape {
  double _x, _y, _radius;
  Circle(this._x, this._y, this._radius, DrawingApi api) :
    super(api);
  // ...
}
The private instance variables are assigned with Dart's wonderful this constructor shorthand. I curse at any language that does not support this. The DrawingApi is assigned via a redirection to the superclass' constructor. That is nice & clean and could be a one-liner if I did not abhor long lines.

The low-level draw() method delegates to the supplied implementor:
class Circle extends Shape {
  // ...
  void draw() {
    _drawingApi.drawCircle(_x, _y, _radius);
  }
  // ...
}
As long as the implementor continues to support that DrawingApi interface, it can change as much as it likes. As for the high-level, abstraction specific resize method, it simply multiplies the radius by a percentage:
class Circle extends Shape {
  // ...
  void resizeByPercentage(double pct) {
    _radius *= (1.0 + pct/100.0);
  }
}
And that is the pattern. If I had to change the implementation details of the resize function, I could do so with no fear of breaking the low-level implementor. The same goes for the implementor—if I need to change how drawing works or add another type of implementor, I can do so without affecting the abstraction.

Client code can create a 2 shape list, each with a different drawing implementor. I can then loop over each to resize and draw:
main() {
  List shapes = [
    new Circle(1.0, 2.0, 3.0, new DrawingApi1()),
    new Circle(5.0, 7.0, 11.0, new DrawingApi2())
  ];

  shapes.forEach((shape){
    shape.resizeByPercentage(2.5);
    shape.draw();
  });
}
This results in:
$ ./bin/draw.dart           
[DrawingApi1] circle at (1.0, 2.0) with radius 3.075
[DrawingApi2] circle at (5.0, 7.0) with radius 11.275
Nice! There is still much to explore in this pattern, but that is a nice start.

Play with the code on DartPad: https://dartpad.dartlang.org/2b092185cb17ebebecef.


Day #75