1

Most programmers (including me) believe that methods with a boolean flag parameter should be refactored into two methods without the flag parameter. Are there any use cases for a boolean parameter where it isn't a flag? I haven't been able to think of any. However, just because I can't think of an example doesn't mean that one doesn't exist.

I'm after an example where at least 90% of programmers would agree that a boolean parameter makes the most sense, produces the cleanest, most elegant code, etc. That is to say, the use case should be fairly uncontroversial. The method should use the boolean value itself and not simply pass it through to some other method. If you believe there can never be such an example, please explain your rationale.

The boolean shouldn't be retrieved by your library or passed to another (that's an interface design issue).

class BooleansAreNotFlags {
  function foo() {
    bool a_non_flag_boolean = result_of_calculation_or_logic();
    bar(a_non_flag_boolean);
  }

  function bar(bool not_a_flag) {
    // do something with not_a_flag
  }

What code could go into function bar(bool) {} where refactoring the boolean out of it would make it worse? If you can only think of an example with more than one parameter, that's OK too.

CJ Dennis
  • 659
  • 5
  • 15
  • 2
    Dear Close Voter, I'm asking when a boolean parameter isn't a code smell, if ever. – CJ Dennis Nov 05 '19 at 04:40
  • 9
    I disagree with your first statement. Wouldn't that potentially lead to lots of duplicated code, since (presumably) the two functions would be very similar? With potentially extra conditions to decide which of the two functions to call if the boolean parameter is a variable? – 1201ProgramAlarm Nov 05 '19 at 04:50
  • 1
    @1201ProgramAlarm Consider jQuery's `.show(bool)` and `.hide(bool)` methods. `show()` might be something like `this.attributes.display = 'block'` and `hide()` `this.attributes.display = 'none'`. Yes, they're mostly the same but it's hard to see how combining the two would increase maintainability. `.show(false)` is the same as `.hide()` but writing `.show()` or `.hide()` is more readable than `.show(true)` and `.hide(false)` or `.hide(true)` and `.show(false)`. – CJ Dennis Nov 05 '19 at 05:55
  • @CJDennis that is a biased example. Of course, with one line of simple code duplication won't matter. But what if your method is, say, 50 lines? Methods without boolean parameters may serve some subjective design philosophy. But even then, for non-trivial methods its definitely better to have a method with parameter and call that from the methods without. – marstato Nov 05 '19 at 10:55
  • 1
    Also: what if the method gets wrapped and the wrapping code wants to simply pass on the flag? You end up with if (flag) this() else that() all over the place. Java AWT, e.g., deprecated [Window.show()/hide()](https://docs.oracle.com/javase/7/docs/api/java/awt/Window.html#show()) in favor of setVisible(boolean) for that very reason. – marstato Nov 05 '19 at 10:56
  • 2
    Wouldn't a clear case be when the boolean is data? E.g. you need to represent something based on a set of parameters of which one is a boolean. Maybe you want to create a string, save something to the database, etc. Point is, is it is not a concept you are using to flag but data to be used just a as any other parameter, you might just want to keep it one function instead of multiple? – Nanne Nov 05 '19 at 11:12
  • 8
    "Most programmers (including me) believe that ..." -- Rephrase that to "Some programmers ..." and the question is then actually quite good. – Martin Ba Nov 05 '19 at 11:56
  • I would argue that a function that takes a Boolean and returns another representation (string, perhaps) of that Boolean isn't really using that Boolean as a flag. – kojiro Nov 05 '19 at 12:31
  • @Nanne "The method should use the boolean value itself and not simply pass it through to some other method." – CJ Dennis Nov 05 '19 at 12:35
  • @CJDennis but depending on how you'd define "use", if I make a fucntion saving something to a database that _might_ be handled by another function, but to be fair, if I have a piece of data "receivesMailing", and I want to persist that... you would at a certain point want that as a parameter (if you're not using value objects or something), and you won't exactly "just pass it through. Same goes for if you are using your data for, I don't know, creating a string for some sort of message, where the boolean is part of the data to represent? – Nanne Nov 05 '19 at 12:43
  • 3
    Please after getting 6 answers, do not change the question in away that could lead readers to think that the answers were irrelevant. I'd suggest that you put an "**Edit**" or "**Clarification** title before the new elements that you've added. – Christophe Nov 05 '19 at 12:54
  • 1
    This question is loaded and in you reactions to the answers you are shifting the goalposts, that's why I voted for a close. – Pieter B Nov 05 '19 at 13:50
  • Any question that includes the words "code smell" is subjective by definition. – Robert Harvey Nov 05 '19 at 15:11
  • Most programmers are wrong then. There is nothing wrong with boolean parameters. There are a few antipatterns *involving* boolean parameters which should be avoided. – JacquesB Nov 08 '19 at 16:20

8 Answers8

19

I have one

assert(a == 1);

Why is this OK? Because the boolean is the point of this interface. No one has trouble remembering what it means. That's not always the case so the advice to consider refactoring when faced with boolean flags still stands.

candied_orange
  • 102,279
  • 24
  • 197
  • 315
  • I'm afraid I don't understand. I don't use any language that has `assert()`, and it just sounds like a unit test. In PHPUnit there is `assertTrue()` and `assertFalse()`, so even this is split into two methods. And unit tests are special code. I do things in unit tests I would never do in production code because they would be bad practice, yet are good practice in tests. – CJ Dennis Nov 05 '19 at 02:52
  • 1
    The issue has nothing to do with production verses debugging code. It has to do with readability. The reason this works is because there's one argument to remember and there is no else case. This only does what it does when you pass a false. – candied_orange Nov 05 '19 at 03:13
  • Is this for unit tests only? If not, what use case does it have? Can you provide context around your example code? – CJ Dennis Nov 05 '19 at 03:14
  • Asserts predate unit tests. They made up for the fact that our typing system made it difficult to ensure preconditions. They could be used after something else should have made what they test for impossible to occur. They could be left in production source code and disabled depending on how you compiled. – candied_orange Nov 05 '19 at 03:42
  • Whose typing system? If I want to assert that, I say `assertSame(1, $a)` (exact) or `assertEquals(1, $a)` (allows casting). I don't see were I would use that in production code. – CJ Dennis Nov 05 '19 at 04:20
  • 2
    This is a brilliant answer. I have expanded this to make it more descriptive. @CJ Dennis, this doesn't need to used in unit test. It could be used in production code for error hanlding – Nachiappan Kumarappan Nov 05 '19 at 10:25
  • 2
    @CJDennis lol, just because you don't use such languages doesn't mean other languages have good use for it, does it? Also: arguing X is bad because X is bad is a logical fallacy. – marstato Nov 05 '19 at 10:58
  • 1
    @CJDennis Do you know the "true scotsman fallacy"? You ask for only 1 reason to use a boolean parameter. So only 1 example has to be given to satisfy your request. This answer does exactly that. But now you go and argue: "it doesn't count". This way we can go on forever. – Pieter B Nov 06 '19 at 10:03
7

It all depends on the definition of boolean flag:

