views:

200

answers:

12

An interesting discussion arose today around the concept of having one method with flags versus two methods for each state of the flag. Which makes more sense and why?

void Submit(object data, bool isDraft);

or

void Submit(object data);

void SubmitAsDraft(object data);

I am tending toward the later, where each operation explicitly indicates what the transaction is performing.

Which makes more sense and are there well known rules or patterns that suggest why?

EDIT:

Assume the methods are being exposed as operations via a SOAP Service and OO concepts don't necessarily apply. Although OO is the implementation behind the service.

+4  A: 

I personally go for DRY; don't repeat yourself. If there is a lot of common code between the two, use the method with flag. Otherwise, two methods.

Sinan Taifour
Absolutely, but these methods would simply be a facade.
Student for Life
I agree. If the imlementation are mostly the same, go with the flag. If mostly different go with separate methods.
TheArtTrooper
@Davide, if this is the case, and it is only a question of readability, I'd personally go for 2 methods, but I think it is a matter of taste.
Sinan Taifour
+2  A: 

I would make the IsDraft a property of the object you are passing in, as it seems relevant to the object.

duckworth
Agreed, that definitely makes sense from an OO implementation which may be whats going on in the background but what if you are exposing these operations as a Service where property settings do not apply?
Student for Life
+5  A: 

Which one is more readable?

Submit(data, true); // true what?
// vs
SubmitDraft(data);

I think the answer here is to use explicit separate operation, if your programming language does not support keyword arguments, like

Submit(data, isDraft: true);
Alex B
+12  A: 

If you do use a single function, don't use a bool, use an enum:

enum DocType { Draft, Final };

void Submit(object data, DocType type );

This has two main advantages - it is self documenting at the call site:

Submit( mydata, Draft );

and it extends naturally if you discover you have more than two document types (or statuses).

anon
+1! Although I would call it "Status" rather than Type...
Torsten Marek
+!, although I do see a minor risk. You could easily flood your code with dozens of similar enumeration types that are all almost similar. For example, *enum DocType {Xml, Txt, Doc};* would conflict with the other enum. It gets worse when you name it status. Maybe DocumentStatus? Or DocumentMode? Enums are nice, but too many enums are a Hell.
Workshop Alex
@Workshop I'm not particularly recommending this pattern - I'm simply saying if you DO use it, don't use a bool to switch on, use an enum. But IMHO, it's impossible to make strong recommendations one way or the other without knowing a lot more about the actual problem domain.
anon
+3  A: 

Another alternative: have an enum {DRAFT, FINAL_VERSION} rather than a boolean as parameter.

Michael Borgwardt
+3  A: 

Use object concepts such as polymorphism ;-)

data.submit()

with data being either a Draft or a Final. Both classes implement the same interface with a submit() method.

That way you get rid of the boolean and the awful struct data

cadrian
+12  A: 

I would do this:

void Submit(object data) { _Submit(data, false); }
void SubmitAsDraft(object data) { _Submit(data, true); }
(private) void _Submit(object data, bool isDraft);

But that's just me...

Workshop Alex
Agreed this is also what i do, It improves readability and is also very DRY :)
Kaius
This is exactly what you want in a web service. The two operations are different. The fact that you currently implement them with a flag is irrelevant to the caller.
John Saunders
+1  A: 

almost all of the answers given are correct, but none seem to cover the entire scope, so -

  1. for obvious semantics, two public methods:

    SubmitFinal(data)
    SubmitDraft(data)

  2. for minimal implementation, these two public methods call one internal method:

    submitData(data, isDraft)

  3. for future expansion, use an enum instead of a boolean:

    submitData(data, DocType.Draft)

Attaching the enum to the data object is even better, if this option is available, e.g.

data.DocType = DocType.Draft;
data.Submit();
Steven A. Lowe
A: 

There is no hard and fast rule in this. Sometimes, if you follow the "have different methods" rule too much your api is going to be far too bloated and you'll get confused as to what method actually does the real work. However, if you follow the do everything with parameters approach you could end up with just one method where everything is specified as parameters.

But to address the particular example, it is easier to read method names than it is to read their parameters. In this case, with two methods, you quickly ascertain by reading the method names that you can submit a draft. Though you should probably change the name of the submit method to "submitAsFinal"

Though I'd recommend having two methods, one names submitAsFinal and the other submitAsDraft, they should still defer onto another private method which takes the draft boolean parameter so that you don't have duplicate code.

Michael Wiles
A: 

I am really torn on this problem. I think using the second method is more reliable and easier to debug. Each function becomes a very clear black box. Errors are easier to catch because you can trap input errors within the function. Having the flag outside the scope of the function seems to introduce extra ambiguity into the code. Under what conditions was my function called? Where and why was my flag set? Did some logic error occur to cause the flag to be set inproperly? It also makes you have to test the validity of the flag before you call the function which can be complicated. I think removing the flag can lead to better encapsulation inside the function and error handling of state can be consistently dealt with inside the function.

But like I said I am torn the first method can be really convenient and if you have really complicated logic inside a function it can ensure consistency because of DRY. Not need to repeat really fragile and complicated functionality.

In my mind I think it depends on where you ultimately want to validate input parameters. I think avoiding flags allows for a very clear location to track down problems. Inside the black box.

Also, in addition to flags sometimes I want to know who and what is calling my function. So sometimes I add a reference id as an additional parameter.

void Submit(object data, bool isDraft, string referenceId);

Then I can know more about who is calling submit and can make tracking down errors a little easier if the want to impose rules about who should call your function and understand when in the logic flow it was called.

Gordon Potter
A: 

Bayrak... kimi zaman törenlerde gururlu taşıdığımız, kimi zaman firmanızın dışarıda ki simgesi. Bazende kendinizi ifade ediş tarzınız. Bayrak Milletlerin özgürlük simgesi ve sınırlarımızı belirlediğimiz kutsal değerimiz. bayrak ile alakalı merak ettiğiniz aradığınız herşeyi bu sitede bulacaksınız. Bayrak çeşitlerimizde Türk bayrağı,Makam bayrakları ,Olta bayrakları,Makam bayrakları,Asetatlı makam bayrakları,Flamalar.Kırlangıç bayraklar,Takım bayrakları,Atatürk posterleri,Dizili flamalar,Masa bayrakları,Özel bayraklar,Makam direkleri;masa direkleri ni İmalatını ve üretimini toptan dağıtım ve satışını pazarlıyan firmamız bayrak kalitesiyle size her zaman daha yakın bir bayrak firmasıdır. http://www.bayrak.gen.tr

çok güzel süper olmuş
A: 

I would create the two separate methods:

void Submit(object data);
void SubmitAsDraft(object data);

Boolean parameters have a habit of needing refactoring into enumerations and are harder to read without looking up the format parameter name.

Then, assuming there is some commonality within these methods, factor the common parts into methods of their own to be called by the implementation of the above two. It's not likely you would call some underlying method and pass that a boolean unless the only difference in functionality is saving a boolean field the database.

WW