D
Dave Benjamin
There's been a lot of discussion lately regarding Ruby and the notion of a
"humane" interface to objects like arrays and maps, as opposed to
"minimalist" ones. I believe the article that started the debates was this
one by Martin Fowler:
http://www.developertesting.com/archives/month200512/20051218-HumaneInterfaceOfMinimalInterface.html
And this one was posted in response by Bruce Eckel:
http://www.artima.com/forums/flat.jsp?forum=106&thread=141312
When I see the term "Humane Interface", I immediately think of the book
"The Humane Interface" by the late Jef Raskin. Although this book mainly
focuses on GUI interaction, it is also about the human-computer interface
in general, and makes some points that apply to the programming experience
as well.
The irony, I find, is that Raskin's definition of a humane interface seems
to better fit what Fowler describes as "minimalist". Raskin argues that
two ideals in interface design are what he calls "modelessness" and
"monotony". The two terms essentially relate to causes and effects.
Modelessness means that the same cause produces the same effect. "Modes"
are the different states that an application might be in; for example, if
an app has a "novice" and "expert" mode, the user has to be consciously
aware of which mode they are in, and performing the same action in
novice mode may not produce the same result as if it were performed in
expert mode. This somewhat resembles the notions of referential
transparency, side-effects, global and shared state in programming.
The other side of the coin, "monotony", says that one effect should have,
ideally, only one related cause. In a nutshell, "there's only one way to
do it". Many of the arguments given in this newsgroup in favor of this
Python design principle use a similar rationale:
"I use the term monotonous, tongue partially in cheek, to describe an
interface having only one way to accomplish a task (See Appendix B;
Alzofon and Raskin 1985, p. 95). Monotony is the dual of modelessness in
an interface. In a modeless interface, a given user gesture has one and
only one result: Gesture g always results in action a. However, there is
nothing to prevent a second gesture, h, from also resulting in action a. A
monotonous interface is one in which any desired result has only one means
by which it may be invoked: Action a is invoked by gesture g and in no
other way. An interface that is completely modeless and monotonous has a
one-to-one correspondence between cause (commands) and effect (actions).
The more monotony an interface has for a given task space, the easier it
is for the user to develop automaticity, which, after all, is fostered by
not having to make decisions about what method to use."
Thus, when I see people claiming that Ruby's array interface is more
humane because it offers a "last" method as an alternative to the
equivalent "get" method with a last index, I have trouble reconciling
these two views. I especially have trouble with the idea that method
aliases (like "size" and "length" methods that do the same thing) are
somehow more humane. How is it an advantage that half the programmers
accomplish a given task with method A, and the other half use method B? It
doesn't seem much friendlier to me, since I have to look up these aliases
to make sure my assumption is correct that they are identical. Usually,
when I see two names for the same thing, I assume there's some (perhaps
not-so) subtle difference in their purpose.
On the other hand, absolute minimalism may not be the most user-friendly.
Python's strings support "startswith" and "endswith" methods, which could
easily be implemented--outside of the string class--in terms of slices.
However, I love having these methods available off of the string, not
in some library of string utilities, because they are so handy and so
often useful (and they save me from having to think about indexes and
offsets when, conceptually, they are not relevant to the problem at hand).
As an example of the minimalist viewpoint, I highly recommend reading
Bjarne Stroustrup's interview with Artima from a couple of years ago,
called "The C++ Style Sweet Spot":
http://www.artima.com/intv/goldilocks.html
In the article, he explains an approach to class design that I have found
invaluable: giving the class responsible for maintaining the invariant,
and moving utility methods that do not bear this responsibility into
utility libraries. If this approach were taken with Python's built-in data
types, surely a few methods would have to go elsewhere, but I think that
Python takes a pretty minimalist approach, and encourages the writing of
utility functions as opposed to making every useful tool "part of the
core". I think that, in contrast, Ruby goes a bit overboard.
Note that Stroustrup is willing to budge on this ideal for the sake of
efficiency: "you might have five or ten member functions that are there
because they are logically necessary, or for performance reasons".
Likewise, Python sometimes includes methods in the core classes that could
be implemented elsewhere, specifically for the sake of performance.
"dict.setdefault" comes to mind. Another, more debatable reason, is
convenience, and this is where most disagreement is found. What is
convenient to one person is added conceptual baggage for another. It is
difficult to strike a good balance between the two, but erring on the side
of minimalism is much easier to correct in the long term.
One last comment I'd like to make is regarding the notion that minimalist
and humane are mutually exclusive. This is a false dichotomy. According to
Webster:
Main Entry: minimalism
Pronunciation: 'mi-n&-m&-"li-z&m
Function: noun
1 : MINIMAL ART
2 : a style or technique (as in music, literature, or design) that is
characterized by extreme spareness and simplicity
Main Entry: humane
Pronunciation: hy-'mAn, y-
Function: adjective
Etymology: Middle English humain
1 : marked by compassion, sympathy, or consideration for humans or animals
2 : characterized by or tending to broad humanistic culture : HUMANISTIC
<humane studies>
Accepting both of these definitions as (potentially) ideal, we have humane
minimalism: a style or technique that is characterized by extreme
spareness and simplicity, marked by compassion and sympathy, in
consideration of humans. In a world of increasing software complexity,
this doesn't sound half bad to me.
"humane" interface to objects like arrays and maps, as opposed to
"minimalist" ones. I believe the article that started the debates was this
one by Martin Fowler:
http://www.developertesting.com/archives/month200512/20051218-HumaneInterfaceOfMinimalInterface.html
And this one was posted in response by Bruce Eckel:
http://www.artima.com/forums/flat.jsp?forum=106&thread=141312
When I see the term "Humane Interface", I immediately think of the book
"The Humane Interface" by the late Jef Raskin. Although this book mainly
focuses on GUI interaction, it is also about the human-computer interface
in general, and makes some points that apply to the programming experience
as well.
The irony, I find, is that Raskin's definition of a humane interface seems
to better fit what Fowler describes as "minimalist". Raskin argues that
two ideals in interface design are what he calls "modelessness" and
"monotony". The two terms essentially relate to causes and effects.
Modelessness means that the same cause produces the same effect. "Modes"
are the different states that an application might be in; for example, if
an app has a "novice" and "expert" mode, the user has to be consciously
aware of which mode they are in, and performing the same action in
novice mode may not produce the same result as if it were performed in
expert mode. This somewhat resembles the notions of referential
transparency, side-effects, global and shared state in programming.
The other side of the coin, "monotony", says that one effect should have,
ideally, only one related cause. In a nutshell, "there's only one way to
do it". Many of the arguments given in this newsgroup in favor of this
Python design principle use a similar rationale:
"I use the term monotonous, tongue partially in cheek, to describe an
interface having only one way to accomplish a task (See Appendix B;
Alzofon and Raskin 1985, p. 95). Monotony is the dual of modelessness in
an interface. In a modeless interface, a given user gesture has one and
only one result: Gesture g always results in action a. However, there is
nothing to prevent a second gesture, h, from also resulting in action a. A
monotonous interface is one in which any desired result has only one means
by which it may be invoked: Action a is invoked by gesture g and in no
other way. An interface that is completely modeless and monotonous has a
one-to-one correspondence between cause (commands) and effect (actions).
The more monotony an interface has for a given task space, the easier it
is for the user to develop automaticity, which, after all, is fostered by
not having to make decisions about what method to use."
Thus, when I see people claiming that Ruby's array interface is more
humane because it offers a "last" method as an alternative to the
equivalent "get" method with a last index, I have trouble reconciling
these two views. I especially have trouble with the idea that method
aliases (like "size" and "length" methods that do the same thing) are
somehow more humane. How is it an advantage that half the programmers
accomplish a given task with method A, and the other half use method B? It
doesn't seem much friendlier to me, since I have to look up these aliases
to make sure my assumption is correct that they are identical. Usually,
when I see two names for the same thing, I assume there's some (perhaps
not-so) subtle difference in their purpose.
On the other hand, absolute minimalism may not be the most user-friendly.
Python's strings support "startswith" and "endswith" methods, which could
easily be implemented--outside of the string class--in terms of slices.
However, I love having these methods available off of the string, not
in some library of string utilities, because they are so handy and so
often useful (and they save me from having to think about indexes and
offsets when, conceptually, they are not relevant to the problem at hand).
As an example of the minimalist viewpoint, I highly recommend reading
Bjarne Stroustrup's interview with Artima from a couple of years ago,
called "The C++ Style Sweet Spot":
http://www.artima.com/intv/goldilocks.html
In the article, he explains an approach to class design that I have found
invaluable: giving the class responsible for maintaining the invariant,
and moving utility methods that do not bear this responsibility into
utility libraries. If this approach were taken with Python's built-in data
types, surely a few methods would have to go elsewhere, but I think that
Python takes a pretty minimalist approach, and encourages the writing of
utility functions as opposed to making every useful tool "part of the
core". I think that, in contrast, Ruby goes a bit overboard.
Note that Stroustrup is willing to budge on this ideal for the sake of
efficiency: "you might have five or ten member functions that are there
because they are logically necessary, or for performance reasons".
Likewise, Python sometimes includes methods in the core classes that could
be implemented elsewhere, specifically for the sake of performance.
"dict.setdefault" comes to mind. Another, more debatable reason, is
convenience, and this is where most disagreement is found. What is
convenient to one person is added conceptual baggage for another. It is
difficult to strike a good balance between the two, but erring on the side
of minimalism is much easier to correct in the long term.
One last comment I'd like to make is regarding the notion that minimalist
and humane are mutually exclusive. This is a false dichotomy. According to
Webster:
Main Entry: minimalism
Pronunciation: 'mi-n&-m&-"li-z&m
Function: noun
1 : MINIMAL ART
2 : a style or technique (as in music, literature, or design) that is
characterized by extreme spareness and simplicity
Main Entry: humane
Pronunciation: hy-'mAn, y-
Function: adjective
Etymology: Middle English humain
1 : marked by compassion, sympathy, or consideration for humans or animals
2 : characterized by or tending to broad humanistic culture : HUMANISTIC
<humane studies>
Accepting both of these definitions as (potentially) ideal, we have humane
minimalism: a style or technique that is characterized by extreme
spareness and simplicity, marked by compassion and sympathy, in
consideration of humans. In a world of increasing software complexity,
this doesn't sound half bad to me.