  • for some, every boolean is a boolean flag. By induction every parameter would then just be a packet of flags grouped for the convenience of a higher purpose. Ultimately, according to your statement, any parameter passing would be a smell. Seriously ?
  • for some, only certain kind of arguments are a flag. It’s when you try to make different actions with the same function depending on the parameter. But then, how much different is different ? After all, print(char a) will do 256 different things depending on a, whereas print(bool b) would do only two different things. Why would the first be ok and the second a smell ?

So either we conclude that every parameter passing is a smell, which is absurd, or we accept that booleans can be data like any other.

Of course, bad function design can happen with boolean parameters (e.g. coupling unrelated actions in a single function), but exactly as with other data types as well (e.g. using integer options to choose between more than 2 alternatives).

Examples?

Just take any function where the boolean corresponds to a status/condition: user.setMarried(false)): Don't tell me that it should be refactored into user.setSpouse(otheruser), because if you don't need to know the spouse identity the refactoring wouldn’t be GDPR compliant ;-)

Edit: You could indeed consider that this can be refactored in setMaried() and setSingle(). But as consequence, you'd need to make the difference between the cases in your code whenever you want to move that data. So the simple a.setMarried(b.getMarried()) would become if(b.getMaried()) a.setMarried() else a.setSingle()). In the end, handling boolean data differently than non boolean types might result in transgressing the law of demeter.

