0

I have had hard times naming boolean fields.

On the one hand, i've read that it is good to name them as affirmative statements, like hasAge, or canDance. It's not a problem when naming local variables, for example

boolean itemIsActive;
boolean everyItemHasName;

But i don't see how these rules could apply this to field name

Let's assume that in our project user can define multiple currencies, and determine which one of them is the default one.

class Currency {
  String name;
  boolean myProblematicVariable; // this variable should say 'I AM or I AM NOT the default currency'
}

How would you name myProblematicVariable? I have few types but none of them seems right

  • default - Taking aside the fact that it's a keyword in many languages (that's not the point of this discussion), i like the fact that if we are using standard getters then i can write boolean currencyIsDefault = currency.isDefault(). Hovewer, it's not affirmative.
  • isDefault - My next guess, but it's standard getter and setter looks the same as it would look for field named default. This is a problem when it comes to serialization/deserialization, for example .: Java's jackson (json serialization/deserialization library) will serialize this
class Test {
  private boolean isActive = true;

  public boolean isActive() {
    return this.isActive;
  }

  public void setActive(boolean isActive) {
    this.isActive = isActive;
  }
}

as this

{"active":true}

And this is true for all serialization/deserialization libraries operating on getters and setters. This creates confusion and inconsistency between, for example, how dto looks on the server and client side. I could, ofcourse tell jackson that "This field is named isActive" using annotation, but this seems like a hack used to repair bad design.

  • currencyIsDefault - seems kinda right, but feels too much. I mean, what's the point of using currency as part of it's field's name, that comest from context. And imagine writing boolean currencyIsDefault = currency.isCurrencyIsDefault(). Awful.

And please don't stick to single language standards, assume that Currency is DTO which can be sent between client and server.

Edit

Some ground rules .:

  • Only one currency at a time can be default
  • This discussion is not about design patterns but strictly about field naming. Instead of determining whenever the currency is default it could be whenever it's active, enabled, archived, maybe hovered (in gui application) or really, anything else that comes to your mind.
  • 2
    You give hasAge and canDance as examples of affirmative statements, but isDefault is a question, in your opinion. What is the difference? To me, isDefault is affirmative and this is the preferred name. – www.admiraalit.nl May 4 at 12:21
  • You're right, had a brain fart. I have other issues with isDefault though, will update question in a minute. – Kamil Bęben May 4 at 21:46
3

The X problem

I think we're dealing with an XY problem here, as your question is trying to implement something that should've been fixed another way.

Let's assume that in our project user can define multiple currencies, and determine which one of them is the default one.

The choice of your application's default currency should not be contained in the currency class itself. The currency class (and any object of this type) only cares about its personal data (e.g. name, currency symbol, format, ...)

Which currency is the default is not a setting that is specific to a given currency, it's a setting that is specific to the current application (or e.g. a user, if your users can have different default currencies set).

Think of it this way: what happens when more than one currency claims it is the default? Your likely response is "well that shouldn't happen, the application should only set one currency as the default", and that proves my point that the application is the one who manages this information, not the currency itself.

You should not be doing this:

class Currency
{
    public bool IsDefault { get; set; }
}

You should be setting the default on a scope that is appropriate to the application. One simple example (out of many possible options):

static class ApplicationSettings
{
   public static Currency USD = new Currency("USD", "dollar", "$");
   public static Currency EUR = new Currency("EUR", "euro", "€");
   public static Currency GBP = new Currency("GBP", "pound", "£");

   public static Currency DefaultCurrency = ApplicationSettings.USD;
}

I used a static example because it's the shortest complete example I could think of that highlights the point I'm making. Like I said, there are many possible approaches.
The main takeaway here is that the selection of the default currency happens outside of the Currency class itself.

Not only does this ensure that the decision is made at the appropriate level, it also prevents the issue with possible having multiple default currencies, since it's now actually impossible to have more than one value set as the default currency.

This means we're dealing with an XY problem, and your posted question (Y) becomes moot.

However, the rest of the answer will still answer your posted question (Y). You posted a well-formed question which suggests it's something you do want an answer to in general, not just for this specific scenario. It just doesn't quite fit for the scenario that prompted you to ask the question in the first place.


