If you don't understand the Java hexagonal architecture, come here!

Overview

Hexagonal architecture is a software architecture that enables applications to be equally driven by users, programs, automated tests, or batch scripts, and can be developed independently of its runtime target system. The goal is to create an application that can run without a user interface or database so that we can run automatic regression tests on the application, use the application when the runtime system (such as a database) is not available, or integrate without a user interface application.

motivation

Many applications have two purposes: user side and server side, and are usually designed with a two-tier, three-tier or n-tier architecture. The main problem of the n-tier architecture is that the layer lines are not taken seriously, which leads to application logic leaking across the boundary. This entanglement between business logic and interaction makes it impossible or difficult to extend or maintain an application.

For example, when the application business logic is not completely isolated within its own boundaries, adding new attractive UIs to support new devices can be a daunting task. In addition, an application can have more than two aspects, which makes it difficult to better adapt to a one-dimensional layer architecture.

The hexagonal or port and adapter or onion structure solves these problems. In this architecture, internal applications communicate with external systems through a certain number of ports. Here, the term "hexagonal" is not important in itself, but indicates the effect of inserting ports and adapters in a uniform and symmetrical manner in the application. The main idea is to isolate the application domain by using ports and adapters.

Organize code around ports and adapters

Let's build a small anagram application to show how to organize code around ports and adapters to represent the interaction between the inside and outside of the application. On the left side, we have an application, such as a console or REST, and inside is the core business logic or domain. The anagram service takes two strings and returns a Boolean value corresponding to whether the two String parameters are letters of each other. On the right, we have server-side or infrastructure, for example, a database for recording metrics about service usage.

The following Anagram application source code shows how to isolate the core domain internally and how to provide ports and adapters to interact with it.

Domain layer

The domain layer represents the inside of the application and provides a port for interaction with application use cases.

  • The IAnagramServicePort interface defines a method that accepts two String characters and returns a Boolean value.
  • AnagramService implements the INagramServicePort interface and provides business logic to determine whether the two String parameters are anagrams. It also uses INagramMetricPort to output service usage metrics to external entities (such as databases) at server-side runtime.

Application layer

The application layer provides different adapters for external entities to interact with the domain. Interaction dependencies go inside.

  • ConsoleAnagramAdaptor uses IanagramServicePort to interact with domains within the application.

  • AnagramsController also uses IAnagramServicePort to interact with the domain. Similarly, we can write more adapters to allow various external entities to interact with the application domain.

Infrastructure layer

Provide adapters and server-side logic to interact with the application from the right. Server-side entities (such as databases or other runtime devices) use these adapters to interact with the domain. Note that the interaction dependencies are located internally.

Interaction between external entities and applications

The following two external entities use adapters to interact with the application domain. As we have seen, application domains are completely isolated and driven equally by them, regardless of external technology.

This is a simple console application that uses an adapter to interact with the application domain:

@Configuration

public class AnagramConsoleApplication {
    
    

@Autowired

private ConsoleAnagramAdapter anagramAdapter;
public static void main(String[] args) {
    
    
Scanner scanner = new Scanner([http://System.in](https://link.zhihu.com/?target=http%3A//System.in));
String word1 = scanner.next();
String word2 = scanner.next();
boolean isAnagram = anagramAdapter.isAnagram(word1, word2);
if (isAnagram) {
    
    
System.out.println("Words are anagram.");
} else {
    
    
System.out.println("Words are not anagram.");
}
}
}

This is an example of a simple test script that uses a REST adapter to simulate user interaction with the application domain.

@SpringBootTest

@AutoConfigureMockMvc

public class AnagramsControllerTest {
    
    

private static final String URL_PREFIX = "/anagrams/";

@Autowired

private MockMvc mockMvc;

@Test

public void whenWordsAreAnagrams_thenIsOK() throws Exception {
    
    

String url = URL_PREFIX + "/Hello/hello";

this.mockMvc.perform(get(url)).andDo(print()).andExpect(status().isOk())

.andExpect(content().string(containsString("{\"areAnagrams\":true}")));

}

@Test

public void whenWordsAreNotAnagrams_thenIsOK() throws Exception {
    
    

19

String url = URL_PREFIX + "/HelloDAD/HelloMOM";

this.mockMvc.perform(get(url)).andDo(print()).andExpect(status().isOk())

.andExpect(content().string(containsString("{\"areAnagrams\":false}")));

}

@Test


public void whenFirstPathVariableConstraintViolation_thenBadRequest() throws Exception {
    
    

String url = URL_PREFIX + "/11/string";

this.mockMvc.perform(get(url)).andDo(print()).andExpect(status().isBadRequest()).andExpect(

content().string(containsString("string1")));

}

@Test

public void whenSecondPathVariableConstraintViolation_thenBadRequest() throws Exception {
    
    

String url = URL_PREFIX + "/string/11";
this.mockMvc.perform(get(url)).andDo(print()).andExpect(status().isBadRequest()).andExpect(
content().string(containsString("string2")));
}
}

in conclusion

Using ports and adapters, the application domain is isolated at the internal hexagon, and regardless of the external system or technology, it can also be driven by users or automated test scripts.

Click me more-"" "" "

Guess you like

Origin blog.csdn.net/Java_Yhua/article/details/110727797