views:

194

answers:

3

Given a class that is semantically supposed to be an object of a certain type, but also has multiple operations for operating on objects of its own type, what is the best way(pattern?) of organizing the class in this type of scenario? I find this to be a common occurrence when a developer creates objects but is thinking with a procedural mindset.

Example:

Class User {
  private m_userData;
  function User() {}
  function GetUserData() {}

  function KillAllUsers(){}
  function MaimAllUsers(){}
}
+3  A: 

It's not very clear from your description, but it seems that the "KillAllUsers" and "MainAllUsers" methods are operating on a set of users. I would recommend creating a custom UserCollection that has these methods as instance methods or create them as statics and pass in a collection of users. In modern domain model terms, you'd be dealing with a UserRepository.

Christophe Herreman
+4  A: 

I'd rather tend to separate these two purposes into a User and a UserManager class. IMO this provides a clearer separation of what the classes are supposed to do.

Edit: As Dunk correctly observed, the actual name in your application should not be UserManager, but something more descriptive of it's actual purpose. Often times you'll find a design pattern for the functionality you are going to use, so the name of the class will be provided by that pattern. This might lead to names such as UserRepository or UserFactory.

Adrian Grigore
Not sure if I'd call it "UserManager" but it makes sense that the code that is creating these users is responsible for killing/maiming them.
Outlaw Programmer
The manager class wouldn't *have* to be a creation factory... If you want to enforce just a single user manager per application (which can be legitimate) then have User have a set of static functions is reasonable too.
Jeff Kotula
<Rant> Please remove the word manager from your vocabulary when talking about class names. The name of the class should be descriptive of its' purpose. Manager is just another word for *dumping ground*. Any functionality will fit there. The word has been the cause of many extremely bad designs
Dunk
Dunk: I agree that usermanager is not very descriptive, but I chose this name because I could not see any design pattern that fits the two functions KillAllUsers and MaimAllUsers (a Repository does not maim...). Perhaps Dewayne needs in fact a factory class, in which case it would be a UserFactory.
Adrian Grigore
+1  A: 

Make an abstraction of the operations you want to perform on your objects, for example by creating an interface. Then you can worry later on how to provide the implementation of the actual logic.

Usually, when dealing with collections of objects of, say, type User, it will not be User itself that will implement it, but another object like UserService for example. If absolutely want it to be available on the class level, you can define a static method that returns the interface type and a default implementation.

eljenso
Not sure where you're going with the part about creating an interface. That's not going to choose between making a static method in User or putting it someplace else.
Outlaw Programmer
The choice is very clear: don't do it using static methods on User. Put is somewhere else. If you do want it on User as some kind of static, it's better to have a static getUserService method on User that returns the interface type and a default implementation.
eljenso
+1 for the best answer that was ignored.
Xaqron