Assignment 4: Backend Design & Implementation
Overview. Congratulations! Over the last three weeks, you ideated and converged on a preliminary design for your social media app. Over the next four weeks, you’ll realize your design as a working backend and frontend implementation.
In this assignment, you’ll focus on your app’s backend (server-side) functionality. We will give you starter code that implements the functionality for some basic social media concepts including User
, WebSession
, Post
, and Friend
. Your job is to extend this code— adjusting these concepts as need be and adding additional concepts—so that you have a working implementation of the design you converged on in A3.
As you work through this assignment, you are likely to find that translating your abstract design ideas into code surfaces issues with your design that you had not previously anticipated. For example, perhaps you made some assumptions about how a concept would be used, or perhaps there are some ambiguities in your design. Feel free to make any changes to your conceptual design that you feel are necessary, but take careful notes on changes that you make. These notes will inform a brief design reflection that you’ll also submit, summarizing the changes you made and their rationales.
Purpose. This assignment helps you practice: (a) formulating concept states with abstract data models; (b) translating abstract data models into concrete data representations; (c) designing web service endpoints that conform to RESTful design principles; (d) implementing a client-server architecture using Node.js and Express.
Deadlines. The final version of this assignment is due in just under two weeks’ time (2:00pm on Wed Oct 11), but you must also submit an intermediate milestone midway through (11:59pm on Tues Oct 3) containing deliverables specified below. This milestone will only be graded for completion (i.e., have you submitted the required materials), and the assignment will be graded as a whole after the conclusion of the final deadline. Slack days may be used only to extend the final deadline; you must turn your milestone in by the associated deadline.
Your Tasks
-
Starter Code. Fork this GitHub repository by clicking the green “Use this template” button and selecting your personal GitHub account (we cannot use the
61040-fa23
GitHub organization due to limitations with the free tier of the deployment platform, Vercel). This repository contains starter code for the assignment, and theREADME.md
file describes its structure. Read through this file, follow the initial steps to install Node.js, Express and other necessary packages as well as register for the cloud-based services for MongoDB (your persistent data store) and Vercel (the deployment platform). Verify that you’re able to get the backend service running locally. -
Starter Code Tutorial. Read through the tutorial we’ve published to familiarize yourself with how the starter code is structured, and how it implements ideas we have covered in class thus far. Our starter code wraps Express.js to eliminate some common headaches, and to better align with concept design. So we strongly encourage you to read this tutorial even if you have prior experience working with this tech stack.
-
Data Modeling. For each of the concepts in your design from A3, create an abstract data model of the state, comprising, for each concept, a list of state variables, each declared to be a set, or a relation from one set to another. Make each concept as generic as possible, and include in the concept header (after the concept name) any type parameters. Write a definition of your app as a list of concepts, with type parameters instantiated appropriately, and draw a diagram (like those we looked at in lecture) showing the state of the entire app, with contours showing which subdiagrams belong to which concepts. (With the exception of the diagram, all of this was included in the previous assignment. This task gives you an opportunity to refine your previous work.)
-
Data Representation. Convert each of your data models into concrete representations (in TypeScript, these are denoted with the keyword
interface
). Your representation should comprise, for each concept, one or more documents (more properly, document collections) that extend theBaseDoc
provided in the starter code. -
RESTful Routes. For each of your concepts, expose their actions as routes (in
server/routes.ts
) that follow the RESTful principles discussed in lecture. In particular, URL paths should correspond to different resources and HTTP methods should indicate the operations that can be performed on the resource. When designing and implementing your routes, consider how to make your web service robust to malformed or erroneous requests, or access violations. Remember, too, that your web service is itself an interface (i.e., for frontend developers). So, how might you use appropriate HTTP status codes and error messages (found inserver/concepts/errors.ts
) to communicate why a request was rejected? -
Synchronizations. For each of your routes, define a controller function that supports the route by calling actions in your concepts. These functions are the implementations of your concept synchronization, along with some that support querying of concept states (often by combining queries of multiple concepts). In addition to implementing your routes in
server/routes.ts
, enumerate your routes inpublic/util.ts
to automatically extend the lightweight frontend interface for testing your implementation. -
Deployment. Deploy your code so that your backend service (and the provided GUI) can be accessed at a public URL. See the deployment guide in the
README.md
file for more instructions. -
Design Reflection. Once you have a working backend service, reflect on how implementing it affected your original conceptual designs. What ambiguities or omissions did you discover in your designs that needed to be resolved? What design decisions did you make to resolve them, and what was your rationale? What alternatives did you consider, and why did you reject them? Would you have done anything differently? Write a succinct summary (i.e., no more than 300 words) of your reflection, and post it to your portfolio.
Deliverables
You have two weeks to work on this assignment. After two weeks (i.e., by 2:00pm on Wed Oct 11), you should have a fully implemented and deployed backend service that is accessible at a public URL.
However, one week in (i.e., by 11:59pm on Tue Oct 3), we would like you to make a milestone submission to signal you are making adequate progress. This milestone will only be graded for completion (i.e., only to determine that you have submitted the required materials). Your milestone materials should include the following:
- Complete abstract data models for all concepts in your design posted to your portfolio.
- A full, working implementation for two concepts in your design beyond the four we provide you with.
- An initial deployment of your web service to Vercel. It is fine if you do not get things to work completely or correctly by the milestone deadline, but we would like to see you make a good faith attempt at deployment. In past years, deployment has proven trickier than students anticipated, so we’re eager to surface any problems early on so we can help you.
- An initial outline of the design of your RESTful routes for your remaining concepts. This outline need only comprise function declarations in
server/routes.ts
and associated documentation/comments—you may leave the function bodies (i.e., the controllers/concept synchronizations) empty.
To help make all parts of this assignment accessible, your portfolio should also provide prominent links to your backend code repository and deployed service.
Slack days may be used only to extend the final deadline; you must turn your milestone in by the associated deadline.
Submission
For the milestone submission, follow the two-step process from previous assignments (i.e., post necessary material to your portfolio, and submit the Google form to confirm your Git commit hash).
For the final submission, update or add new material to your portfolio. Then, submit the Google form twice: once with your portfolio URL and its Git commit hash, and second with your deployed backend service URL and the corresponding Git commit hash for your backend repo.
Rubric
Component | Excellent | Satisfactory | Poor |
---|---|---|---|
Data models | Simple and compact relational model of state for each concept that has no redundancies, and is sufficient to support actions | Relational model of state for each concept that is sufficient to support actions but may be needlessly complicated and include small redundancies | Models of state are insufficient to support actions or not clearly relational |
Genericity | Concepts are generic when possible, and genericity is clearly indicated by parameterized data models, and instantiated appropriately | Concepts are generic when possible and genericity is clearly indicated, but some opportunities for genericity are missing or instantiation is unclear | Concepts are not generic when they might be, or genericity is not clearly indicated |
Functionality | The deployed web service reflects all the functionality described by the operational principles and actions of your conceptual design | Most of the functionality described the operational principles and actions can be found in the deployed web service, but some actions or other parts are missing | Even the operational principles are not fully implemented in the deployed web service |
RESTful Design | All API endpoints are well-designed: paths map to resources and reflect appropriate hierarchical relationships, and HTTP methods indicate actions that can be performed resources | Most API endpoints follow RESTful principles, but some paths or HTTP methods are used in ways that might violate a developer’s expectations about RESTful endpoints | Several API endpoints violate RESTful principles |
Synchronizations | Synchronizations and queries that implement routes make appropriate use of concept actions, including actions that act as validators | Routes are implemented using concept actions but may be more complex than needed | Routes are not implemented appropriately in terms of concepts |
Robustness | Where appropriate, API endpoints anticipate malformed or erroneous input, or access violations; informative error messages and corresponding HTTP status codes are returned | API endpoints largely account for erroneous input or access violations, but some missed opportunities to improve robustness. Error messages and status codes are returned, but could be better chosen or more informative | Several API endpoints are not robust against malformed input or access violations (e.g., web service may crash). Custom error messages and appropriate HTTP status codes are not used, or are uninformative |
Design Reflection | A crisp and thoughtful summary of design issues that surfaced during implementation, discussing why they occurred, how they were resolved, and/or any tradeoffs or tensions involved | A clear identification of non-trivial design ambiguities or omissions, with a brief discussion of how they were addressed. However, design tradeoffs and/or tensions are not richly described. | A terse reflection that describes strawman issues or poorly explains design decisions |
Advice
Concept design
Refining your concepts. Make sure to use this opportunity to refine your concept design as your understanding of concepts has deepened. Perhaps you can focus the purpose of a concept more clearly, for example. Or perhaps you notice flaws that can be fixed, such as a concept having an intrinsic dependency on another concept (for example because it uses a type defined in the other concept).
Abstract data models
Reviewing materials. You may want to review the data model lecture slides for examples of state variable declarations and global data diagrams. See also the resource guide article on data modeling, and the tutorial on concept state.
Relations over more than two sets. You don’t need to have relations that involve three or more sets, because you can always introduce a “tuple set.” For example, to model the fact that a person has a salary at a company (a three-way relation), you could introduce a set of Job objects, each of which is mapped to a person, company and salary.
Multiplicities. A relation can map an object in one set to any number of objects in another set: exactly one (in which case it represents a total function); zero or one (a partial function); or any number (a general relation). Use the keywords one
, lone
and set
for these three cases.
Sequences. There’s no need for a special sequence constructor. A sequence of objects of some type T
can be viewed as an ordering (a relation T -> T
), or as a mapping from indexes to T
(a relation Int -> T).
Instantiaton of generics. In your application declaration, you should list each concept in the app, along with a list of types corresponding to its parameters. These types should be types that come from other concepts, and should be referred to as C.T
, where C
is the concept and T
is the type. For example, if your app included a generic Favorite concept in which the items being favorited were the tweets from the Tweet concept, and a Follower concept in which the parties following and being followed were the users of the User concept, and the published items were tweets, you might write something like:
app Twitter
concepts
Tweet
User
Favorite [Tweet.Tweet]
Follower [User.User, Tweet.Tweet]
Web Service Implementation
Collaboration and ChatGPT. As a reminder, our class guide encourages you to collaborate with other students as long as you actually write up your work by yourself and note the set of people you collaborated with. Moreover, you’re welcome to use ChatGPT (or other generative AIs) to help with this assignment; if you do so, however, you should include a brief note in your portfolio describing how you used it.
Third-party code. Similarly, as per our class guide, you are free to use any third-party code (whether as libraries, Node packages or code snippets) provided that it is publicly available and appropriately cited (see the section on code in the MIT handbook on academic integrity for more details).
Consult documentation. Express and MongoDB are both widely used packages, with extensive documentation that provide useful references.
Code quality. While we will not be grading your code, we expect you to organize your code thoughtfully, with appropriate structure, names, comments, etc. If you write sloppy code, you will likely find it harder to achieve reliable functionality (which we will be grading).
Code modularity. Following the structure of the starter code, ensure that each concept is implemented in its own module, and that concept modules have no dependences on each other.
Keep detailed notes. In our experience, it’s often hard to look back on your design and implementation process and “un-see” the solution you’ve crafted. Once you’re done with your implementation, your web service will feel like the only or most obvious way to address any design problems that cropped up. And, chances are, you will have a difficult time remembering the alternatives you had considered.
Consider keeping a lightweight notebook to document your progress. This might comprise just a collection of bullet points that describe what you’re currently working on, what issues you are hoping to address, why you believe an idea might work, and what limitations or problems you encounter along the way. You can then synthesize your design reflection from your notebook, and doing so will feel easier, more productive, and yield a more compelling reflection.