Skip to content

Assignment 4: Backend Design & Implementation

Abstract Data Models

All of these were taken from here

User

User State Machine

concept User

purpose authenticate a partipicant of RealTalk

state

registered: set User
username, password: registered -> one String

actions

register(n, p: String, out u: User)

u not in registered
registered += u
u.username := n
u.passowrd := p

authenticate(n, p: String, out u: User)

u in registered
u.username = n and u.password = p

operational principle

after a user registers with a username and password, they can authenticate with that same username and password
after register(n, p, u), u in registered, u.username = n, u.password = p; authenticate(n, p, u') results in u = u'

Session

Session State Machine

concept Session [User]

purpose authenticate users for an extended period of time

state

active: set Session
curUser: active -> one User

actions

start(u: User, out s: Session)

s not in active
active += s
s.curUser = u

end(s: Session)

s in active
active -= s

getUser(s: Session, out u: User)

s in active
u := s.curUser

operational principle

after a session starts until it ends, getUser returns the same user that started the session
after start(u, s) until end(s, u), getUser(s, u') results in u = u'

Friend

Friend State Machine

concept Friend [User]

purpose increase connections between others

state

friends: User -> set User

actions

friend(u1, u2: User)

u1.friends += u2
u2.friends += u1

unfriend(u1, u2: User)

when u2 in u1.friends
u1.friends -= u2
when u1 in u2.friends
u2.friends -= u1

areFriends(u1, u2: User, out b: Boolean)

when u2 in u1.friends or u1 in u2.friends
b := True
otherwise
b := False

operational principle

after a user friends another user, they are both considered each others friends until one of them unfriends the other
after friend(u1, u2) until unfriend(u1, u2), u2 in u1.friends, u1 in u2.friends, and areFriend(u1, u2, b) results in b = True

Post

Post State Machine

concept Post [User, Content]

purpose share content with others

state

posts: User -> set Post
content: Post -> one Content
author: Post -> one User

actions

post(u: User, c: Content, out p: Post)

p.content := c
p.author := u
u.posts += p

unpost(u: User, p: Post)

when p in u.posts u.posts -= p
forget content of p
forget author of p

operational principle

after post(u, p, c) until unpost(u, p), p in u.posts, u = p.author, and c = p.content

Comment

Comment State Machine

concept Comment [Target, User, Content]

purpose react to other content

state

comments: Target -> set Content
author: Content -> one User

actions

comment(t: Target, u: User, c: Content)

t.comments += c
store u as author c is from

uncomment(t: Target, u: User, c: Content)

when the author of c is u
t.comments -= c
forget author of c

operational principle

after comment(t, u, c) until uncomment(u, c), c in t.comments and u is author of c

Like

Like State Machine

concept Like [Target, User]

purpose show approval or disapproval of information

state

likes, dislikes: Target -> set User

actions

like(t: Target, u: User)

t.likes += u

dislike(t: Target, u: User)

t.dislikes += u

neutralize(t: Target, u: User)

when u in t.likes
t.likes -= u
when u in t.dislikes
t.dislikes -= u

operational principle

after like(t, u) until dislike(t, u) or neutralize(t, u), u in t.likes
after dislike(t, u) until like(t, u) or neutralize(t, u), u in t.dislikes

Trust

Trust State Machine

concept Trust [Target, User]

purpose show agreement or disagreement with the truthfulness of information

state

trusts, mistrusts: Target -> set User

actions

trust(t: Target, u: User)

t.trusts += u

mistrust(t: Target, u: User)

t.mistrusts += u

neutralize(t: Target, u: User)

when u in t.trusts
t.trusts -= u
when u in t.mistrusts
t.mistrusts -= u

operational principle

after trust(t, u) until mistrust(t, u) or neutralize(t, u), u in t.trusts
after mistrust(t, u) until trust(t, u) or neutralize(t, u), u in t.mistrusts

Karma

Karma State Machine

concept Karma [User]

purpose show how truthful a user is

state

karma: User -> one Integer

actions

increase(u: User)

when u in karma
u.karma := u.karma + 1
when u not in karma
u.karma := 1

decrease(u: User)

when u in karma
u.karma := u.karma - 1
when u not in karma
u.karma := -1

operational principle

after increase(u) until decrease(u), u.karma is 1 more than before
after decrease(u) until increase(u), u.karma is 1 less than before

App State Diagram

App State Diagram

Design Reflection

When designing comments, likes, and trusts, I did not consider that I would have to ensure their target existed before trying to apply the comment, like, or trust to the target. When actually implementing comments and likes, I realized I had to check to make sure a comment wasn't applied to a comment, or a like wasn't applied to a user. I did this by checking the ObjectId of the target and ensuring it existed as a post. I could have allowed commenting, liking, or trusting any target, but this could result in liking likes which is extremely strange for a social media.

When implementing the karma system dependent on trusts and mistrusts, I ran into two bugs that allowed infinite karma farming. The first bug was simply trusting over and over again. Even though an error was returned, the backend code didn't check for an error before increasing karma. This was easily fixed by checking for an error before touching karma. The second bug was more complicated. User A could trust, mistrust, and then neutral trust User B's post or comment, causing a net karma of +1. This was caused by the backend code not checking the previous trust state of a target. For example, a trust would always give +1 karma, even if the post was previously mistrusted by the same person. In that case, it should give +2 to offset the -1 from a mistrust, and vice versa for trust to mistrust.

Backend Code

Deployed Service