Assignment 4: Backend Design & Implementation (beta)
Data modeling
Abstract data model
concept User
purpose
provide authentication
principle
after registration, returns the object associated with provided credentials if they're right
state
// User is a class defined within the User concept
username, password: User -> one String
actions
register(name, pwd: String, out u: User)
getUserById(id: String, out u: User)
getUserByUsername(username: String, out u: User)
// returns usernames of each id provided
idsToUsernames(ids: set String, out u:)
// if empty, returns all users
getUsers(username?: String)
authenticate(username, password: String)
update(id: String, update, out u: User)
delete(id: String)
userExists(id: string)
// checks if username and password are adequate for registration
canCreate(username: String, password: String)
// checks whether a username already exists
isUsernameUnique(username: String)
concept User
purpose
provide authentication
principle
after registration, returns the object associated with provided credentials if they're right
state
// User is a class defined within the User concept
username, password: User -> one String
actions
register(name, pwd: String, out u: User)
getUserById(id: String, out u: User)
getUserByUsername(username: String, out u: User)
// returns usernames of each id provided
idsToUsernames(ids: set String, out u:)
// if empty, returns all users
getUsers(username?: String)
authenticate(username, password: String)
update(id: String, update, out u: User)
delete(id: String)
userExists(id: string)
// checks if username and password are adequate for registration
canCreate(username: String, password: String)
// checks whether a username already exists
isUsernameUnique(username: String)
concept Session[User]
purpose
provide authentication for extended period
principle
after a session starts (and before it ends), authentication won't be needed again, until the session is ended.
state
// if a session goes inactive, it's removed from
// the relation
user: Session -> one User
actions
start(u: User, out s: Session)
getUser(s: Session, out u: User)
end(s: Session)
isLoggedIn(s: Session)
isLoggedOut(s: Session)
concept Session[User]
purpose
provide authentication for extended period
principle
after a session starts (and before it ends), authentication won't be needed again, until the session is ended.
state
// if a session goes inactive, it's removed from
// the relation
user: Session -> one User
actions
start(u: User, out s: Session)
getUser(s: Session, out u: User)
end(s: Session)
isLoggedIn(s: Session)
isLoggedOut(s: Session)
concept Tag[Post]
purpose
provide systematic classification
principle
after associating tags to objects, when given a determined tag, returns
all posts with that tag associated
state
// Tag is a class defined within the Tag concept
attachments: Tag -> many Post
actions
getAllWithTag(tag: Tag, out u: set Post)
createAttachment(tag: Tag, post: Post)
deleteAttachment(tag: Tag, post: Post)
createTag(name: String, out u: Tag)
deleteTag(tag: Tag)
getTagByName(name: String, out u: Tag)
concept Tag[Post]
purpose
provide systematic classification
principle
after associating tags to objects, when given a determined tag, returns
all posts with that tag associated
state
// Tag is a class defined within the Tag concept
attachments: Tag -> many Post
actions
getAllWithTag(tag: Tag, out u: set Post)
createAttachment(tag: Tag, post: Post)
deleteAttachment(tag: Tag, post: Post)
createTag(name: String, out u: Tag)
deleteTag(tag: Tag)
getTagByName(name: String, out u: Tag)
concept Thumbnail[Post]
purpose
create images that convey the tone of a text
principle
for every post, there'll be a thumbnail, a visual representation of the tone in the text.
state
// Thumbnail is a class defined within the Thumbnail concept
thumbnails: Thumbnail -> many Post
actions
createThumbnail(content: Post, out u: Thumbnail)
concept Thumbnail[Post]
purpose
create images that convey the tone of a text
principle
for every post, there'll be a thumbnail, a visual representation of the tone in the text.
state
// Thumbnail is a class defined within the Thumbnail concept
thumbnails: Thumbnail -> many Post
actions
createThumbnail(content: Post, out u: Thumbnail)
concept Feed[Post, User]
purpose
bring together content from multiple sources into a single, centralized location
principle
add objects to a feed, that can be retrieved when lookup (sorted differently according to whom it belongs)
state
composition: Feed -> set Post
assignment: Feed -> one User
actions
// if feed doesn't exist, creates one
getFeedByUser(user: User, out u: Feed)
getFeedById(id: String, out u: Feed)
removeFromFeed(user: User, post: Post)
addToFeed(user: User, post: Post)
concept Feed[Post, User]
purpose
bring together content from multiple sources into a single, centralized location
principle
add objects to a feed, that can be retrieved when lookup (sorted differently according to whom it belongs)
state
composition: Feed -> set Post
assignment: Feed -> one User
actions
// if feed doesn't exist, creates one
getFeedByUser(user: User, out u: Feed)
getFeedById(id: String, out u: Feed)
removeFromFeed(user: User, post: Post)
addToFeed(user: User, post: Post)
concept Post[User]
purpose
allow users to contribute to the community
principle
after creating content, it is made into an object that allows removing and editing
state
// Post is a class defined within the Post concept
author: posts -> User
content: posts -> String
actions
create(author: User, content: String, out u: Post)
// Given a series of selections, returns all posts that
// satisfy that filter
getPosts(query, out u: set Post)
getByAuthor(author: User, out u: set Post)
update(post: Post, update)
delete(post: Post)
isAuthor(user: User, post: Post)
concept Post[User]
purpose
allow users to contribute to the community
principle
after creating content, it is made into an object that allows removing and editing
state
// Post is a class defined within the Post concept
author: posts -> User
content: posts -> String
actions
create(author: User, content: String, out u: Post)
// Given a series of selections, returns all posts that
// satisfy that filter
getPosts(query, out u: set Post)
getByAuthor(author: User, out u: set Post)
update(post: Post, update)
delete(post: Post)
isAuthor(user: User, post: Post)
concept Sort[View, Post, Algorithm]
purpose
sorts a set of object by their view using Algorithm as sorting algorithm
principle
when asked about highlights, Sort takes in all posts of the specified
date and sorts them by views (more to less).
state
collection: View -> Post
actions
// creates a new entry post -> iniVal
create(post: Post, iniVal: View)
sort(posts: set Post, out u: set Post)
// updates the number of views for post
update(post: Post, toAdd: View)
delete(post: Post)
concept Sort[View, Post, Algorithm]
purpose
sorts a set of object by their view using Algorithm as sorting algorithm
principle
when asked about highlights, Sort takes in all posts of the specified
date and sorts them by views (more to less).
state
collection: View -> Post
actions
// creates a new entry post -> iniVal
create(post: Post, iniVal: View)
sort(posts: set Post, out u: set Post)
// updates the number of views for post
update(post: Post, toAdd: View)
delete(post: Post)
app ADDapp
include User
include Session
include Post
include Feed[Post.Post, User.User]
include Thumbnail[Post.Post]
include Tag[Post.Post]
include Sort[Number, Post.Post, regular sorting of numbers]
app ADDapp
include User
include Session
include Post
include Feed[Post.Post, User.User]
include Thumbnail[Post.Post]
include Tag[Post.Post]
include Sort[Number, Post.Post, regular sorting of numbers]
Diagram
Design reflection
While implementing the Thumbnail concept, I faced a dilemma: I needed to perform two distinct tasks – generating a prompt from a post and creating an image based on that prompt. Initially, I contemplated splitting these tasks into separate concepts like PromptGenerator and ImageGenerator, as they could have broader applications, such as creating prompts from any text or generating images from any text. However, this approach seemed overly granular, potentially confusing future code readers, including myself. Managing the synchronization between two narrowly defined concepts could also harm modularity. Therefore, I opted to combine both tasks within a single concept, given the low likelihood of needing their individual functionalities in the future.
Another challenge was determining where to implement post filtering by date. While only the Sort feature required post filtering, I questioned whether this should be the exclusive responsibility of Sort. However, to avoid duplicating posts in Sort every time a new post was created and to minimize memory usage, I integrated the date filtering into the Post concept. This decision ensured flexibility for potential future features dependent on date filtering.
In designing the Sort concept, my initial idea was to sort posts based on their views and update view counts by increments. However, I recognized the value of making this concept more versatile. Instead of limiting it to numerical views and ascending sorting, I generalized it. The "view" parameter could be of any type, and the sorting algorithm could follow any criteria. Additionally, the update function for a "view" could accommodate various operations as desired by the user. This versatility allows for future adaptability in diverse scenarios, hence the decision to implement it with a custom link (of type T), a custom sorting algorithm, and a custom update function.