Showing posts with label memento. Show all posts
Showing posts with label memento. Show all posts

Saturday, December 5, 2015

The Caretaker, Mel, and One Velvet Fog Machine to Rule Them All


Once upon a time there was a wise a benevolent creature known as the Caretaker:



The Caretaker was responsible for playing the ultimate selections of Mel Tormé music on the magnificent Velvet Fog Machine:



Every now and then the Caretaker got special coins that remembered a particular song at a particular time:



The Caretaker could used these to got back to these very special moments.



The Caretaker had no idea how the Velvet Fog Machine knew what to do with these coins and did not care. Mel Tormé played all the time and special moments could be had a plenty.

But one day something strange happened. The Caretaker tried something a little different and... all of the sudden there were three identical (but for the hashCode) velvet fog machines:



This was confusing to the Caretaker and seemed likely to cause more problems in a life that should be dedicated to Melvie. So that Caretaker decided that the VelvetFogMachine needed to be a singleton. Happily, the Caretaker favored bliss and so was programming with Dart. And so a factory constructor was able to resolve these woes:
class VelvetFogMachine {
  // ...
  static final VelvetFogMachine _vfm = new VelvetFogMachine._internal();
  factory VelvetFogMachine() => _vfm;
  VelvetFogMachine._internal();
  // ...
}
With that, the originator of the magical best-of-Mel coins, the VelvetFogMachine would always return the same _vfm instance of itself. So there was one instance of the velvet fog machine no matter how the Caretake might interact with it:



And the Caretakee could enjoy Mel until the end of days. And the Caretaker was happy.


Day #24

Friday, December 4, 2015

Serializing Mementos: A Good Idea?


I'm pretty the answer is going to be "don't."

Still, I would like to explore serializing the memento object in the memento pattern for offline storage. The whole point of the memento pattern is to facilitate restoring state without allowing access to that state. This exercise may come down to semantics, but let's try it out first.

Currently, I am working with my Dart VelvetFogMachine object, which aids in the search for the ultimate Mel Tormé playlist. This is the originator in the memento pattern. In the caretaker code, I keep a list of saved state and work with this VelvetFogMachine:
  // List of mementos
  List replayer = [];

  // The originator
  var scatMan = new VelvetFogMachine();
This caretaker code cannot see inside the memento—and thus cannot access the internal state of the VelvetFogMachine. It can tell the machine to play music and, at particularly moving moments of playback, request a bookmark so that we can return to this point in the current song:

  // ...
  scatMan.play(
      '\'Round Midnight',
      'Tormé'
  );
  replayer.add(scatMan.nowPlaying);
  // ...
  scatMan.play(
      'New York, New York Medley',
      'A Vintage Year'
  );
  replayer.add(scatMan.nowPlaying);
  // ...
The play() sends the currently playing song to STDOUT, so running this code results in a report similar to:
$ ./bin/play_melvie.dart
Playing 'Round Midnight // Tormé @ 0.00
...
Playing New York, New York Medley // A Vintage Year @ 0.00
...
And, when the VelvetFogMachine is sent back to a memento:
  // Restore a memento
  scatMan.backTo(replayer.last);
It is reported as:
  *** Whoa! This was a good one, let's hear it again :) ***
Playing New York, New York Medley // A Vintage Year @ 1.27
So things work well and encapsulation is maintained. There is no way for the caretaker to get at the current state of the VelvetFogMachine(). All interaction goes through the play() method which is then solely responsible for updating the internal state of things. By keeping the VelvetFogMachine interface narrow like this, it will be more reliable and is more extensible.

So what about storing the replayer list of mementos offline for later restore? Will something like the following break encapsulation?
  var saved = serializePlaylist(replayer);
  // Then, some time later...
  var restored = deserializePlaylist(saved);
  scatMan.backTo(restored.first);
To answer that question, I start in the velvet_fog_machine library by importing the dart:convert library so that the object can be serialized into JSON:
library velvet_fog_machine;

import 'dart:convert';
//... 
The memento object itself, which describes the currently playing song, will need to support a toJson() method to work with the JSON.encode() method:
// The Memento
class _Playing {
  Song _song;
  double _time;
  _Playing(this._song, this._time);
  Map toJson() => {'song': _song.toJson(), 'time': _time};
}
That makes the serializePlaylist() helper function quite straight-forward. I can simply call JSON.encode on the list of _Player mementos and dart:convert does the rest:
String serializePlaylist(List<_Playing> list) => JSON.encode(list);
As for getting the memento back, that is a little harder. This is where the knowledge of the underlying implementation is needed. I have to decode the JSON list of mementos, then map each item in the list into a _Playing object:
List<_Playing> deserializePlaylist(String json) {
  return JSON.decode(json).map((p) {
    var time = p['time'];
    var song = new Song(p['song']['title'], p['song']['album']);
    return new _Playing(song, time);
  });
}
With that, the serialize/deserialize code in the caretaker:
  var saved = serializePlaylist(replayer);
  var restored = deserializePlaylist(saved);
  scatMan.backTo(restored.first);
