views:

796

answers:

16

What factors determine which approach is more appropriate?

A: 

Not nearly enough information here. It depends if your language even supports the construct "Thing.something" or equivalent (ie. it's an OO language). If so, it's far more appropriate because that's the OO paradigm (members should be associated with the object they act on). In a procedural style, of course, DoSomethingtoThing() is your only choice... or ThingDoSomething()

Loren Segal
+8  A: 

To be object-oriented, tell, don't ask : http://www.pragmaticprogrammer.com/articles/tell-dont-ask.

So, Thing.DoSomething() rather than DoSomethingToThing(Thing n).

benefactual
"Tell dont ask" I like that!! Niiice!!
Mostlyharmless
It's one of those trite little sayings that seems to stick :)
benefactual
Excellent article
Horace Loeb
A: 

DoSomethingToThing(Thing n) would be more of a functional approach whereas Thing.DoSomething() would be more of an object oriented approach.

Bryan Roth
A: 

That is the Object Oriented versus Procedural Programming choice :)

I think the well documented OO advantages apply to the Thing.DoSomething()

Guido
+3  A: 

If you're dealing with internal state of a thing, Thing.DoSomething() makes more sense, because even if you change the internal representation of Thing, or how it works, the code talking to it doesn't have to change. If you're dealing with a collection of Things, or writing some utility methods, procedural-style DoSomethingToThing() might make more sense or be more straight-forward; but still, can usually be represented as a method on the object representing that collection: for instance

GetTotalPriceofThings();

vs

Cart.getTotal();

It really depends on how object oriented your code is.

Aeon
A: 

Here are a couple of factors to consider:

  • Can you modify or extend the Thing class. If not, use the former
  • Can Thing be instantiated. If not, use the later as a static method
  • If Thing actually get modified (i.e. has properties that change), prefer the latter. If Thing is not modified the latter is just as acceptable.
  • Otherwise, as objects are meant to map on to real world object, choose the method that seems more grounded in reality.
Chris Comeaux
A: 

Even if you aren't working in an OO language, where you would have Thing.DoSomething(), for the overall readability of your code, having a set of functions like:

ThingDoSomething() ThingDoAnotherTask() ThingWeDoSomethingElse()

then

AnotherThingDoSomething()

and so on is far better.

All the code that works on "Thing" is on the one location. Of course, the "DoSomething" and other tasks should be named consistently - so you have a ThingOneRead(), a ThingTwoRead()... by now you should get point. When you go back to work on the code in twelve months time, you will appreciate taking the time to make things logical.

Ken Ray
A: 

In general, if "something" is an action that "thing" naturally knows how to do, then you should use thing.doSomething(). That's good OO encapsulation, because otherwise DoSomethingToThing(thing) would have to access potential internal information of "thing".

For example invoice.getTotal()

If "something" is not naturally part of "thing's" domain model, then one option is to use a helper method.

For example: Logger.log(invoice)

killdash10
A: 

If DoingSomething to an object is likely to produce a different result in another scenario, then i'd suggest you oneThing.DoSomethingToThing(anotherThing).

For example you may have two was of saving thing in you program so you might adopt a DatabaseObject.Save(thing) SessionObject.Save(thing) would be more advantageous than thing.Save() or thing.SaveToDatabase or thing.SaveToSession().

I rarely pass no parameters to a class, unless I'm retrieving public properties.

digiguru
A: 

To add to Aeon's answer, it depends on the the thing and what you want to do to it. So if you are writing Thing, and DoSomething alters the internal state of Thing, then the best approach is Thing.DoSomething. However, if the action does more than change the internal state, then DoSomething(Thing) makes more sense. For example:

Collection.Add(Thing)

is better than

Thing.AddSelfToCollection(Collection)

And if you didn't write Thing, and cannot create a derived class, then you have no chocie but to do DoSomething(Thing)

David Arno
+13  A: 

I think both have their places.

You shouldn't simply use DoSomethingToThing(Thing n) just because you think "Functional programming is good". Likewise you shouldn't simply use Thing.DoSomething() because "Object Oriented programming is good".

I think it comes down to what you are trying to convey. Stop thinking about your code as a series of instructions, and start thinking about it like a paragraph or sentence of a story. Think about which parts are the most important from the point of view of the task at hand.

For example, if the part of the 'sentence' you would like to stress is the object, you should use the OO style.

Example:

fileHandle.close();

Most of the time when you're passing around file handles, the main thing you are thinking about is keeping track of the file it represents.

CounterExample:

string x = "Hello World";
submitHttpRequest( x );

In this case submitting the HTTP request is far more important than the string which is the body, so submitHttpRequst(x) is preferable to x.submitViaHttp()

Needless to say, these are not mutually exclusive. You'll probably actually have

networkConnection.submitHttpRequest(x)

in which you mix them both. The important thing is that you think about what parts are emphasized, and what you will be conveying to the future reader of the code.

Orion Edwards
+3  A: 
  1. Thing.DoSomething is appropriate if Thing is the subject of your sentence.
  2. DoSomethingToThing(Thing n) is appropriate if Thing is the object of your sentence.
  3. ThingA.DoSomethingToThingB(ThingB m) is an unavoidable combination, since in all the languages I can think of, functions belong to one class and are not mutually owned. But this makes sense because you can have a subject and an object.

Active voice is more straightforward than passive voice, so make sure your sentence has a subject that isn't just "the computer". This means, use form 1 and form 3 frequently, and use form 2 rarely.

For clarity:

// Form 1:  "File handle, close."
fileHandle.close(); 

// Form 2:  "(Computer,) close the file handle."
close(fileHandle);

// Form 3:  "File handle, write the contents of another file handle."
fileHandle.writeContentsOf(anotherFileHandle);
Kevin Conner
A: 

Even in object oriented programming it might be useful to use a function call instead of a method (or for that matter calling a method of an object other than the one we call it on). Imagine a simple database persistence framework where you'd like to just call save() on an object. Instead of including an SQL statement in every class you'd like to have saved, thus complicating code, spreading SQL all across the code and making changing the storage engine a PITA, you could create an Interface defining save(Class1), save(Class2) etc. and its implementation. Then you'd actually be calling databaseSaver.save(class1) and have everything in one place.

rassie
A: 

I have to agree with Kevin Conner

Also keep in mind the caller of either of the 2 forms. The caller is probably a method of some other object that definitely does something to your Thing :)

Daniel
+1  A: 

I agree with Orion, but I'm going to rephrase the decision process.

You have a noun and a verb / an object and an action.

  • If many objects of this type will use this action, try to make the action part of the object.
  • Otherwise, try to group the action separately, but with related actions.

I like the File / string examples. There are many string operations, such as "SendAsHTTPReply", which won't happen for your average string, but do happen often in a certain setting. However, you basically will always close a File (hopefully), so it makes perfect sense to put the Close action in the class interface.

Another way to think of this is as buying part of an entertainment system. It makes sense to bundle a TV remote with a TV, because you always use them together. But it would be strange to bundle a power cable for a specific VCR with a TV, since many customers will never use this. The key idea is how often will this action be used on this object?

Tyler