Christophe
  • 74,672
  • 10
  • 115
  • 187
  • I think most programmers would treat a bit (as in one eighth of a byte) differently from a boolean (a data type), even though a boolean in theory only needs one bit to represent it. In practice, booleans are normally not packed together eight to a byte. And `setMarried()` could have a counterpart `setSingle()` which eliminates the need for a boolean. – CJ Dennis Nov 05 '19 at 10:42
  • @CJDennis Yes it could have a counterpart - But you haven't said why it should? Almost all code has at least 1 alternative way of writing it (I would say all code, but absolutes are "almost" never correct!). To me, user.setMarried(true) is just as quick to grok as user.setMarried() & user.setSingle(), and it would depend on the domain language we are using. If my client/users said "A user is single" I would use your option, user.setSingle(). If they said "A user is not married" I would use user.setMarried(false). – Jack Nov 05 '19 at 10:53
  • @CJDennis would it be better? Do you think that copying the status with a.setMarried(b.getMarried()), is worse than if(b.getMaried()) a.setMarried() else a.setSingle() ? when at he same time for a non boolean you’d just stick to the a.setXxx(b.getXxx) ? Wouldn’t handling all the booleans like this not violate the law of demeter ? And if it would be so much better, why wouldn’t you generalize it to other types, for example setBirth(year) would become setBirthyear1970(), setBirthYear1971(),setBirthYear1972(), etc... ? “Most of the programmers” prefer to handle data as data and not as code. – Christophe Nov 05 '19 at 11:18
  • To attempt to sincerely answer your question, I think it's because we as humans don't think about "is Chris married true?" or "is Chris married false?", just "is Chris married?" which gets a yes/no answer (possibly with additional information, "no, but Chris just got engaged!", "not yet", "Chris divorced last year", "this is Chris' third marriage"), not a true/false answer. Whereas we think about "what year was Chris born in?" which gets a numerical answer. – CJ Dennis Nov 05 '19 at 11:34
  • @CJDennis For some systems, the question is just to know whether or not a person is married at the time of the registration, without care for any other variants. In this case the yes/no is a data. Bollean is a legitimate encoding. Coding it as a string "YES"/"NO" could avoid the boolean, but that's my point: do we have to avoid the boolean ? Why shouldn't booleans have the same rights than other types: just because of some prejudice, because sometimes they are used in the wrong way ? Are cars forbidden because some people make accidents with it ? – Christophe Nov 05 '19 at 11:49
  • That's not what I'm saying at all. I'm saying we don't say "Chris is married true" but we do say "Chris was born in 1972". So the natural data to manage is "married" and "1972". – CJ Dennis Nov 05 '19 at 11:58
  • @CJDennis Sorry, I didn't catch that. Can you elaborate how the closeness to natural language could help to define what is a smell and what isn't ? – Christophe Nov 05 '19 at 12:06
  • The reason to use meaningful method names is to make it easier on the programmer reading the code. The closer it is to natural language (without being contrived in code) the better. The same with data. The more familiar it is and the closer it is to everyday concepts, the easier the programmer will find it to think about and manipulate. For example "not hidden" has a higher cognitive load than "visible". If you don't agree, see how long it takes you to be certain of the meaning of "not unhidden". – CJ Dennis Nov 05 '19 at 12:21
  • I believe the common argument against the last example is that it should be something like `setMarriageStatus(MARRIED)`, even if `MarriageStatus` is initially an enum with just two values, it's easier to change later. – WorldSEnder Nov 05 '19 at 12:23
  • @CJDennis does the boolean `isMarried` really create a cognitive load ? Does anyone have to struggle with its meaning ? I believe most programmers won't have an issue with it and would not have anything to unhide here. I agree with the issue related to hiding the true meaning of parameters; but again, it's unrelated to booleans. And it's not because too many programmers make ugly tricks with obscure boolean flags, that most programmers should ban booleans from their language features. – Christophe Nov 05 '19 at 12:38
  • @WorldSEnder indeed! Boolean is at the same time an encoding and a full data type. You could imagine one day to implement fuzzy logic in your app. Then suddenly, all the booleans related to the problem space would no longer be `{ true, false }` but a a probability of truth, with an almost continuous universe between the two extreme values. In this case it would make sense to have a `FuzzyBolean isMarried` that is safely copied with `b.setMarried(a.getMarried())` whereas the harsh `if (a.getMarried())` would loose the accuracy of the original fuzzy truth value. – Christophe Nov 05 '19 at 12:47
  • So, basically the case where boolean parameters are ok, are all those that don't break the principle of least astonishment. In other words, what candied_oranga suggest. When it's expected and it doesn't force us to look inside the method to know for what is. – Laiv Nov 05 '19 at 15:11
