Hexagonal Architecture Java vs Golang

Hexagonal Architecture Java vs Golang

In the modern era, companies and development teams are increasingly focused on applying best practices to build systems with future scalability and adaptability in mind. The goal is to ensure that, when changes are needed—whether it’s swapping out a framework, changing databases, or adapting to new requirements—these modifications can be made with minimal disruption and without extensive rework. To achieve this, various design patterns and architectural approaches can be applied to help mitigate potential challenges and future-proof applications.

Now, we will discuss how to apply hexagonal architecture in both Java and Golang, and explore the differences between them.

Basic structure:

In this section, we can see that most of the folders are practically the same, with the main differences being the file names and the location of the root folder.

Java
Article content
Golang
Article content

Core

We will start since the top to the under. with the creation of service and uses case in the folder core.


Uses Cases:

In this section, we will create a simple interface with one method that returns a String. The main difference lies in the response types defined in each language: in Java, it simply returns a String, whereas in Golang, we can define both a String and an Error response.

ITestUseCase.java
Article content
Java
itestusecase.go
Article content
Golang

Services

In the service folder, there is a significant difference: both implementations will create the GetTest method, but in Golang, we need to include more than just this method. The NewTestService method is used to create a new instance of the service. It's important to remember that in Golang, dependency management must be handled manually.

TestServices.java
Article content
testservice.go

We create some variables to implement the singleton pattern in the NewTestService method, ensuring that no more than one instance is created.

Article content


Infra (infrastructure)

Config

The config folder within the infra (infrastructure) folder plays a crucial role in handling external configurations and setting up the dependencies required for the application to function. In Java, we use annotations like @Bean and @Component to define the creation and management of service class instances. On the other hand, in Golang, we don’t use such annotations and instead manage instance creation manually.

UsesCases.java
Article content
usescases.go
Article content

Primary - Controller

In both Java and Golang, the role of the controller is to handle HTTP requests and direct them to the appropriate services. However, the way controllers are structured and instantiated in each language differs due to the nature of the frameworks and the language paradigms.

TestController.java

In the Java implementation, we use the Spring Boot framework to handle the HTTP requests. The TestController class is annotated with @RestController and @RequestMapping to define it as a controller that listens to HTTP requests at the /test endpoint.

  • Dependency Injection: In Java, dependency injection is handled automatically by Spring Boot through the constructor. The ITestUseCase is injected into the TestController using the constructor, without the need to manually manage its instantiation.
  • Request Handling: The @RequestMapping("/") annotation defines the specific HTTP endpoint, and the GetTest() method returns the result directly as a String.

Article content
testcontroller.go

In the Golang implementation, we use the Gin framework for routing and handling HTTP requests. The TestControlleris structured differently, with manual management of both dependency injection and routing.

  • Manual Singleton Pattern: In Go, we manually manage the creation of the TestController using a singleton pattern. The sync.Once mechanism ensures that only one instance of the controller is created, which is a common pattern in Go to avoid multiple instances of services.
  • Request Handling: Instead of annotations, Gin uses explicit method calls to register routes. The RunController()function registers the /test endpoint with the r.GET() method, and the response is returned as JSON using the c.JSON() function.

Article content

Key Differences:

  • Dependency Injection: In Java, Spring Boot handles dependency injection automatically with annotations. In Go, we manually manage dependency injection and instance creation using the singleton pattern.
  • Routing: Java uses annotations like @RequestMapping to define routes, while Golang uses explicit function calls (r.GET()) to register routes.
  • Response Handling: Java directly returns the String response from the controller method, while in Golang, the response is manually formatted as JSON and sent using Gin's context (c.JSON()).


Let me list some advantages of the hexagonal architecture:

  • Decoupling of Business Logic and Infrastructure
  • Improved Testability
  • Flexibility and Adaptability
  • Easier Maintenance
  • Supports Multiple Interfaces

Links:

To view or add a comment, sign in

More articles by Wilson Jesus Sayago Lugo

Insights from the community

Others also viewed

Explore topics