I have quite a few Helper classes in my project. I have read that this is a bad thing, but I suspect that "Helper" is the wrong suffix for them. I'll give an example.
First, I have a User
class. I need a method GetSuggestedFriends()
for a user. I want to keep the logic for determining the list of suggested friends out of the User
class, so it doesn't get bloated. Right now, I have a FriendshipHelper
which receives a User
in its constructor. It contains the logic for getting suggested friends, and I can now call myUser.FriendshipHelper.GetSuggestedFriends()
.
Originally FriendshipHelper
had static methods only, and a User
object was passed into each one. If I was writing the class from scratch now, maybe I'd call it FriendshipManager
- it also does things like adding and removing friends.
I've also read that ...Manager
classes are bad, though. What should I call this class? Or, is this "bad code"? Where should the logic for getting suggested friends, current friends, and adding and removing friends live? Surely not all in a giant User
class?
2 Answers 2
How to avoid ...Helper or ...Manager classes«
In general: by good Design
First, I have a User class. I need a method GetSuggestedFriends() for a user.
Yes. A user
has a relationship to other users
. And the relationship could be expressed as a method on user
, e.g. user.isFriend(user2)
.
This is the responsibility of the user
-object.
Besides that, you ask another object for help finding other friends.
You delegate the responsibility for finding friends to another object and that's quite fine.
Right now, I have a FriendshipHelper which receives a User in its constructor. It contains the logic for getting suggested friends, and I can now call myUser.FriendshipHelper.GetSuggestedFriends()
That is not per se bad, but has one downside: initializing the "Helper" with one user
limits the possibilities to that one user
.
What you need is an object, which helps finding friends to any user. So a generic method would make sense: userMatcher.findFriendsFor(user)
which in return delivers a collection of possible friends (user
).
If I was writing the class from scratch now, maybe I'd call it FriendshipManager
Your problem is not writing "helper classes", it is finding the right names. ;)
it also does things like adding and removing friends.
That is a wrong design. Take yourself for example: Does your mommy add friends to your life or do you add them by yourself?
Of course the collection of friends is a property of user
itself and so is the method user.addFriend(user)
or user.removeFriend(user)
What should I call this class?
As said before: you only have a naming issue and your "helpers" are okay. But you have to think more carefully about the responsibilities of each object.
Where should the logic for getting suggested friends, current friends, and adding and removing friends live? Surely not all in a giant User class
No. These are two jobs for which you need one separate object, like in real life where you have people and a dating agency.
-
8Great explanation, but you've clearly never met my mother. :'(Matt– Matt05/08/2017 16:50:00Commented May 8, 2017 at 16:50
-
3@HEATH3N I hope, that does not influence your software modeling capabilities.Thomas Junk– Thomas Junk05/09/2017 10:15:22Commented May 9, 2017 at 10:15
I would suggest that you have a FriendshipService
class that has a (non-static) GetSuggestedFriends(User)
method. Avoid static methods since you cannot implement an interface which makes it more difficult to test. Avoid adding the user object to the constructor since you might want to extend your FriendshipService with methods not specifically related to a single user. (For example, you might want to suggest friends to a set of users, or suggest friends based on something else)
A user should most likely not be aware of the FriendshipService
(due to the Single Responsibility Pattern)
-
10Changing the suffix from "Helper" to "Service" doesn't make it any easier to get an idea of the class's responsibility by its name, which I think is the heart of the question.Mike Partridge– Mike Partridge06/26/2015 14:38:57Commented Jun 26, 2015 at 14:38
-
Well, the name itself may not say that much, but I would say that using the suffix "Service" is a more standardized way of communicating that the class performs some sort of advanced logic. "Helper" classes are (at least to my experience) usually more related to very simple tasks, such as simple formatting and small static methods. I would expect that you could replace a "Service"-interface with different implementations. Futhermore, there are a lot of questions here, not only the naming.Bjorn– Bjorn06/26/2015 14:45:13Commented Jun 26, 2015 at 14:45
-
1Agreed. All three of "Helper", "Manager", and "Service" are ways that we group methods to avoid tons of super-specific classes with a single method, but "Service" has a little more meaning, as you described. I would add that it implies that the class is part of the service layer interface, helping to simplify access to the business logic (which may be made up of many more specific classes) for a given domain class. Whether the suggestion logic should be in a separate class from the add/remove logic depends on how complex the suggestion logic implementation is.Mike Partridge– Mike Partridge06/26/2015 15:56:59Commented Jun 26, 2015 at 15:56
-
1When we name classes ThingManager or ThingService we open the door to creating classes that grow out of control. Because the name doesn't clearly indicate anything specific that belongs in the class, it doesn't exclude anything either. I need a new method that deals with Thing. Where does it go? Idk, put it in ThingManager with all the other methods.Scott Hannen– Scott Hannen12/29/2019 04:16:41Commented Dec 29, 2019 at 4:16
Facebook
?