Will produce:
  *** Whoa! This was a good one, let's hear it again :) ***
Playing New York, New York Medley // A Vintage Year @ 1.27
--
  *** Whoa! This was a good one, let's hear it again :) ***
Playing 'Round Midnight // Tormé @ 2.89
So it works, but does it violate the either the letter or the spirit of the memento pattern law?

I would argue that it does not violate the spirit of the law. All of the internal knowledge of the implementation details remains in the velvet_fog_machine library. The caretaker code still maintains the list of mementos. And it still cannot access the internal state of the VelvetFogMachine.

That said, it could get access to the internal state and some idea of the implementation by looking at the serialized mementos in the list:
[{"song":
   {"title":"'Round Midnight","album":"Tormé"},
 "time":2.89},
{"song":
   {"title":"New York, New York Medley","album":"A Vintage Year"},
"time":1.27}]
Ultimately, I think this is probably OK-ish. Even armed with with this knowledge, the caretaker code still cannot access the actual data in the memento. It is still forced to work through the play() method to interact with the internal state of the originator. Some details are exposed, but not in a manner in which the caretaker can affect the originator. So the originator retains encapsulation and the code remains maintainable.

So the answer would seem to be, "do". But only if necessary.

Play with this code on DartPad: https://dartpad.dartlang.org/69bc9464388fadee2042.


Design Patterns in Dart


Day #23

Thursday, December 3, 2015

An Iterator Memento


I can't see any good reason to try this... So of course I'll try it anyway.

The Gang of Four book includes a memento pattern iterator inspired by Dylan. Dart supports iterators natively, so there is no need for adapting this approach, but what the hey?

I start with the memento. In this implementation, the memento is the iteration state. For illustration purposes, this state will be a simple counter:
class IterationState {
  int index = 0;
  void increment() { index++; }
}
This example might benefit from a more complex state, but I'll start simply to get things working.

Pulling almost directly from the Gang of Four book, I declare the iterator collection as:
class SongCollection {
  List _list = [];

  SongCollection();

  IterationState createInitialState() => new IterationState();
  void next(IterationState state) { state.increment(); }
  bool isDone(IterationState state) => state.index >= _list.length;
  Song currentItem(IterationState state) => _list[state.index];

  void add(Song s) { _list.add(s); }
}
The private _list is appended via the add() method. Everything else in there works with the memento.

I continue to use the same Song class from the past couple of days:
class Song {
  String title, album;
  Song(this.title, this.album);
  void play() {
    print("Playing ${toString()}");
  }
  String toString() => "$title // $album";
}
Instances of this object will be added to the SongCollection iterator so that each be played. Hopefully that will do it for the setup.

In the caretaker context, I create the collection and add a choice selection of great songs:
  var collection = new SongCollection();
  collection
    ..add(new Song('The Lady is a Tramp', 'The Velvet Frog: The Very Best of Mel Tormé'))
    ..add(new Song('New York, New York Medley', 'A Vintage Year'))
    ..add(new Song('Blue Moon', 'The Velvet Frog: The Very Best of Mel Tormé'))
    ..add(new Song('\'Round Midnight', 'Tormé'));
Next, I grab a reference to the initial collection state (also know as the memento):
  var state = collection.createInitialState();
With that, I am able to iterate over the collection:
  while (!collection.isDone(state)) {
    collection.currentItem(state).play();
    collection.next(state);
  }
And that works as expected. Each song is played in the order in which is was added to the collection:
$ ./bin/play_melvie.dart
Playing The Lady is a Tramp // The Velvet Frog: The Very Best of Mel Tormé
Playing New York, New York Medley // A Vintage Year
Playing Blue Moon // The Velvet Frog: The Very Best of Mel Tormé
Playing 'Round Midnight // Tormé
On the face of it, there is little benefit to this approach. The forEach() of a Dart List could accomplish much the same behavior with no additional classes. That said, as the Gang of Four book mentions, it would be possible for multiple state mementos to work on the same collection (e.g. if multiple fans wanted to listen to the Velvet Fog at their convenience). Additionally, the internals of the state are not exposed to the caretaker—only the SongCollection has access to it, preserving encapsulation. This is not of much benefit when the state is a tracking integer, but more complex state mementos would certainly benefit from this approach.

In the end, this was a fun exercise. But I'll probably stick with forEach() all the same.

Play with this code on DartPad: https://dartpad.dartlang.org/d5e3ffb470d140142e36.


Day #22

Wednesday, December 2, 2015

Incremental Mementos


