Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I was thinking about this when I was starting to set up some code for a new project: are there any rules of thumb for when a method should be part of an object, and when it should be a stand alone function that takes an object as a parameter?

EDIT: as pointed out in a comment, this can depend on language. I was working in C++ when it came to mind, though I'm this is an issue across a number of languages (and would still love to see answers that pertain to them).

share|improve this question
2  
Depends on a language! In C#/Java/etc. functional programming style is not idiomatic. I Clojure/Lisp object-oriented programming is not idiomatic. I would say this: if you do not need to preserve the state, then go the functional route. If you have to worry about multi-threading, then go the functional route. Other than that, it depends ... –  Job Feb 15 '11 at 22:11
    
In Common Lisp, this wouldn't come up. (function object ...) is how these things are written, regardless of what function is. –  David Thornley Feb 15 '11 at 22:23
1  
@Job - I think GSto means func as in imperative procedural programming, as C++ is multi-paradigm, rather than functional programming –  Gerry Feb 15 '11 at 22:25
add comment

4 Answers

  • If it does not conceptionally belong to the class, it should be a standalone function. (it may also be that it logically belongs to the class, but there are so many similar functions that keeping them all as members would bloat the class interface and compromise encapsulation. In this case it is better to draw a boundary between the "outer circle" of utility functions and the "inner circle" of core class interface functions, the former being standalone functions implemented in terms of the latter.)

  • If it belongs to the class but its first parameter may be an instance of a different type, it should be a standalone (possibly friend) function (a typical example is operator +).

    (Scott Meyers puts it more elegantly in Effective C++ 3rd Edition, Item 24: Declare non-member functions when type conversions should apply to all parameters)

  • if it needs to be virtual or uses private parts of the class, it must be a member.

  • Otherwise it should be a member function is to some extent a matter of preference.

Note: the code examples you show make me assume the language is C++. In many other languages such as Java the question is meaningless because there are no standalone functions.

share|improve this answer
2  
Myers changed his mind: drdobbs.com/184401197 –  Crazy Eddie Feb 15 '11 at 22:34
    
@Crazy Eddie, good to know. Thanks and +1 for the link :-) –  Péter Török Feb 15 '11 at 22:53
add comment

Prefer non-member, non-friend functions: How Non-Member Functions Improve Encapsulation by Scott Meyers :

When it comes to encapsulation, sometimes less is more.

[...] If you're writing a function that can be implemented as either a member or as a non-friend non-member, you should prefer to implement it as a non-member function. That decision increases class encapsulation. When you think encapsulation, you should think non-member functions. [...]

share|improve this answer
add comment

Keep in mind that if you use func(obj), you lose the ability to have polymorphism.

share|improve this answer
    
This just means that your general functions need to be truly general, either working with templates, using polymorphic functions, or primitive type public instance variables. –  Hack Saw Feb 15 '11 at 23:06
    
@Client Miller: Except in Python, where it's not a problem at all. –  S.Lott Feb 15 '11 at 23:08
    
@S.Lott How does Python allow polymorphism here? It's been a couple years since I worked in Python. So, maybe newer features have been added to extend polymorphism support. But, can you really do draw(circle) and draw(rectangle) and have different draw() functions called? –  Clint Miller Feb 15 '11 at 23:23
    
@S.Lott (BTW, I know that Lisp does support this type of polymorphism, which is one of the coolest things about Lisp. But, I'm not familiar with other languages supporting it.) –  Clint Miller Feb 15 '11 at 23:24
    
Numerous Python builtins (str, repr, len, etc., etc.) all work polymorphically through "special method names". One can trivially implement this oneself, also, since Python uses pure "duck" typing. It's a challenge to provide an example as a comment on this answer. Given your comment on LISP, you might want to retool your answer, since it seems a bit too strong a statement given your own counter-example. –  S.Lott Feb 16 '11 at 15:45
add comment

The single responsibility principle often helps, when you have to decide whether some method or more broader some functionality belongs to an object.

Please also note, that if some functionality related to some object doesn't belong to one object, it still might make sense to encapsulate it in another object, as in other->func(obj).

class Mouth {
    void say(String msg);
    void sayHello(Person to);
    void sayBye(Person to);
}

Now the 2nd and 3rd method will actually just call the say method and they really don't belong to the responsibility of the Mouth anyway.

interface Out {
    void say(String msg);
}
class Mouth implements Out {
    void say(String msg);
}
class Phrases {
    void new(Language language);
    void sayHello(Person to, Out over);
    void sayBye(Person to, Out over);
}

Of course it might make more sense to pass an Out-instance to Phrases upon construction. Or to wrap it in yet another class. Or whatever.
But it definitely doesn't make sense to have those methods in Mouth, as the SRP suggests.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.