Goに入門して、ついでにクリーンアーキテクチャに入門した　ーその1

## はじめに
業務でLaravelを使ってMVCでアプリケーションを作成したことはありますが、どうやらGoは「Clean Architecture（クリーンアーキテクチャ）」で開発するのが主流なようです。

今回はコードを書いたりAIに聞いたりしながらGoとクリーンアーキテクチャについて学んでみました！

:::note warn
思考整理のためのアウトプットですので、情報の正確性などは保証できません！ご容赦ください:cop_tone2:
:::


## インターフェース指向
クリーンアーキテクチャで重要になってくるのが**インターフェース**です。

ChatGPTによると、Goは「インターフェース指向」の言語と言われているようです。
**オブジェクト指向**はよく耳にしますが、インターフェース指向という言葉もあるんですね。

インターフェースという概念はどの言語にも存在すると思いますが、GoのインターフェースはPHPなどのそれとは多少異なるらしく、わかりやすくChatGPTに教えてもらいました。

> 例えばJavaやC#では、あるクラスがインターフェースを「implements」や「: InterfaceName」として明示的に実装する必要があります。
でもGoでは…
対応するメソッドを「たまたま」持っていれば、そのインターフェースを満たしているとGoは判断します。

うーん、よくわかりません笑

ということで、いったんmain.goにインターフェースを含むコードを書いてみて、インターフェースについてわかってきたらクリーンアーキテクチャについても深掘りしていこうと思います。

## Goのインターフェースを理解する
例としてAnimalインターフェースを定義してみます。
最初にコード全体を貼っておきます。

```go:main.go
package main

import (
	"fmt"
)

// インターフェースの定義
type Animal interface {
	Speak() string
}

type Dog struct {
	Name string
}

// Dog に Speak() メソッドを実装（インターフェースを満たす）
func (d Dog) Speak() string {
	return d.Name + " says: わん！"
}

type Cat struct {
	Name string
}

func (c Cat) Speak() string {
	return c.Name + " says: にゃー！"
}

// Animal インターフェースを受け取る関数
func MakeItSpeak(a Animal) {
	fmt.Println(a.Speak())
}

func main() {
	dog := Dog{Name: "ポチ"}
	cat := Cat{Name: "ミケ"}

	MakeItSpeak(dog)
	MakeItSpeak(cat)
}
```

ターミナルで`go run main.go`を実行することで、`ポチsays:わん！　ミケsays：にゃー！`が出力されます。

では順番にコードを追っていきましょう。

---

```go
type Animal interface {
	Speak() string
}

type Dog struct {
	Name string
}

type Cat struct {
	Name string
}
```
Animalインターフェースでは「Speak()」という、戻り値の型が文字列のメソッドを定義しています。

また、 Dog ・ Cat それぞれの構造体が定義されています。

<br>

```go
func (d Dog) Speak() string {
	return d.Name + " says: わん！"
}

func (c Cat) Speak() string {
	return c.Name + " says: にゃー！"
}
```
次に Dog・Cat 構造体をレシーバーとして、自分の鳴き声を返すSpeak()メソッドを実装します。

Goでは、**構造体がSpeak()メソッドを持っていれば、それだけでAnimalインターフェースを満たしている、と暗黙的に判断されます。**

この実装は構造体とインターフェースの間に明示的な結びつきを持たないため、疎結合な設計を自然に実現できるようです。

<details><summary>レシーバーについて補足</summary>
「値レシーバー」と「ポインタレシーバー」

仮にメソッド内の処理として、構造体のフィールド（他の言語でいうクラスのメンバー・プロパティ）の値を更新したい場合
```go
func (*d Dog) Speak() string {}
```
のように構造体の変数の前にアスタリスクを記述します。

こうすると、メソッド内でフィールドを変更すると参照元の構造体にもその変更が反映されます！

アスタリスクが付く方はポインタレシーバー、付かない方は値レシーバーと言います。
</details>

<br>

```go
func MakeItSpeak(a Animal) {
	fmt.Println(a.Speak())
}
```

そして、MakeItSpeak()関数は**引数にAnimal型をとっており**、DogやCatはSpeak()メソッドを実装しているため、**Animalインターフェースを満たしているとみなされます。**

:::note info
※この後の章で触れますが、他の言語のように明示的に「Animal型を実装します」という宣言が不要なのがGoの特徴です。（例：implementsキーワードなど）
そのため、上記の説明も満たしていると"みなされる"というニュアンスになります。
より厳密にいうとGoのコンパイラが自動で判断する、ということです。
:::

そのため、Animal型の引数をとるMakeitSpeak()関数に渡すことができるということです。

<br>

```go
func main() {
	dog := Dog{Name: "ポチ"}
	cat := Cat{Name: "ミケ"}

	MakeItSpeak(dog)
	MakeItSpeak(cat)
}
```
ということで、最終的にmain関数内でMakeItSpeak()に Dog・Cat（=Animalインターフェース）を渡して実行することで、それぞれの動物の鳴き声が出力されました！

## PHPでAnimalインターフェースを書いてみる
試しにPHP（オブジェクト指向言語）でAnimalインターフェースがどのようなコードになるか比較すると、よりGo言語の特徴がわかりやすいかと思ったので、AIにお願いして書いてもらいました。

