[phobos] Time to get ready for the next release
Robert Jacques
sandford at jhu.edu
Sat Apr 23 10:03:38 PDT 2011
On Fri, 22 Apr 2011 13:22:31 -0400, Steve Schveighoffer
<schveiguy at yahoo.com> wrote:
>> From: Robert Jacques <sandford at jhu.edu>
[snip]
>> Third, came criticisms of naming a factory method 'seconds' in the
>> first place (noun/verb distinctions, etc), and the associative
>> criticisms of fixing a bad design via a proverbial sledgehammer.
>
> The goal was to have something short. At the time, I was fighting for
> changing the time code in Tango, and one of the criticisms was that the
> factory method names were too long (don't remember what I originally
> had). Code like Socket.select(5.0) was going to be replaced with
> Socket.select(TimeSpan.seconds(5)). This was sort of a compromise.
> Ironically, we had to change it to something more verbose because of
> this problem.
I understand. But I think you side-stepped my actually thought a bit, so
let me be a bit more verbose. Conciseness and clarity are probably the two
most at odds aspects of any API design. The general conventions are
variables/fields/'property's should be names and functions/methods should
be verbs. I have seen many a post in the 'property' discussions regarding
how verb = value or noun(value) is Evil(TM). Personally, I take it as a
rule of thumb and not as a hard and fast rule. Anyways, any designer who
uses a noun for an action, should be aware that they are actively courting
the very confusion in this bug report. So, from an API design perspective,
the author sacrificed too much clarity for consciousness. And this
criticism remains true even with @property, enabled. Users are still going
to try compile s.seconds = 5, because the API design of 'seconds' differs
from the design of its class, its module, its library and general
expectations. They are just going to get a compiler error, instead of a do
nothing expression. And while we deal with non-standard designs all the
time, in the form of DSLs, mini-DSLs and 'by convention' frameworks, a
single, non-standard function generally only increases a programmer's
cognitive load, without any additional benefits. And proposing the
creation/justification of a language level features in order to mitigate
(not fix) a minor issue with an API, which exists solely due to the API's
poor design (which violates its class's design guides), is like taking a
sledge hammer to kill a fly.
>> Forth, came the realization that in D2 'seconds' would probably be
>> pure, which would cause s.seconds = 5 to be compiler error.
>
> No, it wouldn't be an error. s.seconds(5) is exactly the same as
> TimeSpan.seconds(5), both would be callable as pure functions. In other
> words, s isn't actually passed to the function, it's just used as a
> namespace.
>
>
>> Currently I'm pondering whether capitalized factory methods, in order
>> to mimic ctor syntax, would be an acceptable design. I doubt anyone
>> would every have tried s.Seconds = 5, and thanks to auto, I also doubt
>> anyone would call TimeSpan.Seconds s. And unlike (an impure) s.seconds
>> = 5, TimeSpan.Seconds s; simply doesn't compile. Plus, it
>> self-documents the factory concept in the name.
>
> If you used C# regularly, where everything is capitalized, you might
> expect capitalized method names and properties. But in any case, why is
> capitalization more of a distinguisher than parentheses or lack thereof?
Capitalization in D and other languages is generally used for user defined
types (structs/classes)[1], while variable, field and method names use
camelCase or under_scores (i.e. they start with a lower case). The primary
exception to this are constructors, which used the type name and therefore
are capitalized. Since a factory method is conceptually identical to a
constructor, capitalizing factory methods provides an innate understanding
of what the method does, what it is used for and how you should call it,
to both the corder and code reviewer. Mandated parenthesis, on the other
hand, allows the code reviewer only to understand that it is an action,
not what type of action it is and the for coder to get a compiler error
when they misunderstand, because the API is poorly designed, what the
method does, what it is used for and how you should call it.
[1] Of course, sometimes UDTs use lower case, like float3, to make them
feel more like built-in types.
More information about the phobos
mailing list