views:

237

answers:

9

So, when you are writing a boolean method, do you use tense, like "has" or "was", in your return method naming, or do you solely use "is"?

The following is a Java method I recently wrote, very simply ..

boolean recovered = false;

public boolean wasRecovered()
{
     return recovered;
}

In this case, recovered is a state that may or may not have already occurred at this point in the code, so grammatically "was" makes sense. But does it make the same sense in code, where the "is" naming convention is usually standard?

+6  A: 

I prefer to use IsFoo(), regardless of tense, simply because it's a well-understood convention that non-native speakers will still generally understand. Non-native speakers of English are a regular consideration in today's global dev't industry.

Greg D
Until the last few years it wouldn't have occured to me that non-native speakers would be looking at 'my' code - but it in increasingly likely. This is a point that hadn't occured to me.
Ragster
Not only for non-native English speakers, either--I speak fluent English and I still think that having a consistent `is` prefix is much more readable and less confusing than having different prefixes for different (but very similar) uses.
musicfreak
A: 

I tend to, yes. For example in error checking:

$errors = false;
public function hasErrors()
{
  return $this->errors;
}
Dickie
A: 

The conceit for method naming is that you are retrieving information about the object in question. For it to be named in the past tense, it would have to be information about a previous state of the object, rather than its current state.

The only reason I could ever think of for using past tense is if I was checking a cached result of something that previously occurred but is no longer the case. For a contrived example, perhaps retriveing the previous value after something like a swap() call. It could be useful in operations that are atomic by design. Not real likely in the wild though.

T.E.D.
Isn't *every* retrieval about a previous state? Some might consider it to be just semantics, but the time between the assignment of state and the (1) retrieval and (2) use of that sate is not always insignificant. See Jared's example about `thread.IsAlive` vs. `thread.WasAlive`.
reemrevnivek
+4  A: 

I use the tense which is appropriate the meaning of the value. To do otherwise essentially creates code which reads one way and behaves another. Lets look at a real world example in the .Net Framework: Thread.IsAlive

This property is presented with the present tense. This has the implication the value refers to the present and makes code like the following read very well

