DEV Community

Vitor Rios
Vitor Rios

Posted on

Arquitetura Hexagonal: Exemplo com JS/TS

A Arquitetura Hexagonal, também conhecida como Ports and Adapters, é um modelo arquitetural criado por Alistair Cockburn para tornar aplicações mais modulares, flexíveis e testáveis. Essa abordagem separa a lógica de negócio das dependências externas, como bancos de dados, APIs e interfaces gráficas, garantindo um sistema desacoplado e de fácil manutenção.

🔄 O Conceito da Arquitetura Hexagonal

A ideia principal da Arquitetura Hexagonal é criar um núcleo independente que contenha as regras de negócio da aplicação, se comunicando com o mundo externo através de ports (portas) e adapters (adaptadores). Isso permite que diferentes tecnologias possam ser conectadas sem impactar diretamente no core da aplicação.

A representação visual da arquitetura é um hexágono, mas essa forma é apenas uma ilustração do conceito de múltiplas entradas e saídas.

Estrutura da Arquitetura Hexagonal

  1. Core (Núcleo da Aplicação): Contém as regras de negócio e não deve depender de frameworks ou tecnologias específicas.
  2. Ports (Portas): Interfaces que definem os pontos de interação da aplicação com o mundo externo.
  3. Adapters (Adaptadores): Implementações concretas das portas, conectando a aplicação a bancos de dados, APIs externas, interfaces de usuário, entre outros.

Essa separação permite que mudanças no banco de dados, por exemplo, sejam feitas sem impactar o core da aplicação.

🛠️ Implementando uma Arquitetura Hexagonal em TypeScript

Vamos construir um sistema de cadastro de usuários seguindo a Arquitetura Hexagonal.

1. Criando a Port (Interface)

Começamos definindo uma interface que representa um repositório de usuários:

interface UserRepository {
  create(user: User): Promise<User>;
  findByEmail(email: string): Promise<User | null>;
}
Enter fullscreen mode Exit fullscreen mode

Essa interface define o contrato que qualquer repositório de usuários deve seguir, independentemente da tecnologia utilizada.

2. Criando o Core (Serviço de Negócio)

Agora, criamos um serviço que usa a interface UserRepository para gerenciar usuários:

class UserService {
  constructor(private userRepository: UserRepository) {}

  async registerUser(email: string, name: string) {
    const existingUser = await this.userRepository.findByEmail(email);
    if (existingUser) throw new Error('User already exists');

    const newUser = { email, name };
    return this.userRepository.create(newUser);
  }
}
Enter fullscreen mode Exit fullscreen mode

Aqui, o UserService não sabe se os dados serão armazenados em um banco relacional, NoSQL ou mesmo em um arquivo. Ele apenas interage com UserRepository.

3. Criando um Adapter (Implementação do Repositório para MongoDB)

Criamos um adaptador para o MongoDB, implementando a interface UserRepository:

class MongoUserRepository implements UserRepository {
  async create(user: User): Promise<User> {
    return await MongoDB.collection('users').insertOne(user);
  }

  async findByEmail(email: string): Promise<User | null> {
    return await MongoDB.collection('users').findOne({ email });
  }
}
Enter fullscreen mode Exit fullscreen mode

Essa implementação pode ser substituída por outra (como um banco SQL) sem alterar o UserService.

4. Conectando Tudo na Aplicação

Criamos uma API Express para interagir com o UserService:

const userRepository = new MongoUserRepository();
const userService = new UserService(userRepository);

app.post('/register', async (req, res) => {
  try {
    const user = await userService.registerUser(req.body.email, req.body.name);
    res.status(201).json(user);
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});
Enter fullscreen mode Exit fullscreen mode

Agora, nossa aplicação segue a Arquitetura Hexagonal, permitindo trocar de banco de dados facilmente, sem alterar a lógica de negócio.

✨ Benefícios da Arquitetura Hexagonal

🔄 Baixo acoplamento: O core da aplicação não depende de tecnologias específicas.

🔧 Fácil manutenção: Permite trocar partes da aplicação (como o banco de dados) sem alterar o core.

🔍 Maior testabilidade: Podemos testar a lógica de negócio isoladamente, substituindo adaptadores por mocks.

🚀 Flexibilidade: A mesma lógica de negócio pode ser utilizada em diferentes interfaces (API REST, CLI, UI, etc.).

💪 Conclusão

A Arquitetura Hexagonal é uma excelente abordagem para tornar aplicações mais modulares, organizadas e testáveis. Ela facilita a evolução do software, permitindo a troca de componentes sem impactar a lógica de negócio.

Se você trabalha com aplicações escaláveis e deseja evitar o alto acoplamento, considerar a Arquitetura Hexagonal pode ser um excelente caminho!

O que achou desse modelo arquitetural? Pretende utilizá-lo nos seus projetos? Deixe seu comentário! 🚀

Top comments (0)