3

If an If statement needs to be repeated very often to determine which of the two method should be called. I could definitely see it being better to have that if statement inside the method instead.

the_lotus
  • 153
  • 7
2

just because a re-factoring of a bool parameter produces 'only' two functions, doesn't mean it's always a good idea to re-factor.

Do you have a source for your statement 'most programmers believe'?

What about serialization? would you have two methods, one for serializing true, and one for serializing false?

Aganju
  • 1,453
  • 13
  • 15
  • PHP serialises for me. It takes any constant or parameter, not just booleans. I would never need to write my own serialiser. As for "most programmers believe", it's based on the answers on this very site for multiple questions about boolean parameters. – CJ Dennis Nov 05 '19 at 04:24
  • 3
    Well you asked if there is a use case, and I gave you one. Now you say you wouldn't need that in one specific language - that doesn't make it invalid for all other languages. If you care only about bools in php, add it to the question. Otherwise, I can bring ten more examples, and you can bring ten more languages were those specific examples might not apply. - My impression is that your mind was already made up, and the question is purely rherotic. – Aganju Nov 05 '19 at 05:33
  • 1
    If I'd asked about passing integers, strings, or arrays, etc., the answer would be "it's unlimited". It would be very difficult to write most code in most modern languages without one of the basic types, all except booleans. The use case of serialisation is very niche. Let's say I'm writing a web application. When would I need to write a method that accepts a boolean? What about code to analyse signals from deep space? Etc. I accept that as written my question mightn't express what I want to ask. – CJ Dennis Nov 05 '19 at 05:42
  • 2
    I agree with Aganju, it seems like you've already made your mind up about what the answer is. You're arguing the No true scotsman fallacy. Somebody has to write the serializers of the world. – Blake Nov 05 '19 at 12:59
2

The use of boolean parameters has been frowned upon by Robert C. Martin (Uncle Bob) in his clean code video series for a reason. It doesn't need to be bad all the times. There are many in the industry who recognize that it is easy to produce bad code with boolean parameters. Refer here and here for more info.

A bool will always flag: A boolean variable has only two states (true and false). So a boolean variable can not be used for anything but flagging. So a boolean parameter will always act as a flag to a function.

Now the question is why is flag parameter to a function bad. A flag parameter in the function doesn't cause any harm to the body of the function. It reduces the calling code's readability.

