# The Back End ## Database fundamentals We talked about the difference between relational and NoSQL databases in [Part I](./1.md#Relational vs NoSQL). Databases like PostgreSQL and MongoDB can be installed on your machine to store and retrieve data. This is great for experimentation and testing. However in production databases are typically not deployed together with the back-end application. Production databases should run across multiple, independent servers to offer better performance, security, and reliability. Companies like Heroku and Amazon Web Services (AWS) offer hosted databases that greatly simplify this task. ## SQL the database language Relational databases like PostgreSQL and MySQL speak SQL. Database queries are written in SQL to perform actions on records in the database. Reading a table using a `SELECT` statement: ```sql SELECT * FROM weather; ``` This returns everything in the `weather` table. If we are only interested in specific columns, we can tell the database to return just those: ```sql SELECT city, temp_lo, temp_hi, prcp, date FROM weather; ``` That should save some processing and memory space. SQL queries can be further refined to sort results, filter based on column values, combine records across tables, and much more. ### Accessing other databases Each database has its own API or protocol. Libraries are typically available for most popular languages and frameworks. Modern databases like MongoDB have a more programming-like syntax. ### Map-Reduce Map-reduce is a pattern used by many databases to iterate over records one by one, processing each independently (mapping) or tracking only specific fields (reducing). ## Server side code A very basic web server in JavaScript is simply: ```js var http = require('http') http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}) res.end('Hello World') }).listen(1337, '127.0.0.1') console.log('Server running at http://127.0.0.1:1337/') ``` Try it out: 1. Open Terminal (OS X) or Command Prompt (Windows) 1. Run `node` 1. Copy & paste the above code snippet 1. Visit in the browser This uses Node.js' built-in support for HTTP. The server listens for connections and always responds with a simple `Hello World` text message. Try modifying the response to an error header, some JSON data, an HTML document, or serving a static file. Servers typically record log messages to the standard output and/or log files. Use `console.log` in Node.js just like in the browser. ## The anatomy of a web server Node.js' `http` module listens for incoming requests from the web browser. It is up to our application to read the request information (e.g. URL path, headers, etc) and formulate an appropriate response. ### Request Handlers In the above example, the callback function passed to `createServer` receives request and response arguments. We can turn that callback into a *router* that will call further functions based on the URL path. That way the code is not just one huge callback but can be neatly divided into multiple function and files. ### Middleware There are [many packages](http://expressjs.com/resources/middleware.html) for Node.js that offer *middleware* for various common web server tasks. For example logging, serving static files, compressing the response, handling security, and so on. ## Understanding architecture and why it's important Let's take a look at different methods of building a back-end. ### MVC Model-View-Controller is a programming pattern that is used by web application frameworks to separate logic concerning the data access (model), output rendering (view), and business logic (controller). Back-end frameworks and applications often organise source code into folders: - Views for HTML templates - Models for data base and third-party API access - Controllers for route handlers and data processing ### RESTful API The back-end router can map resources to URL patterns and HTTP methods. The route handlers simply respond with JSON-formatted data. Instead of rendering dynamic HTML pages for each interaction, the back-end can serve light-weight data. The front-end uses JavaScript to make HTTP requests. This offloads the effort of building the HTML document in the back-end. This is less work for the back-end and reduces the amount of data transferred to the front-end. #### Example Use HTTP methods to implement CRUD operations on the following **endpoints**: - `/friends` - `/friends/:id` List all my friends: ``` GET /friends => [{name: 'Alice', id: 1}, {name: 'Bob', id: 2}] ``` Look up Bob's profile: ``` GET /friends/2 => {name: 'Bob', id: 2} ``` Befriend Eve: ``` POST /friends {name: 'Eve'} => {name: 'Eve', id: 3} ``` Rename Alice to Alan: ``` PUT /friends/1 {name: 'Alan'} => {name: 'Alan', id: 1} ``` Unfriend Eve: ``` DELETE /friends/3 => 200 OK ``` ### Micro-Services As a back-end application grows, it may be performing lots of different tasks. These tasks end up becoming so complex that they are best split into independent applications. The back-end API then becomes a thin gateway. For example an ecommerce back-end can be split into - payment processing - inventory management - catalog listing - product recommendations - shipping caculator Each microservice could have its own deployment infrastructure, typically using application containers (like Docker) on virtual servers (like AWS EC2 or Heroku). ## Server side frameworks In Node.js the most popular web server framework is [Express](http://expressjs.com/). ## Exercise: creating a micro-service that stores and serves some data Extend the above web server example to support the friends API.