Assignment 4: Backend Design & Implementation (Beta)
October 12th, 2023
Concept States
Concept 1: User
State:
registered: set User
username, password: registered -> one String
registered: set User
username, password: registered -> one String
Actions
register(n: String, p: String, out u: User)
u not in registered
registered += u
u.username := n
u.password := p
authenticate(n, p: String, out u: User)
u in registered
u.username = n and u.password = p
register(n: String, p: String, out u: User)
u not in registered
registered += u
u.username := n
u.password := p
authenticate(n, p: String, out u: User)
u in registered
u.username = n and u.password = p
Concept 2: Session[User]
State:
active: set Session
user: active -> one User
active: set Session
user: active -> one User
Actions
start(u: User, out s: Session)
s not in active
active += s
s.user := u
getUser(s: Session, out u: User)
s in active
u := s.user
end(s: Session)
active -= s
start(u: User, out s: Session)
s not in active
active += s
s.user := u
getUser(s: Session, out u: User)
s in active
u := s.user
end(s: Session)
active -= s
Concept 3: Group[User]
State:
groups: set Group
name: Group -> one String
admin: Group -> one User
members: Group -> set User
groups: set Group
name: Group -> one String
admin: Group -> one User
members: Group -> set User
Actions
create(u: User, n: String)
groups += Group (name=n, admin=u, members = {})
delete(g: Group)
groups -= g
addMember(g: Group, u: User)
groups[g]['members'] += u
deleteMember(g: Group, u: User)
groups[g]['members'] -= u
create(u: User, n: String)
groups += Group (name=n, admin=u, members = {})
delete(g: Group)
groups -= g
addMember(g: Group, u: User)
groups[g]['members'] += u
deleteMember(g: Group, u: User)
groups[g]['members'] -= u
Concept 4: Post[User]
State:
posts: set Post
author: Post -> one User
content: Post -> String
sharedWith: Post -> set User
posts: set Post
author: Post -> one User
content: Post -> String
sharedWith: Post -> set User
Actions
create(a: User, n: Note, c: String, l: Link, s: set User, out post: Post)
post := Post (author=a, content=c, link= l, note=n, sharedWith=g)
posts += post
delete(post: Post)
posts -= post
view(u: User, p: Post, out p: Post)
if u in p.sharedWith return p
create(a: User, n: Note, c: String, l: Link, s: set User, out post: Post)
post := Post (author=a, content=c, link= l, note=n, sharedWith=g)
posts += post
delete(post: Post)
posts -= post
view(u: User, p: Post, out p: Post)
if u in p.sharedWith return p
Concept 5: Note[User, Post]
State:
notes: set Note
author: Note -> one User
content: Note -> String
target: Note -> lone Post
notes: set Note
author: Note -> one User
content: Note -> String
target: Note -> lone Post
Actions
create(a: User, c: String, post: Post)
note := Note (author=a, content=c)
notes += note
post += note
create(a: User, c: String, post: Post)
note := Note (author=a, content=c)
notes += note
post += note
Concept 6: Link[Post]
State:
description: Link -> String
url: Link -> String
paywall: Link -> one Boolean
target: Link -> one Post
description: Link -> String
url: Link -> String
paywall: Link -> one Boolean
target: Link -> one Post
Actions
create(d: String, u: String, post: Post)
link := Link (description=d, url=u)
post += link
create(d: String, u: String, post: Post)
link := Link (description=d, url=u)
post += link
Synchronizations
include User
include Session[User.User]
include Group[User.User]
include Post[User.User, Link.Link, Note.Note]
include Note[User.User, Post.Post]
include Link[Post.Post]
sync createUser(n: String, p: String)
User.register(n, p)
Group.create(n, "Everyone")
sync startSession(n: String, p: String)
User.authenticate(n, p)
Session.start
sync createLink(d: String, u: String)
Link.create(d, u)
sync createNote(a: User, c: String)
Note.create(a, c)
sync createGroup(u: User, name: String)
Group.create(u, name)
sync addGroupMember(g: Group, u: User)
Group.addMember(g, u)
sync removeGroupMember(a: User, u: User, g: Group)
Group.deleteMember(g, u)
sync createPost(u: User, n: Note, c: String, l: Link, g: Group)
Post.create(u, n, c, l, g)
sync viewPost(u: User, p: Post)
Post.view(u, p)
include User
include Session[User.User]
include Group[User.User]
include Post[User.User, Link.Link, Note.Note]
include Note[User.User, Post.Post]
include Link[Post.Post]
sync createUser(n: String, p: String)
User.register(n, p)
Group.create(n, "Everyone")
sync startSession(n: String, p: String)
User.authenticate(n, p)
Session.start
sync createLink(d: String, u: String)
Link.create(d, u)
sync createNote(a: User, c: String)
Note.create(a, c)
sync createGroup(u: User, name: String)
Group.create(u, name)
sync addGroupMember(g: Group, u: User)
Group.addMember(g, u)
sync removeGroupMember(a: User, u: User, g: Group)
Group.deleteMember(g, u)
sync createPost(u: User, n: Note, c: String, l: Link, g: Group)
Post.create(u, n, c, l, g)
sync viewPost(u: User, p: Post)
Post.view(u, p)
Data Model Diagram
Design Reflection
One of the design features left ambiguous was regarding a "draft" feature. In the case where a draft might exist, a user first creates a post just visible to themselves, or published to no groups. They would optionally take the next step to publish it to one or more groups, otherwise it would just stay put in its draft state. I decided instead to allow the user the option to either specify a group to publish to, or by default publish to all groups. This would reduce the friction needed to make a post in general, and also encourage publishing content to a wider audience. Another design decision that I made was to keep track of links and notes by using "targets" in each concept, keeping a record of which post each annotation is linked to. An alternate option would be to keep track of this information in each post, but I chose the target approach to reduce complexity, so the database can manage notes and links by themselves as opposed to through the post concept. For example, features such as getting the links of each post is useful if the user wants a condensed version of their feed. Nested deletion is still used in this representation, so deleting one post will delete its associated link and note.
Links
Backend repository: https://github.com/anna8murphy/pulse-backend
Vercel deployment: https://pulse-backend.vercel.app/