Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

201
Visualizações
In Hexagonal architecture, can a service rely on another service, or is that tight coupling?

I am creating a banking application. Currently, there is one primary service, the transaction service. This service allows getting transactions by id, and creating transactions. In order to create a transaction, I first want to check if the transaction is valid, by checking the balance of the account it is trying to deduct from, and seeing if they have enough balance. Right now I am doing

TransactionController calls TransactionService. TransactionService creates Transaction, then checks if this is a valid transaction. At this point, I have created an AccountsService, that queries the AccountsRepository, returns an Account. I then do the comparison based on Account.balance > Transaction.amount.

I am conscious here that the TransactionService create method is relying on the AccountService get method. Additionally, AccountService is never directly called from a controller.

Is this an ok way to architect, or is there a more elegant way to do this?

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

In your case, I would say it is ok because I guess that if Account.balance < Transaction.amount you don't really want to go forward with the transaction. So you must at some point get the needed data from the AccountService, there is no way around that.

If you just wanted o trigger some side-effect task (like sending an email or something) you could rely on an event-based approach on which TransactionService would publish an event and a hypothetical NotificationsService would react to it at some point in time and do its thing.

over 4 years ago · Santiago Trujillo Relatório

0

Your logic seems fine. If you only need the Account Service from the Transaction service (or another Service), this is valid. No need to call an Account Service from a Controller just to do so if the logic makes no sense. In fact some Services that are invoked from a Controller may call many other services - such as an Email Service, a Text Message Service, and so on.

over 4 years ago · Santiago Trujillo Relatório

0

You can reference your AccountRepository directly in your TransactionService.

Sorry I don't speak Java but here is a C# example :

public class Transaction {
  // implementation redacted

  public Transaction(decimal amount, Account from, Account to) {
    if(amount > from?.Balance) throw ... ;
    // redacted
  }
}
public class TransactionService {
  private readonly AccountRepository accounts; // by injection
  private readonly TransactionRepository transactions; // by injection

  public void AddTransaction(decimal amount, int source, int destination) {
    var from = accounts.Find(source); // throws if not found
    var to = accounts.Find(destination); // throws if not found
    var transaction = new Transaction(amount, from, to);
    transactions.Insert(transaction);
    transactions.Persist();
  }
}

However, this solution is less ORM friendly because of the Transaction constructor. Another way around would be to use Account as your root aggregate, and place the business rule validation and entities relationship handling code there :

public class Account {
  // implementation redacted

  public void AddTransaction(decimal amount, Account to) {
    if(amount > this.Balance) throw ... ;
    // more redacted validations
    this.Debitus.Add(new Transaction { Amount = amount, From = this, To = to });
  }
}
public class TransactionService {
  private readonly AccountRepository accounts; // by injection

  public void AddTransaction(decimal amount, int source, int destination) {
    var from = accounts.Find(source); // throws if not found
    var to = accounts.Find(destination); // throws if not found
    from.AddTransaction(amount, to);
    accounts.Persist();
  }
}
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda