Exercises in Programming Style–Letterbox

NOTE : read the rest of the series, or check out the source code.

If you enjoy read­ing these exer­cises then please buy Crista’s book to sup­port her work.

exercises-prog-styles-cover

Fol­low­ing on from the last post, we will look at the Let­ter­box style today.

 

Style 11 – Letterbox

You may also know this style as mes­sage pass­ing, or SmallTalk style (or Objec­tive-C for that mat­ter). It was also what Alan Kay had in mind when he coined the term Object Ori­en­ta­tion all those years ago ;-)

image

image

 

Constraints

  • Larg­er prob­lem is decom­posed into things that make sense for the prob­lem domain
  • Each thing is a cap­sule of data that expos­es one sin­gle pro­ce­dure, name­ly the abil­i­ty to receive and dis­patch mes­sages that are sent to it
  • Mes­sage dis­patch can result in send­ing the mes­sage to anoth­er cap­sule

 

The things that we end up with in this style is very sim­i­lar to that of the Things (or OOP) style from the last post:

  • DataS­tor­age­M­an­ag­er
  • Stop­Words­Man­ag­er
  • Word­Fre­quen­cy­Man­ag­er
  • Word­Fre­quen­cy­Con­troller

The dif­fer­ence here is that, each of these things expos­es only a Dis­patch method.

 

Let’s look at the DataS­tor­age­M­an­ag­er first, a faith­ful trans­la­tion of Crista’s exam­ple would look like this:

image

Com­pared to the DataS­tor­age­M­an­ag­er imple­men­ta­tion in the Things style, there are some notable dif­fer­ences:

  • we lose type safe­ty as we have to com­bine init and words into a sin­gle Dis­patch method
    • what ‘func­tion­al­i­ties’ the things can pro­vide is implied through the tagged arrays that the Dis­patch log­ic is hap­py to accept
    • the return types have to be uni­fied to obj
  • data has to be muta­ble
    • con­se­quent­ly words also has to become a func­tion

 

Giv­en the strong­ly typed nature of F# we also need to explic­it­ly cast every result to obj. This, of course, is not an issue in dynam­i­cal­ly typed lan­guages such as SmallTalk and Python. But, we’re in F# so let’s make the type sys­tem work for us rather than against us.

We can eas­i­ly uni­fy the dif­fer­ent mes­sages a Thing can accept into a union type:

Style11_01

Whilst we could also add a union type for the results, such as:

    type DSMan­ager­Re­sult = Init of unit | Words of string[]

I don’t con­sid­er it to be much bet­ter because as a con­sumer of this API I still find it ambigu­ous. The sig­na­ture Dis­patch : DSMan­ager­Mes­sage -> DSMan­ager­Re­sult would sug­gest that you can always get either Init of unit or Words of string[] for any DSMan­ager­Mes­sage, which isn’t true.

If you know of a bet­ter way to add type safe­ty to the return type in this case, please let me know via the com­ments sec­tion below.

 

Mov­ing on to the Stop­Words­Man­ag­er, we can apply the same approach:

Style11_02

And the same goes to the Word­Fre­quen­cy­Man­ag­er:

Style11_03

And last­ly, the Word­Fre­quen­cy­Con­troller:

Style11_04

in the init func­tion here, we’ll ini­tial­ize the var­i­ous depen­den­cies and instruct each to ini­tial­ize accord­ing­ly:

Style11_05

in the run func­tion, we’ll con­nect the var­i­ous Things togeth­er by dis­patch­ing mes­sages to them in a pipeline:

Style11_06

To get the answer, we’ll have to send some mes­sages to an instance of Word­Fre­quen­cy­Con­troller:

Style11_07

 

Wait, all these mes­sage dis­patch­ing busi­ness look an awful lot like actors, couldn’t we have imple­ment­ed the Things using F#‘s mail­box proces­sors instead?

There’s actu­al­ly a sub­tle dif­fer­ence here in that actors are char­ac­terised by an inter­nal mes­sage queue (which is out­side the scope of the con­straints here) and mes­sages are sent asyn­chro­nous­ly. If you’re a fan of mail­box proces­sors then wor­ry not, the Actor style comes lat­er on in this series.

 

You can find the source code for this exer­cise here.