アジャイルソフトウェア開発の奥義のDelayedTyper.javaをC++で書く

# 概要
ロバート・C・マーチンの「アジャイルソフトウェア開発の奥義」の13章。
DelayedTyper.javaをC++にしようとしたら嵌りました。
「Effective Modern C++」に答えがありました。

・発端：何度も使うnewでメモリーリーク。
・shared_ptrでいいんでしょ。
・あれ？thisはどうする？
・enable_shared_from_thisを使う。


# 前提
・「アジャイルソフトウェア開発の奥義　第２版」が手元にあり、13章を読んでいる。
・C++14

# 結論
newの代わりにshred_ptrを使い、thisのところはshared_from_this()を使う。
コンストラクタは隠してshared_ptrを戻すfactory関数の使用を強制する。
思ったより複雑な話だった。

```command.hpp
	//省略
class command: public std::enable_shared_from_this<command>
{
public:
	//省略
	virtual void execute() = 0;
};
```
```DelayedTyper.hpp
	//省略
class delayedTyper:public command
{
public:
	static std::shared_ptr<delayedTyper> create(const long its_delay, const char its_char)
	{
		return std::shared_ptr<delayedTyper>(new delayedTyper(its_delay, its_char));
	}

	void execute() override
	{
		printf("%c", m_Char);
		if(!ms_stop) delayAndRepeat();
	}

	static void dt_main();

private:
	long m_Delay;
	char m_Char;
	static bool ms_stop;
	static activeObjectEngine* ms_engine;

	delayedTyper(const long its_delay, const char its_char)
		: m_Delay(its_delay),
		m_Char(its_char)
	{
	}
	
	void delayAndRepeat() 
	{
		ms_engine->addCommand(sleepCommand::create(m_Delay, ms_engine, shared_from_this()));
	}
	
};
```
あとは素直に置き換え。

# 発端：何度も使うnewでメモリーリーク。
13章のcommandパターン→Active Object パターンの流れでの話。
p.207のDelayedTyper.javaのdelayAndRepeat()を形式的にC++に置き換えるとこうなる。

```DelayedTyper.hpp
	//省略
class delayedTyper:public command, public std::enable_shared_from_this<delayedTyper>
{
public:
	//省略
private:
	//省略	
	void delayAndRepeat() 
	{
		ms_engine->addCommand(new sleepCommand(m_Delay, ms_engine, this));
	}
};
```

C++にはガベージコレクションがない。
このコードをDr.Memoryに通すと案の定怒られる。

```
　~~Dr.M~~ ERRORS FOUND:
　~~Dr.M~~       0 unique,     0 total unaddressable access(es)
　~~Dr.M~~       0 unique,     0 total uninitialized access(es)
　~~Dr.M~~       0 unique,     0 total invalid heap argument(s)
　~~Dr.M~~       0 unique,     0 total GDI usage error(s)
　~~Dr.M~~       0 unique,     0 total handle leak(s)
　~~Dr.M~~       0 unique,     0 total warning(s)
　~~Dr.M~~       2 unique,   337 total,  16228 byte(s) of leak(s)
　~~Dr.M~~       0 unique,     0 total,      0 byte(s) of possible leak(s)
```

# shared_ptrでいいんでしょ
問題のsleepCommandは自らをactive object のキューに入れることがある。
deleteしていいタイミングが分かりにくい。
こういうときはshared_ptrだって偉い人が言ってた。

```DelayedTyper.hpp
	//省略
class delayedTyper:public command, public std::enable_shared_from_this<delayedTyper>
{
public:
	//省略
private:
	//省略
	
	void delayAndRepeat() 
	{
		ms_engine->addCommand(std::make_shared<sleepCommand>(m_Delay, ms_engine, this));
	}
};
```

# あれ？thisはどうする？
これでactiveObjectEngine::addCommand()には、command* ではなく、shared_ptr<command>を入力することになってしまった。
（commandはsleepCommandとdelayedTyperの共通の基底クラス。）
上記の最後尾の引数のthisはdelayedTyperクラスで、この先のどこかでshared_ptr<command>にしないといけない。困った。
thisをどこかで

```
std::shared_ptr<delayedTyper> dt(this);
```

のようにしてしまうと、同じthisを扱う別々のshared_ptrを量産してしまう。
→　同じthisを２回deleteしてしまう。そこから先は動作未定義。

# enable_shared_from_thisを使う
「Effective Modern C++」にピッタリのことが書いてあった。p129付近。
enable_shared_from_this<delayedTyper>を継承して、shared_from_this()を使う。
奇妙に再帰したテンプレートパターン(Curiously Recurring Template Pattern, CRTP)というやつ。
本当に使うことがあったんだ。

