Agile Zone is brought to you in partnership with:

I am an author, speaker, and loud-mouth on the design of enterprise software. I work for ThoughtWorks, a software delivery and consulting company. Martin is a DZone MVB and is not an employee of DZone and has posted 83 posts at DZone. You can read more from them at their website. View Full User Profile

Flag Argument

06.24.2011
| 6117 views |
  • submit to reddit

A flag argument is a kind of function argument that tells the function to carry out a different operation depending on its value. Let's imagine we want to make booking for a concert. There are two ways to do this: regular and premium . To use a flag argument here we'd end up with a method declaration along these lines:


//pseudo-code
    class Concert...
      public Booking book (Customer aCustomer, boolean isPremium) {...}

My general reaction to flag arguments is to avoid them. Rather than use a flag argument, I prefer to define separate methods.


    class Concert...
      public Booking regularBook(Customer aCustomer) {...}
      public Booking premiumBook(Customer aCustomer) {...}
  

My reasoning here is that the separate methods communicate more clearly what my intention is when I make the call. Instead of having to remember the meaning of the flag variable when I see book(martin, false) I can easily read regularBook(martin).

Tangled Implementation

My general dislike of flag arguments does have some subtleties and consequences, the first of which is how to deal with a tangled implementation.

In the simplest case, the reaction to the flag is effectively to call different methods.


    public Booking book (Customer aCustomer, boolean isPremium) {
      if(isPremium) 
       // logic for premium book
      else
       // logic for regular booking
    }

but sometimes the logic is more tangled

 public Booking book (Customer aCustomer, boolean isPremium) {
      lorem().ipsum();
      dolor();
      if(isPremium)
        sitAmet();
      consectetur();
      if(isPremium)
        adipiscing().elit();
      else {
        aenean();
        vitaeTortor().mauris();
      }
      eu.adipiscing();

 

In this situation it can be messy to try to extract the regular and premium book methods into separate methods without significant duplication between the two. In this case one option is to retain the method with the flag argument, but keep it hidden.

    class Order...
      public Booking regularBook(Customer aCustomer) {
        return hiddenBookImpl(aCustomer, false);
      }
      public Booking premiumBook(Customer aCustomer) {
        return hiddenBookImpl(aCustomer, true);
      }
      private Booking hiddenBookImpl(Customer aCustomer,  boolean isPremium) {...}

 

The point here is that only the regular and premium book methods should call hiddenBookImpl. I like to telegraph this by using an ugly name - which also has the bonus that, if you have to, you can easily add a regex probe to ensure nobody else is calling it.

Deriving the flag

How about if the decision on whether to use a premium booking process depends upon the status of the customer. Let's assume an elite customer gets premium booking while a regular customer gets the regular treatment. In this case, of course, we shouldn't have a boolean flag - but is the customer object itself acting as a flag?

I would look at this as about capturing the intention of the caller. If how to book depends only on the status of the customer, then the caller has no business caring about the difference between premium and regular booking - and thus it's perfectly reasonable for the booking routine to derive it's true method based on the customer status. You only want different methods when the caller needs to specify which one she wants.

Boolean Setting Method

Connected to this is the issue of how to name boolean setting methods. Here I agree with Kent's advice - I would rather see


 void setOn();
    void setOff();

than see


    void setSwitch(boolean on);

But again to agree with Kent, this does depend on how the method is used. If you pulling data from a boolean source, such as a UI control or data source, I'd rather have setSwitch(aValue) than


   if (aValue)
      setOn();
    else
      setOff();

This is an example that an API should be written to make it easier for the caller, so if we know where the caller is coming from we should design the API with that information in mind. This also argues that we may sometimes provide both styles if we get callers in both ways.

That same logic applies to book. If there is a check-box on the screen and we are just passing its value to book then a flag argument has some justification. In this example I wouldn't say it's a simple choice - most of the time I'd argue that the flag argument for book is much harder to understand than a simple boolean setter, and is thus worth the explicit methods.

References
Published at DZone with permission of Martin Fowler, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Lund Wolfe replied on Sat, 2011/06/25 - 12:45pm

This could go either way, but I guess I completely agree. Certainly, using a boolean to make a method overgeneralized or multi-purpose is a bad idea. Co-locating the same sequential code in the same method for alternate or extra processing to follow the DRY principle, as you mentioned, seems like a good idea. However, using separate methods that are one above the other would be just as maintainable, simpler (avoiding interspersed/tangled conditional logic), and more flexible to future changes.

I would go with the flag method for simple code and then refactor it into separate methods when the conditionals start making it hard to read or modify.

A single method with a boolean or other indicator could be added that forwards to the other two separate methods if that simplifies the client code.

Erwin Mueller replied on Sun, 2011/06/26 - 3:46pm

Please don't use booleans for flags.

You have the alternatives:
* use different methods
* use different implementations of the class (PremiumCustomer/RegularCustomer)
* use Enums

Also, I don't agree that a Concert class should have a booking method at all. If you book a concert ticket for a customer you have to touch many aspects, like money transfer, reservations, sending confirmation, taking care of refunds, etc. All such things don't have anything to do with a Concert.

PS: stupid rich text edit, why we have to use it?

Artur Biesiadowski replied on Mon, 2011/06/27 - 5:09am

There was a big discussion about that around java 1.1 with

frame.setVisible(true)/frame.setVisible(false)/frame.isVisible()

versus

frame.show()/frame.hide()/frame.isVisible()

As you probably know, setVisible(boolean) won (even if show/hide were left as legacy methods).

I don't particularly like boolean setters to have so huge side effects, but that's java for you. As for the original method, if you follow this route blindly, it can easily lead to explosion of number of methods. Instead of having

book(Customer, enum TicketType, Collection<ExtraService>) 

you will end up with having


bookPremiumWithPopcorn(Customer)

bookPremiumWithoutPopcorn(Customer)

bookNormalWithPopcorn(Customer)

bookNormalWithoutPopcorn(Customer)

bookSeniorDiscountWithoutPopcornWithHearingAid(Customer)

....

While having boolean is not a good solution, refactoring from there (moving to enum for booking type, adding collection of extra options) is better direction IMHO than going from separate method for everything and having to upgrade each caller site each time you add new type of ticket or something (as opposed to just pass through opaque TicketType through the layers).

Mladen Girazovski replied on Thu, 2011/06/30 - 8:50am in response to: Erwin Mueller

Erwin,

regarding your comment about the concert class, it sounds to me like you're insisting on a "anemic domain modell", where all the business logic goes into Services and Entites are mere Datastructures, the usual procedural design very popular in most projects.

Of course a concert can take care of its reservations depdeing on the domain model, but that doesn't mean that it has to handle money transfer, sending conformations, taking care of refunds etc. pp.

But lets get back to the article, lets argue about flags ;)

Flags make methods more complex, each if/else construct increases the intranel complexity of the method (more execution paths to test, etc. pp.), which are usually unnessecary, since the caller of the method should already know what kind of booking needs to be made, so the caller could easily call another spezialized method, or using a ParameterObject, many options, flag arguments are something that is natural in procedural languages like C.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.