OmniAICreator/Qiita-1.07M huggingface dataset:
Svelteで Todo Example ( vs Riot )

[Riot](https://riot.js.org/)の[Todo Example](https://riot.js.org/documentation/#todo-example)を
[Svelte](https://svelte.jp/)で実装したら、どうなるかを試してみました。

下記のコードがSvelte の[REPL](https://svelte.jp/repl/hello-world?version=3.49.0)でデモを見れます。

とりあえず試した所感としては
Svelteのバインドは本当に便利！

チェックボックスの状態の切り替えると
inputの値の更新が直感で利用できます。

これのおかげで、
scriptで書く関数も少なくて済む。

```javascript
<script>
	let title = 'I want to behave!';
	let items = [
		{ title: 'Avoid excessive caffeine', done: true },
		{ title: 'Hidden item',  hidden: true },
		{ title: 'Be less provocative'  },
		{ title: 'Be nice to people' }
  ];
	
	let inputText = '';
	
	function addItem() {
		items = items.concat({title: inputText});
		inputText = '';
	}
</script>

<body>
	<h3>{title}</h3>
	
	<ul>
		{#each items as item}
		<li>
      <label class={item.done ? 'completed' : null}>
        <input type="checkbox" bind:checked={item.done}/>
        {item.title}
      </label>
    </li>
		{/each}
	</ul>
	
	<input bind:value={inputText}>
	<button disabled={!inputText} on:click={addItem}>
      Add #{items.length + 1}
	</button>
</body>


<style>
	body {
  	font-family: 'myriad pro', sans-serif;
  	font-size: 20px;
  	border: 0;
		display: block;
  	max-width: 400px;
  	margin: 5% auto;
	}

	button {
  	background-color: #1FADC5;
  	border: 1px solid rgba(0,0,0,.2);
  	font-size: 75%;
  	color: #fff;
  	padding: .4em 1.2em;
  	border-radius: 2em;
  	cursor: pointer;
  	margin: 0 .23em;
  	outline: none;
	}

	button[disabled] {
  	background-color: #ddd;
  	color: #aaa;
	}

	ul {
  	padding: 0;
	}

	li {
  	list-style-type: none;
  	padding: .2em 0;
	}

	.completed {
  	text-decoration: line-through;
  	color: #ccc;
	}

	label {
  	cursor: pointer;
	}
</style>
```
DDDの集約について考える

# はじめに
集約がまじでわからん。
ということで、自分の理解のために考えてみた。
注：間違っている可能性が高いです

# 集約の意義
サークルにはメンバーが加入でき、加入できる人数は最大10人まで、みたいなルールがあった場合に
エンティティとしてはサークル has many メンバーみたいな感じ
で、サークルにメンバーを加入するロジックとしては
```
circle.members.add(user)
```
ただこれだと、利用側で人数に関するバリデーションをかけなければならず、
```
if circle.members.count > 10 {
  "人数が上限を上回っています"
}
```
同じロジックが複数箇所に書かれてしまう。
なので、サークルを集約ルートとして、人数に関するルールはサークルに実装することで、ロジックの散在を防ぐことができる。
```
circle.join(user)
```
と、この辺までは教科書的な説明で簡単。
難しいのは、repositoryとかが絡んできたとき。

# 集約とrepositoryについて深堀

あるサークルにメンバーを追加したいとする。
テーブル的にはclrcle_membersにレコードを作成することになる。
（circle_idとuser_idをもっている）
この場合、circle_idとuser_idを受け取ってcircleMemberRepsitoryに渡すべきか？
ただそうすると、先程の人数に関するルールが守られない可能性がある。
```
circle_member = new CircleMember(circle_id, user_id)
circleMemberRepository.save(circle_member) # 10人以上保存できてしまう
```
常にルールを守らせるようにするには、circleを通して変更する必要がある。
では、どうするか？
```
circle = circleRepository.find(circle_id)
member = userRepository.find(user_id)
circle.join(member)
circleRepository.save(circle)
```
つまり、circleRepositoryで紐づくmemberも保存すべし、となる。
まとめると、repositoryを集約単位で作ることで、集約に関するルールを常に守らせることができる。

別の例。
ユーザが複数のメールアドレスを登録できるが、最大３つまで、みたいなルールがあったとする。
この場合の集約ルートはユーザということになる。
テーブル構成的にユーザテーブルに３つのカラムとしてアドレスを含めることもできるが、
アドレスを登録するタイミングがユーザ作成のタイミングと異なり１個１個登録する場合は
ユーザメールアドレスというテーブルを作ることも考えられる。
今回はそのケースで考える。
先程の教訓から行くと、メールアドレスを追加したい場合はuserRepositoryを通して行う、ということになる。
```
user = userRepository.find(user_id)
user.addEmail(address)
userRepository.save(user)
```
この場合、userRepository.findで紐づくメールアドレスも取得し、
userRepository.saveで紐づくメールアドレスも保存する、となる。

紐づくメールアドレスも保存する、の部分について詳しく。
上記の場合であれば、追加されたメールアドレスだけ保存すればよいが、
UI上複数のメールアドレスを一括で登録したい、みたいな要件があった場合。
（常にユーザが入力したメールアドレスのセットを正として洗い替えを行うとする）
```
user = userRepository.find(user_id)
user.replaceEmails(addresses)
userRepository.save(user)
```
この場合は、`userRepository.save(user)`の中で紐づくメールアドレスのdelete-insertを行う。

別のユースケースで、単純にユーザの更新のみを行いたい場合。
```
user = userRepository.find(user_id)
user.name = "hoge"
userRepository.save(user)
```
この場合、`userRepository.find(user_id)`の時点で紐づくメールアドレスも取得しているので、
`userRepository.save(user)`で無駄なアップデート処理が走るが、実害はない。
もしも`userRepository.find(user_id)`で紐づくメールアドレスを取ってこなかったとすると、
`userRepository.save(user)`の際に元々存在していたメールアドレスを消すことになってしまう。

# 思ったこと
repositoryは集約単位で作る。
その場合は、必ず生成と保存を集約単位で行う必要がある。