Affordances: Factory Pattern

Many programming languages provide support for
reflection,
which allows for very creative metaprogramming when solving problems.
The reflection facilities in various languages differ in the kinds of
features they provide, their ease of use, and their verbosity.

Reflection is a kind of affordance.

Reflection is often used to implement the
Factory Pattern. As
an example, consider an application that receives commands over a
socket. Each command takes a different set of arguments and performs
some more or less complex action in response. This example was
inspired by John Pignata’s excellent talk at
Mountain West Ruby Conference 2013,
Code Smells: Your Refactoring Cheat Codes.

Assuming that each command has been encapsulated into its own subclass
of Command, the obvious solution is to dispatch commands with a case
statement.

Note that C++ doesn’t allow strings as case options in a switch
statement, so we’re forced to use a series of if statements
instead. This is also a kind of affordance.

Dispatch with Case Statement

std::unique_ptr<Command>command;

if(commandToken=="PING")

{

command.reset(newPing);

}

elseif(commandToken=="SEND")

{

command.reset(newSend);

}

...

else

{

throwCommandNotFound(commandToken);

}

command->execute(arguments);

Every time we add a new command, we have to update this if
statement. Since C++ only has minimal reflection capabilities, we
might choose to stop there, or we might introduce some kind of command
registry using macros or explicit initialization.

In Ruby, since we have reflection and metaprogramming
facilities, we can come up with something a little more maintainable:

Now, adding a new command is as simple as adding one more entry in the
COMMANDS hash.

In Ruby, superclasses don’t know about their subclasses by default.
This is not true of Smalltalk, though, so we can take advantage of that:

Smalltalk Dispatcher

Commandclass>>dispatch:aStringarguments:anArray

class=selfallSubclasses

detect:[:each|eachtoken=aString]

ifNone:[(CommandNotFoundcommand:aString)raise].

classnewexecute:anArray

Commandclass>>token

^selfsubclassResponsibility

Pingclass>>token

^'PING'

Sendclass>>token

^'SEND'

By taking advantage of Smalltalk’s reflection, we can completely
eliminate any central registry of commands. Now, adding a new command
is as simple as introducing a new Command subclass. As long as the
new class inherits from Command and implements the class-side
token method, it will automatically be found by the dispatcher.

It is possible to implement a similar approach in Ruby using
Class#inherited, but that’s a bit more work to set up.

And that’s actually the point of affordances. Because Smalltalk
provides direct access to subclasses, it affords the ability to find
the commands dynamically. Because Ruby and Smalltalk provide
reflection, they afford a cleaner implementation of the factory
pattern than languages without reflection.