Skip to content

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

diagram

Wireframes

Home page
home pageCaption: The main feed. Posts are visible when a user has been added to one or more groups that have published a post.

New postnew post pageCaption: 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 circlescircles pageCaption: 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.

Figma Link: https://www.figma.com/file/2WhNvbzESMh88Wm9Jo6dkG/Assignment-3?type=design&node-id=0%3A1&mode=design&t=KwNxrW7u2lYdqVfj-1

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