Affirmative phrasing

i can write boolean currencyIsDefault = currency.isDefault(). Hovewer, it's not affirmative.

This is actually affirmative.

In this context, "affirmative" means "not negative". isNotDefault is an example of something that's not affirmative, i.e. negative.

Similarly, isDead and isAlive are both affirmative - even though they are opposite. isNotDead and isNotAlive are not affirmative.

The reason this rule exists is to avoid double negations. If you use negatively defined boolean such as isNotDead, then you mean end up writing code like:

if(!isNotDead)
{
     Console.WriteLine("I am alive");
}

Which is really hard to read because of the double negation.

In case you didn't notice yet, the console message is wrong, the subject is actually not alive but dead (!isNotDead is equal to isDead). The fact that you probably did not catch this immediately proves the readability issue.

But i don't see how these rules could apply this to field name

Whether something is a variable or a field is a consideration that is entirely separate from the meaning of a value (and thus the name it should have to portray that meaning). I'm not sure how you come to the conclusion that you can't use the same naming approach.


Your suggestions

  • default

I would expect a field named default to contain the default value itself, not a confirmation on whether this object is the default value or not.

boolean itemIsActive;

Note that "item" is optional here. If the code (in which the local variable is declared) makes it clear that you're working with an item, you don't need to specify that in the local variable name. Take the following example:

public void DescribeItem(Item i)
{
    bool isActive = (i.Status != Status.Inactive);

    if(isActive)
    {
        Console.WriteLine("This is an active item!");
    }
    else
    {
        Console.WriteLine("This is an inactive item!");
    }
}

There's no readability improvement from using itemIsActive over isActive. However, if the code was handling multiple objects, then it does become relevant to specify that this boolean labels the activeness (activity?) of the item as opposed to another object.

  • currencyIsDefault

I established the point that "item" can be optional, because of the following consideration: when dealing with class fields/properties, it's always obviously in scope of the current object.

Therefore, the isDefault property of the Currency class is always understood to mean thisCurrencyIsDefault, and therefore you don't have to specify it any more than isDefault already does.

  • isDefault

This is the correct approach. It allows for readable object-based access (myCurrency.IsDefault), it semantically describes the object in question, and it makes it clear that this field contains confirmation on something being a default, rather than the default value itself.


Note
There's a conflict in considering whether isDefault should be the field or the setter method. Ideally, it should be both, but that's impossible in Java due to the lack of class properties. That's a language-specific issue, and you should solve it using conventional Java standards and practices. Personally, I'd go with isDefault for the field and setDefault for the setter, but I'm a C# dev and unsure if this is the conventional Java syntax.

You asked for a language-agnostic answer, so I have avoided a Java-specific answer except for this last note.

| improve this answer | |
  • Please tell: Was the bug in if (! isNotDead) by accident or intentional? Or should this have been an enum with three values: Dead, alive, and undead? – gnasher729 May 6 at 11:52
  • @gnasher729: In this answer? It was intentional. I got the idea when I needed a second to re-read the if when I was writing the WriteLine as it proves the point in case. But had I not taken the time to re-read it, it could've definitely been an accident :) Also let's not get into different types of undead, as I would consider a zombie and a ghost both undead yet mutually exclusive in the manner of undeadness :) – Flater May 6 at 11:54
  • As for the first paragraph of "Affirmative phrasing" section, i meant that the field name (default) itself is not affirmative, i guess i need to work on my english as well. Hovewer, you've got some valid point saying that you expect default to hold the default value of the field. I am now convinced to use isDefault as the field name regardless of serialization / deserialization issues. – Kamil Bęben May 9 at 13:03
1

I think your trouble is that you're looking only at the field name to judge name quality. But the public interface of your class contains the field name and the field type.

In my view, a Boolean field called default says exactly what it has to say. If it were a method, I'd want to know whether this method computes the default, sets the default (and to what?), or whether it changes the default currency. If it were a string it might be the name of the default currency, or the default name of this currency. But as a Boolean field, the meaning pretty much can only be "does this object represent the unique default currency or not?".