Let's have some fun with incremental mementos. I have a decent memento pattern example ready for Design Patterns in Dart. Hopefully it can be adapted to produce incremental memento objects instead of the full state object that it is currently returning.

The example application is the velvet fog machine, used by lover's of Mel Tormé everywhere to produce the perfect playlist for any occasion. The originator class in the pattern is the VelvetFogMachine, which serves as a digital jukebox. It plays songs:
class VelvetFogMachine {
  // ...
  void play(String title, String album, [double time = 0.0]) {
    _play(new Song(title, album), time);
  }
  // ...
}
It can send back mementos of the current song / time within the song:
class VelvetFogMachine {
  // ...
  Playing get nowPlaying => new Playing(currentSong, currentTime);
  // ...
}
It can use these Playing mementos to return to previous states:
class VelvetFogMachine {
  // ...
  void backTo(Playing p) {
    print("\n===> (backTo)");
    _play(p._song, p._time);
  }
}
Currently, that Playing class stores both the currentSong and currentTime every time that the nowPlaying getter is invoked in VelvetFogMachine. But why bother doing that if the song stays the same while the time increases:
  List<Playing> replayer = [];

  var scatMan = new VelvetFogMachine();
  scatMan.play(
      'New York, New York Medley',
      'A Vintage Year'
  );
  replayer.add(scatMan.nowPlaying);
  replayer.add(scatMan.nowPlaying);
  replayer.add(scatMan.nowPlaying);
  replayer.add(scatMan.nowPlaying);

  // Now move back to the different bookmarked times in the 
  // New York, New York song
  scatMan.backTo(replayer.removeLast());
  scatMan.backTo(replayer.removeLast());
  scatMan.backTo(replayer.removeLast());
  scatMan.backTo(replayer.removeLast());
The result of running this code looks something like:
Playing New York, New York Medley // A Vintage Year @ 0.00

===> (backTo)
Playing New York, New York Medley // A Vintage Year @ 5.10

===> (backTo)
Playing New York, New York Medley // A Vintage Year @ 4.22

===> (backTo)
Playing New York, New York Medley // A Vintage Year @ 2.35

===> (backTo)
Playing New York, New York Medley // A Vintage Year @ 0.51
There really is no need to store the song in each memento. But where should the responsibility lie for remembering the previous memento, determining the difference between increments?

I think it has to be the originator—the VelvetForMachine. One way or another, the VeletFogMachine needs to know what to do when it sees a null song in backTo():
  void backTo(Playing p) {
    print("\n===> (backTo)");
    var song = (p._song == null) ? currentSong : p._song;
    _play(song, p._time);
  }
So if the VelvetFogMachine is handling increments when restoring state, it stands to reason that it should do the same when creating state:
  Playing get nowPlaying {
    var song  = (_lastSong == currentSong) ? null : currentSong;
    _lastSong = currentSong;

    return new Playing(song, currentTime);
  }
Introduced here is _lastSong to track which song was playing the last time state was recorded in a memento. If the last song and the current song are the same, then the memento records a null song. Otherwise the actual song is recorded to note the change in songs.

That seems to work. When the code is run, the output is reported as:
Playing New York, New York Medley // A Vintage Year @ 0.00
...

===> (backTo)
Playing New York, New York Medley // A Vintage Year @ 5.10

===> (backTo)
Playing New York, New York Medley // A Vintage Year @ 4.22

===> (backTo)
Playing New York, New York Medley // A Vintage Year @ 2.35

===> (backTo)
Playing New York, New York Medley // A Vintage Year @ 0.51
Despite the seemingly working code, I have some reservations about this—at least about including it in the book. I am faking the times with a random increment. That does not seems conceptually hard for full state, but I worry that it will be confusing should I choose to discuss it in the book. Perhaps I can simply gloss over incremental changes as did the Gang of Four book.

I also have the feeling that this incremental code really ought to move out into its own class. I left it in the VelvetFogMachine as I explored, but if the rest of the pattern is obsessed with single-responsibility, then it seems like this is asking for trouble.

All that said, I may investigate this further. Just because the GoF did not discuss incremental changes in detail does not give me warrant to do the same. If I can do so easily and if it helps support discussion of the pattern, I am obligated to pursue it. Tomorrow.

Play with this code on DartPad: https://dartpad.dartlang.org/4bde9f50dfd2dea2c872.


Day #21

Tuesday, December 1, 2015

Dart Has Friend Class Baked In


The great thing about blogging every day is that I'm guaranteed to make an idiot out of myself. There is just no way around it. There are some days (sometimes even several days in succession) when a obvious solution just isn't obvious. And it's very liberating to accept that and just move forward with learning.

Actually, it's still completely embarrassing, but I'll stick with the first story.

