Assignment 3: Convergent Design
September 26th, 2023
Table of Contents
Pitch
Have you ever wanted to share an interesting news article with your friends or family? Pulse is a platform that empowers you to curate, share, and discover current events through your social circles. Imagine a virtual library where you can view the thought-provoking content being consumed by those closest to you. No more scrambling to look for scattered recommendations; everything is neatly organized in one space. Pulse doesn't stop with organization. It's designed to be a social experience. You can create circles tailored to your different social groups – friends, family, colleagues, and more – ensuring that your content resonates with the right audience. Share your insights with them by annotating your findings with your most salient thoughts. Let Pulse reduce the noise of traditional social media and be your hub for organized, interactive content-sharing among your networks. Keep a pulse on what's happening-- stay informed, stay connected.
Concepts
Concept 1: User
Purpose - Provide authentication of users.
Principle - After a user registers with a username and password, they can authenticate as that user by providing a matching username and password.
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]
Purpose - Authenticate user for an extended period of time.
Principle - After a session starts (and before it ends), the getUser action returns the user identified at the start.
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]
Purpose - Provide access control to limit which users or groups of users can see a specific resource.
Principle - Place a user within a group to give them access to resources visible to that group.
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] += u
deleteMember(g: Group, u: User)
groups[g] -= 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] += u
deleteMember(g: Group, u: User)
groups[g] -= u
Concept 4: Post[User, Link, Note]
Purpose - Share content with others.
Principle - If a user shares a post with a set of users, those users will be able to see the post and its content. After a post is created, a user has the option to delete it.
State
posts: set Post
author: Post -> one User
content: Post -> String
link: Post -> one Link
note: Post -> lone Note
sharedWith: Post -> set User
posts: set Post
author: Post -> one User
content: Post -> String
link: Post -> one Link
note: Post -> lone Note
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]
Purpose - Share organized thoughts, reactions, or insights of a particular artifact.
Principle - For an artifact created by a user, that same user can create annotations to appear associated with the artifact.
State
notes: set Note
author: Note -> one User
content: Note -> String
notes: set Note
author: Note -> one User
content: Note -> String
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]
Purpose - Direct a user to content on another website.
Principle - Clicking a descriptive hyperlink on a post will redirect the user to the linked content.
State
description: Link -> String
url: Link -> String
description: Link -> String
url: Link -> String
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)
Dependency Diagram
Wireframes
Home page
Caption: The main feed. Posts are visible when a user has been added to one or more groups that have published a post.
New postCaption: To create a new post, a user is required to input a title, link, and enter a source. Optionally, the user may add a note and specify which circles the post should be visible to (otherwise, by default is shared with Everyone).
Edit circlesCaption: The user can create an empty circle or delete an existing circle. Additionally, they can add a user to a circle or remove them from a circle.
Design Tradeoffs
1. Merge friends and groups
a) Users can request to follow another user and be added to their group.
b) A user adds members to their own group.
Choosing b) allows users to directly add a user to a specific group, removing the intermediary step of accepting a follower then sorting that follower into an appropriate group. This design aligns with the app's vision for users to share content with their immediate social circles while proactively managing their networks.
2. User privacy over discoverability
a) Users can see what groups they're a member of and other members within the group.
b) Users can't see what groups they're in, or the other members.
Choosing b) protects the privacy of the user and reduces discoverability, which is a value that is central to this app. Adding connections directly instead of through mutual connections preserves the tight-knit community that this platform fosters.
3. Remove feed filters
a) Have all posts consolitated in one feed.
b) Allow user to filter posts they see based on groups or content topics.
While option b) might provide flexibility and some functionality to a user, several issues arise from this. A user's groups are composed of members that a user's post is shared with, but the reverse is not necessarily true. Filtering based on a user's own groups may not reflect the groups that they are a part of. In addition, filtering based on content topic would require users to manually enter topics that their chosen piece of content might relate to. To reduce this friction in the posting process, this design feature was tossed. Thus, option a) was chosen.
Sources:
The Essence of Software, Daniel Jackson