▶️
DDDの使い道を見つけた話。ChatGPTと単体ファイルのDDDの相性はとても良い。
その1: mapにデータを格納するコードを単体ファイルのDDDで作成する
抽象型(リポジトリ) type IUserRepository interface を作っておく。
具象実装(リポジトリ) type InMemoryUserRepository struct をDBに変更する予定で何も考えずに作る。
package main
import (
"errors"
"fmt"
"log"
"unicode/utf8"
"net/mail"
"time"
"github.com/oklog/ulid/v2"
)
// ---appService型-s-
type SaveUserUseCase struct {
userServ *UserService
}
//
func NewSaveUserUseCase(userServ *UserService) *SaveUserUseCase {
return &SaveUserUseCase{userServ: userServ}
}
//
func (uc *SaveUserUseCase) Run(dto SaveUseCaseDto) error {
user, err := NewUser(dto.LastName, dto.FirstName, dto.Email, dto.Post, dto.Idlimit)
if err != nil {
return err
}
return uc.userServ.Repository.Save(user)
}
// DTO
type SaveUseCaseDto struct {
LastName string
FirstName string
Email string
Post string
Idlimit time.Time
}
//
//---e-
// ---appService型-s-
type FindUserUseCase struct {
userServ *UserService
}
//
func NewFindUserUseCase(userServ *UserService) *FindUserUseCase {
return &FindUserUseCase{userServ: userServ}
}
//
func (uc *FindUserUseCase) Run(dto FindUseCaseDto) (*FindUseCaseDto, error) {
user, err := uc.userServ.Repository.FindByFullName(dto.LastName, dto.FirstName)
if err != nil {
return nil, err
}
return &FindUseCaseDto{
ID: user.ID(),
LastName: user.LastName(),
FirstName: user.FirstName(),
Email: user.Email(),
Post: user.Post(),
Idlimit: user.Idlimit(),
}, nil
}
// DTO
type FindUseCaseDto struct {
ID string
LastName string
FirstName string
Email string
Post string
Idlimit time.Time
}
//
//---e-
// --- app/domain/
// --- 処理型 -s-
type User struct {
id string
lastName string
firstName string
email string
post string
idlimit time.Time
}
// private
func newUser(id string, lastName string, firstName string, email string, post string, idlimit time.Time) (*User, error) {
// ガード節
if utf8.RuneCountInString(lastName) < nameLengthMin || utf8.RuneCountInString(lastName) > nameLengthMax {
return nil, errors.New("名前(姓)の値が不正です。")
}
if utf8.RuneCountInString(firstName) < nameLengthMin || utf8.RuneCountInString(firstName) > nameLengthMax {
return nil, errors.New("名前(名)の値が不正です。")
}
if _, err := mail.ParseAddress(email); err != nil {
return nil, errors.New("メールアドレスの値が不正です。")
}
if !isDateFormatValid(idlimit.Format("2006-01-02")) {
return nil, errors.New("無効な日付形式です")
}
return &User{id: id, lastName: lastName, firstName: firstName, email: email, post: post, idlimit: idlimit}, nil
}
// 日付の形式が有効かどうかを検証する関数
func isDateFormatValid(dateStr string) bool {
_, err := time.Parse("2006-01-02", dateStr)
return err == nil
}
//
const (
nameLengthMax = 255
nameLengthMin = 1
)
//
func NewUser(lastName string, firstName string, email string, post string, idlimit time.Time) (*User, error) {
return newUser(NewULID(), lastName, firstName, email, post, idlimit)
}
//
func Reconstruct(id string, lastName string, firstName string, email string, post string, idlimit time.Time) (*User, error) {
return newUser(id, lastName, firstName, email, post, idlimit)
}
//
func (u *User) ID() string {
return u.id
}
//
func (u *User) LastName() string {
return u.lastName
}
//
func (u *User) FirstName() string {
return u.firstName
}
//
func (u *User) Email() string {
return u.email
}
//
func (u *User) Post() string {
return u.post
}
//
func (u *User) Idlimit() time.Time {
return u.idlimit
}
//
func (u *User) PrintUserDetails() {
fmt.Printf("ID: %s\nLastName: %s\nFirstName: %s\nEmail: %s\nPost: %s\nIdlimit: %s\n\n",
u.ID(), u.LastName(), u.FirstName(), u.Email(), u.Post(), u.Idlimit())
}
//---e-
//---pkg/ulid
func NewULID() string { //同じidを生成してしまう対策
return ulid.Make().String()
}
//
func IsValid(s string) bool {
_, err := ulid.Parse(s)
return err == nil
}
//---e-
// --- ドメインサービス用型(メソッドのみ) -s-
type UserService struct {
Repository IUserRepository //抽象化
}
//
func NewUserRepository(repository IUserRepository) *UserService {
return &UserService{Repository: repository}
}
//---e-
// --- 抽象型(リポジトリ) -s-
type IUserRepository interface {
Save(user *User) error
FindByFullName(lastName string, firstName string) (*User, error)
FindAllUsers() ([]*User, error)
}
// --- e-
// --- 具象実装(リポジトリ) -s-
type InMemoryUserRepository struct {
Users map[string]*User
}
//
func NewInMemoryUserRepository() *InMemoryUserRepository {
return &InMemoryUserRepository{
Users: make(map[string]*User),
}
}
//
func (imur *InMemoryUserRepository) Save(user *User) error {
//fmt.Println("Saving user with ID:", user.ID())
imur.Users[user.ID()] = user
return nil
}
//
func (imur *InMemoryUserRepository) FindByFullName(lastName string, firstName string) (*User, error) {
for _, user := range imur.Users {
if user.LastName() == lastName && user.FirstName() == firstName {
return user, nil
}
}
return nil, errors.New("User not found")
}
//
func (imur *InMemoryUserRepository) FindAllUsers() ([]*User, error) {
users := make([]*User, 0, len(imur.Users))
for _, user := range imur.Users {
users = append(users, user)
}
return users, nil
}
//---e-
func main() {
// Initialize repository
inMemoryUserRepository := NewInMemoryUserRepository()
// Initialize service with the repository
userService := NewUserRepository(inMemoryUserRepository)
// Initialize use cases with the service
saveUserUseCase := NewSaveUserUseCase(userService)
findUserUseCase := NewFindUserUseCase(userService)
// Save user
saveDto := SaveUseCaseDto{
LastName: "Smith",
FirstName: "John",
Email: "john.smith@example.com",
Post: "Chief",
Idlimit: time.Now().AddDate(50, 0, 0),
}
err := saveUserUseCase.Run(saveDto)
if err != nil {
log.Fatal("Error saving user:", err)
}
// Save another user
saveDto2 := SaveUseCaseDto{
LastName: "Doe",
FirstName: "Jane",
Email: "jane.doe@example.com",
Post: "Manager",
Idlimit: time.Now().AddDate(50, 0, 0),
}
err = saveUserUseCase.Run(saveDto2)
if err != nil {
log.Fatal("Error saving user:", err)
}
// Find user by full name
findDto := FindUseCaseDto{
LastName: "Smith",
FirstName: "John",
}
foundUserDto, err := findUserUseCase.Run(findDto)
if err != nil {
log.Fatal("Error finding user:", err)
}
// Print found user details
fmt.Println("===Found User:===")
fmt.Printf("ID: %s\nLastName: %s\nFirstName: %s\nEmail: %s\nPost: %s\nIdlimit: %s\n",
foundUserDto.ID, foundUserDto.LastName, foundUserDto.FirstName, foundUserDto.Email, foundUserDto.Post, foundUserDto.Idlimit)
// Fetch and display all users
allUsers, err := userService.Repository.FindAllUsers()
if err != nil {
log.Fatal("Error fetching all users:", err)
}
fmt.Println("")
fmt.Println("===All Users:===")
for _, user := range allUsers {
user.PrintUserDetails()
}
}
その2: SQLiteにデータを格納するコードをChatGptにお願いする。
InMemoryUserRepositoryをSQLiteUserRepositoryに載せ替えて。
"github.com/mattn/go-sqlite3"を使って。
package main
import (
"errors"
"fmt"
"log"
"unicode/utf8"
"net/mail"
"time"
"database/sql"
"github.com/oklog/ulid/v2"
_ "github.com/mattn/go-sqlite3" //SQLite用サードパーティードライバ
)
// ---appService型-s-
type SaveUserUseCase struct {
userServ *UserService
}
//
func NewSaveUserUseCase(userServ *UserService) *SaveUserUseCase {
return &SaveUserUseCase{userServ: userServ}
}
//
func (uc *SaveUserUseCase) Run(dto SaveUseCaseDto) error {
user, err := NewUser(dto.LastName, dto.FirstName, dto.Email, dto.Post, dto.Idlimit)
if err != nil {
return err
}
return uc.userServ.Repository.Save(user)
}
// DTO
type SaveUseCaseDto struct {
LastName string
FirstName string
Email string
Post string
Idlimit time.Time
}
//
//---e-
// ---appService型-s-
type FindUserUseCase struct {
userServ *UserService
}
//
func NewFindUserUseCase(userServ *UserService) *FindUserUseCase {
return &FindUserUseCase{userServ: userServ}
}
//
func (uc *FindUserUseCase) Run(dto FindUseCaseDto) (*FindUseCaseDto, error) {
user, err := uc.userServ.Repository.FindByFullName(dto.LastName, dto.FirstName)
if err != nil {
return nil, err
}
return &FindUseCaseDto{
ID: user.ID(),
LastName: user.LastName(),
FirstName: user.FirstName(),
Email: user.Email(),
Post: user.Post(),
Idlimit: user.Idlimit(),
}, nil
}
// DTO
type FindUseCaseDto struct {
ID string
LastName string
FirstName string
Email string
Post string
Idlimit time.Time
}
//
//---e-
// --- app/domain/
// --- 処理型 -s-
type User struct {
id string
lastName string
firstName string
email string
post string
idlimit time.Time
}
// private
func newUser(id string, lastName string, firstName string, email string, post string, idlimit time.Time) (*User, error) {
// ガード節
if utf8.RuneCountInString(lastName) < nameLengthMin || utf8.RuneCountInString(lastName) > nameLengthMax {
return nil, errors.New("名前(姓)の値が不正です。")
}
if utf8.RuneCountInString(firstName) < nameLengthMin || utf8.RuneCountInString(firstName) > nameLengthMax {
return nil, errors.New("名前(名)の値が不正です。")
}
if _, err := mail.ParseAddress(email); err != nil {
return nil, errors.New("メールアドレスの値が不正です。")
}
if !isDateFormatValid(idlimit.Format("2006-01-02")) {
return nil, errors.New("無効な日付形式です")
}
return &User{id: id, lastName: lastName, firstName: firstName, email: email, post: post, idlimit: idlimit}, nil
}
// 日付の形式が有効かどうかを検証する関数
func isDateFormatValid(dateStr string) bool {
_, err := time.Parse("2006-01-02", dateStr)
return err == nil
}
//
const (
nameLengthMax = 255
nameLengthMin = 1
)
//
func NewUser(lastName string, firstName string, email string, post string, idlimit time.Time) (*User, error) {
return newUser(NewULID(), lastName, firstName, email, post, idlimit)
}
//
func Reconstruct(id string, lastName string, firstName string, email string, post string, idlimit time.Time) (*User, error) {
return newUser(id, lastName, firstName, email, post, idlimit)
}
//
func (u *User) ID() string {
return u.id
}
//
func (u *User) LastName() string {
return u.lastName
}
//
func (u *User) FirstName() string {
return u.firstName
}
//
func (u *User) Email() string {
return u.email
}
//
func (u *User) Post() string {
return u.post
}
//
func (u *User) Idlimit() time.Time {
return u.idlimit
}
//
func (u *User) PrintUserDetails() {
fmt.Printf("ID: %s\nLastName: %s\nFirstName: %s\nEmail: %s\nPost: %s\nIdlimit: %s\n\n",
u.ID(), u.LastName(), u.FirstName(), u.Email(), u.Post(), u.Idlimit())
}
//---e-
//---pkg/ulid
func NewULID() string { //同じidを生成してしまう対策
return ulid.Make().String()
}
//
func IsValid(s string) bool {
_, err := ulid.Parse(s)
return err == nil
}
//---e-
// --- ドメインサービス用型(メソッドのみ) -s-
type UserService struct {
Repository IUserRepository //抽象化
}
//
func NewUserRepository(repository IUserRepository) *UserService {
return &UserService{Repository: repository}
}
//---e-
// --- 抽象型(リポジトリ) -s-
type IUserRepository interface {
Save(user *User) error
FindByFullName(lastName string, firstName string) (*User, error)
FindAllUsers() ([]*User, error)
}
// --- e-
// --- 具象実装(リポジトリ) -s-
type SQLiteUserRepository struct {
db *sql.DB
}
//
func NewSQLiteUserRepository() (*SQLiteUserRepository, error) {
db, err := sql.Open("sqlite3", "database.sqlite")
if err != nil {
return nil, err
}
// Create the users table if it doesn't exist
_, err = db.Exec(`
CREATE TABLE IF NOT EXISTS users (
id TEXT PRIMARY KEY,
last_name TEXT,
first_name TEXT,
email TEXT,
post TEXT,
idlimit TEXT
);
`)
if err != nil {
return nil, err
}
return &SQLiteUserRepository{db: db}, nil
}
//
func (r *SQLiteUserRepository) Save(user *User) error {
_, err := r.db.Exec(
"INSERT INTO users (id, last_name, first_name, email, post, idlimit) VALUES (?, ?, ?, ?, ?, ?)",
user.ID(), user.LastName(), user.FirstName(), user.Email(), user.Post(), user.Idlimit().Format("2006-01-02"),
)
return err
}
//
func (r *SQLiteUserRepository) FindByFullName(lastName string, firstName string) (*User, error) {
var user User
row := r.db.QueryRow("SELECT * FROM users WHERE last_name = ? AND first_name = ?", lastName, firstName)
var idlimitStr string
if err := row.Scan(&user.id, &user.lastName, &user.firstName, &user.email, &user.post, &idlimitStr); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, nil // User not found
}
return nil, err // Handle other errors
}
idlimit, err := time.Parse("2006-01-02", idlimitStr)
if err != nil {
return nil, err
}
user.idlimit = idlimit
return &user, nil
}
//
func (r *SQLiteUserRepository) FindAllUsers() ([]*User, error) {
rows, err := r.db.Query("SELECT * FROM users")
if err != nil {
return nil, err
}
defer rows.Close()
var users []*User
for rows.Next() {
var user User
var idlimitStr string
err := rows.Scan(&user.id, &user.lastName, &user.firstName, &user.email, &user.post, &idlimitStr)
if err != nil {
return nil, err
}
idlimit, err := time.Parse("2006-01-02", idlimitStr)
if err != nil {
return nil, err
}
user.idlimit = idlimit
users = append(users, &user)
}
return users, nil
}
func main() {
// Initialize repository with the SQLite database
sqliteUserRepository, err := NewSQLiteUserRepository()
if err != nil {
log.Fatal("Error initializing SQLite repository:", err)
}
defer sqliteUserRepository.db.Close()
// Initialize service with the repository
userService := NewUserRepository(sqliteUserRepository)
// Initialize use cases with the service
saveUserUseCase := NewSaveUserUseCase(userService)
findUserUseCase := NewFindUserUseCase(userService)
// Save user
saveDto := SaveUseCaseDto{
LastName: "Smith",
FirstName: "John",
Email: "john.smith@example.com",
Post: "Chief",
Idlimit: time.Now().AddDate(50, 0, 0),
}
err = saveUserUseCase.Run(saveDto)
if err != nil {
log.Fatal("Error saving user:", err)
}
// Save another user
saveDto2 := SaveUseCaseDto{
LastName: "Doe",
FirstName: "Jane",
Email: "jane.doe@example.com",
Post: "Manager",
Idlimit: time.Now().AddDate(50, 0, 0),
}
err = saveUserUseCase.Run(saveDto2)
if err != nil {
log.Fatal("Error saving user:", err)
}
// Find user by full name
findDto := FindUseCaseDto{
LastName: "Smith",
FirstName: "John",
}
foundUserDto, err := findUserUseCase.Run(findDto)
if err != nil {
log.Fatal("Error finding user:", err)
}
// Print found user details
fmt.Println("===Found User:===")
fmt.Printf("ID: %s\nLastName: %s\nFirstName: %s\nEmail: %s\nPost: %s\nIdlimit: %s\n",
foundUserDto.ID, foundUserDto.LastName, foundUserDto.FirstName, foundUserDto.Email, foundUserDto.Post, foundUserDto.Idlimit)
// Fetch and display all users
allUsers, err := userService.Repository.FindAllUsers()
if err != nil {
log.Fatal("Error fetching all users:", err)
}
fmt.Println("\n===All Users:===")
for _, user := range allUsers {
user.PrintUserDetails()
}
}
その3: PostgreSQLにデータを格納するコードをChatGptにお願いする。
SQLiteUserRepositoryをPostgreSQLUserRepositoryに載せ替えて。
"github.com/lib/pq"を使って。
package main
import (
"errors"
"fmt"
"log"
"unicode/utf8"
"net/mail"
"time"
"database/sql"
"github.com/oklog/ulid/v2"
_ "github.com/lib/pq" //PostgreSQL用サードパーティードライバ
)
// ---appService型-s-
type SaveUserUseCase struct {
userServ *UserService
}
//
func NewSaveUserUseCase(userServ *UserService) *SaveUserUseCase {
return &SaveUserUseCase{userServ: userServ}
}
//
func (uc *SaveUserUseCase) Run(dto SaveUseCaseDto) error {
user, err := NewUser(dto.LastName, dto.FirstName, dto.Email, dto.Post, dto.Idlimit)
if err != nil {
return err
}
return uc.userServ.Repository.Save(user)
}
// DTO
type SaveUseCaseDto struct {
LastName string
FirstName string
Email string
Post string
Idlimit time.Time
}
//
//---e-
// ---appService型-s-
type FindUserUseCase struct {
userServ *UserService
}
//
func NewFindUserUseCase(userServ *UserService) *FindUserUseCase {
return &FindUserUseCase{userServ: userServ}
}
//
func (uc *FindUserUseCase) Run(dto FindUseCaseDto) (*FindUseCaseDto, error) {
user, err := uc.userServ.Repository.FindByFullName(dto.LastName, dto.FirstName)
if err != nil {
return nil, err
}
return &FindUseCaseDto{
ID: user.ID(),
LastName: user.LastName(),
FirstName: user.FirstName(),
Email: user.Email(),
Post: user.Post(),
Idlimit: user.Idlimit(),
}, nil
}
// DTO
type FindUseCaseDto struct {
ID string
LastName string
FirstName string
Email string
Post string
Idlimit time.Time
}
//
//---e-
// --- app/domain/
// --- 処理型 -s-
type User struct {
id string
lastName string
firstName string
email string
post string
idlimit time.Time
}
// private
func newUser(id string, lastName string, firstName string, email string, post string, idlimit time.Time) (*User, error) {
// ガード節
if utf8.RuneCountInString(lastName) < nameLengthMin || utf8.RuneCountInString(lastName) > nameLengthMax {
return nil, errors.New("名前(姓)の値が不正です。")
}
if utf8.RuneCountInString(firstName) < nameLengthMin || utf8.RuneCountInString(firstName) > nameLengthMax {
return nil, errors.New("名前(名)の値が不正です。")
}
if _, err := mail.ParseAddress(email); err != nil {
return nil, errors.New("メールアドレスの値が不正です。")
}
if !isDateFormatValid(idlimit.Format("2006-01-02")) {
return nil, errors.New("無効な日付形式です")
}
return &User{id: id, lastName: lastName, firstName: firstName, email: email, post: post, idlimit: idlimit}, nil
}
// 日付の形式が有効かどうかを検証する関数
func isDateFormatValid(dateStr string) bool {
_, err := time.Parse("2006-01-02", dateStr)
return err == nil
}
//
const (
nameLengthMax = 255
nameLengthMin = 1
)
//
func NewUser(lastName string, firstName string, email string, post string, idlimit time.Time) (*User, error) {
return newUser(NewULID(), lastName, firstName, email, post, idlimit)
}
//
func Reconstruct(id string, lastName string, firstName string, email string, post string, idlimit time.Time) (*User, error) {
return newUser(id, lastName, firstName, email, post, idlimit)
}
//
func (u *User) ID() string {
return u.id
}
//
func (u *User) LastName() string {
return u.lastName
}
//
func (u *User) FirstName() string {
return u.firstName
}
//
func (u *User) Email() string {
return u.email
}
//
func (u *User) Post() string {
return u.post
}
//
func (u *User) Idlimit() time.Time {
return u.idlimit
}
//
func (u *User) PrintUserDetails() {
fmt.Printf("ID: %s\nLastName: %s\nFirstName: %s\nEmail: %s\nPost: %s\nIdlimit: %s\n\n",
u.ID(), u.LastName(), u.FirstName(), u.Email(), u.Post(), u.Idlimit())
}
//---e-
//---pkg/ulid
func NewULID() string { //同じidを生成してしまう対策
return ulid.Make().String()
}
//
func IsValid(s string) bool {
_, err := ulid.Parse(s)
return err == nil
}
//---e-
// --- ドメインサービス用型(メソッドのみ) -s-
type UserService struct {
Repository IUserRepository //抽象化
}
//
func NewUserRepository(repository IUserRepository) *UserService {
return &UserService{Repository: repository}
}
//---e-
// --- 抽象型(リポジトリ) -s-
type IUserRepository interface {
Save(user *User) error
FindByFullName(lastName string, firstName string) (*User, error)
FindAllUsers() ([]*User, error)
}
// --- e-
// --- 具象実装(リポジトリ) -s-
type PostgreSQLUserRepository struct {
db *sql.DB
}
//
func NewPostgreSQLUserRepository() (*PostgreSQLUserRepository, error) {
db, err := sql.Open("postgres", "user=postgres dbname=postgres password=postgresgo sslmode=disable")
if err != nil {
return nil, err
}
// Create the users table if it doesn't exist
_, err = db.Exec(`
CREATE TABLE IF NOT EXISTS users (
id TEXT PRIMARY KEY,
last_name TEXT,
first_name TEXT,
email TEXT,
post TEXT,
idlimit TEXT
);
`)
if err != nil {
return nil, err
}
return &PostgreSQLUserRepository{db: db}, nil
}
//
func (r *PostgreSQLUserRepository) Save(user *User) error {
/*
_, err := r.db.Exec(
"INSERT INTO users (id, last_name, first_name, email, post, idlimit) VALUES (?, ?, ?, ?, ?, ?)",
user.ID(), user.LastName(), user.FirstName(), user.Email(), user.Post(), user.Idlimit().Format("2006-01-02"),
)
*/
_, err := r.db.Exec(
"INSERT INTO users (id, last_name, first_name, email, post, idlimit) VALUES ($1, $2, $3, $4, $5, $6)",
user.ID(), user.LastName(), user.FirstName(), user.Email(), user.Post(), user.Idlimit().Format("2006-01-02"),
)
return err
}
//
func (r *PostgreSQLUserRepository) FindByFullName(lastName string, firstName string) (*User, error) {
var user User
//row := r.db.QueryRow("SELECT * FROM users WHERE last_name = ? AND first_name = ?", lastName, firstName)
row := r.db.QueryRow("SELECT * FROM users WHERE last_name = $1 AND first_name = $2", lastName, firstName)
var idlimitStr string
if err := row.Scan(&user.id, &user.lastName, &user.firstName, &user.email, &user.post, &idlimitStr); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, nil // User not found
}
return nil, err // Handle other errors
}
idlimit, err := time.Parse("2006-01-02", idlimitStr)
if err != nil {
return nil, err
}
user.idlimit = idlimit
return &user, nil
}
//
func (r *PostgreSQLUserRepository) FindAllUsers() ([]*User, error) {
rows, err := r.db.Query("SELECT * FROM users")
if err != nil {
return nil, err
}
defer rows.Close()
var users []*User
for rows.Next() {
var user User
var idlimitStr string
err := rows.Scan(&user.id, &user.lastName, &user.firstName, &user.email, &user.post, &idlimitStr)
if err != nil {
return nil, err
}
idlimit, err := time.Parse("2006-01-02", idlimitStr)
if err != nil {
return nil, err
}
user.idlimit = idlimit
users = append(users, &user)
}
return users, nil
}
//---e-
func main() {
// Initialize repository with the PostgreSQL database
postgreSQLUserRepository, err := NewPostgreSQLUserRepository()
if err != nil {
log.Fatal("Error initializing PostgreSQL repository:", err)
}
defer postgreSQLUserRepository.db.Close()
// Initialize service with the repository
userService := NewUserRepository(postgreSQLUserRepository)
// Initialize use cases with the service
saveUserUseCase := NewSaveUserUseCase(userService)
findUserUseCase := NewFindUserUseCase(userService)
// Save user
saveDto := SaveUseCaseDto{
LastName: "Smith",
FirstName: "John",
Email: "john.smith@example.com",
Post: "Chief",
Idlimit: time.Now().AddDate(50, 0, 0),
}
err = saveUserUseCase.Run(saveDto)
if err != nil {
log.Fatal("Error saving user:", err)
}
// Save another user
saveDto2 := SaveUseCaseDto{
LastName: "Doe",
FirstName: "Jane",
Email: "jane.doe@example.com",
Post: "Manager",
Idlimit: time.Now().AddDate(50, 0, 0),
}
err = saveUserUseCase.Run(saveDto2)
if err != nil {
log.Fatal("Error saving user:", err)
}
// Find user by full name
findDto := FindUseCaseDto{
LastName: "Smith",
FirstName: "John",
}
foundUserDto, err := findUserUseCase.Run(findDto)
if err != nil {
log.Fatal("Error finding user:", err)
}
// Print found user details
fmt.Println("===Found User:===")
fmt.Printf("ID: %s\nLastName: %s\nFirstName: %s\nEmail: %s\nPost: %s\nIdlimit: %s\n",
foundUserDto.ID, foundUserDto.LastName, foundUserDto.FirstName, foundUserDto.Email, foundUserDto.Post, foundUserDto.Idlimit)
// Fetch and display all users
allUsers, err := userService.Repository.FindAllUsers()
if err != nil {
log.Fatal("Error fetching all users:", err)
}
fmt.Println("\n===All Users:===")
for _, user := range allUsers {
user.PrintUserDetails()
}
}
その4: pkg分け
。。。
結論
『集約の境界』&『依存関係逆転の原則(DIP)』がChatGPT3.5のおバカさんと相性が良い。
mapにデータ格納のDDDを作って、あとはAIに数秒で変更してもらう。
Discussion