11

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?

4
  • Where does this code live? Is it a service? Does it access a data store? It is the UI for doing this friend-y stuff?
    – Telastyn
    Commented Jun 26, 2015 at 13:24
  • 3
    Once you got rid of all the static methods and found a real home in your OOP design, these classes are really not helper classes, so feel free to rename. There's nothing wrong with a FriendshipManager if you need to manage friendships in your project.
    – JeffO
    Commented Jun 26, 2015 at 13:35
  • What's wrong with Facebook? Commented Jun 27, 2015 at 11:06
  • Possible duplicate of Which is a better practice - helper methods as instance or static?
    – gnat
    Commented Aug 29, 2016 at 16:09

2 Answers 2

13

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.

2
  • 8
    Great explanation, but you've clearly never met my mother. :'(
    – Matt
    Commented May 8, 2017 at 16:50
  • 3
    @HEATH3N I hope, that does not influence your software modeling capabilities. Commented May 9, 2017 at 10:15
3

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)

4
  • 10
    Changing 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. Commented 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
    Commented Jun 26, 2015 at 14:45
  • 1
    Agreed. 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. Commented Jun 26, 2015 at 15:56
  • 1
    When 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. Commented Dec 29, 2019 at 4:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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