Anteckningar fr�n f�rel�sning 9

Detta �r den programkod vi skrev -- anteckningarna �r gjorda bara f�r att vara ett st�d f�r minnet f�r dem som var d�r, och d�rf�r inte n�dv�ndigtvis fullst�ndiga eller ens sammanh�ngande. Betydligt mer hj�lp finns att h�mta i kompendiet.

OH-bilder finns h�r.

Vi b�rjade med att titta lite p� den konto-klass som vi skrev f�rra g�ngen, denna g�ng l�t vi n�gra av metoderna returnera v�rden:

class Account {

    private double balance = 10;    // attribut
    private int accountNumber;

    public Account  (int accountNumber) {     // konstruktor
        // k�rs n�r kontot skapas
        balance = 0;
        this.accountNumber = accountNumber;
    }

    public int getAccountNumber() {
        return accountNumber;
    }

    public double deposit(double amount) {   // metod
        if (amount >= 0) {
            balance += amount;
            return amount;
        }
        return 0;
    }

    public double withdraw(double amount) {
        if (amount < 0) {
            return 0;
        }
        if (amount > balance) {
            amount = balance;
        }
        balance -= amount;
        return amount;
    }

    public double getBalance() {
        return balance;
    }
}

Jag f�rs�kte f�rklara vad som egentligen h�nder n�r vi skapar ett konto, och ritade (ungef�r) f�ljande figur:

D�refter b�rjade vi skissa p� en Bank-klass, och kom f�rst fram till att vi ville anv�nda en lista med konton i den:

class Bank {

    private List<Account> accounts = new ArrayList<Account>();

    public Bank  () {    // egentligen on�dig
    }
}

Vi ritade en figur som visar en bank med n�gra konton (det �r ungef�r denna slags figur ni skall rita i inl�mningsuppgift 3):

Jag visade sedan en klass som testar Account-klassen och en Bank-klass -- test-klassen finns l�ngst ner p� denna sida. Vi skrev sedan klassen Bank s� h�r (i olika steg):

class Bank {

    private List accounts = new ArrayList();
    private double noAmount = Double.NEGATIVE_INFINITY;

    public boolean createAccount(int accNo) {
        if (this.hasAccount(accNo)) {
            return false;
        }
        accounts.add(new Account(accNo));
        return true;
    }

    public boolean hasAccount(int accNo) {
        if (getAccount(accNo) != null) {
            return true;
        }
        return false;
    }

    public double deposit(int accNo, double amount) {
        if (!hasAccount(accNo)) {
            return 0;
        }
        Account acc = getAccount(accNo);
        return acc.deposit(amount);
    }

    private Account getAccount(int accNo) {
        for (Account acc : accounts) {
            if (acc.getAccountNumber() == accNo) {
                return acc;
            }
        }
        return null;
    }

    public double getBalance(int accNo) {
        if (!hasAccount(accNo)) {
            return noAmount;
        }
        return getAccount(accNo).getBalance();
    }

    public double withdraw(int accNo, double amount) {
        Account acc = getAccount(accNo);
        if (acc == null) {
            return noAmount;
        }
        return acc.withdraw(amount);
    }
}

Vi kan testa v�rt program genom att k�ra bank-programmet ovan, mata in v�rden och se att vi f�r r�tt resultat. Men en b�ttre l�sning �r att anv�nda test-programmet:

class BankTesting {

    public static void main(String[] args) {
        new BankTesting().run();
    }

    void run() {
        try {
            header("Testar klassen Account");
            testAccount();
            header("Testar klassen Bank");
            testBank();
        } catch (Exception e) {
            System.out.println("Testerna avbr�ts...: " + e.toString());
        }
    }

    void header(String text) {
        System.out.println();
        System.out.println("==== " + text + " ====");
        System.out.println();
    }

    void test(boolean condition, String message) {
        System.out.println((condition ? " OK" : "FEL") + ": " + message);
        if (!condition) {
            throw new RuntimeException();
        }
    }

    boolean equals(double x, double y) {
        return Math.abs(x - y) < 0.001;
    }

