# 2104-GHP-NY-WEB-FT: Week 2 Notes
## Client/Server Architecture
Client/server describe two roles in communication
- Clients initate requests for information
- Servers respond with the information
Some examples of clients are:
- Browser
- Desktop App
- Mobile App
- Postman/API Testing Client
- Smart Devices
A server is a program running on a computer connected to the internet, and its purpose is to serve content requested by remote clients. Servers are an integral piece of web applications.
## HTTP
Keywords:
- HTTP
- Protocol
- HTTP Verbs
HTTP facilitates the connection and data exchange between clients and servers using the request-response cycle
A protocol is a set of rules that determines how data is transmitted
### Main HTTP Verbs We Use
- GET - fetching data
- POST - creating data
- PUT - updating data
- DELETE - deleting data
These correspond to what we refer to as CRUD app operations:
- C - create
- R - read
- U - update
- D - delete
### What are the categories of HTTP status codes?
- 2xx: Okay, things went as expected
- 3xx: Further information/guidance is returned. Most commonly this is a URL level redirect ("look somewhere else")
- 4xx: Client Problems. Often correctable, or at least explainable. Usually has to do with the client requesting a resource that doesn't exist
- 5xx: Errors. Typically this is a catastrophic error that cannot be correct by the client. The server is unreachable, or crashed in some way
### Request-response Cycle
The flow of data from client to server and back. 1 request, 1 response.
## Node
Keywords and concepts:
- Node
- Modules/NPM
- Synchronous Programming
- Asynchronous Programming
- Event loop
- Promises
### What is Node?
Node.js is a JavaScript runtime environment built on Chrome’s V8 engine, and it allows us to run JavaScript code on our operating system. We can build servers for our applications using Node.js
### What are modules?
Modules (we can also call them files) are collections of organized code which can be reused throughout the Node application. There are 3 types of modules:
- Core modules (ones that are built in such as `http`, `path`, `fs`)
- Local modules (ones we define ourselves)
- Third party modules (provided to us from NPM)
### What is NPM?
NPM is a command line tool that installs or uninstalls Node packages. It also is an online repository for open source Node packages.
### What is synchronous programming?
In synchronous programming, only one thing can happen at a time, which means that when a function is called, any subsequent function calls are not run until the first function call completes. This is often referred to as blocking code.
### What is asynchronous programming?
Contrastingly, asynchronous programming, or non-blocking code, allows multiple things to happen at the same time. In other words, the execution order is not dependent on the command order. Asynchronous programming in JavaScript is event based, which means that when a function is executed, it kicks off some external process and registers an event handler (i.e. callback function) for when that process finishes. The callback function will execute when the process finishes
### What is the Event Loop?
The Event loop is the way Node achieves asynchrnous programming. As we know, JavaScript runs executing programs synchronously in the call stack. But when it get to a piece of code that is asynchronous (promises, using something like setTimeout), that piece of code will be put onto a queue to be executed later while Node processes the rest of the code. When later comes, the event loop processes the stuff in the queue and sends it back to the call stack
### What is a Promise?
A promise is a JavaScript object that represents the eventual resolution of an asynchrounous action. This is similar to a sandwich counter. When you order your sandwich, they give you a ticket. Once the sandwich is ready, your number is called out.
### What are the advantages of Promises over callbacks?
Promises are portable values (objects) that can be passed to where they are needed. They give "consequences" in JavaScript. We can keep track of the status of what is happening when we issue some sort of request over the internet. When we get our Promise back, we can then tell it what to do.
Contrast to callbacks where we don't really have a way to keep track of what happens when it goes to the internet as well as the fact that we need to send in a function that will execute as soon as it is done.
### Where can you use `async` and `await`?
`async` is placed in front of a function definition. `await` can ONLY be used inside of an `async` function.
If you do not `await` inside an `async` function, you will be returned with a promise
```javascript=
async function main () {
console.log(await promisifiedReadFile('./path-to-file.txt', 'utf-8')
}
main()
```
Or if using arrow functions:
```javascript=
const main = async() => {
console.log(await promisifiedReadFile('./path-to-file.txt', 'utf-8')
}
main()
```
#### Why use `async/await`?
It makes our code **look** more synchronous so it's easier (arguably) to read and write
## Express
The Express library allows us to easily create servers in Node and handle requests from the client via route handling. The library is an abstraction over Node’s built-in http module
### Express Routes
A set of methods that come from the HTTP verbs that describe what we are doing with some data being passed back and forth
### API
A set of Express routes (not exclusive to Express) make up an API. An API is how two applications communicate and share data. Whenever we are using some type of application, say, Facebook Messenger, we are using an API. The application is passing data back and forth behind the scenes for us to be able to use the application.
When we write our APIs, we are defining the set of the data that we want our application to use. Note: This doesn't have to be data we "expose" externally like using a Food API to get a list of food.
### Express Middleware
Middleware is a term used to describe functions that are executed in between the server receiving the request (req) and responding with a response (res). Middleware functions are often responsible for parsing requests, logging, and handling errors.
Another use cause is login. We will use middleware to check if someone can access the page they are trying to access
### `next` parameter in Express Routes
The `next` parameter is a function in Express which, when invoked, executes the middleware after the current middleware. If the current middleware function doesn’t end the request-response cycle by sending a response, it must call next() to pass the request to the next middleware function. Otherwise, the request is left hanging.
### `app.use` vs `app.get`
- app.get is only used for GET requests and the URL specified in the route must exactly match the URL in the request in order for the code in that route to execute
- app.use handles all verbs (GET, POST, PUT, DELETE) and the URL specified in the route must start with the URL in the request in order for the code in that route to execute
### URL Parameters in Express
URL parameters are accessible in the the params property of the request object (req.params). If the Express route is “/puppies/:id”, Express will interpret the colon as a wildcard and attach whatever is after “/puppies/” to req.params. Therefore, if the request URL was “/puppies/100”, then req.params.id = 100 in the Express route. For the same request, if the Express route was “/puppies/:puppyId”, then req.params.puppyId = 100
### How are URL queries handled in Express routes?
URL queries are accessible in the query property of the request object (req.query). If the URL is something like "/users/billy/tasks?status=complete", Express will intrepret the question mark as the start of a query and will place whatever is after in `req.query`. So above URL would generate an object on req.query that looks like `{ status: 'complete' }`. In addition, you can have multiple key-value pairs on a query. You would use the ampersand (&) to separate them. Example: "/users/billy/tasks?status=complete&topic=programming"
### What is `req.body?`
When submitting (usually) form data and we have appropriate body-parsing middleware, the form entries will be attached to the `req.body`. So, if we had a form that had name and email and we submitted it with values of Ben and ben@ben.com, `req.body` would look like: { name: 'Ben', email: ben@ben.com }
## `pg` and Database Drivers
### What is a database driver?
A database driver is an installable module that bridges between a programming language and a database.
It abstracts the network connection and specifics of sending/recieving messages to/from the database server.
`pg` (node-postgres) is an example of that driver
Basically the whole point of a database driver is to make sure a database can communicate with an application because JavaScript (and other programming languages) and databases (ex: relational using SQL) don't understand each other
## REST Architecture
Keywords and concepts:
- REST
- Common REST-ful mistakes
- Express Router
### What is REST?
REST stands for Representational State Transfer and is a style for designing backend applications. It helps answer the question on how to organize routes and how to map functionality to our data.
- Paths represent "nouns" or resources
- HTTP "verbs" map to specific data operations
Example:
- Users and Posts are example of resoures (`app.get('/users' ...)`, `app.get('/posts' ...)`)
### Example of a RESTful architecture
In Express, we use something called `Router` Middleware which enables us to split our routes into multiple different files so that we can modularize them. Each file should contain one resource. Using the users and posts example, we should have one file of each and the operations are exclusive to that resource
So, for the users router file:
- GET /users (Show all users)
- GET /users/4 (Get a single user whose ID = 4 in the DB)
- POST /users (Create a new user in the DB)
- PUT /users/4 (Update single user whose ID = 4 in the DB)
- DELETE users/4 (Delete single user whose ID = 4 in the DB)
### Common RESTful Mistake 1: Mixing Verbs and Nouns
- Feature: We need to delete individual records from the bears table
- Mistake: GET /bears/delete/:id
The url attempts to specify the operation to take in the url path and query string. Paths should only convey information about the resource.
DELETE /bears/id
### Common RESTful Mistake 2: Opaque Resource
- Feature: We have a historical chess database. We have pages for individual moves in historic games
- Mistake: GET /games/:gameId/:moveNumber
GET /games/4/2 is not expressive enough. What is 2 referring to? This should be self-evident in the route definition
GET /games/:gameId/moves/:moveNumber
### Common RESTful Mistake 3: Misleading Resource
- Feature: We are scientific lab. Our employees generate a lot of reports. We need to get a list of all the reports generated by a particular request
- Mistake: GET /reports/:scientistID
GET /reports/4 translates to "get report #4 NOT "get all reports by scientist #4. Either one below will work
- Query String: GET /reports?scientistId=4
- Sub-Resource for Users: GET /users/:scientistId/reports
### Common RESTful Mistake 4: Unpredictable URL Structure
- Feature: We're a big e-commerce site. We want to show all the reviews for a particular project on the same page
- Mistake: GET /reviews/products/:productId
As a rule of thumb we expect RESTful URIs to follow the pattern /foo/:fooID/bar/:barID/baz/:bazID etc. REST is all about predictability via consistency, and /reviews/products/4 contradicts that—reviews is not followed by an identifying key, it is followed by a separate resource name (products).
Another way to think about it is that it is similar to Misleading Resource. The GET request indicates that we're getting something, but what are we getting? One product? Many products? One review? Many reviews?
Either one below will work
- Query String: GET /reviews?productId=4
- Sub-Resource for Reviews: GET /products/:productId/reviews
## Sequelize
### What is Object Relational Mapping, and why do we use it?
An ORM acts as a bridge between your code and the RDBMS. Using an ORM, data can be easily stored and retrieved from a database without writing SQL statements directly.
### What are the differences between model and instance methods?
- Model methods operate on a table as a whole, for instance finding or updating multiple rows.
- Instance methods operate on a single row.
### How do we CRUD model instances using Sequelize?
Sequelize models and instances expose methods for doing so.
- Create: `Model.create({...})`
- Read: `Model.findByPk()` or `Model.findAll()`. There are several others, but these are the ones you'll probably use most
- Update: `Model.update()` to update multiple rows or `instance.save()` for individuals
- Delete: `Model.delete()` to delete multiple rows or `instance.delete()` for individuals
### What are Sequelize hooks and why do we use them?
Every instance goes through lifecycle events called Hooks. Hooks allow you to add functions to be run when certain events occur on an instance.
### What are associations?
Associations are setting up tables to be related to each other by ways of
- 1-to-many relationships
- Many-to-many relationship
- 1-to-1 relationships
This is how we related data together
For example: Articles, Authors, Tags
We need to think about the relationships among all these tables and think about the features we need to implement
- Do articles and authors have a relationship? Yes, Authors can make many articles, and for the most part (unless you want to do multiple authors for one article, which you can if the feature calls for it. Then this becomes a many-to-many relationship), an article "belongs to" an author
- Do articles and tags have a relationship? Yes, they have a many-to-many relationship because tags can be associated with many different articles ('science' tag can be on multiple articles) and articles can have many tags (an article can have a 'science' tag as well as 'physics' tag)
- Do tags and authors have a relationship? This depends. Does our app let authors create tags? If so, then this would be a 1-to-many relationship. An author can make multiple tags, but tags belong to an author (If a tag already exists, we don't need to make a new one hence not being associated with many authors). If not, and there are predefined tags to choose from, then there will be no relationship.
**If we create associations then a lot of stuff happens behinds the scenes including**:
* The FK relationships getting established for us (see below for examples)
* Getting "magic methods" (also see below)
* Being able to "eager load" data (also see below)
### How does Sequelize affect the 'belongsTo' and 'hasMany' associations?
Sequelize will create a foreign key for you. When defining a `belongsTo` relation on a model, the foreign key will be created on that model's table. When defining a `hasMany` relation, it will be defined on the opposite table.
for instance:
```javascript=
const User = db.define('user', {...})
const Pet = db.define('pet', {...})
// foreign key is on pets
Pet.belongsTo(User)
User.hasMany(Pet)
```
### How does Sequelize affect the `belongsToMany` association?
Sequelize will create a thru/join table that connects the table or tables it is joining. That thru table will contain the foreign keys of the table or tables it is joining. Those foreign keys make up something called the primary composite key. You will need to use the `through` attribute in the association to define the thru table.
```javascript=
const Article = db.define('article', {...})
const Tag = db.define('tag', {...})
// foreign key is on pets
Article.belongsToMany(Tag, {through: 'ArticleTags'})
Tag.belongsToMany(Article, {through: 'ArticleTags})
```
### What is eager loading?
- **The equivalent to doing an `LEFT JOIN` in SQL.**
- By default it does a `LEFT JOIN`.
Please, refer to Day 10's Exit Ticket [Solutions](https://hackmd.io/@2ctk-Q4uQAmhb4qw1GghPA/HyELWnay_) for more info
### What are magic methods and what are their uses?
Please, refer to this [gist](https://gist.github.com/b17z/efd811d177cdcffcb5ad1ccbd6ddef91) for more info
Magic methods are created when we create associations. These methods are special functions we can use to be able modify, and get data from associated tables
An example from our demo inside our `POST` route:
```javascript=
await newPokemon.setTypes([firstType, secondType])
```
Pokemon is a separate table from the Type table, but we created the associations for it (see below and check `db/index.js`)
```javascript=
Pokemon.belongsToMany(Type, {through: 'pokemon_types'})
Type.belongsToMany(Pokemon, {through: 'pokemon_types'})
```
In our `POST` route, we wanted to create a Pokémon that was submitted from our form, but the data from our form also include data that are in separate tables such as Types and Trainer. We would use magic methods to be able to set this data appropriately. So, taking a look at this again:
```javascript=
await newPokemon.setTypes([firstType, secondType])
```
We are saying, "On the New Pokémon that was created, let's set their types (which will be saved in a different table) that we got from our form"