Today's embarrassment comes in the form friend classes in Dart. I continue to explore the memento pattern for the forthcoming Design Patterns in Dart. The implementation section in the Gang of Four book suggests that, to preserve encapsulation, the memento should expose its properties only to the originating class of the pattern, but not to anything else.

Specifically, the caretaker that saves memento objects should not itself be able to access the properties of the memento. Since the memento represents a previous internal state, the caretaker should not be looking under the covers, so to speak. If it needs to know anything, it should ask the originating class. In the Gang of Four book, this is achieved via friend classes.

For the past two nights, I have struggled to bend Dart to my will in achieving this friend class behavior. Instead, as the esteemed James Hurford pointed out in last night's comments, Dart's libraries simply work this way.

Private variables in Dart are private to a library, not a class. So if I make the properties of my memento object private, nothing outside of the library (like the caretaker from the pattern) can access them. But the originator class in the same library should still be able to access them.

The originating class with which I have been experimenting is the VelvetFogMachine, which plays wonderful selections of the great crooner's catalog. The nowPlaying getter method is used to generate the Playing memento objects:
class VelvetFogMachine {
  Song currentSong;
  double currentTime;
  // ...

  // Create a memento of the current state
  Playing get nowPlaying => new Playing(currentSong, time);
  // ...
}
Following James' suggestion, I should make the properties of Playing private (leading underscore variables are private in Dart):
// The Memento
class Playing {
  Song _song;
  double _time;
  Playing(this._song, this._time);
}
Next, I ensure that both of these classes exist in the velvet_fog_machine library:
library velvet_fog_machine;
// The "Originator"
class VelvetFogMachine { /* ... */ }
// The Memento
class Playing { /* ... */ }
With that, the VelvetFogMachine should have access to Playing's _song and _time private variables when restoring a previous memento:
class VelvetFogMachine {
  // ...
  // Restore from memento
  void backTo(Playing p) {
    print("  *** Whoa! This was a good one, let's hear it again :) ***");
    _play(p._song, p._time);
  }
}
And that actually works right away. Well, I shouldn't say "actually." I really should have remembered that this is how private variables work, but this is so much simpler than any of the craziness that I had been trying the previous two nights.

Back in the caretaker code—and outside the velvet_fog_machine library—I can play songs, store mementos, and restore mementos:
  import 'package:memento_code/velvet_fog_machine.dart';
  // ...
  List<Playing> replayer = [];

  var scatMan = new VelvetFogMachine();
  // ...
  scatMan.play(
      'New York, New York Medley',
      'A Vintage Year'
  );
  replayer.add(scatMan.nowPlaying);

  scatMan.play(
      'The Lady is a Tramp',
      'The Velvet Frog: The Very Best of Mel Tormé'
  );

  // The New York, New York Medley with George Shearing really is wonderful
  scatMan.backTo(replayer.last);
Running this from the command line produces the usual play() messages and verifies that the backTo() method was able to access the memento's private properties:
./bin/play_melvie.dart
Playing Blue Moon // The Velvet Frog: The Very Best of Mel Tormé @ 0.00
Playing 'Round Midnight // Tormé @ 0.00
Playing It Don't Mean A Thing (If It Ain't Got That Swing) // Best Of/ 20th Century @ 0.00
Playing New York, New York Medley // A Vintage Year @ 0.00
Playing The Lady is a Tramp // The Velvet Frog: The Very Best of Mel Tormé @ 0.00
  *** Whoa! This was a good one, let's hear it again :) ***
Playing New York, New York Medley // A Vintage Year @ 1.28
Best of all, if I try to access the private variables from the caretaker:
    print("Caretaker says last remembered song is: ${replayer.last._song}");
Then I get no-such-method errors and dartanalyzer complains:
[warning] The getter '_song' is not defined for the class 'Playing' (/home/chris/repos/design-patterns-in-dart/memento/bin/play_melvie.dart, line 40, col 68)
This is exactly the "friend class" behavior that I wanted.

So the moral of the story is that it takes two days of trying dumb stuff on the internet before a kind soul takes pity on you and points you in the right direction. No wait, the moral of the story is that if you want friend classes in Dart, keep them in the same library. Thanks James!


Day #20

Monday, November 30, 2015

Runtime Narrow Interfaces in Dart


My memento has a wide interface. I continue to work with the memento pattern in Dart. The initial implementation went well, but the devil is in the details.

The details in this case come in the form of implementation item #1 from the Gang of Four book, which suggest that only the originator class should have access to the properties of the memento object. As I found last night, that is not an easy thing to do in Dart. There is no concept of friend classes in Dart. There is not even an easy way to obtain the caller of a function to determine access.

In the end, I hacked a caller into the memento object in my example code by examining the stacktrace of a thrown exception. There is no world in which that is a good idea, so tonight, I try to do a little better. Since neither the requirements nor the limitations have changed, I have to try an alternate approach. And I think it all has to be done at runtime.