Example 1: Consider the below code for computation of simple and compound interest. The readability of the function body is not bad. But if you look at the calling code in isolation it's difficult to say if we are trying to compute simple interest or compound interest with out looking it to the signature of the method. So the readability of the calling code is compromised. If we refactor this method into two methods, then the calling code will have better readability.

Function definition

int ComputeInterest(int principal, int period, int rate, bool isSimple)
{
   if(isSimple)
   {
      return something;
   } else {
      return somethingelse;
   } 
}

Calling code

//Looking at the lines below difficult to say which is simple interest and which is compound
var x = ComputeInterest(1000,1,10,true); //ComputeSimpleInterest(1000,1,10) is more readable
var y = ComputeInterest(1000,1,10,false); //ComputeCompoundInterest(1000,1,10) is more readable

Example 2: Imagine a code to mark an order complete. It has an optional parameter to send a mail.

MarkOrderComplete(string orderId, bool isMailRequired);

//Now looking at the calling code, it will be difficult to say where we will be sending the mail and which will not be

MarkOrderComplete("ord12345", true); //CompleteOrderWithMail("ord12345") is more readable
MarkOrderComplete("ord123456", false); //CompleteOrder("ord123456") is more readable

Example of boolean parameter being good: The above examples really make boolean parameter a bad choice. However there are cases when it can be good as pointed out by candied_orange here

AssertTrue(bool isEqual, string message)
{
   if(!isEqual) throw new TestFailedException(message);
}

AssertTrue(5 == numberOfMonths, "Number of months is not equal"); //There is no readability issue here.

AssertTrue((5 < numberOfMonths ) && ( 10 > numberOfMonths), "Number of months is not okay"); //There is no readability issue here.

//AssertTure with boolean parameter gives as different ways to assert without loosing readability

Nachiappan Kumarappan
  • 1,404
  • 1
  • 9
  • 19
  • I agree that flag parameters are bad and should be refactored by using meaningful method names. You say a boolean will always be a flag. That's the heart of my question. If this statement is true (a boolean is a flag), why must it be? – CJ Dennis Nov 05 '19 at 10:36
  • The thing is that most of the times, the caller knows the value of the flag so it can decide to call callee.methodA() or callee.methodB() indistinctly what makes the code more expressive than passing the boolean to callee.method(bool) which in many cases leads to break the principle of "least astonishment" (we have to look inside the method). Whether there're are not legit cases for flag arguments, if they can be replaced by a better "design" then doesn't matter if they are legit or not. In other words, doesn't matter if you find the Lost Ark, you will not be allowed to open it for longer. – Laiv Nov 05 '19 at 10:52
  • @CJDennis, when you look at the method body, you are receiving a boolean, so it can only flag something as true or false. I don't think there is another way about it. – Nachiappan Kumarappan Nov 05 '19 at 11:01
  • In the calling side if you pass the value "true" or "false" the readability will be compromised. On the other hand if you pass an expression that gets evaluated to a boolean, then the readability is not compromised. – Nachiappan Kumarappan Nov 05 '19 at 11:03
  • arent your good examples actual taking a boolean function parameter? – Ewan Nov 05 '19 at 12:12
  • Yes!!! Precisely the point. Thanks for pointing it out! A boolean parameter doensn't make the function bad. If an expression is passed as a boolean parameter, then there would be no issue of readability with boolean parameter – Nachiappan Kumarappan Nov 05 '19 at 12:14
  • Swift: markOrder(_ order: String, completeWithEmall: Bill withEmail). A call: markOrder (“ord12345”, completeWithEmail: true). No need for any stupid refactoring. – gnasher729 Nov 05 '19 at 15:15
1

Technically, one never needs a boolean flag as a method parameter. Boolean flags are so popular because they are the physical "incarnation" of bits. In practice, boolean values are simply the elementary unit of information, as they have the smallest possible domain (2 different possible values). For this reason, they are extremely pervasive, but they are only within context when coding at a very low level.

