0

I have working code which I am refactoring to make it more readable/follow Java/OOP conventions.

I will share the code and then some of my thoughts:

public class AbstractTaggingService {

@Autowired
private JoinPointTaggingService joinPointTaggingService;

@Autowired
private StackTraceTaggingService stackTraceTaggingService;

@Autowired
private UserTaggingService userTaggingService;

public Iterable<Tag> getTags(ProceedingJoinPoint joinPoint, MetricsContextHolder contextHierarchy, Authentication authentication){
    return Tags.of(
        Iterables.concat(
            joinPointTaggingService.getTags(joinPoint),
            stackTraceTaggingService.getTags(contextHierarchy),
            userTaggingService.getTags(authentication)
        )
    );
}

.

public class JoinPointTaggingService {

public Iterable<Tag> getTags(ProceedingJoinPoint joinPoint) {

    return Tags.of(
        "methodName", joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName(),
        "parameters", parameters.toString()
    );
}

.

public class StackTraceTaggingService {

public Iterable<Tag> getTags(MetricsContextHolder contextHolder) {
    Stack<MetricsContext> contextHierarchy = contextHolder.getStack();
    return Tags.of(
        "trace", contextHierarchy.toString(),
        "parent", getParent(contextHierarchy),
        "children", contextHierarchy.peek().childrenToString(),
        "threadID", contextHolder.getID()
    );
}
}

.

public class UserTaggingServiceImpl implements UserTaggingService {

@Override
public Iterable<Tag> getTags(Authentication authentication) {
    OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication.getDetails();
    return Tags.of(
        "user", getUserName(authentication),
        "auth_session_id", getUserSessionID(details)
    );
}
}

My thought was that these individual tagging services should all be abstractions of some abstract tagging service, where that service will be called and decide the correct service to use based on arg type (overloading).

However, I don't know that this works this way in Java OOP. An Interface method is only overridden if it takes the same arg types, for example.

So here is the question: I have 3 classes which all implement a method getTags which returns Iterable<Tag>. Each takes a different arg type as a parameter and has some behavior to return tags from that object. I don't want to do something ugly like typecasting, etc. What is the correct abstraction? How would you refactor this code?

8t12c7081
  • 683
  • 3
  • 9
  • 30

0 Answers0