Reputation: 4934
Which would be the better way to design an API:
Example A:
public class UserService {
public void addUser(final User user);
public void addUserToIndex(final User user, final int index);
public User lookUpUser(final User user);
public User getUserByIndex(final int index );
public void removeUser(final User user);
public List<User> getAllUsers();
}
Example B:
public class UserService {
public void add(final User user);
public void add(final User user, final int index);
public User lookUp(final User user);
public User get(final int index);
public void remove(final User user);
public List<User> getAll();
}
Obviously this code will not run - it should just show the problem. I like the second approach more. The method name might be a little bit generic but the context (className, parameter, return Type) makes it pretty clear. One problem which the second approach might have is, what happens if I would need another get method with the same Type. For example, if I want to get a User by their age. Thanks in advance for any help.
kuku
Upvotes: 5
Views: 1876
Reputation: 15129
First approach seems cleaner. Gives more information up front. People reading code will instantly know the meaning of the code, which is important while debugging or maintaining someone else's code.
Here are 2 examples that are close to what you're doing from 2 of the best designed frameworks:
JDK7
package java.security.acl
public interface Group extends Principal
{
public boolean addMember(Principal user);
public boolean removeMember(Principal user);
public boolean isMember(Principal member);
public Enumeration<? extends Principal> members();
}
Spring:
public interface GroupManager {
List<String> findAllGroups();
List<String> findUsersInGroup(String groupName);
void createGroup(String groupName, List<GrantedAuthority> authorities);
void deleteGroup(String groupName);
void renameGroup(String oldName, String newName);
void addUserToGroup(String username, String group);
void removeUserFromGroup(String username, String groupName);
List<GrantedAuthority> findGroupAuthorities(String groupName);
void addGroupAuthority(String groupName, GrantedAuthority authority);
void removeGroupAuthority(String groupName, GrantedAuthority authority);
}
As you can see from these interfaces, if I was reading the code, it'd be instantly possible to tell what the code is doing without having to go back and look at the type of the object.
I vote for your Example A. It just makes everybody's lives simpler.
Upvotes: 1
Reputation: 100821
There are two main questions, which you need to answer to make your choice much easier:
Are you absolutely 100% sure that you will never have this service deal with more than one entity?
In other words, can there be a scenario where UserService
will have additional methods such as getRoles()
? If the answer is yes, you're definitely going with option A.
If you're definitely going to have one entity per service, do you even need a per-service interface or would you rather use a common generic one?
So, instead of your option B you can have something like
public class Service<T> {
public void add(final T entity);
public void add(final T entity, final int index);
public T lookUp(final T entity);
public T get(final int index);
public void remove(final T entity);
public List<T> getAll();
}
Concrete services that need more specific functionality can then extend this generic service.
Upvotes: 3
Reputation: 55886
Your problem is 'getting verbose' vs 'getting confused'. As getting verbose makes client to code by guessing the functionality by looking at the method name. However, I prefer the second version, since method signature (and return type) makes it clear what it does. With IDE support and proper comment/document, the 2nd version is more terse and equally handy.
There is no other way to interpret UserService#add(User)
will do anything other than adding user
; same goes for other methods. The code looks small and it's less typing.
Upvotes: 1
Reputation: 347332
Given modern IDEs these days, I agree with Tomasz, that's a rather subjective question.
You have to consider what the code might end up looking like (and possible extenstions to the API).
a.add(b); // :P this would make no sense at all
a.addUser(b) // is at least more descriptive
There is an argument for for and against verbose method names. Personally with the abilities of modern IDEs, I'd say the argument against is slowly losing weight.
Personally, I prefer example A, it's much clearer the intention of what each method is doing
Upvotes: 2