```DelayedTyper.hpp
	//省略
class delayedTyper:public command, public std::enable_shared_from_this<delayedTyper>
{
public:
	//省略
private:
	//省略
	
	void delayAndRepeat() 
	{
		ms_engine->addCommand(std::make_shared<sleepCommand>(m_Delay, ms_engine, shared_from_this()));
	}
	
};
```
怒られなくなった。

```
~~Dr.M~~ NO ERRORS FOUND:
~~Dr.M~~       0 unique,     0 total unaddressable access(es)
~~Dr.M~~       0 unique,     0 total uninitialized access(es)
~~Dr.M~~       0 unique,     0 total invalid heap argument(s)
~~Dr.M~~       0 unique,     0 total GDI usage error(s)
~~Dr.M~~       0 unique,     0 total handle leak(s)
~~Dr.M~~       0 unique,     0 total warning(s)
~~Dr.M~~       0 unique,     0 total,      0 byte(s) of leak(s)
~~Dr.M~~       0 unique,     0 total,      0 byte(s) of possible leak(s)
```


#shared_from_this()の仕組み
動作の仕組みについてはこちらを参考にさせていただいた。感謝。


https://www.ogis-ri.co.jp/otc/hiroba/technical/boost/column/enable_shared_from_this.html

#公開するのはコンストラクタではなくfactory
上の仕組みからshared_from_this()が呼び出されるより前にshared_ptrをつくることが必須。
「Effective Modern C++」によるとコンストラクタはprivateにして、shared_ptrを返すfactory関数でオブジェクトを作るのが定石とのこと。

```DelayedTyper.hpp
class delayedTyper:public command, public std::enable_shared_from_this<delayedTyper>
{
public:
	static std::shared_ptr<delayedTyper> create(const long its_delay, const char its_char)
	{
		return std::shared_ptr<delayedTyper>(new delayedTyper(its_delay, its_char));
	}
	//省略

private:
	delayedTyper(const long its_delay, const char its_char)
		: m_Delay(its_delay), m_Char(its_char)
	{
	}

	void delayAndRepeat() 
	{
		ms_engine->addCommand(sleepCommand::create(m_Delay, ms_engine, shared_from_this()));
	}
	//省略
};
```

#多重継承を避ける
今回の場合は実害は無いが、気分的に多重継承を避けたい。
あとsleepCommandにもこの継承は必要だったので、commandにこの機能がついているべきなのだろう。
delayedTyperの基底クラスのcommandにenable_shared_from_thisを継承させることにした。

```command.hpp
class command: public std::enable_shared_from_this<command>
{
public:
	command() = default;
	command(const command& other) = default;
	command(command&& other) noexcept = default;
	command& operator=(const command& other) = default;
	command& operator=(command&& other) noexcept = default;
	virtual void execute() = 0;
	virtual ~command()= default;
};
```

なんでstd::enable_shared_from_this\<delayedTyper\>ではなく、基底クラスでのstd::enable_shared_from_this\<command\>の継承でもいいか。
enable_shared_from_thisの型仮引数Tは、以下２点で使わるのでcommandならOK。
　・shared_ptrのコンストラクタでenable_shared_from_thisの関数を呼んでいいかどうか判断するためのパターンマッチング
　　　→　Tは本当になんでもいい。
　・shared_from_this()が作るshared_ptrの型を決める
　　　→　TはdelayedTyperがpublic継承しているクラスであればいい。

#おわり
問題としては典型的なものだった。おかげでC++の標準の機能で解決できた。
余計にdelayedTyperをC++にした記事というのをみつけられなかったのが不思議。

#参考
ロバート・C・マーチン「アジャイルソフトウェア開発の奥義　第２版」
スコット・メイヤーズ「Effective Modern C++」
[コラム2. enable_shared_from_this](https://www.ogis-ri.co.jp/otc/hiroba/technical/boost/column/enable_shared_from_this.html)
[std::shared_ptrでthisを使いたい時に注意すること](https://suzulang.com/stdshared_ptr%E3%81%A7this%E3%82%92%E4%BD%BF%E3%81%84%E3%81%9F%E3%81%84%E6%99%82%E3%81%AB%E6%B3%A8%E6%84%8F%E3%81%99%E3%82%8B%E3%81%93%E3%81%A8/)
[cpprefjp - C++日本語リファレンス　std::enable_shared_from_this](https://cpprefjp.github.io/reference/memory/enable_shared_from_this.html)