1. I spent about 5 hours on this assignment. Most of my time is creating tests and updating my server code to support the tests
2. I spent most of my time writing my tests and debugging my request handlers. Sometimes I did not understand why my request handlers were sending back a 404 request for specific tests when it expects a 200 status code.
3. I struggled thinking about what tests to create. I've thought a lot aabout complex tests that we may need to enforce protection regarding relationships among multiple tables, such as not being able to delete an author when we have an associated book in the table
1.Some of the issues that Typescript helped me prevent is not being able to get away from default and implicit assumptions of dynamic types in my code. IF I did want to use dynamic types, I would have to explcitly type out 'any', and that made me think more on how to craft my code with purpose and understand what I expect to return in everyone of my functions.
2. Kind of values I struggle to type correctly were what specfically I should expect to return in my handlers. Some holes in the system could be just explicitly using any for everything you return. While not perfect, at least there is a manual effort to say that, yes, I do want this type to be 'any', instead of in just plain Javascript, that's just the norm..
1. My experience writing tests were quite tedious and not rewarding for the most part. The only rewarding part is when my tests pass. I do realize that this is quite important when designing any API, because you want to at least test out what you know about the system as you develop your code, and refine as you learn your system more.
2.My tests helped find me some bugs such as an inconsistent database state when I trigger multiple endpoints in a row in a test.If I had not done this, then I would have an API that prevents data dependency issues.
3.I would structure my testing differently in the future by implementing more scalable testing, such as implementing more Insert queries, perhaps test more if the REST API is tolerable of large requests, albeit for a basic REST API prompt for this assignment, I would think more about testing regarding stress requests, traffic, and if it is tolerable of more requests that may remove interdependencies.
Initially, the back-end had limited filtering capabilities. As the front-end developed, I needed to enhance the endpoints to support ore complex queries, like searching by book ID, title, publication year, and genre. This required modifying the SQL queries to be more dynamic.
The initial back-end setup had basic error handling. With a more interactive front-end, I had to improve this to provide more descriptive errors to be useful for both debugging and informing the user of the frontend, especailly to return a status message after a request is sent.
In future projects, I would focus on creating a robust API from the start, anticpate more complex queries. Best REST API practices will be taken into account everytime I design an API moving forward
I've done more server validation than client-side validation in this homework assignment. Client-side validation improves the user experience because the client can be immediately notified of anything before any server interaction is required. Server-side validation is essential for security because it can do more validation with keeping details private, but can make the application possibly slower since we need to perform a full-stack trip. A combination of both can clarify what events are necessary for certain requests and actions
Manipulating state in React, especially with the 'useEffect' hook was a learning curve. Initially, managing side effects like API calls and syncrhonizing state with the server was challenging. This means to understand the dependencies of certain components and when components would be re-rendered. For example, fetching data when a component mounts and avoiding unecessary re-renders is important. With a simple application like this, I can start to realize that managing state can be a headache in complex web apps.
Building an SPA was challenging due to the complexity of state management and being exposed to some deep concepts from React's documentation. For example, React has a lifecycle, hooks, and a component architecture. I can see that React's learning curve can be steep when you want to develop complex web applications, so state management libraries seems valuable to me now. Developing an MPA felt more straight forward in terms of structuring the application. Each page was largely indepedent, and the flow of data was typically simpler. However, managing the server-side rendering and ensuring the consistency of the state across different pages is a different beast in MPAs I can imagine. I enjoy SPAs more right now since I'm in the "developing SPAs" mood, due to learning React right now.
I chose to integrate book editing and deletion functionalities directly into the table that lists the books. Each row of the book table has an "Edit" and "Delete" button. This design was chosen for its straightforwardness, allowing users to easily understand and use the functionalities.I struggled to confirm deletion actions because I needed to think about how to design the user experience to ensure the user wants to confirm to delete a book.
Transitioning into existing UI with Material UI was straighforward due to just replacing each HTML tag with its Material UI equaivalent. The most notable difficulty however is adjusting the custom styling originally to align with Material UI's styling system. Integrating Material UI's table components with dynamic data and actions, like editing and deleting, required a deeper understanding on how to embed sub componenets
Adding the editing endpoint and writing associated tests was challenging. Having previosuly implemented POST endpoints, I had a foundational understanding of handling HTTP requests and responses, which made the process smoother. Writing tests for the editing endpoint required careful consideration of various scenarios, including valid edits, attempts to edit non-existent books, and invalid input cases. Ensuring coverage to catch this bugs were time consuming and I had to mentally debug a lot.
I struggled with handling state managment for user authentication status effectively across different components. Implementing a user-friendly way to display error messages and feedback from the login process was difficult as well.
It was my first time learning about how to store and manage session information on the sever in a secure manner while keeping the API stateless. I learned about how to implemenet and test password hashing and comparison logic with argon2. By doing this, the login endpoint was more secure against possible vulnerabilities such as SQL injection
If my app was vulnerable to XSS attacks, I mitigated this by sanitize input on client side and server side
I do not think I did any exact implementation details to protect against CSRF attacks, but one could possibly use CSRF tokens in forms and verify these tokens on the server instead. I am not sure about more implementation
Rate limiting could be implemented by using express-rate-limit on the Node express server
HTTP headers are useful because we can set up Content-Security-Policy to prevent content from being loaded from any unauthorized resources. This improves web security