Assume I have the following method that does the same logic but deals with different objects (It's more a pseudocode):
private <E> List<E> updateOrInsert(List<E> list) {
if (list == null && list.size() == 0) {
return list;
}
if (list.get(0) instanceof Explore) {
List<String> numbers = new ArrayList<>();
List<Explore> explorisList = (List<Explore>) list;
explorisList.forEach(item -> {numbers.add(item.getNumber());});
List<Explore> exploreDB = explorisRepository.findAllByNumberIn(numbers);
Map<String, Explore> map = new HashMap<>();
exploreDB.forEach(item -> {
map.put(item.getNumber(), item);
});
explorisList.forEach(item -> {
Explore itemMap = map.get(item.getNumber());
if (itemMap != null) {
item.setId(itemMap.getId());
}
});
return (List<E>) explorisRepository.saveAll(explorisList);
} else if (list.get(0) instanceof Capital) {
List<String> codes = new ArrayList<>();
List<Capital> listOfCompanies = (List<Capital>) list;
listOfCompanies.forEach(item -> codes.add(item.getCode()));
List<Capital> capitalDB = companyRepository.findAllByCodeIn(codes);
Map<String, Capital> map = new HashMap<>();
capitalDB.forEach(item -> {
map.put(item.getCode(), item);
});
((List<Capital>) list).forEach(item -> {
Capital itemMap = map.get(item.getCode());
if (itemMap != null) {
item.setId(itemMap.getId());
}
});
return (List<E>) companyRepository.saveAll(capitalSet);
//if statement continues but you got the picture
} else {
throw new UnsupportedOperationException("Unsupported operation for " + list.getClass().getName());
}
// ... etc.
As you can see each list has the same business logic but it deals with different objects.
Is it better to separate them to different methods? And why?
My argument for such an approach is I assume that a function/method should only represent one piece of logic. So, creating a different functions that do the same logic is a bad design.
What about maintainability?
I also got a comment that I am using Java Generics in a wrong way and I'm dealing with Java as a functional language.
CapitalandExploreshould both implement the sameinterfaceto expose their identity, but they (presumably) don't - e.g.item.getIdentity(). Similarly, it also looks as if you could generalise aninterfaceto your repositories as well. It seems to me as if can solve the problem without a generic method, instead generalise the concept of object identity in your code using interfaces - both on theCapital/Exploreobjects and on the repository methods which beginfindAllBy....