    void testAccount() {
        Account acc1 = new Account(1010);
        Account acc2 = new Account(1020);
        test(acc1.getAccountNumber() == 1010, "Kontonummer");
        test(acc2.getAccountNumber() == 1020, "Kontonummer");
        test(equals(acc1.getBalance(), 0), "Startsaldo");
        test(equals(acc2.getBalance(), 0), "Startsaldo");
        test(equals(acc1.deposit(-100), 0), "Felaktig ins�ttning");
        test(equals(acc1.getBalance(), 0), "Saldo efter otill�ten ins�ttning");
        test(equals(acc1.deposit(100), 100), "Ins�ttning p� tomt konto");
        test(equals(acc1.getBalance(), 100), "Ins�ttning och saldo p� tomt konto");
        test(equals(acc1.deposit(50), 50), "Vanlig ins�ttning");
        test(equals(acc1.getBalance(), 150), "Vanlig ins�ttning och saldo");
        test(equals(acc2.getBalance(), 0), "Saldo p� tomt konto efter ins�ttning p� annat konto");
        test(equals(acc1.withdraw(100), 100), "Vanligt uttag");
        test(equals(acc1.getBalance(), 50), "Vanligt uttag och saldo");
        test(equals(acc1.withdraw(200), 50), "�vertrassering");
        test(equals(acc1.getBalance(), 0), "Saldo efter �vertrassering");
        test(equals(acc1.deposit(50), 50), "Vanlig ins�ttning efter �vertrassering");
        test(equals(acc1.getBalance(), 50), "Saldo efter �vertrassering");
    }

    void testBank() {
        Bank bank1 = new Bank();
        Bank bank2 = new Bank();
        test(!bank1.hasAccount(1010), "Hittar inte konto som inte finns");
        test(bank1.createAccount(1010), "Kan skapa konto med nytt kontonummer");
        test(bank1.createAccount(1020), "Kan skapa konto med nytt kontonummer");
        test(!bank1.createAccount(1010), "Kan inte skapa konto med gammalt kontonummer");
        test(!bank1.createAccount(1020), "Kan inte skapa konto med gammalt kontonummer");

        test(!bank2.hasAccount(1010), "Hittar inte konto som inte finns (ny bank)");
        test(bank2.createAccount(1010), "Kan skapa konto med nytt kontonummer (ny bank)");
        test(bank2.createAccount(1020), "Kan skapa konto med nytt kontonummer (ny bank)");
        test(!bank2.createAccount(1010), "Kan inte skapa konto med gammalt kontonummer (ny bank)");
        test(!bank2.createAccount(1020), "Kan inte skapa konto med gammalt kontonummer (ny bank)");

        test(equals(bank1.deposit(1010, -100), 0), "Felaktig ins�ttning p� tomt konto");
        test(equals(bank1.getBalance(1010), 0), "Saldo efter felaktig ins�ttning p� tomt konto");

        test(equals(bank1.deposit(1010, 100), 100), "Korrekt ins�ttning p� tomt konto");
        test(equals(bank1.getBalance(1010), 100), "Saldo efter ins�ttning p� tomt konto");

        test(equals(bank1.deposit(1010, 350), 350), "Korrekt ins�ttning p� konto med pengar");
        test(equals(bank1.getBalance(1010), 450), "Saldo efter ins�ttning p� konto med pengar");

        test(equals(bank1.deposit(1010, -100), 0), "Felaktig ins�ttning p� konto med pengar");
        test(equals(bank1.getBalance(1010), 450), "Saldo efter felaktig ins�ttning p� konto med pengar");

        test(equals(bank1.withdraw(1010, 350), 350), "Korrekt uttag p� konto med pengar");
        test(equals(bank1.getBalance(1010), 100), "Saldo efter uttag p� konto med pengar");

        test(bank1.withdraw(1050, 100) < 0, "Inget uttag fr�n konto som inte finns");

    }
}

N�r vi nu k�rde programmet gick samtliga tester igenom. Detta s�tt att programmera -- dvs att f�rst skriva ett test-program och sedan skriva det egentliga programmet -- kallas ibland test driven design. N�r vi skriver test-programmet uppt�cker vi hur vi vill kunna anropa de ing�ende klasserna, och det hj�lper oss att designa dem b�ttre. Dessutom f�r vi ett s�tt att automatiskt kontrollera att v�rt program hela tiden fungerar (�ven om vi skulle g�ra �ndringar i det).

Om det �r n�got du undrar �ver s� �r du hj�rtligt v�lkommen till tisdagens extragenomg�ng (se schemat p� kurshemsidan).