Decoupling in Java

Decoupling in Java

Creating and maintaining a Java codebase is not an easy task, especially with a codebase with thousands of tests. We often try to solve this problem with new libraries, frameworks and even new languages that can create a false sense of decoupling and modularity.
But the answer is not in the libraries, nor in the frameworks. The answer is in the core of the Java language itself and it has been there since the early stages.

66059d4f17b6b7a6888d62caa736a663?s=128

Carlos Chacin

October 15, 2020
Tweet

Transcript

  1. Decoupling in Java

  2. None
  3. $ curl http:!//localhost:8080/commits/abcdef HTTP/1.1 200 OK Content-Type: application/json Content-Length: 66

    Commit[ message=Commit from git, filenames=[ filea.txt, fileb.txt, ] ]
  4. $ curl http:!//localhost:8080/commits/abcdef HTTP/1.1 200 OK Content-Type: application/json Content-Length: 66

    Commit[ message=Commit from local, filenames=[ filea.txt, fileb.txt, ] ]
  5. None
  6. @Path("commits") public class CommitsEndpoint { private final CommitsService service; public

    CommitsEndpoint( final CommitsService service) { this.service = service; } @GET @Path("{sha}") @Produces(MediaType.APPLICATION_JSON) public String getCommit( @PathParam("sha") final String sha) { return service.commitBySha(sha).map(Record!::toString).orElse("NO COMMIT"); } }
  7. public record CommitsService( Repository localRepository, Repository githubRepository) { Optional<Commit> commitBySha(

    final String sha) { return localRepository().commitBySha(sha) .or(() !-> githubRepository().commitBySha(sha)); } }
  8. public interface Repository { Optional<Commit> commitBySha(String sha); List<Commit> commitsByRepo(String repository);

    }
  9. public class GithubRepository implements Repository { @Override public Optional<Commit> commitBySha(

    final String sha) { return Optional.of( new Commit( "Commit from git", List.of("filea.txt,", "fileb.txt") ) ); } @Override public List<Commit> commitsByRepo( final String repository) { return List.of( new Commit( "Commit 1 from git", List.of("filea.txt,", "fileb.txt") ), new Commit( "Commit 2 from git", List.of("filec.txt,", "filed.txt") ) ); } }
  10. public class LocalRepository implements Repository { @Override public Optional<Commit> commitBySha(

    final String sha) { if (new Random().nextBoolean()) { return Optional.empty(); } return Optional.of( new Commit( "Commit from local", List.of("filea.txt,", "fileb.txt") ) ); } @Override public List<Commit> commitsByRepo( final String repository) { return List.of( new Commit( "Commit 1 from local", List.of("filea.txt,", "fileb.txt") ), new Commit( "Commit 2 from local", List.of("filec.txt,", "filed.txt") ) ); } }
  11. @Test @DisplayName("Should return from github when local is empty") void

    shouldReturnFromGithubWhenLocalIsEmpty( @Mock final Repository localRepository, @Mock final Repository gitHubRepository) throws Exception { !// Given when(localRepository.commitBySha(anyString())) .thenReturn(Optional.empty()); when(gitHubRepository.commitBySha(anyString())) .thenReturn(Optional.of(new Commit("git", List.of("git.txt")))); !// When final var commit = new CommitsService(localRepository, gitHubRepository).commitBySha("sha"); !// Then assertThat(commit).contains(new Commit("git", List.of("git.txt"))); verify(localRepository, times(1)).commitBySha(anyString()); verify(gitHubRepository, times(1)).commitBySha(anyString()); }
  12. Service LocalRepository GithubRepository

  13. Service LocalRepository GithubRepository Repository

  14. public class GithubRepository implements Repository { @Override public Optional<Commit> commitBySha(

    final String sha) { … } … } public interface Repository { Optional<Commit> commitBySha(String sha); List<Commit> commitsByRepo(String repository); } @Test @DisplayName("Should return from github when local is empty") void shouldReturnFromGithubWhenLocalIsEmpty( @Mock final Repository localRepository, @Mock final Repository gitHubRepository) throws Exception { !// Given when(localRepository.commitBySha(anyString())) .thenReturn(Optional.empty()); when(gitHubRepository.commitBySha(anyString())) .thenReturn(Optional.of(new Commit("git", List.of("git.txt")))); !// When final var commit = new CommitsService(localRepository, gitHubRepository).commitBy !// Then assertThat(commit).contains(new Commit("git", List.of("git.txt"))); verify(localRepository, times(1)).commitBySha(anyString()); verify(gitHubRepository, times(1)).commitBySha(anyString()); } public class LocalRepository implements Repository { @Override public Optional<Commit> commitBySha( final String sha) { … } … } public record CommitsService( Repository localRepository, Repository githubRepository) { Optional<Commit> commitBySha( final String sha) { return localRepository().commitBySha(sha) .or(() !-> githubRepository().commitBySha(sha)); } }
  15. public interface Repository { Optional<Commit> commitBySha(String sha); List<Commit> commitsByRepo(String repository);

    } public class GithubRepository implements Repository { @Override public Optional<Commit> commitBySha( final String sha) { … } … } public class LocalRepository implements Repository { @Override public Optional<Commit> commitBySha( final String sha) { … } … } @Test @DisplayName("Should return from github when local is empty") void shouldReturnFromGithubWhenLocalIsEmpty( @Mock final Repository localRepository, @Mock final Repository gitHubRepository) throws Exception { !// Given when(localRepository.commitBySha(anyString())) .thenReturn(Optional.empty()); when(gitHubRepository.commitBySha(anyString())) .thenReturn(Optional.of(new Commit("git", List.of("git.txt")))); !// When final var commit = new CommitsService(localRepository, gitHubRepository).commitBy !// Then assertThat(commit).contains(new Commit("git", List.of("git.txt"))); verify(localRepository, times(1)).commitBySha(anyString()); verify(gitHubRepository, times(1)).commitBySha(anyString()); } public record CommitsService( Repository localRepository, Repository githubRepository) { Optional<Commit> commitBySha( final String sha) { return localRepository().commitBySha(sha) .or(() !-> githubRepository().commitBySha(sha)); } }
  16. public interface Repository { Optional<Commit> commitBySha(String sha); List<Commit> commitsByRepo(String repository);

    } public class GithubRepository implements Repository { @Override public Optional<Commit> commitBySha( final String sha) { … } … } public class LocalRepository implements Repository { @Override public Optional<Commit> commitBySha( final String sha) { … } … } @Test @DisplayName("Should return from github when local is empty") void shouldReturnFromGithubWhenLocalIsEmpty( @Mock final Repository localRepository, @Mock final Repository gitHubRepository) throws Exception { !// Given when(localRepository.commitBySha(anyString())) .thenReturn(Optional.empty()); when(gitHubRepository.commitBySha(anyString())) .thenReturn(Optional.of(new Commit("git", List.of("git.txt")))); !// When final var commit = new CommitsService(localRepository, gitHubRepository).commitBy !// Then assertThat(commit).contains(new Commit("git", List.of("git.txt"))); verify(localRepository, times(1)).commitBySha(anyString()); verify(gitHubRepository, times(1)).commitBySha(anyString()); } public record CommitsService( Repository localRepository, Repository githubRepository) { Optional<Commit> commitBySha( final String sha) { return localRepository().commitBySha(sha) .or(() !-> githubRepository().commitBySha(sha)); } }