Search code examples
javaspringarchitectureaopsoftware-design

What is a class good for if it only delegates and does nothing else?


The examples here are taken from the book: Professional Java Development with the Spring Framework.

In the AOP chapter, we a AccountManager implementation is given as an example:

public class AccountManagerImpl implements AccountManager {
    private MailSender mailSender;
    private SimpleMailMessage message;
    private AccountDao accountDao;

    public void setMailSender(MailSender mailSender) {
        this.mailSender = mailSender;
    }

    public void setMessage(SimpleMailMessage message) {
        this.message = message;
    }

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    private void sendMail(Exception ex) {
        SimpleMailMessage msg = new SimpleMailMessage(this.message);
        msg.setText("Encountered exception " + ex.getMessage());
        this.mailSender.send(msg);
    }

    public Account getAccount(String accountId) throws AccountNotFoundException, DataAccessException {
        try {
            return this.accountDao.findAccount(accountId);
        } catch (AccountNotFoundException ex) {
            sendMail(ex);
            throw ex;
        } catch (DataAccessException ex) {
            sendMail(ex);
            throw ex;
        }
    }

    public void createAccount(Account account) throws DataAccessException, {
        try {
            if (isInvalid(account)) {
                throw new InvalidAccountException(account);
                this.accountDao.saveAccount(account);
            } catch(IOException ex){
                sendMail(ex);
                throw ex;
            } catch(DataAccessException ex){
                sendMail(ex);
                throw ex;
            }
        }
    }
}

and then all the advantages of the Aspect Oriented Programming is explained, some configuration is made to move the sendMail(ex)to an Aspect, and we end up with:

public class AccountManagerImpl implements AccountManager {
    private AccountDao accountDao;

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    public Account getAccount(String accountId)
            throws AccountNotFoundException, DataAccessException {
        return this.accountDao.findAccount(accountId);
    }

    public void createAccount(Account account) throws DataAccessException {
        this.accountDao.saveAccount(account);
    }
}

Quoting from the book itself:

The result is a major improvement. The AccountManager is purely responsible for account management, making the code much simpler and easier to read and maintain. The exception notification mechanism is cleanly modularized so that it can be maintained separately from business logic. For example, one developer can now revise the exception notification policy without the need to modify large numbers of files that would be affected in the traditional approach.

To me, it looks like the AccountManagerImpl was actually a Manager before, and the second example is just a disaster.

As seen in the 2nd version of the implementation, the Manager class is not doing at all but delegating everything to one AccountDao.

My concrete question is: Why have this implementation (the 2nd version) at all? We can apply the Aspect to AccountDao too, no?


Solution

  • I agree that the core functionality of the manager does not look convincing after the refactoring. But the reason for that might simply be that the authors didn't spend too much time on looking for better examples.

    The main point of aspects is: to extract cross cutting functionality that can be found in different classes. In other words: you find that one or more classes spend code doing something that doesn't really fit the core responsibility of each class. You then abstract this "non core functionality" as aspect - allowing you to turn to AOP tooling. So that you can unclutter your core business logic by having the tool move the corresponding code into aspects.