if (thread.IsAlive ) {
  // Code that depends on the thread being alive
  ...

The problem here is that the property does not represent the present state of the object it represents a past state. Once the value is calculated to be true, the thread in question can immediately exit and invalidate the value. Hence the value can only safely be used to identify the past state of the thread and a past tense property is more appropriate. Lets now revisit the sample which reads a bit differently

if ( thread.WasAlive ) {
  // Code that depends on the thread being alive
  ...

They behave the same but one reads very poorly because it in fact represents poor code.

Here's a list of some other offenders

  • File.Exists
  • Directory.Exists
  • DriveInfo.IsReady
  • WeakReference.IsAlive
JaredPar
`System.getCurrentTimeMillis`
Steve Jessop
To me, IsAlive reads better. Yes it's only a best guess but sometimes that's all we can do. WasAlive on the other hand sounds like it implies that the thread IsDead but was in a non-dead state some time in the past. Same as in standard English. I ask the question is JaredPar alive and if you answer the comment most would consider it to be a good enough check even though there is a possibility of you being killed by falling whale the moment you press that Add Comment button -->
slebetman
On the other hand if I ask the question was JaredPar ever alive you'll undoubtably take offence and quickly post: I AM STILL ALIVE, I'm not dead yet!!
slebetman
@slebetman I agree that `IsAlive` reads very pleasantly and that's the inherent problem. It reads great but is very much wrong (there is simply no escaping the fact that IsAlive represents the past). API designers should strive to make bad code read poorly. The designers of `IsAlive` and virtually every bool property is `System.IO` failed here.
JaredPar
@slebetman: true, but only in contexts where you apply something other than a boolean value. If what I actually ask is, "was JaredPar alive a second ago?", then obviously you can say "yes" without me thinking he might be dead. I don't think a `WasAlive` function would be confusing, or perhaps better `MaybeStillAlive`. See also, `hasStoppedBeatingHisWife`.
Steve Jessop
@slebetman, and for the record. If someone posted something about me being dead i would not post "I am alive". I would instead quote "Rumors of my death have been greatly exaggerated". :)
JaredPar
I prefer IsAlive since it is semantically correct. What we are trying to answer is whether the thread is alive, not whether it was. But for a method that takes a datetime parameter WasAlive would be good - Thread.WasAlive(DateTime.Now - 5)
Max Malmgren
@Max but that's the problem, `IsAlive` is semantically **incorrect**. You can never know if a thread is alive only that it was alive.
JaredPar
Another example: WeakReference.IsAlive
Justin Van Patten
@Justin, that's a classic.
JaredPar
@JaredPar Of course, but the name matches what the method is attempting to answer. Hence it is correct, even if it is not guaranteed to always answer correctly. Or have I misunderstood?
Max Malmgren
@Max it is only correct if it actually answers the question being asked (which in this case it cannot do).
JaredPar
`IsAlive` is correct, because it states the condition at the exact moment the condition was asked. If a programmer makes any assumptions about how long that condition lasts, then that's the programmer's problem. `WasAlive` seems to indicate whether an object was ever—at *any* time in the past—alive, which is not what we care about. By your logic, `A.Equals(B)` makes no sense, since A or B might be modified by another thread before the next statement. If `A.DidEqual(B)` were used instead, then I would probably go insane very quickly.
Jeffrey L Whitledge
@Jeffrey, The Equals example is a bad analogy. The return of Equals is not subject to timing issues (unless A and B are mutated on different threads at which point you're in another discussion) while `Thread.IsAlive` is subject to timing issues that you have 0 control over. Any code which depends on this value is flawed.
JaredPar
@Jeffrey, at the precise moment it was asked at the kernel or low level API level, yes it's correct. But what advantage does that give you? It can and **will** be invalidated before it's even left the register it was written to.
JaredPar
@JaredPar - There is no difference. You can control the lifetime of whatever threads you create in exactly the same way as you can control the mutations of the values of variables. And there are lots of other examples too. How about `useBillingAddress.WasChecked`? This is the path to madness.
Jeffrey L Whitledge
@Jeffrey no you don't control the absolute lifetime of your threads. They can be taken away from you at any moment for a number of reasons including unhandled exceptions, loaded hooks killing them, access violations, etc ....
JaredPar
If A and B are not marked `volatile`, then `A.Equals(B)` should really be `A.HadAtSomeTimeAValueThatMatchesAPastValueOf(B)`.
Jeffrey L Whitledge
@Jared: The trouble is, "WasAlive" makes it sound like you're asking whether it was *ever* alive. "IsAlive" is more appropriate for "is this alive at the time I call it" even if it's out of date by the time the property actually returns. Perhaps "WasRecentlyAlive"?
Jon Skeet
@Jon I think `WasRecentlyAlive` is a nice compromise.
JaredPar
@JaredPar The world might end, thus causing your program to be terminated. I don't think that justifies naming every method A.IfNotWorldEndedEquals(B). External influences should be put aside, and every method should say what it is trying to answer - implementation details surrounding the method should be in documentation.
Max Malmgren
@JaredPar - I get your point that Thread.IsAlive is an utterly useless property that one should never ever use. However, you have not shown that it is named incorrectly.
Jeffrey L Whitledge
@Jeffrey that's still a bad analogy. It is very possible to reason about the present the state of a subset of objects in your program. You control them and can prevent them from leaking out code which creates these situations (or make them immutable and forget about the issue). Threads and the FileSystem are beyond your control and that's just life. Users can rip out thumb drives, eject CD's or delete files at any time and there's nothing to stop them. Having properties which provide present sounding data for unpredictable state is flawed.
JaredPar
@Max, I'm not attempting to make my program function in the face of the world ending, I'm attempting to make it function in the face of a thread ending.
JaredPar
@Jeffrey, then we're at an impass. How can a function be named correctly if it's value does not provide the information suggested in the name?
JaredPar
@JaredPar - I still don't see why my analagy is bad. A.Equals(B) can return true, even though there was *never* a point in time in which A *actually* was equal to B. This could happen, for example, if A is stored in a register, then modified by another thread, then B is modified and ultimately fetched. This doesn't mean it's named wrong, though, because we all know what the method really means. It's the same with all the stuff you listed. How are any of those things really different? The predicates are just answering the question the best they can at the moment they're asked.
Jeffrey L Whitledge
@Jeffrey it's a bad analogy because issues around control. You cannot control `Thread.IsAlive` no matter how much you try. You can absolutely control Equals by controlling whether A and B exist on multiple threads or if the behavior of Equals is safe in the face of multiple threads (immutable objects for example). The analogy is bad because you're comparing a situation which cannot be controlled to one that can be controlled where the issue of control is at the heart of the original problem.
JaredPar
@JaredPar - What is it about "control" that makes it relevant to the question of verb tense?
Jeffrey L Whitledge
What about `IsAliveNow` :) ... alive when the question was asked, not when the answer comes back; right?
Rex M
@Jeffrey if you could control thread lifetime then IsAlive could be written. It's the lack of control which makes it impossible for the value to be considered valid for any period of time.
JaredPar
@Rex, it's not even valid at the callsite. The thread could be dead before the if statement conditional is evaluated.
JaredPar
The problem is not in the _naming_ of that property, __the problem is that this property exists at all__. What is it useful for? You can ask whether a thread is alive, but as soon as you get the information, it's already stale and might be wrong. It doesn't matter what that property is called, it is useless anyhow. Rather than providing such a dumb property, the designer of that API should have asked themselves __what problems is this supposed to solve__ (but fails), and then solve these problems...
sbi
...For example, people might need to wait for the thread to change its alive state; so there ought to be a way to do this. Or they might want to do something with the thread as long as it is alive; so there ought to be something which, while you hold it in your hands, prevents the thread from dying. I think there is a pattern in there somewhere: When you find it hard to name something properly, it might be because its definition is wrong. An API is there for _humans_ to use. It should be defined in simple terms. __If you can't express it in a simple property name, it's likely wrong.__
sbi
It depends on what the definition of 'is' is.
Kelly French
`Thread.IsAlive` is useless if you want to do something while the thread is alive. If, on the other hand, you want to do something at some point after the thread is no longer alive, then `IsAlive` is useful, since it just says you need to wait a bit more. Perhaps they should have provided `IsDead` instead.
Jeffrey L Whitledge
@Jeffry: or `join()` ;-p. I think `IsDead` would lead to the same coding errors that `IsAlive` does, but with people erroneously thinking "`IsDead` returned `false`, so my thread is alive". The fundamental difficulty is with polling a value which changes asynchronously. The "equals" examples share that difficulty if the object in question is shared with other threads. That's something Java programmers (a) opt in to by sharing objects, and (b) have some measures to deal with, such as locks. For threads and filesystems, which necessarily are "shared with the universe", there's no (b).
Steve Jessop
... there are some cases where you can use `Directory.Exists` sanely, but those are cases where your application has "reserved" some section of the filesystem for its own use, meaning it has documented, and users can reasonably be assumed to accept, that if anyone else touches that part of the fs, then the program won't work properly. It can then assume, "all changes are made by me", so the existence or not of a file or directory is meaningful. Threads aren't even that good -- if it's possible that a thread has ended, then it's possible it ends slightly "after" you called `IsAlive`.
Steve Jessop
@Jeffrey: I guess what I'm saying is that "You can control threads the same way as mutations of the values of variables" isn't true. You can synchronise on objects, but you can't control exactly when a thread ends. If it's busy-looping then it won't die, barring something abnormal like `stop()` or the end of the universe. But if you let it exit at all, you can't stop it exiting in the narrow window between calling IsAlive and using the result. You could suspend, but that's not a good place to be either. It's safer to control your threads with wait/notify. Then you don't need (or want) IsAlive.
Steve Jessop
@Steve, even using `Directory.Exists` when the file system is reserved is not safe. You cannot for example stop a user from ripping out the USB drive where you are working in. The file system is a ever shifting environment.
JaredPar
@JaredPar: of course I can't stop them, but if ripping out the drive would have caused the program to fail anyway, then quite possibly isn't a bug for my program to make the assumption that directories won't just disappear. "Assuming" something doesn't mean I actually believe the thing is true, it means that my program will fail if it's not true. Obviously there are bugs around erroneous use of Exists, but for many or most programs, "user rips out drive and program fails for a subtly different reason from the one it would have failed with anyway 0.01 seconds later" is not a bug.
Steve Jessop
@Steve, the point I'm trying to make is that you can't control the file system, period. No matter how many precautions you take the file system can and will change out from under you. Ripping out a USB key is just one, of several, acts which you cannot guard against. If your program were to crash from that it would crash from several other more normal incidents (hidden files you can't see, super users mucking with permissions, etc ...). If you ever depend on the result of `Directory.Exist` remaining true for a period of time then it is a bug.
JaredPar
While interesting (and passionate discussion), I think it misses an important point: *It's impossible to find concise names for properties/methods that clearly communicate all constraints, invariants, and behavioral nuances*. Anyone who assumes otherwise, rather than reading the doc (or implementation) is setting themselves up for problems. There's sufficient ambiguity in names like `WasAlive`, `DidExist` - that you still need to read the doc to understand exactly what it does. The best we can do, is to make names simple, easy to remember, and somewhat relevant to the subject they pertain to.
LBushkin
@LBushkin, yes you can't make a name convey all semantics. But I disagree that IsAlive is a better choice than the suggested alternatives. It is clearly suggestive of a semantic it cannot deliver and should be improved upon.
JaredPar
@JaredPar: I think most would agree (most certainly you and I) that misleading names are bad. The trouble is that for something like temporal semantics, *virtually every name is misleading*. Take the example with `Thread` - properties like `ThreadState`, `CurrentPrincipal`, `Priorty` - can all change out from under you as easily as `IsAlive`. Equally incorrect code can result based on assumptions about the temporal stability of values returned from these properties. Should they be renamed? If so, to what? `Thread.LastPrincipalAssigned`? `Thread.LastKnownPriority`? Are these really any clearer?
LBushkin
@LBushkin personally I think they should be removed vs. renamed. But yes I think Last or Recent prefixes are much better than the current. Their name at least implies it's a temporal / changing value. It by no means adds absolute clarity to the property but the added hint substantially changes the way the code is read by an observer. In it's current name Thread.IsAlive makes bad code read well. Giving it a better prefix helps prevent this problem by making bad code read poorly. Making bad code look bad increases the chances it will be caught and corrected during a code review.
JaredPar
@JaredPar: I can understand your point. I don't know if it could be universally applied however. Take some of the new Concurrent collections - they expose properties like `Count` and `IsEmpty` which have the same misleading temporal semantics - particularly since collections like `ConcurrentQueue` are specifically intended to be used in multithreaded scenarios where changes can be taking place from multiple threads simultaneously. I think it would be harder to argue that `ConcurrentQueue` shouldn't implement `ICollection` because it's confusing.
LBushkin
@LBushkin, I made that very argument, concurrent collections shouldn't implement the standard collection interfaces, to the PCP team during the 4.0 development cycle. They agreed it was confusing and had a lot of potential issues. In the end they left it because it is possible to use those interfaces safely if you properly constrained the situation. The other temporal properties we've discussed can't be constrained in those ways.
JaredPar
+1  A: 

I don't mind wasRecovered that much. Recovery is a past event that may or may not have happened - this tells you whether it did or not. But if you're using it because of some consequence of recovery, I'd prefer isCached, isValid, or some other description of what those consequences actually are. Just because you've recovered something doesn't inherently mean you haven't lost it again since.

Always beware that in English, the use of a past participle as an adjective is ambiguous between transitive and intransitive verbs (and perhaps between active and passive voice). isRecovered might mean that the object has been recovered by something else, or it might mean that the object has recovered. If your object represents a patient at a hospital, does "isRecovered" mean that the patient is fit and well, or that someone has fetched the patient back from the X-ray department? wasRecovered might therefore be better for the latter.

Steve Jessop
A: 

Since your question is specific to Java, the method name should start with "is" if your class is a JavaBean and the method is an accessor method for a property.

http://download.oracle.com/javase/tutorial/javabeans/properties/properties.html

Matt
+2  A: 

The isXxx prefix is a widespread naming convention, so it's generally the best choice.

For order-sensitive operations, wasXxx is appropriate. For example, in JDBC, retrieving the value of a database column might return zero when the field is actually NULL (unset); in this case, a follow-up call to wasNull determines which it is after the actual retrieval was performed.

For retrieving attribute settings, hasXxx may be more appropriate. It's a grammar preference, as in "the object's flag is set" versus "the object has an attribute".

Then there are capability tests canXxx. For example, calling canWrite to see if a file is writable. But names like these can probably be renamed to the isXxx form, such as isWritable.

Loadmaster
ISTM that CanWrite and IsWriteable can have two very different meanings. CanWrite would refer to the instance being able to write something somewhere. Whereas IsWriteable would refer to somebody else's capability to write to the instance. i.e. the instance not writing but being written to.
Marjan Venema
@Venema, I see your point, but I take it as "I (the calling method) can write to it" versus "it is writable by me (the calling method)".
Loadmaster
+1  A: 

I am not sure that you are thinking about this correctly. The reason one would use the Recovered property is because that is the state the object is in now, not because that was the state the object used to be in. There may have been some process in the past (The Recovery) that has now completed, but the fact that we are accessing this property now means that there is something about that completed process that altered current state, and that current state is important. To me "Recovered" captures the nature of that state. For this example (and most similar situations) I would use IsRecovered to name the predicate that indicates this condition. (This also matches normal English: "This is a recovered document.")

It is extremely rare that I would use anything other than present tense to name a predicate (IsDirty, HasCoupon) or boolean function (IsPrime(x)) in a program.

An exception would be to indicate state that has since been changed that might need to be reinstated (DocumentWindow.WasMaximizedAtLastExit).

I would usually use an infinitive for future tense (ToBeCopied rather than WillBeCopied), since the best laid plans of software are sometimes altered (or cancelled).

Jeffrey L Whitledge
So "isInARecoveredState()" is more correct in your opinion? I might be prone agree with this.
P. Deters
A: 

It depends on whether or not you care about the past or future state of the property in question.

To try to simplify the semantics, realize that there are a few scenarios that make the IsXXX form debatable and some very common scenarios where the IsXXX form is the only useful one.

Below is the 'truth table' for Thread.IsAlive() based on possible states of the thread over time. Forget about why a thread might flip flop states, we need to focus on the language used.

Scenarios of possible thread states over time:

    Past        Present     Future  
    =====       =======     =======  
 1. alive       alive       alive  
 2. alive       alive       dead  
 3. alive       dead        dead  
 4. dead        dead        dead
 5. dead        dead        alive
 6. dead        alive       alive
 7. dead        alive       dead
 8. alive       dead        alive

Note: I talk about the Future state below for consistency. Knowing whether a thread will die is very likely unknowable as a subset of The Halting Problem)

When we interrogate an object by calling a method, there is a common assumption "Is this thread alive, at the time I asked? For these cases, the answer in the "Present" column is all we care about and using the IsXXX form works fine.

Scenarios #1(always alive) and #4(always dead) are the simplest and most common. The answer to IsAlive() will not change between calls. The battle over language that comes up is due to the other 6 cases where the result of calling IsAlive() depends on when it is called.

Scenarios #2(will die) and #3(has died) transitions from alive to dead.
Scenarios #5(will start) and #6(has started) transitions from dead to alive.

For these four (2, 3, 5, 6) the answer to IsAlive() is not constant. The question becomes, do I care about the Present state, IsAlive(), or am I interested in the Past/Future state, WasAlive() and WillBeAlive()? Unless you can predict the future, the WillBeAlive() call becomes meaningless for all but the most specific designs.

When dealing with a thread pool, we might need to restart threads that are in the 'dead' state to service connect requests and it doesn't matter whether they were ever alive, just that they are currently dead. In this case we might actually want to use WasDead(). Of course we should try to guarantee we don't restart a thread that was just restarted but that is a design problem, not a semantic one. Assuming that no one else can restart the thread, it doesn't matter much whether we use IsAlive() == false or WasDead() == true.

Now for the last two scenarios. Scenario #7(was dead, is alive, will be dead) is practically the same as #6. Do you know when in the future it will die? In 10 seconds, 10 minutes, 10 hours? Are you going to wait before deciding what to do. No, you only care about the current (Present) state. We're talking about naming here, not multi-threaded design.

Scenario #8(was alive, is dead, will be alive), is practically the same as #3. If you are reusing threads, then they can cycle through the alive/dead states several times. Worrying about the difference between #3 and #8 goes back to the Halting Problem and so can be disregarded.

IsAlive() should work for all cases. IsAlive() == false works (for #5 and #6) instead of adding WasAlive().

Kelly French