O encapsulamento vazou, o comportamento e estado foram separados.
// Deveria ser:
public Class AlgumLugar{
public void metodo(){
Aluno aluno = new Aluno();
if(aluno.**estaInscritoEmTreinamento**()){
// faz algo
}
}
}
public class RecebeRespostaController {
public void executa(){
Resposta novaResposta = // faz uma lógica para guardar uma resposta;
//pseudocódigo
//rabbitTemplate.send("analisaRespostas", mensagem) -- acoplado
filaProcessamentoResposta.send(mensagem);
}
}
Essa decisão é bem mais de negócio do que de código, o código reflete sua decisão, acoplar com algum vendor em específico não é necessariamente ruim, mas se você está incerto ou possui quase certeza que isso precisará ser trocado em breve, crie interfaces comuns à essas funcionalidades.
public class Treinamento {
public Treinamento (Collection<NovaAtividadeRequest> atividades){
this.atividades = atividades.map (a-> a.toModel(this));
// isso é horrível, uma classe de domínio, o básico do sistema está projetada para observar classes para receber parâmetros da web.
}
@Getter
@Setter
Collection<NovaAtividadeRequest> atividades;
}
Quando a camada mais interna se acopla à camada mais externa, qualquer alteração nessa camada impactará todo o sistema, que tem como fundação a camada interna acoplada.
public interface NovaAtividade{
Atividade toModel(Treinamento treinamento);
}
public class NovaAtividadeRequest implements NovaAtividade{
toModel(Treinamento treinamento){
//
}
}
public class Treinamento {
public Treinamento (Collection<**INovaAtividade**> atividades){
this.atividades = atividades.map (a-> a.toModel(this));
}
}
Assim, passamos a ter uma dependência de uma interface de domínio, bem mais estável.
Se não tiver certezas quanto à libs, pode usar wrappers que utilizam dessa lib
public class AnalisaComplexidadeDeCodigo{
public int analisa(){
new Biblioteca biblioteca = biblioteca();
biblioteca.analisa();
}
}
Classes com campos obrigatórios e construtores públicos sem argumentos com getters/setters são úteis em casos em que a classe é usada como um recipiente de dados simples e é fácil criar a instância da classe com as informações necessárias. Essa abordagem também é útil ao trabalhar com frameworks ou bibliotecas que dependem de reflexão para criar instâncias da classe, como bibliotecas de serialização e deserialização.
Por outro lado, usar construtores com campos obrigatórios e um construtor privado sem argumentos para impor as regras do domínio é uma maneira de garantir que as instâncias da classes estejam sempre em um estado válido e pode tornar mais fácil detectar e prevenir erros em tempo de execução. Essa abordagem também é útil ao trabalhar com Design Orientado ao Domínio (DDD), onde o foco é modelar a lógica de negócios e impor as regras do domínio de problema.