Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

The task:

There is an AccountManager that makes transfers. It receives 2 arrays of the same size: accounts and sums. They need to be transferred to the accounts correspondingly.

public interface AccountManager {
    public boolean transfer(Account[] accounts, int[] deltas);
}

There is also an Account interface:

public interface Account {
    public void change(int delta) throws TryAgainException, BlockAccountException;
}

If change() throws TryAgainException, we just need to repeat the transfer operation. If change() throws BlockAccountException, we need to roll back the transfer operation. That is, reverse all changes to previous accounts.

AccountClass

public class AccountClass implements Account {

    // setting initial value to 100. so that account would not be empty
    private int accountNum;
    private int currentAccount = 100;

    public AccountClass(int accountNum) {
        this.accountNum = accountNum;
    }

    @Override
    public void change(int delta) throws TryAgainException,
            BlockAccountException {
        System.out.println("account before change" + toString());

        int newBalance = getCurrentAccount() + delta;
        if (newBalance < 0) {
            throw new BlockAccountException(
                    "money cannot be withdrawn as balance will be negative");
        } else if (delta == 100) {
            throw new TryAgainException();
        }
        setCurrentAccount(getCurrentAccount() + delta);

        System.out.println("account after change" + toString());
    }

    public int getCurrentAccount() {
        return currentAccount;
    }

    @Override
    public String toString() {
        return "Account" + accountNum + " [currentAccount=" + currentAccount + "]";
    }

    // making setter private so it will be impossible to modify account from
    // outside
    private void setCurrentAccount(int currentAccount) {
        this.currentAccount = currentAccount;
    }

AccountManagerClass

public class AccountManagerClass implements AccountManager {

    @Override
    public boolean transfer(Account[] accounts, int[] deltas) {
        for (int i = 0; i < accounts.length; i++) {
            int tryNum = 0;
            while (true) {
                try {
                    accounts[i].change(deltas[i]);
                    break;
                } catch (TryAgainException e) {
                    tryNum++;
                    if (tryNum == 5) {
                        break;
                    }
                    System.out.println("trying again");
                } catch (BlockAccountException e) {
                    // rollback
                    System.out.println(e.getMessage());
                    System.out.println("rolling back");
                    if (i > 0) {
                        for (int j = i - 1; j >= 0; j--) {
                            try {
                                accounts[j].change(-deltas[j]);
                            } catch (TryAgainException e1) {
                                // TODO Auto-generated catch block
                                e1.printStackTrace();
                            } catch (BlockAccountException e1) {
                                // TODO Auto-generated catch block
                                e1.printStackTrace();
                            }
                        }
                    }
                    return false;
                }
            }
        }

        return true;
    }

Main

public class Main {

    public static void main(String[] args) {

        AccountManagerClass accountManagerClass = new AccountManagerClass();
        Account[] accounts = {new AccountClass(1), new AccountClass(2), new AccountClass(3), new AccountClass(4)};
        int[] deltas = {100, 200, -200, 99};
        accountManagerClass.transfer(accounts, deltas);
    }

}
share|improve this question
1  
Usually its the responsibility of a database transaction. Can you use database transactions? –  Peter Rader Aug 17 at 14:09
    
Is concurrency a requirement, or just something nice to consider in your codebase? –  h.j.k. Aug 17 at 14:45
    
It's extremely weird to fix a starting account balance to 100, unless this is part of an exercise and indicated as such... we're not in Monopoly here... –  h.j.k. Aug 17 at 14:46
    
sorry, i should've mention, yes it is an exercise not a real case –  rigby Aug 17 at 15:14

1 Answer 1

// making setter private so it will be impossible to modify account from
// outside
private void setCurrentAccount(int currentAccount) {
    this.currentAccount = currentAccount;
}

So, what's the point of this setter at all? :)

share|improve this answer

We're looking for long answers that provide some explanation and context. Don't just give a one-line answer; explain why your answer is right, ideally with citations. Answers that don't include explanations may be removed.

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.