When writing a library, designing a class or extending some existing API, we often need to express actions or relations involving noun entities:
- "Place the ball in the bin"
- "Obtain the coat for the client"
(I'm trying to use concrete examples without too many programming connotations here.)
at times, only the nouns are properly named, and then we write code such as: coats[client]
(which could be a lookup using an index or a hash). At other times, we're writing an actual named function or method. And now we face a dilemma - which name do we go with?
cloackroom.obtain_coat(some_client); /* vs */ cloackroom.obtain_coat_for(some_client);
red_ball.place(the_blue_bin); /* vs */ red_ball.place_in(the_blue_bin);
and if we're writing functions, these will be:
obtain_coat(some_client); /* vs */ obtain_coat_for(some_client);
place(discarded_ball, the_blue_bin); /* vs */ place_in(discarded_ball, the_blue_bin);
I find myself torn between these two naming options:
- naming without a preposition vs
- naming with a preposition as a suffix (
_in
,_for
etc.)
My dilemma is a combination of clarity/exactness-of-expression, aesthetics and succinctness. But other than succinctness which is obvious here, I can't even decide what's "better". Seeing just the method or function name, the suffix kind of irks me; but reading obtain_coat(some_client)
is also aesthetically grating (as opposed to functions whose name is a transitive verb: refund(some_client)
). On the other hand - a function is an action, so it makes sense to name it using just a verb, leaving the object-related prepositions for other syntactic elements. Some languages sorta-kinda support that, through named arguments:
ball.place(target_receptacle <- the_blue_bin)
obtain_coat(requisitor <- some_client)
but let's assume that's not available to us.
My question: If you've faced this dilemma when designing (or rather, naming) some API - what were your significant consideration for and against the use of prepositions?
Note: If you have a language-specific or language-category-specific answer, that's perfectly ok; like I said, language features seem to have impact on this choice.
3 Answers 3
The preposition is indeed very expressive. And expressiveness reduced the errors that are due to ambiguity or misunderstandings.
However, this expressivity is only granted for methods with a single argument. If you have more parameters, the advantage of prefix will be less obvious.
Then come the practical aspects: programmers who are not native speakers will start to wonder if it should be _in
_on
or _of
or _for
or _to
. Or you may want to add a parameter to a function without prefix; or refactor the order of the parameters. And what about an optional/default parameter? The prefix approach creates in these circumstances a lot more question, hesitations and changes than the simpler approach.
Perhaps this is why so many projects and naming convention go for the more neutral and less expressive form without prefix.
But your concern is completely valid. There are a lot of programming language that use named parameters for exactly this reason. Your example in swift would for example look like:
cloackroom.obtainCoat(for:someClient);
red_ball.place(in:theBlueBin,with:leftHand,mode:swiftly);
Of course, if you have an API with prefix naming convention that you’d use in a language with named parameters, this could look very odd ;-) A reason more for avoiding ending prefixes in the method name?
-
I think it would be very fair to adapt an API from a language without named parameter passing, in the bindings for a language with such passing, by dropping prepositions. However, there's another isssue...einpoklum– einpoklum01/23/2020 14:13:24Commented Jan 23, 2020 at 14:13
-
It is problematic, IMO, to name a parameter using just a preposition. That is, in the body of the
obtainCoat
method, we will be referring tofor
as a noun. Very confusing! (even if we ignore the fact that it's a reserved word in many languages). We might even end up with statements such aswith(with) do { ...stuff... }
einpoklum– einpoklum01/23/2020 14:15:52Commented Jan 23, 2020 at 14:15 -
@einpoklum fair point for the adapter. In think that the prefix in the function can be convenient for a function with a single (mandatory) parameter. But confusion arises most often when there are several arguments (e.g "was it first client, the the actuator or the contrary?"). And there the prefix in function name would not help. About the nice prefix in argument naming vs ugly prefix use in implementation: maybe other conventions could be better, the example was just meant to show that it is more expressive.Christophe– Christophe01/23/2020 15:51:17Commented Jan 23, 2020 at 15:51
-
You'll notice that, in the question, I suggested adjective/noun names which, while not making the call read like a regular sentence, convey meaning more strongly and consistently, and are close to being a sentence, e.g. "cloackroom, obtain a coat with the requisitor being some_client".einpoklum– einpoklum01/23/2020 16:18:06Commented Jan 23, 2020 at 16:18
-
Swift neatly solves that problem by separating "argument labels" from "parameter names", e.g.,
greet(person: String, from hometown: String)
being called asgreet(person: "Bill", from: "Cupertino")
.phipsgabler– phipsgabler01/24/2020 10:15:29Commented Jan 24, 2020 at 10:15
I am for using prepositions when it makes sense. It helps make the code more readable, and with modern IDEs, type-ahead features make any ambiguity a non-issue.
- Prepositions can clarify the direction of processing:
closet.obtain_coat_for(client)
has different semantics fromcloset.obtain_coat_from(client)
. - When your team all speaks the same verbal language, there is no question to the meaning of the API call.
The concerns about language are only pertinent in the following cases:
- Your API is pubic to be used by 3rd parties
- You are working in an open source project
-
1. Who are "2nd parties" in your answer, as opposed to "3rd parties"? 2. Non-open-source software is an aberration, and should be considered an exception to the rule. So, of course it's FOSS...einpoklum– einpoklum01/23/2020 15:45:06Commented Jan 23, 2020 at 15:45
-
But +1 for mentioning team conventions and shared understanding of semantics.einpoklum– einpoklum01/23/2020 15:47:27Commented Jan 23, 2020 at 15:47
-
I live in the world of commercial software. I use FOSS, and even work on some projects. However, there is a lot of development that happens in the commercial world. I don't understand where 2nd parties came from.Berin Loritsch– Berin Loritsch01/23/2020 17:12:43Commented Jan 23, 2020 at 17:12
I always preferred a programming style which is like the natural language.
For me as german native speaker it is normal to have only one word, combining preposition and verb. Please see LEA-Dictionary: to put inside = hineinlegen as an example.
So I would prefer the version red_ball.place_in(the_blue_bin);
or in german roterBall.legeIn(kasten)
.
For other countries this could be differnt and maybe confuse the reader. So I think the answer to your question is depending on the culture and language.
-
Readability by non-native-English-speakers is also an important consideration. But do you really believe the
place_in
would confuse a reader? I mean, if the code is generally in English already?einpoklum– einpoklum01/23/2020 14:39:33Commented Jan 23, 2020 at 14:39 -
No. Just wanted to say that it is a lot cultural.Tobias Otto– Tobias Otto01/23/2020 15:34:51Commented Jan 23, 2020 at 15:34
-
1@einpoklum unlike the unambiguous German "hineinlegen", "place_in" seems confusing: is it a getter for the place in the object is ? is it to find the position where the object is located? If there’s a potentially bidirectional semantic, what is the meaning of blueBin.place_in(redBin): does it tell you for sure what bin is placed in which bin? I mean does it tell you more than place() would do ?Christophe– Christophe01/23/2020 16:01:23Commented Jan 23, 2020 at 16:01
-
"hinein" is not a preposition, it's an adverb.Christian Hackl– Christian Hackl01/25/2020 00:51:57Commented Jan 25, 2020 at 0:51
Explore related questions
See similar questions with these tags.
obtain_coat_for(client)
,obtain_coat_with(ticket)
,obtain_coat_from(countertop)
, ... ?