To reduce code duplication between InMemoryOneTimeTokenService and JdbcOneTimeTokenService, need to separate out the shared code in AbstractOneTimeTokenService. This class can be made part of public API so that developers can create their own implementations based on existing logic.

Comment From: jzheaux

Thanks for the suggestion, @franticticktick. I'm not seeing very much in common between these two classes, making me feel that it's too early to do something like this.

What functionality are you hoping to share across implementations?

Comment From: franticticktick

Maybe:

public class AbstractOneTimeTokenService {
    protected Clock clock = Clock.systemUTC();

    protected OneTimeToken generateTone(GenerateOneTimeTokenRequest request){
        String token = UUID.randomUUID().toString();
        Instant fiveMinutesFromNow = this.clock.instant().plus(Duration.ofMinutes(5));
        return new DefaultOneTimeToken(token, request.getUsername(), fiveMinutesFromNow);
    }

    protected boolean isExpired(OneTimeToken ott) {
        return this.clock.instant().isAfter(ott.getExpiresAt());
    }

    public void setClock(Clock clock) {
        Assert.notNull(clock, "clock cannot be null");
        this.clock = clock;
    }
}

Comment From: jzheaux

Gotcha, thanks for the additional detail, @franticticktick.

I feel like it's too early for something like this. I'm generally opposed to abstract classes unless the shared code is quite complex, there are several implementations, or implementation details would otherwise be exposed.

Given that the shared logic is quite simple, that there are only two implementations so far, and that the relationship isn't necessary to maintain encapsulation, I'm going to decline this for the time being.

I'm open to revisiting this down the road as more implementations surface.