エンジニアのソフトウェア的愛情

または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか

Roleについて考える

今朝の書き込みのあと、半日ほど経過して、頭の中が整理されてきて、あらためてコードを書き直してみた。


コードを書き直して気がついたのが、以前書いたByte ReaderByte WriterってRoleに該当するのかもしれない、ということ。

手前味噌で恐縮ですけど…そんなにずれてない気がする。
もっと考えてみる。
つづく。


以下コード。

#include <iostream>
#include <sstream>
#include <string>
#include <typeinfo>

class Context;

struct Account
{
    std::string     accountNumber;
    int             balance;

    Account(const std::string& accountNumber) : accountNumber(accountNumber), 
                                                balance(10000) {}
};

class Context
{
public:
    virtual ~Context() {}
    virtual void show(const std::string& s) = 0;
};

class TargetAccount
{
public:
    TargetAccount(Account& account, Context& context) : account_(account), context_(context) {}

    void deposit(int amount)
    {
        account_.balance += amount;
    }

private:
    Account& account_;
    Context& context_;
};

class SourceAccount
{
public:
    SourceAccount(Account& account, Context& context) : account_(account), context_(context) {}

    void transferTo(TargetAccount& target, int amount)
    {
        withdraw(amount);
        target.deposit(amount);
    }

    void withdraw(int amount)
    {
        account_.balance -= amount;
    }

private:
    Account& account_;
    Context& context_;
};

class AccountView
{
public:
    AccountView(Account& account, Context& context) : account_(account), context_(context) {}

    void show()
    {
        std::ostringstream oss;
        oss << "Account " << account_.accountNumber << " -> " << account_.balance;
        context_.show(oss.str());
    }
private:
    Account& account_;
    Context& context_;
};

class TransferUsecase : public Context
{
public:
    void execute(const std::string& a, const std::string& b, int money)
    {
        Account accountA = find(a);
        Account accountB = find(b);

        SourceAccount source(accountA, *this);
        TargetAccount target(accountB, *this);

        source.transferTo(target, money);

        AccountView fview(accountA, *this);
        AccountView tview(accountB, *this);

        fview.show();
        tview.show();
    }

    void show(const std::string& s)
    {
        std::cout << s << std::endl;
    }

    Account find(const std::string& accountNumber)
    {
        return Account(accountNumber);
    }
};

int main(int, char* [])
{
    TransferUsecase transferUsecase;
    transferUsecase.execute("1111", "2222", 3000);

    return 0;
}