Skip to content

Feedback + some issues I faced with an idiomatic structure/ non layered structure #40

@dumindu

Description

@dumindu

Describe the feature

First of all, Thanks a lot working on Gorm from v1 to cli generators. Really enjoyed the dev process, preloads and docs.

1. Idiomatic folder structure

As the layered architecture considered not quite idiomatic in Go, I tried to create some usecase / modular way to keep the handler, model, repository together in each case, instead of put all models, all repositories, all filters as layers.

// 💡 Example: a simple bookshelf 

├── app
│   ├── book
│   │   ├── bookrepo      # 💡generated with gorm-cli via the interface in book/repository.go
│   │   │   └── repository.go
│   │   ├── form_util.go
│   │   ├── handler.go
│   │   └── repository.go
│   └── router
│       └── router.go

In the beginning I tried to put form and model inside app/book but due to circular dependencies I had to move model(entities) / form outside folders. It may make sense as shared preloads. I used bookrepo as It can have more than 1 repo/ repo interfaces, inside that module. So, repositories auto generate per usecase/ module. (Project can have duplicated repo func but all autogenerated and isolated to the usecase folder/ module.

About filters, first issue I got is that it uses same Struct name and can't place same place together with Model.

My suggestion: Assume we use modular usecase folder isolation; handler.go, model.go, repository.go together,

  1. Use filename_gen.go instead of separate "generated" folder for generated files. And all in together. Use IRepo for interface and Repo for Struct.
  2. Allow generate repo functions from an interface + allow add extra manually to same repo when auto generated not enough: in the same place.

This way code can kept more idiomatic and groups related files by usecase/ module, instead of layers.

2. Formatting

I used following for bookshelf CRUD.

  1. We can't use same model name as the variable name. ex @book.Title . Used data instead book
  2. Most IDEs underlines comments when not started with same func name. ListBooks comment should start with // ListBooks .... As I understood, this breaks the generated SQL
  3. Queries in comment can't divide into multiple lines sometimes. Example VALUES on insert. When the table getting bigger this might be an issue. Is this a design choice/ constrain or I'm wrong here?
  4. Suggestion: If the cli can generate multiple files(1 per each RepoInterface) from 1 Query file, we can keep all interface in 1 file and generate multiple repo files per interface.
//go:generate gorm gen -i repository.go::IBookRepo -o bookrepo
type IBookRepo interface {
	// SELECT * FROM books LIMIT @limit OFFSET @offset
	ListBooks(ctx context.Context, limit int64, offset int64) (model.Books, error)

	// INSERT INTO books (id, created_at, updated_at, title, author, published_date, image_url, description) VALUES (@data.ID, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, @data.Title, @data.Author, @data.PublishedDate, @data.ImageURL, @data.Description)
	// RETURNING *
	CreateBook(ctx context.Context, data *model.Book) (*model.Book, error)

	// SELECT * FROM books WHERE id = @id
	ReadBook(ctx context.Context, id uuid.UUID) (*model.Book, error)

	// UPDATE books
	// SET updated_at=CURRENT_TIMESTAMP, title=@data.Title, author=@data.Author, published_date=@data.PublishedDate, image_url=@data.ImageURL, description=@data.Description
	// WHERE id = @data.ID
	// RETURNING *
	UpdateBook(ctx context.Context, data *model.Book) (*model.Book, error)

	// DELETE FROM books WHERE id = @id
	// RETURNING true
	DeleteBook(ctx context.Context, id uuid.UUID) (bool, error)
}

Thanks again for your work.

Motivation

  1. Keep the codebase not layered and keep more idiomatic.
  2. Understand code organization and best practices while using GORM CLI.
  3. Understand formatting query comments into multiple lines

Related Issues

https://github.com/learning-cloud-native-go/myapp/tree/main/app/book (Not a direct issue) Just wanna understand anything missing or can improve

Thanks

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions