views:

184

answers:

6

Hi guys, a point of architectural style that I'd like your opinion on please:

My ORM has given me a User object which corresponds to a user of my system. I wanted to develop a bunch of methods for handling Users - GetByUsername(), Authenticate(), VerifyLoginPassword() etc. However it feels to me that some of these methods don't really belong to the User class - e.g. GetByUsername() feels like a static method of User at least, but wouldn't it be more "clean" to have another class, say "UserManager" which provides us with these User-management type of tasks? It seems a little strange for a User instance to contain the Authenticate() method, for example, if it's the security system that does the authenticating?

The thing I worry about is that I end up following this model to the point where the User class is no more than a struct, and my User Manager and Security Manager classes actually do all the method work. It doesn't feel very "OO" to have all these manager classes manipulating lightweight objects.

Any thoughts or links to prior art on this philosophical matter would be appreciated!

A: 

The situation you are describing is related to whether objects follow the Self-Servicing or Adapter pattern for saving to a repository (i.e. Database).

Self-servicing would have Objects save 'themselves' as in myObjectInstance.Save(), whereas the Adapter pattern would be myObjectAdapter.Save(myObjectInstance).

The Adapter form is often favoured because it removes any repository functionality from objects.

Mitch Wheat
Why do you call it Adapter? Does it have anything in common with this Adapter pattern?http://en.wikipedia.org/wiki/Adapter_pattern
Pavel Feldman
+3  A: 

Martin Fowler has some useful views on this.

The fundamental choice is between Service Locator and Dependency Injection. The first point is that both implementations provide the fundamental decoupling that's missing in the naive example - in both cases application code is independent of the concrete implementation of the service interface. The important difference between the two patterns is about how that implementation is provided to the application class. With service locator the application class asks for it explicitly by a message to the locator. With injection there is no explicit request, the service appears in the application class - hence the inversion of control.

Inversion of control is a common feature of frameworks, but it's something that comes at a price. It tends to be hard to understand and leads to problems when you are trying to debug. So on the whole I prefer to avoid it unless I need it. This isn't to say it's a bad thing, just that I think it needs to justify itself over the more straightforward alternative.

Rich Seller
+5  A: 

It sounds like you at that point where you are moving beyond defining objects as "a dog is-a animal" and moving into object definitions in terms of roles, responsibilities, and behaviors.

I would recommend this book to help you make that transition and really "get it":

Object Design: Roles, Responsibilities, and Collaboration

I don't have an answer to your specific question because it is such a fundamental design decision that you really should learn about the "bigger picture." This book will give you a good foundation in the principles and techniques of Responsibility-Driven Design.

Enjoy,

Robert C. Cartaino

Robert Cartaino
+1  A: 

You can continue to refactor all the functionality out of your User class, but as you said you may end up with nothing left in it. At this point, you could choose to evaluate all the other classes you have created, and then make an individual judgement on each of these classes, deciding on a case by case basis if these classes contain enough functionality to warrant a whole new class.

If you decide that some of these classes are too small, you can then put their functionality back into the User class. I see nothing wrong with having, for instance, a Validate function on the User, rather than having a UserValidation class with only one method on it.

Patrick McDonald
+3  A: 

It doesn't feel very "OO" to have all these manager classes manipulating lightweight objects.

I don't know if this is very "OO", but to me it feels very MVC and Separations-of-Concerns-like. Having very lightweight business-classes (to the point they are just data containers) and then repository-objects that move them around is a common pattern.

Michael Stum
+1  A: 

I think you are on the money when you say that those methods may not belong on the user object. The Get/Search/Save methods can be debated, but I'm of the opinion that they should not be on the business object themselves and should either be done with a Repository (the repository pattern), or via Query Objects if you do not wish to abstract away your ORM in a repository.

As far as the authentication goes, it would be better to have a set of classes that a responsible for authentication and leave that off the user object altogether. This set of classes could be aware of the user object, or better yet they should be aware of a contract such as a Credential.

Daniel Auger