| improve this answer | |
  • 2
    Yes, the interface contains the field type. But when the field is used elsewhere in the source code, then the field type is often not visible. I prefer isDefault. – www.admiraalit.nl May 4 at 12:23
  • I agree with @www.admiraalit.nl here. Except for the interface/contract itself, the type is generally hidden from sight and thus can't be relied on for immediate readability. While Hungarian notation (i.e. literally stating the type in the name) is no longer advised, names should still indirectly suggest what is contained within, which generally also hints at the type used. – Flater May 6 at 10:41
0

When specifying Java beans, says the "is" should be with the boolean variable. So something that can be formed with "is":

Generate Getters and Setters in Eclipse dialog

If you call the variable defaultCurrency, it comes out as follows:

public class Currency {
    private boolean defaultCurrency;
    private String name;

    public boolean isDefaultCurrency() {
        return defaultCurrency;
    }

    public void setDefaultCurrency(boolean defaultCurrency) {
        this.defaultCurrency = defaultCurrency;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Regardless, I wouldn't have many objects, and each has a property “I'm the default” (what do you do if more than one says “I am”) but on a higher level, the application has a default currency, and then pointing to Currency.

public class Config {
    private Currency defaultCurrency;
}

public class Currency {
    private String name;
}
| improve this answer | |
0

isDefault is the same as hasAge and canDance - they all work as questions when you are getting the value, and statements when setting the value.

if (myCurrency.isDefault)   // makes sense

myCurrency.isDefault = true; // also makes sense
| improve this answer | |
  • I've updated question explaining what's my issue with prefixing boolean's field name with is. (tldr; using standard getters serialization to json / anything else is very confusing) – Kamil Bęben May 4 at 22:09
  • OP did ask for a language-agnostic answer, but they are using Java. And since Java doesn't have class properties, you're sadly unable to have a private field and setter method with the same name. Unless you make it a public field, but that isn't a great blanket solution either. I do fully agree with this answer assuming the language in question allows for this syntax. – Flater May 6 at 11:04
0

From my point of view you do not have a problem with naming your variables but more a problem of general software design. Your problem is typical for a so called Strategy Pattern.

Try to separate the concerns. At the moment your currency class has two concerns:

  • Validating if it is the default currency
  • Holding currency-specific properties

The following code sample is an example of how to use strategy:

class Currency {
    name: string;
}

class DefaultConfiguration {
    defaultCurrency: Currency;
}

class User {
    currency: Currency;
}
| improve this answer | |
  • In other words: isDefault (or whatever you want to name it) is not a property of Currency. It is a property of some external entity that has an interest in currencies. – Martin Maat May 4 at 16:51
  • Might be that the example i provided is not correct, what about if instead of declaring whenever currency is default we had to declare whenever it's active? Like in the situation when user really can't delete it from the system because it is already used in some other entities, but it can't be used anymore in new entities. I don't see how strategy pattern could resolve this. – Kamil Bęben May 4 at 17:21
  • @KamilBęben Okay, this is a different use case of course. In this case you can use a boolean variable inside Currency (something like "active") and use some sort of service class which applies the given currency iff the currency is active. A different approach would be to use some sort of "registry" (e.g. a hashmap) to decouple this behaviour from the Currency class. This registry holds all active currencies. The service class then looks up the registry for the given currency and checks if it is active. The latter one is almost equally fast due to the hashmap (personally i like it more). – null1 May 4 at 19:26
  • I'm not really asking how to implement the logic behind this, this discussion is strictly about naming fields – Kamil Bęben May 4 at 21:34
0

isDefaultCurrency is perfectly fine if this is a property that is true for one currency and false for all others.

But we don’t know that. Before you pick a name, specify precisely what the property means, and only then we can talk.

As edited, "isDefaultCurrency" is perfectly fine. From a development point of view, I might not have this property at all, but have a class property "defaultCurrency" of type Currency, which returns nil or the default currency. That makes it easier to change. On the other hand, if you have "German Euro" and "French Euro" as separate currencies, and they can both be the default currency at the same time, then it would be a property of the currency (this would be strange though).

| improve this answer | |
  • I've edited the question, i think that solves all inaccuracies – Kamil Bęben May 4 at 17:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.