[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