Além da resposta aceita, quero mencionar outro exemplo de uma preocupação transversal: comunicação remota. Digamos que eu apenas queira chamar outros componentes em meu ecossistema localmente como se eles estivessem em execução no processo. Talvez em alguns casos até façam. Mas agora quero executar meus serviços distribuídos em uma nuvem ou cluster. Por que devo me preocupar com esse aspecto como desenvolvedor de aplicativos? Um aspecto poderia cuidar de descobrir para quem ligar e como, serializando os dados transmitidos se necessário e fazendo uma chamada remota. Se tudo estivesse funcionando no processo, o aspecto apenas encaminharia a chamada local. No lado do receptor, o aspecto desserializaria os dados, faria a chamada local e retornaria o resultado.
Agora, deixe-me contar uma pequena história sobre coisas "triviais" como saída de log: apenas algumas semanas atrás, refatorei uma base de código complexa, mas não muito grande (cerca de 250 mil linhas de código) para um cliente. Em algumas centenas de classes, um tipo de estrutura de registro foi usado, em outras centenas de outras. Então, havia vários milhares de linhas deSystem.out.println(*)
onde realmente deveria haver uma saída de log. Portanto, acabei corrigindo milhares de linhas de código espalhadas por toda a base de código. Felizmente, eu poderia usar alguns truques inteligentes no IntelliJ IDEA (pesquisa e substituição estrutural) para acelerar toda a ação, mas cara, você não acha que foi trivial! Claro, o registro de depuração fortemente dependente do contexto sempre ocorrerá dentro de um corpo de método, mas muitos tipos importantes de registro, como chamadas de método de rastreamento (mesmo hierarquicamente com uma saída bem recuada), registro de exceções manipuladas ou não, auditoria de usuário (registro de chamadas para métodos restritos com base em funções de usuário) e assim por diante podem ser facilmente implementados em aspectos sem que poluam o código-fonte. O desenvolvedor de aplicativos do dia a dia não precisa pensar sobre isso ou mesmo ver as chamadas do logger espalhadas pela base de código.
Posso apresentar explicações semelhantes para outras questões transversais. Manter o código limpo e livre de espalhamento e emaranhamento IMO é uma questão de profissionalismo, não algo opcional. Por último, mas não menos importante, ele mantém o código legível, sustentável e refatorável. Amém.