As a result, multiple boolean values make up other pieces of information through composition. When did you last think that your int values are simply 32 (or 64) "booleans" packed together. You could always use an int to branch, only your domain would be vastly increased, so there is no practical use for this.

In short, "boolean flags" are at the heart of information theory (call them bits), and their value is, usually, a "static" one, i.e. they are used to represent information. Because, in isolation, they represent only two different cases, programmers thought it would be a great abstraction for... alternatives?! (I wouldn't know how else to call a conceptual analog...). So, there you have it. When we use our human mind, we very.. very very often think in terms of choices, and all that often in terms of mutually exclusive choices, and, as it seems, even more often in terms of pairs of mutually exclusive choices. Booleans seemed a great fit, so "we" embraced them naturally!

In simple words, "we" seem to make a pattern out of whatever bears significant resemblance to our natural abstracting mode of human thought.

By the way, even if you refactor a boolean flag into two methods, how would you know which one to invoke, if not for some boolean flag, somewhere higher up the call hierarchy? In fact, all you gain is expressiveness, not total substitution.

Apart from that, I can only see a single valid use case that fits your definition/take at boolean flags, and this being the elementary information representation conversion:

Convert.ToString(bool value);

See, you have to check which of the two values this is, so, unless you prefer to have the following all over your codebase...

if (value)
    return "true";
else
    return "false";

you are probably better of with Convert.ToString(bool value); than booleanTrue() and booleanFalse() methods that, again, in my opinion, don't really add any value.

Vector Zita
  • 2,372
  • 8
  • 19
  • Probably a better word for "dilemma" would be "alternative". I studied the play _A Man for all Seasons_ in school and I still remember the line "There is no third alternative" because my teacher explained that is has a double meaning, that there were only two choices, and that "alternative" means "the other one", i.e. an alternative is always one of two choices. The only alternative to `if` is `else`, although it can be extended with another `if`. – CJ Dennis Nov 05 '19 at 06:58
  • @CJDennis Indeed, "dilemma" was probably not the most suitable word for what I meant. I replaced it with "alternative" ;-) – Vector Zita Nov 08 '19 at 16:00
1

Generally I believe that bool (boolean) parameter is bad, however in one situation I used 6 boolean parameters and my code reviewers agreed to that decision. Let me explain.

Consider the situation when you have 6 buttons, which can be enabled or disabled in various combinations depending on user selection of a text field elsewhere in the application window. My task was to write a Jemmy unit test and check if these buttons are enabled/disabled in proper combination after specific text field selection. So I created a method with 6 boolean parameters which corresponded to the enable/disable state of each button. By calling this one method I could easily test all text field selection possibilities.

Basically I broke 2 two Uncle Bob (a.k.a Robert C. Martin) rules: I used boolean parameter and I used more than 3 parameters. However in that particular situation this solution work quite well, yet I am still not sure if that was a best decision.

Fataho
  • 57
  • 7
0

Data vs logic

On a big picture (and oversimplified) scale, code can be segregated into two categories: data and logical flow. Many people can add additional ones they think is just as important but they're irrelevant for the answer at hand.

You're right that booleans for logical flow are bad practice. I would slightly alter that interpretation and say that it's bad practice for a public API (what you do internally matters less), but that's maybe a different discussion for a different day.

Booleans as data

By excluding booleans for logical flow, we haven't actually excluded booleans that function as data.

For example, while you might expect an update method to look like this:

public void Update(User u) { ... }

