LoginSignup
2
0

More than 5 years have passed since last update.

goでtraitっぽいやつとDCIっぽいやつ

Posted at

traitのmixinっぽいやつ

っぽいやつじゃなく、mixinのイメージ通りのものは実装されてる方がいらっしゃるみたい。

でもgolangはエイリアス型を宣言できるので、レシーバーでメソッドを付け加えることでtraitっぽいことができるし、作ったオブジェクトの型変換だけでやりたいことは事足りるんじゃ?

構造体のフィールドはそのままで振る舞いだけを特化するので、オブジェクト指向のダウンキャストと違って安全に(アプリ動作的に安全とかではなく、ポインタは変わらないだけだけど)新しい型として振る舞えそう。

以下、妄想で書いてるのでなんの検証もしてません。

例:DCIっぽい実装

シンプルな手続き型言語であることを活かしてDCIっぽく実装できそうとか思ったので、脊髄反射的なサンプル書いてみた。

例1
package main

import (
    "fmt"
)

func main() {
    // 普通のたろー君
    taro := NewPerson("Taro")
    fmt.Printf("ポインタ %pの%sとして生まれた\n", taro, taro.Name)
    // たろー君設計する
    ctxDesign(taro)
    // たろー君プログラマーになる
    ctxProgramming(taro)
    // なんならgoも書くよ
    ctxGoProgramming(taro)

    fmt.Printf("たろー君の人生は終わらない。ポインタはずっと同じ。%p\n", taro)

    // 逝く。
    taro = nil
    fmt.Printf("臨終。%v\n", taro)
}

// 人だよ
type Person struct {
    Name string
}

// 出産
func NewPerson(name string) *Person {
    return &Person{
        Name: name,
    }
}

// 設計書書くよ
type DocumentWritable interface {
    WriteDocument(spec string)
}

// コード書けるよ
type CodeWritable interface {
    WriteCode(code string)
}

// アーキテクト
type Architect Person

func (a Architect) WriteDocument(spec string) {
    fmt.Println(spec)
}

// プログラマー
type Programmer Person

func (p *Programmer) WriteCode(code string) {
    fmt.Println(code)
}

// goプログラマー
type Gopher Programmer

func (p *Gopher) WriteCode(code string) {
    fmt.Printf("fmt.Println(\"%s\")\n", code)
}

// コンテキスト: 人雇って設計書を書かせる
func ctxDesign(p *Person) {
    a := (*Architect)(p)
    fmt.Printf("ポインタ %pのアーキテクト%s\n", a, a.Name)
    a.WriteDocument("こんなあぷりつくる")
}

// コンテキスト: 人雇ってプログラマーとしてコード書かせる
func ctxProgramming(p *Person) {
    pgr := (*Programmer)(p)
    fmt.Printf("ポインタ %pのプログラマ%s\n", pgr, pgr.Name)
    codingTask(pgr)
}

// コンテキスト: 人雇ってgoプログラマーとしてコード書かせる
func ctxGoProgramming(p *Person) {
    pgr := (*Gopher)(p)
    fmt.Printf("ポインタ %pのgoプログラマ%s\n", pgr, pgr.Name)
    codingTask(pgr)
}
func codingTask(coder CodeWritable) {
    coder.WriteCode("HelloWorld!")
}

playground

アンチパターン

オブジェクト指向言語だとエイリアス型の宣言自体がアンチパターンとして挙げられるみたいだし、モデルの振る舞いがデータと切り離されるという意味では、ドメイン駆動に対して典型的な貧血症モデル。構造体はドメイン内でどう振る舞うかなんて知らないから、パッケージ外に複雑な操作は公開しないほうがよさそう。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0