0
\$\begingroup\$

Very simple question. Imagine are designing library API, where you want to provide way to switch boolean flag. Typically to disable or enable a functionality. For argument's sake, let's say it's enabling/disabling sounds and I will be using kotlin in my code samples, but language doesn't really matter. I see 2 ways to put that into interface:

  1. Use toggle/set style:
fun setSound(enabled: Boolean) //or toogleSound
  1. Use explicit method or each functionality:
fun enableSound()

fun disableSound()

Now I can map those way easily between each other so in a sense they are equal:

fun setSound(enabled: Boolean) {
    if (enabled) {
        enableSound()
    } else {
        disabledSound()
    }
}

Or opposite direction:

fun enableSound() {
    setSound(true)
}

fun disableSound() {
    setSound(false)
}

First method is more friendly for programming, because you can just pass boolean variable, which can sometimes be convenient. One feedback I got here is, that in languages, that are not type-safe, this can be broken/unpredictable by passing non-boolean type.

Second method is on the other hand more explicit, easier to read and feels better overall from designing API perspective.

API should obviously contain only one of the options because of the DRY principle and even though I can create mapping (and extension methods in kotlin world), I have to choose only one. I know there are some specific things to consider (ex: what kind of library, what is likely usage of it - if there are hundreds of flags, then "setter" methods is most likely better), but I am looking for general guidance without many specifics.

Which option would you choose and why? If there is another 3rd option, I'd like to hear about it too, but nothing comes to mind.

\$\endgroup\$
1

1 Answer 1

3
\$\begingroup\$

One feedback I got here is, that in languages, that are not type-safe, this can be broken/unpredictable by passing non-boolean type.

In such languages, you should have a type check at the beginning of the method and throw an exception if it's invalid.


A setter has multiple benefits.

First of all, setEnabled is turned into a property so that you can use the following:

object.sound = true

Secondly, I imagine that a common thing to do is to toggle the sound on/off (basically switch the current state), I would not recommend adding a toggleSound method that does this, it feels so much better for me as a programmer to do

object.sound = !object.sound

or

object.setSound(!object.isSound())

If the user wants to toggle the sound the user probably want to know the state that the sound is already in, and a method called toggleSound hides the current state so that you're not aware of it. You could have toggleSound return the state of course, but should it return the old state or the new state?

Using the other approach I would have to do

if (object.isSound()) {
    object.disableSound()
} else {
    object.enableSound()
}

Which takes more space, is harder to read in its entirety, and is just less clean IMO.

If you have a boolean property that can be true or false, using a setter is the best way to change the property instead of having two methods to turn it off and on again.


However, a nitpick with regards to this is that I would consider naming it setSoundEnabled which makes a bit more sense to set to true/false than setSound.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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