The originator class in my example is the VeletFogMachine, which plays various songs from the late, great Mel Tormé. The memento class is Playing, which the caretaker context can use to replay previous songs. Again, the caretaker should not be able to access any song information—only supply the Playing memento to the originator so that it can be handled properly.

What I come up with is a runtime secret, supplied to by the VelvetFogMachine:
class Playing {
  Song _song;
  double _time;
  double _secret;

  // Narrow interface for the world
  Playing();

  // Wide interface for the VelvetFogMachine
  Playing.forTheVelvetFogMachine(this._song, this._time, this._secret);
  // ...
}
This named constructor suggests that it only works with the VelvetFogMachine. In reality, it is possible to use it from outside that context, but it ought to feel really strange to just about anyone.

The secret supplied to the constructor can then be used to check access to a particular method, like the secretSong() method:
class Playing {
  // ...
  Song secretSong(double secret) {
    // Runtime check for access
    _checkAccess(secret, #secretSong);
    return _song;
  }
  // ...

  _checkAccess(secret, memberName) {
    if (secret == _secret) return;

    throw new NoSuchMethodError(this, memberName, [secret], {});
  }
}
The secret itself has to come from the VelvetFogMachine originator class and it has to be private to that class so that no other classes can get access:
import 'dart:math';
final rand = new Random(1);

// The "Originator"
class VelvetFogMachine {
  Song currentSong;
  double currentTime;
  final double _secret = rand.nextDouble();
  // ...

  // Create a memento of the current state
  Playing get nowPlaying {
    // Simulate playing at some time later:
    var time = 5*rand.nextDouble();

    return new Playing.forTheVelvetFogMachine(currentSong, time, _secret);
  }
  // ...
}
That works. The original code continues to function properly when used inside the originator:
class VelvetFogMachine {
  // ...
  void backTo(Playing p) {
    print("  *** Whoa! This was a good one, let's hear it again :) ***");
    _play(p.secretSong(_secret), p.secretTime(_secret));
  }
}
Furthermore, the caretaker code is unable to access the secretSong() method:
List<Playing> replayer = [];

  var scatMan = new VelvetFogMachine();
  // ...

  scatMan.play(
      'New York, New York Medley',
      'A Vintage Year'
  );
  replayer.add(scatMan.nowPlaying);
  // ...

  // This should not work:
  try {
    print("Caretaker says last remembered song is: ${replayer.last.secretSong(0.0)}");
  }
  on NoSuchMethodError {
    print("Yay! Caretaker was denied access to the memento song.");
  }
This results in the NoSuchMethodError output:
$ ./bin/play_melvie.dart                                       
...
Playing New York, New York Medley // A Vintage Year @ 0.00
Playing The Lady is a Tramp // The Velvet Frog: The Very Best of Mel Tormé @ 0.00
  *** Whoa! This was a good one, let's hear it again :) ***
Playing New York, New York Medley // A Vintage Year @ 4.60

Yay! Caretaker was denied access to the memento song.
So this works, but it is an awful lot of work and there are still ways around it. Still, unless someone has a suggestion, I will likely stick with this as the best approach to narrowing the interface of the memento when discussing in Design Patterns in Dart.

Play with this code on DartPad: https://dartpad.dartlang.org/a1971dcad8f0466d7cfe


Day #19

Sunday, November 29, 2015

Making Friends in Dart


The memento in my memento pattern is a tad friendly. In the original Gang of Four book, the suggested implementation has a narrow interface into the memento class. That is, only the originator of the memento can access the memento's properties.

My Dart version is considerably more open:
// The Memento
class Playing {
  Song song;
  double time;
  Playing(this.song, this.time);
}
I continue to work on the VelvetFogMachine application. It needs access to the auto-defined song and time getter methods when restoring a previously playing Mel Tormé song:
// The "Originator"
class VelvetFogMachine {
  // ..
  // Restore from memento
  void backTo(Playing p) {
    print("  *** Whoa! This was a good one, let's hear it again :) ***");
    _play(p.song, p.time);
  }
}
Really, all that the originator needs to access are the getters as shown. I do not need the auto-defined setters. I could address this with private properties paired with explicit, public getters:
class Playing {
  Song _song;
  double _time;
  Playing(this._song, this._time);

  Song get song => _song;
  double get time => _time;
}
This helps a little to address concerns with encapsulation. It is still possible for the caretaker context, which should only play or restore songs (set / restore state), to access the song and time properties. In most cases, this will not be a problem. The caretaker will merrily play and restore without ever wondering about the memento returned by nowPlaying:
  scatMan.play(
      'New York, New York Medley',
      'A Vintage Year'
  );
  replayer.add(scatMan.nowPlaying);
  //  Play other songs...