maybe you want to limit which fields of the user can be updated (e.g. not the username, but the user's first/last name can be changed), which leads you to:

public void UpdateUser(string firstName, string lastName)

It's not too farfetched to think of examples where a boolean field can be changed:

public void UpdateUser(string firstName, string lastName, bool isAlive)

And this is a basic example of why boolean parameters do exist. Some data simply has an innate binary nature, and therefore it is best represented by a boolean.

Let's ignore the "dead people can't come back alive" argument and say that we allow for fixing bad data (we thought the person was dead but we were wrong). I picked living/dead because we can all agree that this is a binary value. Other options exist but I picked the one with the most commonly agreed upon consensus.

No passing allowed?

The method should use the boolean value itself and not simply pass it through to some other method.

I find this a bit too restrictive of a requirement. In effect, the above passes the boolean through many layers down to the DAL. It's eventually translated into e.g. a SQL statement, but it has passed through many layers before it gets to that stage.

Your current phrasing excludes this as a valid answer, but I very much disagree that this particular example is invalid for the core of your question.

Booleans should never change logical flow?

I also find the "no logical flow repercussions from booleans" argument to be excessively broad and restrictive. Taken to heart, you're effectively suggesting that the if statement should have never existed.

I can also think of cases where the boolean causes logical flow variations yet still is relevant, e.g. if the backend uses separate external services for handling living/deceased people.

Consider an application which connects to external services (e.g. government registry: one for the living, one for the deceased), where you do not want to expose to your user that different services are being used. "Unbooleaning" a method leads to something along the lines of

public void DoActionForDeadPerson(...)

public void DoActionForLivingPerson(...)

(Obviously, better names are needed in reality)

But this requires the consumer (i.e. the user of your backend service) to know that there is separate handling for living/deceased people, and this may be considered a leaking abstraction in certain scenarios.

It's perfectly reasonable for your application to specifically hide that fact that there are separate repositories. For example, maybe the living/deceased resource split happened after your application went live (it used to be the same resource) and you're trying to implement it without affecting your public API.

Another example

If you can only think of an example with more than one parameter, that's OK too.

While I think there's no real reason to differentiate between methods with only a boolean parameter and methods with multiple parameters (one of which is a boolean), I'll humor you and give you an additional example of a function with only a boolean parameter:

public void SetUserFieldsReadonly(bool isReadonly)
{
    txtFirstName.IsReadonly = isReadonly;
    txtLastName.IsReadonly = isReadonly;
    txtUserName.IsReadonly = isReadonly;
}

Note that in this case, isReadonly again acts as a data-boolean as opposed to a logical-flow-boolean. It's the same underlying principle as the previous example.

Whether you consider the boolean "passed" on is very arguable. While passing it to a submethod obviously counts as passing it on, does setting a property count too? I think this is highly subjective and liable to opinionated feedback.

Can you separate this into a SetReadonly() and SetEditable()? Sure. But it's unnecessary bloat, in my honest opinion. It's copy/paste and whenever you change one method, you're obviously also going to have to change the other method, so it does not pass the DRY test.

But I still agree with the orignal intention of the "no logical flow" rule

As a basic example of boolean usage where I do agree with you that it should not happen:

public void AddName(string name, bool alsoAddLowerCaseName)
{
    _myList.Add(name);

    if(alsoAddLowerCaseName)
        _myList.Add(name.ToLower());
}

It would be much better by letting the consumer call the Add method twice.

string name = "Robert";

AddName(name);
AddName(name.ToLower());

The consumer retains the same control (choosing whether to add the lower case name or not) but it does not require you to keep changing the method for new possibilities (e.g. upper case, reversed string, HTML encoded string, ...)

I believe that these cases are the core concern of your "no logical flow booleans" argument and I do agree with you there.

Flater
  • 44,596
  • 8
  • 88
  • 122
  • “No passing allowed” is obviously nonsense. A method has an interface and acts accordingly. How it is implemented is nobody’s business. – gnasher729 Nov 05 '19 at 15:09
  • @gnasher729: To be fair, OP is asking for an example implementation to disprove the "no booleans parameters in the interface" argument. So the implementation is exactly OP's business (at least for the sake of example). – Flater Nov 05 '19 at 15:27