GLO-4002 - Site du cours 2023

Temps estimé: 1h15

Exercice sur le TDA

Depuis maintenant quelques années, jouer à la bourse est de plus en plus populaire. Et les opportunités de se faire beaucoup d'argent à développer un produit pour faciliter l'achat et la vente d'actions ne manquent pas! Vous décidez donc de tenter votre chance en codant votre propre application.

Pour développer plus vite votre produit, vous choisissez de réutiliser une petite librairie d'un projet open source (voir fichiers ci-dessous).

Cette librairie est très minimaliste. Elle permet simplement à un Broker (courtier en bourse) d'acheter ou vendre des actions pour ses clients. Toutefois, pour se protéger et protéger ses clients, ce courtier empêche d'acheter des actions à crédit et de vendre à perte (en considérant la petite cote qu'il se prend à chaque transaction 😉).

Comme vous aimez jouer risqué, vous voulez rendre cette librairie plus riche en fonctionnalités en acceptant, par exemple, que certains clients puissent vendre à perte.

Malheureusement, en ouvrant le code de la librairie, vous réalisez que le code ne respecte pas un grand nombre de bonnes pratiques de développement logiciel, en particulier le Tell Don't Ask (TDA).

Pour cet exercice, votre mission est donc de régler ces problèmes de TDA pour rendre plus facile à ajouter des fonctionnalités à cette librairie.

Si durant votre refactoring vous arrivez à une solution qui, par exemple pour la méthode Broker.buyStock, ressemble à ceci:

// ...

if (!wallet.hasEnoughFunds(amount)) {
  throw new RuntimeError("Not enough funds");
} else {
  wallet.withdraw(amount);
  wallet.addStock(stock, quantity);
}

// ...

Sachez qu'il s'agit malheureusement encore d'une violation du TDA. Revoyez bien la définition du TDA et essayez de mieux corriger le problème.


public class Wallet {

    private final Map<String, Integer> stocks;
    private double balance;

    public Wallet(Map<String, Integer> stocks, double balance) {
        this.stocks = stocks;
        this.balance = balance;
    }

    public Integer getStockQuantity(Stock stock) {
        return this.stocks.get(stock.getSymbol());
    }

    public void addStock(Stock stock, Integer quantity) {
        this.stocks.merge(stock.getSymbol(), quantity, Integer::sum);
    }

    public void removeStock(Stock stock, Integer quantity) {
        this.stocks.put(stock.getSymbol(), this.getStockQuantity(stock) - quantity);
    }

    public double getBalance() {
        return this.balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }
}
public class Stock {

    private final String symbol;
    private final double currentPrice;

    public Stock(String symbol, double currentPrice) {
        this.symbol = symbol;
        this.currentPrice = currentPrice;
    }

    public String getSymbol() {
        return this.symbol;
    }

    public double getCurrentPrice() {
        return this.currentPrice;
    }
}
public class Broker {

    private static final double SMALL_FEES = 0.05;
    private static final double BIG_FEES = 0.15;

    private final Map<String, Wallet> wallets;

    public Broker(Map<String, Wallet> wallets) {
        this.wallets = wallets;
    }

    public void buyStock(String customerNo, Stock stock, Integer quantity) {
        Wallet wallet = wallets.get(customerNo);

        double fees;
        if (quantity < 100) {
            fees = BIG_FEES * quantity;
        } else {
            fees = SMALL_FEES * quantity;
        }

        double amount = stock.getCurrentPrice() * quantity + fees;

        if (amount > wallet.getBalance()) {
            throw new RuntimeException("Not enough funds");
        } else {
            wallet.setBalance(wallet.getBalance() - amount);
            wallet.addStock(stock, quantity);
        }
    }

    public void sellStock(String customerNo, Stock stock, int quantity) {
        Wallet wallet = wallets.get(customerNo);

        double fees;
        if (quantity < 100) {
            fees = BIG_FEES * quantity;
        } else {
            fees = SMALL_FEES * quantity;
        }

        double amount = stock.getCurrentPrice() * quantity - fees;

        if (amount < 0 && Math.abs(amount) > wallet.getBalance()) {
            throw new RuntimeException("Not enough funds");
        } else if (quantity > wallet.getStockQuantity(stock)) {
            throw new RuntimeException("Not enough stocks");
        } else {
            wallet.setBalance(wallet.getBalance() + amount);
            wallet.removeStock(stock, quantity);
        }
    }
}

Vérifiez votre solution avec un ou une assistant(e) lors du prochain TD 😉