  // The New York, New York Medley with George Shearing really is wonderful
  scatMan.backTo(replayer.last);
That said, there is virtue in narrowing the interface. Another coder might come along and attempt to get access the memento song title. To achieve that, encapsulation would need to be broken, violating the very intention of the memento pattern.

So what is to be done here? Unfortunately, I cannot think of much in Dart where there is no support for friend classes (as far as I know). The best I can come up with is an ugly hack to determine the caller of a noSuchMethod() invocation.

In Dart, if a method is not found, but the class declares a noSuchMethod(), then that noSuchMethod() method is invoked. I could rewrite the public getters for song and time as:
class Playing {
  Song _song;
  double _time;
  Playing(this._song, this._time);

  noSuchMethod(Invocation i) {
    if (i.memberName == #song) return this._song;
    if (i.memberName == #time) return this._time;

    return super.noSuchMethod(i);
  }
}
That is fairly straight-forward. If the noSuchMethod() method is invoked with song as the method name, then the private _song property is returned. The same thing happens with time. If something else if invoked, then the superclass noSuchMethod() is invoked, likely throwing a halting exception.

This does nothing to prevent classes other than VelvetFogMachine from accessing song and time. For that, I need access to the class that invoked the getter. As far as I know there is no "real" way to accomplish this in Dart. The best I can do is throw an exception and catch the stacktrace:
class Playing {
  Song _song;
  double _time;
  Playing(this._song, this._time);

  noSuchMethod(Invocation i) {
    try { throw new Error(); }
    catch (_exception, stackTrace) {
      if (!stackTrace.toString().contains(new RegExp(r'\#1\s+VelvetFogMachine'))) {
        return super.noSuchMethod(i);
      }
    }

    if (i.memberName == #song) return this._song;
    if (i.memberName == #time) return this._time;

    return super.noSuchMethod(i);
  }
}
That works and dartanalyzer doesn't complain (with a @proxy annotation applied to the class). But yuck. Further, I an unsure if this works in all Dart VMs (it does not work on DartPad, for instance).

So, unless someone has any ideas, it seems safe to say that Dart classes are friendly to everyone. In other words, Dart classes are slightly too friendly for the memento pattern.


Day #18

Saturday, November 28, 2015

Memento Not As State


I really need to cut out the extreme late night coding. I left off last night with a fully formed planned to increase the "Dartiness" in my memento pattern example, but in the light of day I haven't the velvet foggiest notion what that plan might have been. No pity here though, there is still something to say about the existing code.

I am curious about the relationship between the internal state of the originator and the memento object. In particular, should the memento object be the state in the originator class? After last night, that is exactly what the VelvetFogMachine originator class does in its play() method:
// The "Originator"
class VelvetFogMachine {
  // The Memento
  Playing _nowPlaying;

  // Set the state
  void play(String title, String album, [double time = 0.0]) {
    print("Playing $title // $album @ ${time.toStringAsFixed(2)}");
    _nowPlaying = new Playing(title, album, time);
  }
  // ...
}
The second time around with the code, I think perhaps the memento-as-state is inappropriate. Oh, it works—especially in this short example. In real life code however, it is more likely that the VelvetFogMachine would want to track the current song and current time directly. Something along the lines of the following achieves a nearness to a more organic VelvetFogMachine:
class VelvetFogMachine {
  Song currentSong;
  double currentTime;

  void play(String title, String album, [double time = 0.0]) {
    currentSong = new Song(title, album);
    currentTime = time;
    print("Playing $currentSong @ ${time.toStringAsFixed(2)}");
  }
  // ...
}
My romance of a better example would push the song title and album into a new Song class:
class Song {
  String title, album;
  Song(this.title, this.album);
  String toString() => "$title // $album";
}
Ah, Dart code, do I love you because you're beautiful? You certainly know my heart, but I still do not believe that is the "Dartiness" I was planning last night. Hopefully I can figure it out because it's really under my skin.

Back to my example, the currentSong and currentTime feel like properties that could exist before realizing that a memento pattern was needed. In other words, I think this is a stronger memento example. Now what to do with the memento class? Previously, it stored separate song title, album and time properties:
class Playing {
  String title, album;
  double time;
  Playing(this.title, this.album, this.time);
}
I am tempted to stick with with this structure in the memento class. After all, it mirrors the signature of the play() method in the VelvetFogMachine's play() method that creates the internal state being memento-ized. In the end, I think it best for the memento class to mirror the internal structure of the originator class, so title and album are replaced with song:
class Playing {
  Song song;
  double time;
  Playing(this.song, this.time);
}
Now that I have settled on this for the Playing memento, the method that creates the memento in VelvetFogMachine is trivial. The nowPlaying getter method simply instantiates the memento with the current song and time:
class VelvetFogMachine {
  // ...
  Playing get nowPlaying => new Playing(currentSong, currentTime);
  // ...
}
Everyday's a holiday with Dart and hash-rocket return methods. That's good, clean fun.

But what of the method that restores state from a previously recorded memento? It now has to translate the Song-based memento into the three argument play() method:
class VelvetFogMachine {
  // ...
  void backTo(Playing p) {
    print("  *** Whoa! This was a good one, let's hear it again :) ***");
    play(p.song.title, p.song.album, p.time);
  }
}
Some indirection aside, that is not too horrible. Certainly it is better that the VelvetFogMachine be responsible for translating a memento of previous state into a play() instead of the caretaker context. The whole point of the memento after all, is to prevent exposing internal implementation details when saving state.

If the indirection bothers me, I can replace the current play() with a call to a private, Song-based method:
  void play(String title, String album, [double time = 0.0]) {
    _play(new Song(title, album), time);
  }

  void _play(Song s, double t) {
    currentSong = s;
    currentTime = t;
    print("Playing $currentSong @ ${currentTime.toStringAsFixed(2)}");
  }
With that, the restore-from-memento method can invoke the same _play() method:
  void backTo(Playing p) {
    print("  *** Whoa! This was a good one, let's hear it again :) ***");
    _play(p.song, p.time);
  }
I think I prefer that approach. That said, I might stick with the previous, non-private-based play() method in the book. The difference between the three argument play() method and the two-property memento better illuminates the need to hide implementation details of the originator from the outside world.

That's about all for this bit of exploration. I am clearer on the need for the memento to encapsulate, but not be, the internal state of the originator. I had been glossing over that in my mind, but am happy for having cracked that chestnut.

And I do think I remember that "Dartiness" factor I had hoped to explore. Hopefully we are not strangers in the late night and I will still remember it tomorrow. Stay tuned Mel fans!

Play with this code on DartPad: https://dartpad.dartlang.org/35e0056a1f290c74d996

Day #17

Friday, November 27, 2015

A Better Memento Example: Now with More Encapsulation!


Up tonight, I take a closer look at encapsulation in the memento pattern. I have a decent start on the pattern from last night, but I glossed over one of the important reasons behind the memento pattern. Per the Gang of Four book, the pattern is applicable when obtaining state would break encapsulation.

Currently, the caretaker of the pattern plays a song, remembers the state on occasion, and replays particularly good Mel Tormé songs:
  List<String> replayer = [];
  var scatMan = new VelvetFogMachine();
  // ...
  scatMan.play(
      'New York, New York Medley',
      'A Vintage Year'
  );
  replayer.add(scatMan.nowPlaying);
  // ...

  // The New York, New York Medley with George Shearing really is wonderful
  scatMan.backTo(replayer[1]);
The encapsulation in this case is in the nowPlaying getter of the VelvetFogMachine. The nowPlaying property in the Melvie-tastic VelvetFogMachine is a list of strings (the title and album of the song):
class VelvetFogMachine {
  List<String> _nowPlaying;
  // ...
}
There is not much to the state being exposed and what state is exposed comes directly from the caretaker (i.e. the title and album). So this may not be the ideal example. In addition to the song playing, I will try storing the current time within the song as well:
// The Memento
class Playing {
  String title, album;
  double time;
  Playing(this.title, this.album, this.time);
}
If I tried to store this in the caretaker context, then I would certainly be breaking encapsulation. I would have to note the title, album and time at which the playing moved to the next song. Those aren't exactly related values, so this seems a better example.

Since I do not wish to expose the underlying implementation, the replayer can no longer be a list of strings. Instead, it needs to be a list of Playing objects (i.e. a list of mementos):
  List<Playing> replayer = [];
Nothing else needs to change in the caretaker code. The scatMan still plays songs by title and album. The nowPlaying property still returns a memento—albeit a more complex one. The backTo() method still takes the memento and uses it to restore state. Nothing really changed, but the more complex example better justifies the application of the pattern.

The code in VeletFogMachine does not change much—it just needs to accommodate time now. The play() method optionally accepts it:
  void play(String title, String album, [double time = 0.0]) {
    print("Playing $title // $album @ ${time.toStringAsFixed(2)}");
    _nowPlaying = new Playing(title, album, time);
  }
And the backTo() method needs to use the stored value to resume playing where it left off:
  // Restore from memento
  void backTo(Playing memento) {
    print("  *** Whoa! This was a good one, let's hear it again :) ***");
    play(memento.title, memento.album, memento.time);
  }
After adding a random number for the saved time, I have everything working—including restoring from the slightly more complex state:
$ ./bin/play_melvie.dart                                       
...
Playing The Lady is a Tramp // The Velvet Frog: The Very Best of Mel Tormé @ 0.00
  *** Whoa! This was a good one, let's hear it again :) ***
Playing New York, New York Medley // A Vintage Year @ 1.28
That seems a good place to stop for tonight. The memento seems a relatively simple pattern, which is making me feel the urge to move on to other patterns. But it is probably worth exploring a few more facets of the pattern in the next day or so. First up, I plan to see if there is a more "Darty" solution. Tomorrow.

Play with this code on DartPad: https://dartpad.dartlang.org/bf9c7454247a122030f9


Day #16

Thursday, November 26, 2015

The Velvet Fog Memento


I'm picking patterns to explore for Design Patterns in Dart by throwing proverbial darts at whatever design pattern book happens to be closest at hand. Up tonight is the memento.

I don't much care for the abstract nature of the examples in the Wikipedia article on memento. The constraint solver example in the GoF book always seemed too academic to me (though I recognize the importance of constraint solvers). I would prefer an example to which everyone can relate. Maybe something like a machine dedicated to building the ultimate Mel Tormé playlist. Everybody can relate to Melvie.

The "originator" in this scenario will be the VelvetFogMachine. It will be responsible for playing the best of the most gifted scatman of the 20th century. For this first pass, I will forgo the usual method names in the memento pattern (e.g. `CreateMemento`, `restoreFromMemento`). Instead, I would like to explore with more natural names like play(), backTo(), and nowPlaying:
// The "Originator"
class VelvetFogMachine {
  // Set the state
  void play(String title, String album);

  // Return a memento for possible later restoration
  Memento get nowPlaying;

  // Restore from memento
  void backTo(Memento memento);
}
The nowPlaying method will return a memento object that can be used to restore the currently playing song (i.e. the state) at a later time with backTo().

I will worry about proper serialization another day. For now, I make the Memento object as simple as possible. It encapsulates a string representation of the state:
class Memento {
  String state;
  Memento(this.state);
}
Back in the VelvetFogMachine originator, the play() method prints the currently playing song and stores the internal state:
class VelvetFogMachine {
  List<String> _nowPlaying;

  void play(String title, String album) {
    print("Playing $title // $album");
    _nowPlaying = [title, album];
  }
  // ...
}
As for generating a memento, I join the song and album with triple-colons in a string:
Memento get nowPlaying => new Memento(_nowPlaying.join(':::'));
Similarly, going back to a previous state needs to split the triple-colons and change the VelvetFogMachine with its own call to play():
  void backTo(Memento memento) {
    print("  *** Whoa! This was a good one, let's hear it again :) ***");
    var previous = memento.state.split(':::');
    play(previous[0], previous[1]);
  }
That more-or-less covers the functionality of the originator (VelvetFogMachine) and memento (Memento) in the pattern. All that is left is the caretakers. For this first pass, I put the caretaker back in the main() entry point.

Here, I need a list of possible replay targets and an instance of the VelvetFogMachine to play that scat music, save my place on occasion, and replay the very best moments:
main() {
  List replayer = [];

  var scatter = new VelvetFogMachine();
  scatter.play(
      'Blue Moon',
      'The Velvet Frog: The Very Best of Mel Tormé'
  );
  scatter.play(
      '\'Round Midnight',
      'Tormé'
  );
  replayer.add(scatter.nowPlaying);

  scatter.play(
      'It Don\'t Mean A Thing (If It Ain\'t Got That Swing)',
      'Best Of/ 20th Century'
  );
  scatter.play(
      'New York, New York Medley',
      'A Vintage Year'
  );
  replayer.add(scatter.nowPlaying);

  scatter.play(
      'The Lady is a Tramp',
      'The Velvet Frog: The Very Best of Mel Tormé'
  );

  // The New York, New York Medley with George Shearing really is wonderful
  scatter.backTo(replayer[1]);
}
And that does it. I can play some wonderful tunes and, when one really strikes me, I can replay it later thanks to a memento:
$ ./bin/play_melvie.dart
Playing Blue Moon // The Velvet Frog: The Very Best of Mel Tormé
Playing 'Round Midnight // Tormé
Playing It Don't Mean A Thing (If It Ain't Got That Swing) // Best Of/ 20th Century
Playing New York, New York Medley // A Vintage Year
Playing The Lady is a Tramp //  The Velvet Frog: The Very Best of Mel Tormé
  *** Whoa! This was a good one, let's hear it again :) ***
Playing New York, New York Medley // A Vintage Year
I do not know that there is much more to explore in this pattern. Where to serialize should be addressed (maybe in the Memento?). I have more general questions about how to present this—I am not fond of UML and prefer real-world examples over abstract ones. Still, I ought to be able to present how this generalizes for usage elsewhere—it is a pattern after all. Last, I need to see if I can find ways in which the pattern can be "Dartier." But for now, this is a fine stopping place.

Play with this code on DartPad: https://dartpad.dartlang.org/5ea65d5b9e6791462547


Day #15