```php:PHP
<?php
interface Animal {
    public function speak(): string;
}

class Dog implements Animal {
    private string $name;

    public function __construct(string $name) {
        $this->name = $name;
    }

    public function speak(): string {
        return $this->name . " says: わん！";
    }
}

class Cat implements Animal {
    private string $name;

    public function __construct(string $name) {
        $this->name = $name;
    }

    public function speak(): string {
        return $this->name . " says: にゃー！";
    }
}

function makeItSpeak(Animal $animal) {
    echo $animal->speak() . PHP_EOL;
}

$dog = new Dog("ポチ");
$cat = new Cat("ミケ");

makeItSpeak($dog);
makeItSpeak($cat);
```
こうして見比べてみると、割と異なる点が多いように見えます。

PHPでは`implements`というキーワードを使ってインターフェースを明示的に実装する必要があります。

```php:PHP
class Dog implements Animal {...}
class Cat implements Animal {...}
```
また、Goにはコンストラクタ関数が用意されていないため、`dog := Dog{Name: "ポチ"}`のように直接初期化する必要がありますが、$this変数を用いて__constructor関数で初期化しています。

```php:PHP
public function __construct(string $name) {
    $this->name = $name;
}
```

また、メソッドについてですが
`Go` ・・・・構造体が持つ機能・振る舞い
`PHP` ・・・クラスが持つ機能・振る舞い

このような捉え方をすると同じもののように思えますが、実際には少し意味合いが異なるようです。

```go:Go
type Dog struct {
	Name string
}

func (d Dog) Speak() string {
	return d.Name + " says: わん！"
}
```
> Dogという構造体にSpeak()という振る舞いを「結びつけている」

```php:PHP
class Dog {
	private string $name;

	public function __construct(string $name) {
		$this->name = $name;
	}

	public function speak(): string {
		return $this->name . " says: わん！";
	}
}
```
> Dogというクラスにspeak()という振る舞いを「定義している」


仮に犬・猫に続いて「猿」を追加するケースを考えてみます。

猿は鳴きますし、噛み付くし、木に登ります。
この特徴の中で、鳴く・噛み付くは犬にも猫にも当てはまりますよね。

その場合、必要に応じてそれらの振る舞い＝メソッドを Dog・Cat 構造体に結びつけるイメージでしょうか。
クラスにメソッドを定義するのとはちょっと感覚が違いますよね。


```go:Go
type Speaker interface {
	Speak() string // 鳴く
}

type Biter interface {
	Bite() string // 噛み付く
}

type Climber interface {
	Climb() string // 木に登る
}
```
猿
```go:Go
type Monkey struct {
	Name string
}

func (m Monkey) Speak() string {
	return m.Name + " says: ウキキー！"
}

func (m Monkey) Bite() string {
	return m.Name + " が噛みついた！"
}

func (m Monkey) Climb() string {
	return m.Name + " が木に登った！"
}
```
犬
```go:Go
type Dog struct {
	Name string
}

func (d Dog) Speak() string {
	return d.Name + " says: わん！"
}

func (d Dog) Bite() string {
	return d.Name + " が噛みついた！"
}
```

## Goのインターフェースの理解を深める
また、異なる例でPHPとGoのインターフェースの比較ができるコードを出してもらいました。

> 以下のPHPのコードは「渡された動物が Speaker や Climber を実装してるかチェックして、できる行動だけ実行する」という判定をしています。

```php:PHP
function act($animal) {
    if ($animal instanceof Speaker) {
        echo $animal->speak();
    }
    if ($animal instanceof Climber) {
        echo $animal->climb();
    }
}
```

> ポイントは、instanceof Speaker を使うには、**そのクラスがあらかじめ implements Speaker を書いておかないとダメ**という点です。

```php:PHP
interface Speaker {
    public function speak(): string;
}

class Dog implements Speaker {
    public function speak(): string {
        return "わん！";
    }
}
```
> 一方、Goはインターフェースを実装する際の宣言が不要です。
>以下のコードで Dog に「Speaker を実装する」とは一言も書いていませんが、Act() に Dog を渡すと、Dog は Speak() メソッドを持っているので Speaker インターフェースを満たしている（とGoが判断する）。
> よって、a.(Speaker) の型アサーションも true になり、問題なく動作します。

```go:Go
type Speaker interface {
	Speak() string
}

type Dog struct {
	Name string
}

func (d Dog) Speak() string {
	return "ワンワン！"
}

func Act(a interface{}) {
	if s, ok := a.(Speaker); ok {
		fmt.Println(s.Speak())
	}
	if c, ok := a.(Climber); ok {
		fmt.Println(c.Climb())
	}
}
```

つまり、型アサーションで引数の値を調べるときに、**インターフェースを実装しているか知る必要はない**ということになります。

確かにこれは「疎結合」な設計だな、ということがわかりました。

## おわりに
だいぶ内容がGoのインターフェースに関する話に偏ってしまいました。

ですがGoでクリーンアーキテクチャを使って開発するならインターフェースは重要な要素になるので、少しボリュームを割いて理解に努めました。

これで大体インターフェースについてはわかったので、次の記事ではmain.goのコードを責務ごとにファイル分割して、クリーンアーキテクチャをやっていこうと思います:taco:

↓次

https://qiita.com/shimamoooon/items/1ed64734aa08c33e265e

## 参考
- [A Tour od Go | Type assertions](https://go-tour-jp.appspot.com/methods/15)
- [オブジェクト インターフェイス（PHP）](https://www.php.net/manual/ja/language.oop5.interfaces.php)