views:

73

answers:

4

If I have a method that does something and additionally logs information, should I create a new method if I don't want to log or use a flag?

public void MethodA(string myMessage, bool logIt)
{
  if(logIt)
  {
    //do stuff with logging
  }
  {
    //don't need to log
  }
}

...vs...

public void MethodA(string myMessage)
{
  //do stuff with logging
}

public void MethodANoLogging(string myMessage)
{
  //don't need to log
}

My scenario is simple and I'm mainly interested in the flag parameter, which could be an enum creating many if...else if...else if scenarios within the same method. Versus just creating a new method with a different name. I'm in favor of the second solution (new method) since it allows methods to have one responsibility. Fundamentally, that is a simpler solution.

What would be the reason to use the flag version?

A: 

This sort of thing has been (and will be) debated endlessly, but the famous answer is "it depends".

For something like whether or not to log (meaning that there shouldn't be any side effects as far as within the application), I would absolutely not create a new method. You will have to duplicate your logic, which means maintaining it in two places in the future, for no real reason. It makes more sense to do something like...

if(logIt) // log information

// do something

if(logIt) // log other info

// do more

....etc

Your core logic is the same whether or not you want to log, and is only in one place.

Adam Robinson
It's usually not necessary to duplicate the logic -- I'd factor out any duplication into a helper method called by both versions, or else call one method from the other with a default (as described by Luke Schafer).
JacobM
+1  A: 

Normally,to avoid overthinking it, I would do an overload, defaulting to 'false'

public void MethodA(string myMessage)
{
    MethodA(myMessage, false);
}

public void MethodA(string myMessage, bool logIt)
{
  if(logIt)
  {
    //do stuff with logging
  }
  {
    //don't need to log
  }
}

That's my personal preference, I'm sure others will disagree. It doesn't cover every situation, though.

Luke Schafer
+3  A: 

Neither. Your logging configuration should be completely independent of your business methods. That's what AOP is for.

ChssPly76
+1 Absolutely right, but I thought it would be worth defining on a conceptual level.
Adam Robinson
In .NET, I don't see how you will get the exception, which is in the method, to the attribute, which is outside of the method. I say attribute if you want to go straight .NET (no EOS compiler).
4thSpace
I've not encountered AOP before. Could you provide a brief code example to illustrate logging?
Benedict Cohen
Opps, please ignore my last comment. If I'd read the wikipedia article I would have found a lovely example.
Benedict Cohen
@4thSpace - I don't use .NET so I can't address the issue you've raised; your original question was touching general OOD rather than a concrete implementation. If by "exception in the method" you mean an exception being **caught** within your method, then it's either something you've expected and handled (and thus likely won't log) or it should be (wrapped and) rethrown. Mind you, AOP is not "end all be all" solution, for logging in particular there are alternatives like log4net which still very much abstract your logging configuration from your method signature.
ChssPly76
+1  A: 

You should (almost) never overload a method with a boolean flag. There are a variety of reasons:

  1. To avoid confusion, methods should do one thing and one thing only. A boolean flag is a clear indication that a method does more than one thing (from Robert C. Martin).

  2. Reading the code for such a method makes it unclear exactly what is happening. If I am new to the code I see:

    MethodA("This is a message", false);

    It is not entirely clear what false means without going to look at the code. This fails the principle that the intent of a method should be clear from its name alone.

  3. It is sometimes an unecessary binding to a binary choice when more than one choice might need to be added later. For example: let's say you have a method:

    public UpdateCustomer(String name, boolean isPremiumCustomer);

If you later decide to add different categories of customer then you will have to refactor every line of code that calls this method. A better example in your situation is if you wanted to have a method such that you logged only if a debug flag was turned on.

The alternative approaches are roughly as follows:

  1. Create a function with a different name. This is the approach you have taken and probably the one I prefer. In most cases it is enough to have a: doSomething and a doSomethingADifferentWay as in your example. If however you need a second method that takes a flag then you should consider option 2:

  2. Create an enum that describes the options. In your case this would be something like: enum EnableLogging { ENABLE_LOGGING, DISABLE_LOGGING } Then you write your code as:

    MethodA("A Message", DISABLE_LOGGING);

Which is at least explicit. (Note: This solution comes from Item 40 in Effective Java 2nd Edition by Joshua Bloch, but applies equally well to other languages).

Dean Povey
I know this is an old response but it answered a question I was about to to ask. Thx for posting this response.