Consider a application that allows you to create, list and view blog-posts with photos.
However the application also gives a place where user can view all the photos they have added in all of their blog posts. User can also update captions of these photos individually.
Note we do not want the user to be able to add or delete or update a photo on its own. They can only do so in context of a blog.
For this purpose I need a list, update, create blog-post (with photos) API. I also need a seperate list and updateCaption API for the photos.
I am trying to understand how do I fit this in a repository pattern and DDD.
Considering repository is created per domain aggregate, I feel the best way is to have two repositories blogpost and photo. The blogpost repository has methods to update/create/list blog post with photos. And another photo repository which simply has a list and updateCaption method. Is this a correct implementation?
One concern that I have for this implementation is that I have photo as an aggregate root and as a entity in blogpost aggregate and it might not be a correct DDD/repository-pattern implementation.
In pkg repository/blogpost/
// in entity.go file
type BlogPost struct {
ID string
Name string
Author string
Content string
Photos []Photo
}
type Photo struct {
ID string
Caption string
URL string
}
// repository.go
type repository interface {
CreateBlogPost(context.Context, BlogPost) (BlogPost, error)
UpdateBlogPost(context.Context, BlogPost) (BlogPost, error)
ListBlogPosts(context.Context) ([]BlogPost, error)
}
In pkg repository/photo/
// in entity.go file
type Photo struct {
ID string
Caption string
BlogPostID int
URL string
}
// in repository.go file
type repository interface {
UpdateCaption(ctx context.Context, ID string, Caption string) (Photo, error)
ListPhotos(context.Context) ([]Photo, error)
}
There is no point in duplicating the
Photostruct/repository. What you have is two different repositories.Photois linked to a blog post using an ID.What you can do is handle this relation outside of the repository package. When a create request comes in, create the post in the
blogpostrepository and then create the photos in thephotorepository linked to thePostID.To get the photos for a post, create a method that returns photos linked to the given blog post:
photorepository:To create and retrieve posts and photos, consider a package name
serviceas an example:service:You should have different structs in your
servicelayer to avoid sending out repository structs. Basically convert repository structs to service structs and service structs to repository structs.It's also a good idea to run create methods inside of a transaction. You can use dependency injection to inject the transaction.