How would you organize Contexts for Twitter tables?

Hi everyone I’m making a video on making a Twitter clone w/ phoenix 1.7, and I was wondering how’d best to structure the context here’s what I got, but I’m not too sure.

timeline/
├─ likes/
│  ├─ like.ex
├─ posts/
│  ├─ post.ex
├─ likes.ex
├─ posts.ex

I’m referencing Chris’ video for when he did it with 1.5 but I wanted to go a bit further and also go over the new things with 1.7

Anyways, would love feedback on how best to structure things. Also, if anyone wants anything added to the video, let me know, and I’ll try and do it.

3 Likes

You can maintain all post interactions, eg. like, retweet, reply on the post context, because they are fully related to posts (tweets)

1 Like

I would do:

/lib
  /tweets
    /like.ex
    /tweet.ex
    /retweet.ex
  tweets.ex

  /timelines
    /timeline.ex
  timelines.ex

I don’t know what a Post is in this context. Is it like a type of Tweet? If so, keep it in the /tweets folder/context.

1 Like

To echo @sergio, definitely call them tweets and not posts to keep the domain language aligned. I also think their suggestion is solid. I would also consider:

...
/timelines
  /entry.ex
timelines.ex
...

It doesn’t have to be Entry but Timeline to me reads like the “master list of entries belonging to a user” whereas Entry would be the linking table between User and Tweet (and stuff like ordering and other metadata). If Timeline is the master list, then you still need Entry (like maybe holds info on how a timeline is managed for a specific user… I dunno… I honestly don’t know very much about twitter). It all depends on how you draw the relationships.

I would also consider making Likes its own context. If things other than tweets can be liked, this makes it more reusable as a polymorphic app-level context. Otherwise, I would do this:

...
/tweets
  /likes
    /like.ex
  /likes.ex
  /tweet.ex
  /retweet.ex
...

ie, create a Likes sub-context, put all the like-related logic in it, and then delegate from the Tweets context as not to exposed inner modules:

# tweets.ex
#...
alias MyApp.Tweets.Likes

defdelegate like_tweet, to: Likes
defdelegate unlike_tweet, to: Likes

# etc...

This just keeps things neater, imo.

1 Like

Wow thank you for this! I think I’ll go with this approach. @sergio thank you as well!

I’m not sure why I struggle so much with the DDD concept :sweat_smile:

1 Like