diff --git a/module1-introduction-to-backend/r1-introduction-to-backend/README.md b/module1-introduction-to-backend/r1-introduction-to-backend/README.md index 5d5d6ce..425cd73 100644 --- a/module1-introduction-to-backend/r1-introduction-to-backend/README.md +++ b/module1-introduction-to-backend/r1-introduction-to-backend/README.md @@ -1,55 +1,66 @@ # Introduction to Backend + Welcome to your first lesson of the Backend Web Development Bootcamp! The objectives of this lesson are: + 1. To understand the roles of frontend developer vs backend developer vs fullstack developer 2. To get familiar with the basics of backend web architecture Here we go! ## Frontend Developer vs Backend Developer vs Fullstack Developer + As of June 2021, it is estimated that the Internet contains more than 1.8 million websites. No doubt that this a great time to start a career as a web developer, the people who are responsible for coding, building, analyzing, and maintaining all those websites. If you have some experience with web development or have been reading about it, then you already know that web development tends to break down into three main concentrations: frontend, backend, and fullstack. ### What is a Frontend Developer? + The frontend of a website is the visible part that users interact with. It is also called the User Interface (UI). Everything that you see when you're navigating around the Internet, from text, fonts and colors to buttons, dropdown menus and sliders, are a combination of HTML, CSS, and JavaScript being rendered and controlled by your computer's browser. A frontend developer is responsible for writing and maintaining the code for the user interface of the website and the architecture and functionality for the user experience of the website. Frontend developers must be competent in HTML, CSS and Javascript as their foundation along with one or more modern frameworks like ReactJS, AngularJS, VueJS, EmberJS, BackboneJS, Foundation or Svelte. They also work with UI libraries like Sass, Bootstrap, Tailwind, React Bootstrap, Material UI, Ant Design and Semantic UI and tools like Babel, Webpack and Gatsby. Frontend developers are sometimes seen as a combination of a user interface designer, user experience designer and software developer – someone who appreciates the aesthetic, usability as well as functionality of an application. They care about delivering the features and functionalities, but they also go the extra mile to ensure the user interface is aesthetically pleasing and the experience is seamless. A great frontend developer is not only proficient in programming but also good at empathising with the end users. - +![](https://drive.google.com/uc?export=view&id=1EiN2DOjCpmS05ZLyrT73kVhM34Ne0S5-" width="70%) ### What is a Backend Developer? + But where does all the data to be displayed on the frontend come from? How is a website personalized for the logged in user? This is where the backend comes in. The backend of a website consists of a server, an application, and a database. A backend developer builds and maintains the code that powers those components which together enable the user-facing side of the website to even exist in the first place. Backend developers must be competent with one or more server-side languages such as JavaScript (Node.js), Ruby, Python, PHP or Java, frameworks like ExpressJS, Ruby on Rails, Python Django and databases like MySQL, PostgreSQL or MongoDB. They are also familiar with Linux as a deployment environment and DevOps tools like AWS, GCP, Apache, Nginx, Docker and Kubernetes. Backend developers need to be able to navigate across larger codebases and not get lost in the complexities. They also need to be very meticulous when making changes to not "break" anything as there are usually delicate dependencies. Even frontend codebases are large and complex with delicate dependencies, but unlike frontend development where the written code translates directly to visual output one can see and interact with, backend development of business logic is often hard to visualise. Therefore to be a good backend developer, you need to be comfortable with dealing with abstracts. - +![](https://drive.google.com/uc?export=view&id=1PkIrF_pNnGbX1NiW-q1JIKokql1v4FI7" width="50%) ### What is a Fullstack Developer? + A jack of all trades? Pretty much! Often there isn't a black-and-white distinction between frontend and backend development. Frontend developers sometimes need to understand backend concepts like how REST APIs work and backend developers sometimes need to understand how components are rendered with data in their state. The role of a fullstack developer was popularized by Facebook's engineering department. The idea is that a fullstack developer can work cross-functionally on the full "stack" of technology, both the frontend and backend. They are capable of performing both frontend and backend tasks and have a complete understanding of how a web application works, and how the "front" and the "back" are connected. They can build a complete web application on their own. In the current digital economy, companies are looking for such cross-discipline developers or generalists. To be a good fullstack developer, you need to be comfortable with dealing with abstracts as well as empathising with end users. Good fullstack developers also need to know when to wear which hat to work effectively and efficiently because there will always be division of responsibilities - +![](https://drive.google.com/uc?export=view&id=13hdTlUW0tk0J91wV-r7ruPX7uATpt9pe" width="50%) ## Backend Web Architecture + Let's start diving deeper into what do we mean when we say frontend and backend. The frontend is the code that is executed on the client side. This code runs in the user's browser and creates the user interface. The backend is the code that runs on the server, receives requests from the clients, and contains the logic to send the appropriate data back to the client. The backend also includes the database, which will persistently store all of the data for the application. ### What are clients? + The clients are entities that send requests to the backend. They are often browsers that make requests for the HTML and JavaScript code that they will execute to display websites to the end user. However, there are many different kinds of clients: they might be a mobile application, an application running on another server, or even a web enabled smart appliance. ### What is a backend? + The backend is all of the technology required to process the incoming request and generate and send the response to the client. This typically includes three major parts: + - **Server**: This is the computer that receives requests and sends responses. - **Application**: This is the application running on the server that processes the requests, retrieves information from the database, and sends a response. - **Database**: This is used to organize and persist data. ### What is a server? + A server is simply a computer that listens for incoming requests. Though there are machines made and optimized for this particular purpose, any computer that is connected to a network can act as a server. In fact, you will often use your very own computer as a server when developing apps. The term "server" is also very often used to refer directly to the backend application running on the server. For example, if we build a backend application to manage the student data of a university, we can refer to it as the student server. When you hear a developer say "the server has crashed", they could either mean the backend application has crashed due to an error in the code or the server running the application has crashed due to a hardware issue. @@ -59,6 +70,7 @@ Frontends also have servers. Technically when you build a website or a web appli Once we start building our backend applications we will observe the use of this term more in action. ### What kinds of responses can a server send? + The data that the server sends back can come in different forms. For example, a server might serve up an HTML file, send data as JSON, or it might send back only an HTTP status code. You've probably seen the status code "404 - Not Found" whenever you've tried navigating to a URI that doesn't exist, but there are many more status codes that indicate what happened when the server received the request. > Okay I want to see some code now! @@ -66,8 +78,10 @@ The data that the server sends back can come in different forms. For example, a We heard you. In the next lesson, we will learn about Node.js which will be the primary server-side programming framework that we will be using throughout this bootcamp. --- + ## References + - https://www.freecodecamp.org/news/front-end-developer-vs-back-end-developer-definition-and-meaning-in-practice - https://www.udacity.com/blog/2020/12/front-end-vs-back-end-vs-full-stack-web-developers.html - https://sg.alphacamp.co/2018/07/31/what-kind-of-web-developer-should-you-be/ -- https://www.codecademy.com/articles/back-end-architecture \ No newline at end of file +- https://www.codecademy.com/articles/back-end-architecture diff --git a/module1-introduction-to-backend/r1.1-beginners-guide-nodejs-npm/README.md b/module1-introduction-to-backend/r1.1-beginners-guide-nodejs-npm/README.md index f8649fc..40b637c 100644 --- a/module1-introduction-to-backend/r1.1-beginners-guide-nodejs-npm/README.md +++ b/module1-introduction-to-backend/r1.1-beginners-guide-nodejs-npm/README.md @@ -1,32 +1,35 @@ # Beginners guide to Node.js and NPM + We will be working in the Node.js and NPM environment throughout this bootcamp. The objectives of this lesson are: + 1. Understanding the Node.js framework 2. Advantages of Node.js and why this course is focussed on Node.js ## Introduction to Node.js + Is it a programming language? Is it a library? No, it's Node.js. In simple words, Node.js is nothing but JavaScript running on the server-side, and it's awesome. - +![](https://drive.google.com/uc?export=view&id=1oaHgcGKcrKbW6G-gFsncV95WhVmc40M7) But to be specific, Node.js is an open-source, cross-platform, backend JavaScript runtime environment that runs on the V8 engine and executes JavaScript code outside a web browser. And here is what a common Hello World code in Node.js would look like: ```js -const http = require('http') +const http = require("http"); -const hostname = '127.0.0.1' -const port = 3000 +const hostname = "127.0.0.1"; +const port = 3000; const server = http.createServer((req, res) => { - res.statusCode = 200 - res.setHeader('Content-Type', 'text/plain') - res.end('Hello World\n') -}) + res.statusCode = 200; + res.setHeader("Content-Type", "text/plain"); + res.end("Hello World\n"); +}); server.listen(port, hostname, () => { - console.log(`Server running at http://${hostname}:${port}/`) -}) + console.log(`Server running at http://${hostname}:${port}/`); +}); ``` Using the http module, one of many useful Node.js libraries, an HTTP server is created. The server is set to listen on a specified hostname and port. When the server is ready, the callback function is called, in this case informing us that the server is running. Whenever a new request is received from a client, the request event is called, providing two objects: a request and a response. The first provides details of the request, although not used in this example, and the second is used to return data to the client. @@ -34,6 +37,7 @@ Using the http module, one of many useful Node.js libraries, an HTTP server is c You will learn more about the keywords mentioned in this code block throughout this module. ### Some brief history first + Node.js is only 12 years old, not a long time in tech. In comparison, JavaScript itself is more than 20 years old, and we know that it is what runs in our browsers. JavaScript was created at Netscape, which also tried to create LiveWire, an attempt at server-side JavaScript. Unfortunately, it wasn't very successful and server-side JavaScript did not grow in popularity until the introduction of Node.js in 2009. One key factor that led to the rise of Node.js was the timing. Just a few years earlier, JavaScript had started to be considered as a more serious language, thanks to "Web 2.0" applications (such as Flickr, Gmail, etc.) that showed the world what a modern experience on the web could be like. JavaScript engines also became considerably better as many browsers competed to offer users the best performance. Development teams behind major browsers worked hard to offer better support for JavaScript and find ways to make JavaScript run faster. The engine that Node.js uses under the hood, V8 (also known as Chrome V8 for being the open-source JavaScript engine of The Chromium Project), improved significantly due to this competition. @@ -41,6 +45,7 @@ One key factor that led to the rise of Node.js was the timing. Just a few years When Ryan Dahl wrote Node.js, one of his motivations was the limited possibilities of the most popular web server in 2009, Apache HTTP Server, to handle a lot of concurrent connections and the most common way of creating code which either blocked the entire process or implied multiple execution stacks in the case of simultaneous connections. A Node.js app runs in a single process, without creating a new thread for every request. Node.js provides a set of asynchronous I/O primitives in its standard library that prevent JavaScript code from blocking and generally, libraries in Node.js are written using non-blocking paradigms, making blocking behavior the exception rather than the norm. ### Features of Node.js + Firstly, though `.js` is the standard filename extension for JavaScript code, the name "Node.js" doesn't refer to a particular file in this context and is merely the name of the product. It can also be written as "NodeJS" or simply "Node". 1. **Speed**: Having been built on Google Chrome's V8 JavaScript engine, Node.js is extremely fast for code execution. @@ -51,11 +56,12 @@ Firstly, though `.js` is the standard filename extension for JavaScript code, th Node.js is written with C, C++ and JavaScript and uses libuv underhood to handle asynchronous events. Libuv is an abstraction layer for network and file system functionality on the OS. - - +![](https://drive.google.com/uc?export=view&id=18ys74BkK9tzQ6u8avgVw9seweoXY6GnA" width="60%) ### NPM and Packages in Node.js + One of the major factors of Node's success is npm - its popular package manager, which allows JavaScript developers to share useful packages quickly and easily. NPM – or "Node Package Manager" – is the default package manager for JavaScript's runtime Node.js. NPM consists of two main parts: + - a CLI (command-line interface) tool for publishing and downloading packages, and - an online repository that hosts JavaScript packages
@@ -66,7 +72,9 @@ When we have a remote package in our project, it is called as a dependency since Node.js also ships with a collection of [built-in packages](https://nodejs.org/api/index.html) called as Node Standard Library. These packages are essential to perform low-level operations like File System I/O and Networking. We do not have to install them using NPM. ### How much JavaScript should I know to use Node.js? + As a beginner, it can be difficult to understand where does JavaScript end, and where Node.js begins, and vice versa. However, when you're writing code for a Node.js application you are writing JavaScript. So, it is important to grasp the fundamentals of JavaScript syntax such as: + - Lexical Structure - Expressions - Types @@ -86,6 +94,7 @@ As a beginner, it can be difficult to understand where does JavaScript end, and - ECMAScript 6 or ES6 Also, as asynchronous programming is the core of Node.js it is important to understand concepts like: + - [Asynchronous programming and callbacks](https://nodejs.dev/learn/javascript-asynchronous-programming-and-callbacks) - [Timers](https://nodejs.dev/learn/discover-javascript-timers) - [Promises](https://nodejs.dev/learn/understanding-javascript-promises) @@ -96,6 +105,7 @@ Also, as asynchronous programming is the core of Node.js it is important to unde If you're interested to dive deeper into understanding Node.js, [here](https://nodejs.dev/learn/introduction-to-nodejs) is a learning path that you can follow. ## Why are we teaching Node.js in this bootcamp? + From the previous lesson or previous experience, you might already be familiar with other server-side languages like Python, PHP, Ruby or Java. So why did we choose to teach Node.js? 1. **Popularity**: Node.js has been consistently growing in popularity since it's introduction. As per the [Stackoverflow developer survey of 2021](https://insights.stackoverflow.com/survey/2021), JavaScript is the most popular language for 9 years in a row and Node.js has moved up to be the 6th most popular technology. Many companies that we have got in touch with have expressed interest in hiring more Node.js developers. @@ -107,7 +117,9 @@ From the previous lesson or previous experience, you might already be familiar w Now that you have enough context on Node.js, let's prepare our coding environments on our computers. Coming up next is your first assignment of this course which will walk you through setting up your Node.js environment. --- + ## References + - https://medium.com/jspoint/introduction-to-node-js-a-beginners-guide-to-node-js-and-npm-eca9c408f9fe - https://en.wikipedia.org/wiki/Node.js - https://www.simplilearn.com/tutorials/nodejs-tutorial/what-is-nodejs @@ -115,4 +127,4 @@ Now that you have enough context on Node.js, let's prepare our coding environmen - https://www.freecodecamp.org/news/what-is-npm-a-node-package-manager-tutorial-for-beginners/ - https://nodejs.dev/learn/introduction-to-nodejs - https://medium.com/jspoint/how-javascript-works-in-browser-and-node-ab7d0d09ac2f -- https://www.geeksforgeeks.org/top-8-reasons-to-learn-nodejs-in-2020/ \ No newline at end of file +- https://www.geeksforgeeks.org/top-8-reasons-to-learn-nodejs-in-2020/ diff --git a/module1-introduction-to-backend/r2-http-and-rest/README.md b/module1-introduction-to-backend/r2-http-and-rest/README.md index 8467f82..1383800 100644 --- a/module1-introduction-to-backend/r2-http-and-rest/README.md +++ b/module1-introduction-to-backend/r2-http-and-rest/README.md @@ -1,17 +1,21 @@ # HTTP and REST So what exactly happens when you enter a URL starting with `http://` or `https://` on your browser? How do the client and server communicate? The objectives of this lesson are: + 1. Understanding HTTP communication 2. Understanding the request-response lifecycle 3. Understanding REST APIs ## What is HTTP? + HTTP stands for Hypertext Transfer Protocol and is used to structure requests and responses over the internet. The transfer of resources happens using TCP (Transmission Control Protocol). TCP is used to manage many types of internet connections in which one computer or device wants to send something to another. HTTP is the command language that the devices on both sides of the connection must follow in order to communicate. Imagine two people on two sides of a river trying to send goods across to each other. TCP is the bridge they build while HTTP is the language they use to communicate. ### HTTP & TCP: How it Works + When you type a web address such as www.re-coded.com in your browser, here is what happens: + 1. You enter the URL (Uniform Resource Locator) in the browser. 2. The browser looks for the IP address of the domain name in the DNS (Domain Name Server). 3. The browser initiates a TCP connection with the server. @@ -22,32 +26,39 @@ When you type a web address such as www.re-coded.com in your browser, here is wh All these steps happen each time we enter any URL, and they happen in the background within milliseconds. Suppose you want to check out the upcoming coding bootcamps at http://www.re-coded.com. After you type the URL into your browser, your browser will extract the http part and recognize that it is the name of the network protocol to use. Then, it takes the domain name from the URL, in this case "re-coded.com", and asks the Domain Name Server (DNS) to return an Internet Protocol (IP) address. Once the client knows the destination's IP address, it then opens a connection to the server at that address, using the http protocol as specified. It will initiate a GET request to the server which contains the IP address of the host and optionally a data payload. The GET request contains the following text: + ``` GET / HTTP/1.1 Host: www.re-coded.com ``` + This identifies the type of request "GET", the path on www.re-coded.com (in this case, "/") and the protocol "HTTP/1.1." It could also be "HTTP/2.0". These are latest revisions of the original HTTP. If the server is able to locate the path requested, the server might respond with the header: + ``` HTTP/1.1 200 OK Content-Type: text/html ``` + This header is followed by the content requested, which in this case is the information needed to render www.re-coded.com. The first line of the header, HTTP/1.1 200 OK, is confirmation that the server understands the protocol that the client wants to communicate with (HTTP/1.1), and an HTTP status code signifying that the resource was found on the server. The second line, Content-Type: text/html, shows the type of content that it will be sending to the client. If the server is not able to locate the path requested by the client, it will respond with the header: + ``` HTTP/1.1 404 NOT FOUND ``` + In this case, the server identifies that it understands the HTTP protocol, but the 404 NOT FOUND status code signifies that the specific piece of content requested was not found. This might happen if the content was moved or if you typed in the URL path incorrectly or if the page was removed. You can also try to explore this on your browser. If you're using Google Chrome, open a new tab, right click and select "Inspect". This opens up the developer console of the browser. From the top menu on this console, select "Network". Now type https://www.re-coded.com/ in your browser bar and hit Enter. You will see a bunch of requests processed in the Network tab as the website loads. If you navigate to the top most request, you should be able to see the request and response headers we just talked about. - +![](https://drive.google.com/uc?export=view&id=1SJPdV6-75u8iTr5xrlMGGb5IgGeH9nn9) ### Parts of a server URL + In the previous assignment, you were running the server on a URL like this: `http://localhost:3000`. By now you know that `http://` means that the communication will be happening over the HTTP protocol. Now `localhost` here is the **hostname** of the computer. The hostname is what a device is called on a network and to be specific `localhost` means "this computer" and is the standard hostname given to the address of the loopback network interface. Localhost always translates to the loopback IP address 127.0.0.1 in IPv4. So `http://localhost:3000` is actually the same as `http://127.0.0.1:3000`. The final part `:3000` refers to the **port**. In computer networking, a port is a communication endpoint. Usually during development with Node.js, we use port 3000, 8000 or 8080. @@ -55,15 +66,17 @@ By now you know that `http://` means that the communication will be happening ov Once your backend application is ready to move to production, it will have an assigned hostname such as "myhostname.com" or "mycompanyname.com" and communicate through reserved ports like port 80 for HTTP or port 443 for HTTPS. ### What is HTTPS? + Hypertext Transfer Protocol Secure (HTTPS) is the secure version of HTTP. HTTPS uses encryption in order to increase security of data transfer. This is particularly important when users transmit sensitive data, such as by logging into a bank account, email service, or health insurance provider. In modern web browsers such as Chrome, websites that do not use HTTPS are marked differently than those that are. Look for a padlock or similar indicator in the URL bar to signify the webpage is secure. - +![](https://drive.google.com/uc?export=view&id=1NkvHiapLP2dMtFXWe-Q6SAVyJ-1UFdPf) - +![](https://drive.google.com/uc?export=view&id=1EV6uPQJz3SPo2wy5NqUj0gy3Fm_75RX9" width="50%) HTTPS uses an encryption protocol called [Transport Layer Security (TLS)](https://en.wikipedia.org/wiki/Transport_Layer_Security), formerly known as Secure Sockets Layer (SSL). This protocol secures communications by using what's known as an asymmetric public key infrastructure. This type of security system uses two different keys to encrypt communications between two parties: + 1. **Private key**: This key is controlled by the owner of a website and it's kept, as you might have guessed, private. This key lives on a web server and is used to decrypt information encrypted by the public key. 2. **Public key**: This key is available to everyone who wants to interact with the server in a way that's secure. Information that's encrypted by the public key can only be decrypted by the private key. @@ -72,11 +85,13 @@ HTTPS prevents websites from having their information broadcast in a way that's With HTTPS, traffic is encrypted such that even if the packets are sniffed or otherwise intercepted, they will come across as nonsensical characters. **Before encryption** + ``` This is a string of text that is completely readable ``` **After encryption** + ``` ITM0IRyiEhVpa6VnKyExMiEgNveroyWBPlgGyfkflYjDaaFf/Kn3bo3OfghBPDWo6AfSHlNtL8N7ITEwIXc1gU5X73xMsJormzzXlwOyrCs+9XCPk63Y+z0= ``` @@ -84,24 +99,29 @@ ITM0IRyiEhVpa6VnKyExMiEgNveroyWBPlgGyfkflYjDaaFf/Kn3bo3OfghBPDWo6AfSHlNtL8N7ITEw In websites without HTTPS, it is possible for Internet Service Providers (ISPs) or other intermediaries to inject content into webpages without the approval of the website owner. This commonly takes the form of advertising, where an ISP looking to increase revenue injects paid advertising into the webpages of their customers. Unsurprisingly, when this occurs, the profits for the advertisements and the quality control of those advertisements are in no way shared with the website owner. HTTPS eliminates the ability of unmoderated third parties to inject advertising into web content. ### How is HTTPS different from HTTP? + Technically speaking, HTTPS is not a separate protocol from HTTP. It is simply using TLS/SSL encryption over the HTTP protocol. HTTPS communication occurs based upon the transmission of TLS/SSL certificates, which verify that a particular provider is who they say they are. When a user connects to a webpage, the webpage will send over its SSL certificate which contains the public key necessary to start the secure session. The two computers, the client and the server, then go through a process called an SSL/TLS handshake, which is a series of back-and-forth communications used to establish a secure connection. To take a deeper dive into encryption and the SSL/TLS handshake, you can read about what happens in a [TLS handshake](https://www.cloudflare.com/en-in/learning/ssl/what-happens-in-a-tls-handshake/). ### How does a website start using HTTPS? + For an SSL certificate to be valid, domains need to obtain it from a certificate authority (CA). A CA is an outside organization, a trusted third party, that generates and gives out SSL certificates. Many website hosting providers and other services offer free or paid TLS/SSL certificates. You can read more about SSL certificates [here](https://www.cloudflare.com/learning/ssl/what-is-an-ssl-certificate/). Once you have obtained the SSL certificate for your website, you can configure it on your server and enable it to communicate over port 443, which is the port for HTTPS communication over TCP. ### What is an API? + API stands for Application Programming Interface, which is a set of definitions and protocols for building and integrating application software. APIs let your product or service communicate with other products and services without having to know how they're implemented. APIs are sometimes thought of as contracts, with documentation that represents an agreement between parties: If party 1 sends a remote request structured a particular way, this is how party 2's software will respond. When you are developing a server, you will be developing an API that enables the frontend to communicate with your server without necessarily knowing the implementation details on your server. The most popular API architecture is the REST API. ## What is REST? + REST, or **RE**presentational **S**tate **T**ransfer, is an architectural style for providing standards between computer systems on the web, making it easier for systems to communicate with each other. REST-compliant systems, often called RESTful systems, are characterized by how they are stateless and separate the concerns of client and server. It means when a RESTful API is called, the server will transfer to the client a representation of the state of the requested resource. ### Guiding Principles of REST + 1. **Client–server**: By separating the user interface concerns from the data storage concerns, we improve the portability of the user interface across multiple platforms and improve scalability by simplifying the server components. 2. **Stateless**: Each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. Session state is therefore kept entirely on the client. 3. **Cacheable**: Cache constraints require that the data within a response to a request be implicitly or explicitly labeled as cacheable or non-cacheable. If a response is cacheable, then a client cache is given the right to reuse that response data for later, equivalent requests. @@ -110,31 +130,39 @@ REST, or **RE**presentational **S**tate **T**ransfer, is an architectural style 6. **Code on demand (optional)**: REST allows client functionality to be extended by downloading and executing code in the form of applets or scripts. This simplifies clients by reducing the number of features required to be pre-implemented. ### Resource + The key abstraction of information in REST is a resource. Any information that can be named can be a resource: a document or image, a temporal service, a collection of other resources, a non-virtual object (e.g. a person), and so on. REST uses a resource identifier to identify the particular resource involved in an interaction between components. ### Making Requests + REST requires that a client make a request to the server in order to retrieve or modify data on the server. A request generally consists of: + - an HTTP verb, which defines what kind of operation to perform - a header, which allows the client to pass along information about the request - a path to a resource - an optional message body containing data #### HTTP Verbs + There are 4 basic HTTP verbs we use in requests to interact with resources in a REST system: + - **GET** — retrieve a specific resource or a collection of resources - **POST** — create a new resource - **PUT** — update a specific resource - **DELETE** — remove a specific resource ### REST and HTTP are not same! + A lot of people tend to compare HTTP with REST but REST and HTTP are not same. Roy Fielding, who presented REST for the first time in 2000 in his famous dissertation, did not mention any implementation directive – including any protocol preference and HTTP. REST intends to make the web (internet) more streamline and standard, but as long as you are honoring the 6 guiding principles of REST, you can call any interface RESTful. In simplest words, in the REST architectural style, data and functionality are considered resources and are accessed using Uniform Resource Identifiers (URIs). The resources are acted upon by using a set of simple, well-defined operations. The clients and servers exchange representations of resources by using a standardized interface and protocol – typically HTTP. In the next lesson, we'll dive deep into the details of a REST API. ----- +--- + ## References + - https://www.codecademy.com/articles/http-requests - https://afteracademy.com/blog/what-happens-when-you-type-a-url-in-the-web-browser - https://medium.com/extend/what-is-rest-a-simple-explanation-for-beginners-part-1-introduction-b4a072f8740f @@ -143,4 +171,4 @@ In the next lesson, we'll dive deep into the details of a REST API. - https://www.codecademy.com/articles/what-is-rest - https://restfulapi.net/ - https://www.cloudflare.com/en-in/learning/ssl/what-is-https/ -- https://en.wikipedia.org/w/index.php?title=Localhost&oldid=331995451 \ No newline at end of file +- https://en.wikipedia.org/w/index.php?title=Localhost&oldid=331995451 diff --git a/module1-introduction-to-backend/r2.1-diving-into-rest-apis/README.md b/module1-introduction-to-backend/r2.1-diving-into-rest-apis/README.md index 2548b31..35ffa3c 100644 --- a/module1-introduction-to-backend/r2.1-diving-into-rest-apis/README.md +++ b/module1-introduction-to-backend/r2.1-diving-into-rest-apis/README.md @@ -1,13 +1,17 @@ # Diving into REST APIs + HTTP messages are how data is exchanged between a server and a client. There are two types of messages: requests sent by the client to trigger an action on the server, and responses, the answer from the server. The learning objectives of this lesson are: + 1. Understanding HTTP request types 2. Understanding HTTP request and response structure 3. Understanding HTTP response status codes ## HTTP Requests + In the previous lesson, we briefly talked about GET, POST, PUT and DELETE request methods. HTTP defines a set of request methods to indicate the desired action to be performed for a given resource. This set includes: + - **GET**: Requests a representation of the specified resource. Requests using GET should only retrieve data. - **HEAD**: Asks for a response identical to that of a GET request, but without the response body. - **POST**: Used to submit an entity to the specified resource, often causing a change in state or side effects on the server. @@ -23,47 +27,54 @@ While developing APIs, GET and POST are the most commonly and frequently used me ## Structure of an HTTP Request HTTP requests, and responses, share similar structure and are composed of: + 1. A start-line describing the requests to be implemented, or its status of whether successful or a failure. This start-line is always a single line. 2. An optional set of HTTP headers specifying the request, or describing the body included in the message. 3. A blank line indicating all meta-information for the request has been sent. 4. An optional body containing data associated with the request (like content of an HTML form), or the document associated with a response. The presence of the body and its size is specified by the start-line and HTTP headers. ### Start line + HTTP requests are messages sent by the client to initiate an action on the server. Their start-line contain three elements: + 1. An **HTTP method**, a verb (like GET, PUT or POST) or a noun (like HEAD or OPTIONS), that describes the action to be performed. For example, GET indicates that a resource should be fetched or POST means that data is pushed to the server. 2. The **HTTP version**, which defines the structure of the remaining message, acting as an indicator of the expected version to use for the response. 3. The **request target**, usually a URL, or the absolute path of the protocol, port, and domain are usually characterized by the request context. The format of this request target varies between different HTTP methods. It can be - - An absolute path, ultimately followed by a '?' and query string. This is the most common form, known as the origin form, and is used with GET, POST, HEAD, and OPTIONS methods. - ``` - POST / HTTP/1.1 GET /background.png HTTP/1.0 HEAD /test.html?query=alibaba HTTP/1.1 OPTIONS /anypage.html HTTP/1.0 - ``` - - A complete URL, known as the absolute form, is mostly used with GET when connected to a proxy. - ``` - GET https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages HTTP/1.1 - ``` - - The authority component of a URL, consisting of the domain name and optionally the port (prefixed by a ':'), is called the authority form. It is only used with CONNECT when setting up an HTTP tunnel. - ``` - CONNECT developer.mozilla.org:80 HTTP/1.1 - ``` - - The asterisk form, a simple asterisk ('*') is used with OPTIONS, representing the server as a whole. - ``` - OPTIONS * HTTP/1.1 - ``` + - An absolute path, ultimately followed by a '?' and query string. This is the most common form, known as the origin form, and is used with GET, POST, HEAD, and OPTIONS methods. + ``` + POST / HTTP/1.1 GET /background.png HTTP/1.0 HEAD /test.html?query=alibaba HTTP/1.1 OPTIONS /anypage.html HTTP/1.0 + ``` + - A complete URL, known as the absolute form, is mostly used with GET when connected to a proxy. + ``` + GET https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages HTTP/1.1 + ``` + - The authority component of a URL, consisting of the domain name and optionally the port (prefixed by a ':'), is called the authority form. It is only used with CONNECT when setting up an HTTP tunnel. + ``` + CONNECT developer.mozilla.org:80 HTTP/1.1 + ``` + - The asterisk form, a simple asterisk ('\*') is used with OPTIONS, representing the server as a whole. + ``` + OPTIONS * HTTP/1.1 + ``` ### Headers + HTTP headers from a request follow the same basic structure of an HTTP header: a case-insensitive string followed by a colon (':') and a value whose structure depends upon the header. The whole header, including the value, consist of one single line, which can be quite long. Many different headers can appear in requests. They can be divided in several groups: + - General headers, like "Via", apply to the message as a whole. - Request headers, like "User-Agent" or "Accept", modify the request by specifying it further (like Accept-Language), by giving context (like Referer), or by conditionally restricting it (like If-None). - Representation headers like "Content-Type" that describe the original format of the message data and any encoding applied (only present if the message has a body). - +![](https://drive.google.com/uc?export=view&id=1kM2zFsDEUS6ZfHWsfMqN8LCvjM_23Fs0) ### Body + The final part of the request is its body. Not all requests have one: requests fetching resources, like GET, HEAD, DELETE, or OPTIONS, usually don't need one. Some requests send data to the server in order to update it: as often the case with POST requests (containing HTML form data). Bodies can be broadly divided into two categories: + - Single-resource bodies, consisting of one single file, defined by the two headers: Content-Type and Content-Length. - Multiple-resource bodies, consisting of a multipart body, each containing a different bit of information. This is typically associated with HTML Forms. @@ -72,29 +83,37 @@ Bodies can be broadly divided into two categories: The structure is similar to HTTP requests. ### Status line + The start line of an HTTP response, called the status line, contains the following information: + 1. The protocol version, usually HTTP/1.1. 2. A status code, indicating success or failure of the request. Common status codes are 200, 404, or 302 3. A status text. A brief, purely informational, textual description of the status code to help a human understand the HTTP message. ### Headers + HTTP headers for responses follow the same structure as HTTP request headers. Many different headers can appear in responses. These can be divided into several groups: + - General headers, like "Via", apply to the whole message. - Response headers, like "Vary" and "Accept-Ranges", give additional information about the server which doesn't fit in the status line. - Representation headers like "Content-Type" that describe the original format of the message data and any encoding applied (only present if the message has a body). ### Body + The last part of a response is the body. Not all responses have one: responses with a status code that sufficiently answers the request without the need for corresponding payload (like 201 Created or 204 No Content) usually don't. Bodies can be broadly divided into three categories: + - Single-resource bodies, consisting of a single file of known length, defined by the two headers: Content-Type and Content-Length. - Single-resource bodies, consisting of a single file of unknown length, encoded by chunks with Transfer-Encoding set to chunked. - Multiple-resource bodies, consisting of a multipart body, each containing a different section of information. These are relatively rare. ## HTTP response status codes + HTTP response status codes indicate whether a specific HTTP request has been successfully completed. Responses are grouped in five classes: + - Informational responses (100–199) - Successful responses (200–299) - Redirects (300–399) @@ -104,6 +123,7 @@ HTTP response status codes indicate whether a specific HTTP request has been suc You can read more about each status code [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status). The most commonly used status codes are: + - **Status Code 200 OK**: This is the standard "OK" status code for a successful HTTP request. The response that is returned is dependent on the request. For example, for a GET request, the response will be included in the message body. For a PUT/POST request, the response will include the resource that contains the result of the action. - **Status Code 201 Created**: This is the status code that confirms that the request was successful and, as a result, a new resource was created. Typically, this is the status code that is sent after a POST/PUT request. - **Status Code 204 No Content**: This status code confirms that the server has fulfilled the request but does not need to return information. Examples of this status code include delete requests or if a request was sent via a form and the response should not cause the form to be refreshed or for a new page to load. @@ -119,7 +139,9 @@ The most commonly used status codes are: Now that we have learned so much about HTTP requests and responses, let's perform some requests and analyze the responses in our next assignment. --- + ## References + - https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods - https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages - https://developer.mozilla.org/en-US/docs/Web/HTTP/Status diff --git a/module2-databases/r1.2-relational-database-structure/README.md b/module2-databases/r1.2-relational-database-structure/README.md index 24c2851..a001daf 100644 --- a/module2-databases/r1.2-relational-database-structure/README.md +++ b/module2-databases/r1.2-relational-database-structure/README.md @@ -1,69 +1,86 @@ # Relational Database Structure + The objectives of this lesson are: + 1. Understanding the fundamental and important concepts of databases 2. Learning about the different types of relationships ## Fundamental Database Concepts + We have already briefly discussed these in the previous lesson. ### Tables: Rows and Columns + The table is the basic data-storage unit in a relational database. Tables consist of columns and rows. The columns are the attributes or qualities that we want to express, while the rows hold the actual data. Tables can have hundreds, thousands, sometimes even millions of rows of data. These rows are often called records. Tables can also have many columns of data. Columns are labeled with a descriptive name and have a specific data type. For example, a column called `age` may have a type of `INTEGER`. ### Primary Key + A primary key is a special column that uniquely identifies each record (row) in the table. The primary key column must be unique for each row, and must not contain any nulls (non-values). ### Foreign Key + We cannot talk about the yin of primary keys without the yang of foreign keys. The two go hand-in-hand. A primary key uniquely defines a record, while a foreign key is used to reference the same record from another table. We've already seen this in practice in the example from the previous lesson. ### Relationships + Relationships are THE reason why relational databases work so well. If you only learn one concept about databases, this is the one to learn. In relational databases, a relationship exists between two tables when one of them has a foreign key that references the primary key of the other table. ## Other Important Database Concepts + We have discussed the fundamental database concepts, but these are not the only ones. There are also other important secondary concepts worth learning about. ### Indexes + An index in an RDBMS is a data structure that works closely with tables and columns to speed up data retrieval operations. It works a lot like the index at the beginning of a book. In other words, it provides a reference point that allows you to quickly find and access the data you want without having to traverse the entire database. ### Schema + A schema is the structure behind data organization. It is a visual overview of how different tables are related to each other. This serves to map out and implement the underlying business rules for which the database is created. ### Normalization + Normalization is the process of (re)organizing data in a database so that it meets two basic requirements: there is no data redundancy (all data is stored in only one place), and data dependencies are logical (all related data items are stored together). For instance, for a bank's database all customer static data, such as name, address and age, should be stored together. All account information, such as account holder, account type, account branch and so on, should also be stored together; it should also be stored separately from the customer static data. ### Constraints + In the RDBMS world, constraint refers to the exact same thing as in the real world. A constraint is a restriction on the type of data you can input into a certain column. Constraints are always defined on columns. A common constraint is the not-null constraint. It simply specifies that all rows in a table must have a value in the column defined as not null. ## Types of Relationships + Any association between two entity types is called a relationship. Entities take part in the relationship. For example, a teacher teaches students. Here, "teaches" is a relationship and this is the relationship between a Teacher entity and a Student entity. Depending on the structure of your tables and the requirements of your application, you can create different types of relationships. There are three types of relationships that can exist between two entities. + - One-to-One Relationship - One-to-Many or Many-to-One Relationship - Many-to-Many Relationship ### One-to-One Relationship + For example, If there are two entities "Person" (Id, Name, Age, Address)and "Passport"(Passport_id, Passport_no). So, each person can have only one passport and each passport belongs to only one person. - +![](../assets/one-to-one.jpeg) Such a relationship is not very common. However, such a relationship is used for security purposes. In the above example, we can easily store the passport id in the "Person" table only. But, we make another table for the "Passport" because Passport number may be sensitive data and it should be hidden from certain users. ### One-to-Many or Many-to-One Relationship + Such a relationship exists when each record of one table can be related to one or more than one record of the other table. This relationship is the most common relationship found. A one-to-many relationship can also be said as a many-to-one relationship depending upon the way we view it. For example, If there are two entity type "Customer" and "Account" then each "Customer" can have more than one "Account" but each "Account" is held by only one "Customer". In this example, we can say that each Customer is associated with many Account. So, it is a one-to-many relationship. But, if we see it the other way i.e many Account is associated with one Customer then we can say that it is a many-to-one relationship. - +![](../assets/one-to-many.jpeg) Let's take another similar example, a customer may have multiple orders. This is a one-to-many relationship, since one customer has many orders. It should be noted that the foreign key goes on the side that is "many". ### Many-to-Many Relationship + Such a relationship exists when each record of the first table can be related to one or more than one record of the second table and a single record of the second table can be related to one or more than one record of the first table. For example, if there are two entity types "Customer" and "Product" then each customer can buy more than one product and a product can be bought by many different customers. @@ -76,14 +93,16 @@ Many to many relationships often require an intermediate linking table that crea Let's look at another example for a many-to-many relationship. Consider students and classes at a university. A `Student` can take many classes; a `Class` also has many students. Once again you will need a linking table (also known as joining table or bridging table) to create this relationship. In this scenario, it can be `Enrollments`. This table contains the foreign keys of the two tables being connected. You can see in the diagram below, connecting classes and students together through a table called `Enrollments`. Each row in `Enrollments` represents one class that one student is taking; there can be multiple such entries in the table. - +![](../assets/many-to-many.png) Check out this [StackOverflow question](https://stackoverflow.com/questions/4601703/difference-between-one-to-many-and-many-to-one-relationship) for more details about one-to-many and many-to-one relationships. Now that you have a clearer picture of relational database structure, let's dive into how to interact with these databases using SQL in the next lesson. --- + ## References + - https://www.techopedia.com/6/28832/enterprise/databases/introduction-to-databases - https://afteracademy.com/blog/what-are-the-different-types-of-relationships-in-dbms -- https://dzone.com/articles/how-to-handle-a-many-to-many-relationship-in-datab \ No newline at end of file +- https://dzone.com/articles/how-to-handle-a-many-to-many-relationship-in-datab diff --git a/module2-databases/r2.1-introduction-to-mongodb/README.md b/module2-databases/r2.1-introduction-to-mongodb/README.md index 4950692..c257bc2 100644 --- a/module2-databases/r2.1-introduction-to-mongodb/README.md +++ b/module2-databases/r2.1-introduction-to-mongodb/README.md @@ -1,5 +1,7 @@ # Introduction to MongoDB + The objectives of this lesson are: + 1. Understanding the fundamental and important concepts of MongoDB 2. Understanding how MongoDB works differently from relational databases @@ -9,9 +11,11 @@ straightforward to use, because working with it is very similar to working with JSON, which many web developers are familiar with. ## Fundamental MongoDB Concepts + There are no tables, rows and columns in MongoDB but similar concepts for a non-relational structure. ### Collections: Documents and Fields + In MongoDB, a collection is the basic data-storage unit. A database can have many collections. A collection can be considered the equivalent of a table in relational databases. A collection has many documents. A record in a MongoDB collection is basically called a document. The document, in turn, will consist of fields. It is similar to what we know normally as JSON. @@ -19,20 +23,23 @@ A collection has many documents. A record in a MongoDB collection is basically c A field is a name-value pair in a document. A document has zero or more fields. Fields are analogous to columns in relational databases. An example of a document, as taken from the Mongo docs, would look like this. - +![](../assets/document-example.svg) Since there are no column constraints, this document can grow to hold as many new fields as required. -### _id +### \_id + All documents in MongoDB have a field called `_id`. This is a required field and represents a unique value in the MongoDB document. It is like the document's primary key. If you create a new document without an `_id` field, MongoDB will automatically create the field. You can read more about this [here](https://docs.mongodb.com/manual/core/document/#the-_id-field). Visit the [official documentation on collections](https://docs.mongodb.com/manual/core/databases-and-collections/) and the [official documentation on documents](https://docs.mongodb.com/manual/core/document/) for further reference. ## Other Important Concepts + There are some other important concepts beyond the fundamentals. ### Indexes + Indexes support the efficient execution of queries in MongoDB. Without indexes, MongoDB must perform a collection scan, that is, scan every document in a collection, to select those documents that match the query statement. If an appropriate index exists for a query, MongoDB can use the index to limit the number of documents it must inspect. Indexes are special data structures that store a small portion of the collection's data set in an easy to traverse form. The index stores the value of a specific field or set of fields, ordered by the value of the field. The ordering of the index entries supports efficient equality matches and range-based query operations. In addition, MongoDB can return sorted results by using the ordering in the index. @@ -40,36 +47,41 @@ Indexes are special data structures that store a small portion of the collection By default, MongoDB always creates a unique index on the `_id` field. While structuring your database, you can create additional indexes on other fields. You can read about the different types of indexes on the MongoDB documentation [here](https://docs.mongodb.com/manual/indexes/#index-types). ### Data Modelling + Unlike SQL databases, where you must determine and declare a table's schema before inserting data, MongoDB's collections, by default, do not require their documents to have the same schema. However, data modelling is still important and helpful for developers to define how the data is stored and what relationships exist between data entities. Did we just say relationships? Yes, although MongoDB is known as a non-relational database, you can have one-to-many and many-to-many relationships among your collections. MongoDB provides the following two ways to model our data: + 1. **Embedded Documents** : Consider a scenario where you want to save data about blog posts and their comments. One way to model this is to embed the child document in the parent document, that is the comment documents inside the blog post document. It would look something like this: + ```js { _id: , title: "Data Modelling in MongoDB", body: "some long text...", comments: [ - { + { _id: , comment: "some text...", - author: "mike@email.com" + author: "mike@email.com" }, - { + { _id: , comment: "some text...", - author: "jake@email.com" + author: "jake@email.com" } ] } ``` + Embedding documents lead to better performance because we can read and update data in a single database operation, only with the caveats that it can lead to data duplication and should not exceed the allowed maximum size limit of 16MB for a document. Embedded models should be used for one-to-many relationships where entities have a "contains" or "has a" relationship between them. 2. **References** : In this scenario, we would store blog posts and comments in separate collections and reference the blog post document in each comment document, that is the parent document is referenced in the child documents. Pretty much similar to what we would do with foreign keys in SQL databases. It would look like this: + ```js // blog post { @@ -79,17 +91,17 @@ Embedded models should be used for one-to-many relationships where entities have } // comments -{ +{ _id: , comment: "some text...", author: "mike@email.com", postId: . // reference to the blog post }, -{ +{ _id: , comment: "some text...", author: "jake@email.com", - postId: // reference to the blog post + postId: // reference to the blog post } ``` @@ -98,13 +110,16 @@ Referencing documents helps to avoid data duplication, represent complex many-to Referencing model should be used for many-to-many related hierarchical data where read performance is less important than data duplication. ### Aggregation + Aggregation operations are used to perform additional computations on the data beyond what is fetched in the read queries. Aggregation operations group values from multiple documents together, and can perform a variety of operations on the grouped data to return a single result. MongoDB provides three ways to perform aggregation: the aggregation pipeline, the map-reduce function, and single purpose aggregation methods. The aggregation pipeline is the most popularly used option. You can read more about Aggregation on MongoDB [here](https://docs.mongodb.com/manual/aggregation/). Now that you have learned these concepts of MongoDB, let's learn about querying in MongoDB in the next lesson. --- + ## References + - https://www.guru99.com/what-is-mongodb.html - https://docs.mongodb.com/manual/introduction/ - https://docs.mongodb.com/manual/indexes/ -- https://www.educative.io/edpresso/what-is-data-modeling-in-mongodb \ No newline at end of file +- https://www.educative.io/edpresso/what-is-data-modeling-in-mongodb diff --git a/module3-crud-and-data-models/r1.2-principles-of-setting-up-your-schema/README.md b/module3-crud-and-data-models/r1.2-principles-of-setting-up-your-schema/README.md index 2238af1..0a37a08 100644 --- a/module3-crud-and-data-models/r1.2-principles-of-setting-up-your-schema/README.md +++ b/module3-crud-and-data-models/r1.2-principles-of-setting-up-your-schema/README.md @@ -1,18 +1,22 @@ # Principles of setting up your schema + One of the biggest strengths of a well-built backend application is the schema of its database. The objectives of this lesson are: + 1. Understanding best practices of good schema design 2. Preparing to apply schema design in CRUD projects ## What is the significance of good schema design? + Poorly designed databases can cause many problems, including wasting resources, making maintenance difficult, and hindering performance. That's why having a great database schema design is a crucial part of effective data management. By defining categories of data and relationships between those categories, database schema design makes data much easier to retrieve, consume, manipulate, and interpret. Without a clean, efficient, consistent database schema, you'll struggle to make the best use of your enterprise data. For example, the same data might be duplicated in multiple locations or even worse, might be inconsistent between these locations. ## MongoDB schema design + In this lesson we will focus on schema design best practices for MongoDB since we will be building MongoDB based CRUD applications in this module. Developers often don't see the difference between relational database schema and MongoDB schema, but in reality, it is not the same. -meme +![](../assets/relationalDBmeme.png" alt="meme" width="400) We have already read about the differences between relational and non-relational databases in the previous module. So, while developers may have the tendency to design their MongoDB collections like SQL tables, that approach will lead to a poor schema design. This means ignoring the strengths of MongoDB and what it was built for. @@ -21,41 +25,47 @@ In relational databases, models are usually independent of queries, there is no On the other hand, MongoDB gives you more flexibility, there are no rules or rather flexible rules, documents can have new data or fields at any point of time, and there is no need to define fixed types. Data is usually stored in the way it will be queried, so that queries have good performance. ## Embedding vs. Referencing + One of the key points to establish a good schema design (especially, if you are using MongoDB) is whether to embed or reference your data. We have already been introduced to these concepts in the previous module. ### Embedding + When a collection has a document, and this document contains another document, another document contains another sub-document, and so on. This is called embedding or nesting. #### When to Embed + - To retrieve all data in a single query. - Avoid expensive JOINs or $lookups. - Update all data with a single operation. - For one-to-one or one-to-many relationships between documents. ### Referencing + When the value of a field in your document refers to a value of another field in another document. This is called referencing. #### When to Reference + - If you need smaller documents, your data will be separated across multiple documents. - No duplication of data. - To reduce accessing infrequently required data on every query. - For many-to-many relationships between documents. ## Thumb Rules + In general, there are few **rules** you can follow to better design your schema: 1. **Favor embedding over referencing unless there is a compelling reason not to.** -Embedded documents are an efficient and clean way to store related data, especially data that's regularly accessed together. The more often a given workload can retrieve a single document and have all the data it needs, the more consistently high-performance your application will be. + Embedded documents are an efficient and clean way to store related data, especially data that's regularly accessed together. The more often a given workload can retrieve a single document and have all the data it needs, the more consistently high-performance your application will be. 2. **Needing to access an object on its own is a compelling reason not to embed.** -Separate data that can be referred to from multiple places into its own collection. -This is not so much a "storage space" issue as it is a "data consistency" issue. If many records will refer to the same data it is more efficient and less error prone to update a single record and keep references to it in other places. + Separate data that can be referred to from multiple places into its own collection. + This is not so much a "storage space" issue as it is a "data consistency" issue. If many records will refer to the same data it is more efficient and less error prone to update a single record and keep references to it in other places. 3. **Avoid JOINs and $lookups if they can be avoided, but don't be afraid if they can provide a better schema design.** -Having a JOIN or `$lookup` means you are doing some kind of search in your database for the corresponding field and that operation takes time. So if you embed your data in a single object, you will spare this operation, and your query can be much faster and cleaner. + Having a JOIN or `$lookup` means you are doing some kind of search in your database for the corresponding field and that operation takes time. So if you embed your data in a single object, you will spare this operation, and your query can be much faster and cleaner. 4. **How you model your data depends _entirely_ on your particular application's data access patterns.** -This means that no matter what you read or watch, you may still need to make few changes to your schema based on your own use case and application. + This means that no matter what you read or watch, you may still need to make few changes to your schema based on your own use case and application. As you can see there are no absolute fixed Do's and Dont's when it comes to database schema design. There are general guidelines and the advantages and disadvantages of each. When designing your application, it always comes down to how well you have understood the core functional requirements of what you are building. And accordingly applying these guidelines with necessary tweaks to build a robust, reliable and high performance application. @@ -64,6 +74,8 @@ You can read the complete article of MongoDB schema design best practices [here] Now let's put our learnings on schema design into practice in the next few assignments. --- + ## References + - https://www.mongodb.com/developer/article/mongodb-schema-design-best-practices/ - https://www.xplenty.com/blog/complete-guide-to-database-schema-design-guide/ diff --git a/module5-testing/r1.1-testing-philosphy/README.md b/module5-testing/r1.1-testing-philosphy/README.md index 3a92dbf..3312b9a 100644 --- a/module5-testing/r1.1-testing-philosphy/README.md +++ b/module5-testing/r1.1-testing-philosphy/README.md @@ -1,10 +1,13 @@ # Testing Philosophy + Let's discuss some aspects of testing philosophy. The objectives of this lesson are: + 1. Understanding the philosophy and mindset of testing 2. Familiarizing ourselves with the concepts of TDD and BDD 3. Learning the properties of a good test ## Mindset of Testing + In real life, you may perhaps work at companies that do almost no testing (this is not good, but it is the reality). This is especially true in smaller companies. You may work at a company that chooses only to test certain components or write certain types of tests. Finally, as mentioned previously, at some companies, especially bigger ones, you may be required to write tests so that every line of code is covered by a test. @@ -14,7 +17,7 @@ the testing process and the quality of tests. However, how is the mindset of tes Many companies do have a quality assurance or QA team that is responsible for testing a product or application manually as it is getting developed. And then there are developers who are responsible specifically for writing automated tests. These professionals are expected to have a strong analytical mind with critical thinking skills. They are also expected to have empathy for the end users and test the application from their perspective in different scenarios. Wait a minute, isn't all this also expected from developers building the application? Yes, but more often than not there is a difference between a developer and a tester. Developers want to make the application work but testers want to make the application break. No, that does not make testers just a bunch of terrible people, although the programming meme world is full of developers complaining against them. By consistently and curiously looking for faults or failures in the application, testers help to ensure the application can be made as free of errors as possible, which at the end of the day ensures the users are able to use the application efficiently. - +![](../assets/developer-tester.jpeg) More recently with the arrival of many different testing frameworks, the distinction between development and QA has been removed, as companies started to see the value of developers who can also write good tests. Developers are now expected to look at all scenarios and test cases of the functionality they're building and write tests to validate the correctness of their code. This brings us to the concept of the test-driven development which is gaining more popularity. @@ -41,6 +44,7 @@ generally healthy for the robustness of a codebase. If TDD was not present, depending on the company, developers may be less strict about writing tests. ### Is TDD used in the real world? + Many companies do adopt TDD, although in practice, this is still a minority of companies. TDD is far from a perfect philosophy: it does not guarantee good test coverage and it may even encourage developers to write sloppier tests so that @@ -78,57 +82,62 @@ _When_ they click the submit button _Then_ proper validation messages should be shown ## Properties of a good test + As mentioned previously, simply writing a test is not the same as writing a good test. In this section, we'll examine some properties of what makes a good test. ### Size: Focused tests + A well-written test should not test too many things at once. In general, test cases should be well-isolated and have a [single responsibility](https://en.wikipedia.org/wiki/Single-responsibility_principle) or intention. Consider the previous example of the `absolute()` function. Suppose the test instead looked like this: + ```js -describe('absolute', () => { - it('should correctly handle inputs', () => { - const result1 = absolute(1); - expect(result0).toBe(1); - const result1 = absolute(-1); - expect(result1).toBe(1); - const result2 = absolute(0); - expect(result2).toBe(0); - }); +describe("absolute", () => { + it("should correctly handle inputs", () => { + const result1 = absolute(1); + expect(result0).toBe(1); + const result1 = absolute(-1); + expect(result1).toBe(1); + const result2 = absolute(0); + expect(result2).toBe(0); + }); }); ``` Now compare this to the original. Which one do you find more readable and organized? While this is a simple example, separating the cases for clarity becomes especially important with more complex functions. + ```js -describe('absolute', () => { - it('should return positive number if input is positive', () => { - const result = absolute(1); - expect(result).toBe(1); - }); - it('should return positive number if input is negative', () => { - const result = absolute(-1); - expect(result).toBe(1); - }); - it('should return zero if input is zero', () => { - const result = absolute(0); - expect(result).toBe(0); - }); +describe("absolute", () => { + it("should return positive number if input is positive", () => { + const result = absolute(1); + expect(result).toBe(1); + }); + it("should return positive number if input is negative", () => { + const result = absolute(-1); + expect(result).toBe(1); + }); + it("should return zero if input is zero", () => { + const result = absolute(0); + expect(result).toBe(0); + }); }); ``` ### Redundancy: Avoid overlapping test cases + As a related topic, you usually want to avoid test cases that overlap too much with existing test cases. For example, consider the following test case for the `absolute` function. Is it useful, or is it redundant, overlapping with one of the test cases above? ```js -it('should return positive number if input is large and negative', () => { - const result = absolute(-100); - expect(result).toBe(100); +it("should return positive number if input is large and negative", () => { + const result = absolute(-100); + expect(result).toBe(100); }); ``` @@ -145,6 +154,7 @@ scenarios that define the behavior: positive, negative, and zero. Whether the negative number is large or not makes no difference. ### Thoroughness + In this module, it was mentioned several times that good test coverage means that, if the code is behaving incorrectly, even in one line or in one if-condition, some test will fail. @@ -154,8 +164,10 @@ arguments are passed to your function, it behaves differently. A good suite of tests will make sure to cover all the different possible cases. ### Organization: Arrange-Act-Assert + Tests generally follow approximately the same pattern, and this has been crystallized in a commonly adopted idea called ["Arrange Act Assert."](https://automationpanda.com/2020/07/07/arrange-act-assert-a-pattern-for-writing-good-tests/) + 1. **Arrange**: Many tests require some type of intial setup before the tests can be executed. Does the test require any inputs or special settings? Does it need to prep a database? Does it need to log into a web app? Handle all of these operations at the start of the test in the Arrange step. 2. **Act**: In the Act step, the actual behavior being tested should be invoked, such as a function call, a REST API call, an interaction with a web page, a component render, etc. 3. **Assert**: Finally, to ensure correctness, Assert the expected outcomes after the Act step sends a result or response. This was seen earlier using the `expect` function. The terms expect and assert, in this context, are synonymous. Assertions are what ultimately determine if the test passes or fails. @@ -163,16 +175,18 @@ crystallized in a commonly adopted idea called ["Arrange Act Assert."](https://a _Given-When-Then_ is essentially the same formula as _Arrange-Act-Assert_. ## Additional Readings + 1. You can read more about the testing mindset on [this forum](https://club.ministryoftesting.com/t/what-does-testing-mindset-mean-to-you-whats-your-tester-mindset/26422). 2. You can read more about the advantages and disadvantages of TDD [here](https://www.geeksforgeeks.org/advantages-and-disadvantages-of-test-driven-development-tdd/). 3. This [StackOverflow question](https://stackoverflow.com/questions/61400/what-makes-a-good-unit-test) gives some interesting insights into what are considered good properties of a unit test. -Google has a good resource called *Testing on the Toilet*. On the back of the +Google has a good resource called _Testing on the Toilet_. On the back of the door in every toilet stall at Google, you can find a one-page flyer that describes some aspect of testing (that's how important testing is!). These are publicized. Some good ones for junior developers are included below: + - [Keep tests focused](https://testing.googleblog.com/2018/06/testing-on-toilet-keep-tests-focused.html) - [DAMP](https://www.googblogs.com/testing-on-the-toilet-tests-too-dry-make-them-damp/). Don't overuse functions in test code, focus on readability. - [Just say no to end-to-end tests](https://testing.googleblog.com/2015/04/just-say-no-to-more-end-to-end-tests.html). Avoid overusing tests that connect too many parts of your system. -Finally, take a look at [this comprehensive list](https://github.com/goldbergyoni/javascript-testing-best-practices) of best practices for testing in JavaScript and Node.js. Don't worry about memorizing all of this, expose yourself to these ideas and concepts first and then put them into practice in your assignments and projects. You'll find yourself remembering them easily soon. \ No newline at end of file +Finally, take a look at [this comprehensive list](https://github.com/goldbergyoni/javascript-testing-best-practices) of best practices for testing in JavaScript and Node.js. Don't worry about memorizing all of this, expose yourself to these ideas and concepts first and then put them into practice in your assignments and projects. You'll find yourself remembering them easily soon. diff --git a/module5-testing/r1.2-types-of-tests/README.md b/module5-testing/r1.2-types-of-tests/README.md index e1d26fa..dfa0d01 100644 --- a/module5-testing/r1.2-types-of-tests/README.md +++ b/module5-testing/r1.2-types-of-tests/README.md @@ -1,24 +1,30 @@ # Types of tests + There are many many different types of software testing. The objectives of this lesson are: + 1. Familiarize ourselves with common types of testing 2. Understand the concept of building test cases ## Manual and automated testing + At a high level, we need to make the distinction between manual and automated tests. Manual testing is done in person, by clicking through the application or interacting with the software and APIs with the appropriate tooling. This is very expensive as it requires someone to set up an environment and execute the tests themselves, and it can be prone to human error as the tester might make typos or omit steps in the test script. Automated tests, on the other hand, are performed by a machine that executes a test script that has been written in advance. These tests can vary a lot in complexity, from checking a single function to making sure that performing a sequence of complex actions in the UI leads to the same results. It's much more robust and reliable than manual tests – but the quality of your automated tests depends on how well your test scripts have been written. Automated testing is a key component of continuous integration and continuous delivery and it's a great way to scale your QA process as you add new features to your application. ## Unit tests + The examples we've seen so far are examples of **unit tests**. As the name suggests, unit tests test a small unit of code, such as a function or a component. Unit tests are very low level, close to the source of your application. They consist of testing individual methods and functions of the classes, components or modules in your codebase. Unit tests are in general quite cheap to automate and can be run very quickly by a continuous integration server. ## Integration tests + Multiple parts of a system can be tested in integration tests. An example of this would be a test that starts a frontend and a backend, and tests that the frontend registration form works and inserts something in a database. Notice how this would be much different from a unit test, for example, that simply tests whether a registration form properly sends a fetch request to the correct URL (without actually triggering anything in the backend). Integration tests verify that different modules or services used by your application work well together. These types of tests are more expensive to run as they require multiple parts of the application to be up and running. ## End-to-end tests + End-to-end testing replicates a user behavior in a complete application environment. While it's tempting to write only end-to-end tests, thinking that it would be convenient to test all parts at once, these are much harder to maintain, as you need to set up a backend, a database, and a frontend in a test environment and have them all work together. There are also more places where the test could go wrong, which violates our principle of keeping tests isolated. Later, we will discuss the frequency at which different tests can be written. @@ -26,14 +32,17 @@ Note that integration tests may also be referred to as end-to-end tests, or vice necessarily an "official naming" for tests. ## Functional tests + Functional tests focus on the business requirements of an application. They only verify the output of an action and do not check the intermediate states of the system when performing that action. There is sometimes a confusion between integration tests and functional tests as they both require multiple components to interact with each other. The difference is that an integration test may simply verify that you can query the database while a functional test would expect to get a specific value from the database as defined by the product requirements. ## Regression tests + Every time a new module is added leads to changes in the program. This type of testing makes sure that the whole component works properly even after adding components to the complete program. ## Smoke tests + Smoke tests are basic tests that check basic functionality of the application. They are meant to be quick to execute, and their goal is to give you the assurance that the major features of your system are working as expected. For example, if you have a todo list app, this app may simply login users and try to create a list, even if your app has much more functionality than this straightforward flow. The name "smoke test" comes from the idea that, if you have some type @@ -42,20 +51,25 @@ without testing anything -- it hasn't even passed the basics. Smoke tests often run before more expensive tests can be run or before releasing a product as a "sanity test." ## Performance tests + Performance tests check the behaviors of the system when it is under significant load. These tests are non-functional and are aimed to understand the reliability, stability, and availability of the platform. For instance, it can be observing response times when executing a high number of requests, or seeing how the system behaves with a significant load of data. ## Stress tests + This is another type of non-functional test in which, we give unfavorable conditions to the system and check how it performs in those conditions. It helps us improve the system in the face of such possible unfavorable scenarios. ## Acceptance testing + Acceptance tests are formal tests executed to verify if a system satisfies its business requirements. They require the entire application to be up and running and focus on replicating user behaviors. These can also be manual tests, where first a round of alpha testing is conducted by an internal team and then a round of beta testing with a limited number of users for testing in a real-time environment. --- + ## What is the frequency of these tests? + In the ideal testing environment, unit tests will be the most frequent type of testing. As tests increase in granularity -- that is, they include larger pieces of your system -- you want these tests to be less frequent. The smaller tests should be tested individually. In case there is a problem, it becomes easier to isolate issues if they are associated with small tests. - +![](../assets/test-pyramid.png) There is a [test pyramid](https://martinfowler.com/articles/practical-test-pyramid.html) that is frequently cited when discussing testing. While the components of the test pyramid may vary based on the author of the diagram, the important thing is that @@ -63,10 +77,12 @@ the fastest and smallest test (unit tests) should be by far the most frequent. As tests take longer to run and integrate more parts of the system, there should be fewer. - +![](../assets/pyramid2.jpeg" width="70%) --- + ## Test Cases + A test is only as strong as the number of test cases it covers. A test case represents a single scenario of the Given-When-Then principle applied to a functionality. It is very rare that a functionality would have only one test case. Usually the first test case is called the **happy path** test case. Consider the example of a login form. Given the user enters the correct username and password, when they click the login button then the system should successfully login the user and take them to their dashboard. This is the most ideal scenario for the application which indicates that it is working as expected in the user requirements. @@ -80,6 +96,8 @@ We can think of edge cases for our `absolute` function as well. What if the inpu When we run the tests for a piece of functionality, we can see which test cases have passed and which have failed. This helps us debug the specific areas of the codebase and fix issues. --- + ## References + - https://www.atlassian.com/continuous-delivery/software-testing/types-of-software-testing - https://www.geeksforgeeks.org/types-software-testing/ diff --git a/module5-testing/r2.4-static-analysis-testing/README.md b/module5-testing/r2.4-static-analysis-testing/README.md index 6dac0cc..d8c8127 100644 --- a/module5-testing/r2.4-static-analysis-testing/README.md +++ b/module5-testing/r2.4-static-analysis-testing/README.md @@ -1,6 +1,7 @@ # Static Analysis Testing What are some ways to ensure clean and correct code even before we run our unit tests? Can we enforce certain best practices for all team members while they're writing the code itself? The objectives of this lesson are: + 1. Understanding the need for static analysis testing and how it is different from unit testing 2. Understanding the different tools that help with writing well-formatted code @@ -9,6 +10,7 @@ What are some ways to ensure clean and correct code even before we run our unit Static analysis is a method of debugging by examining source code before a program is run. It's done by analyzing a set of code against a set (or multiple sets) of coding rules. In simpler words, static analysis identifies defects before you run a program (between coding and unit testing) while dynamic analysis identifies defects after you run a program (during unit testing). So far everything we learned was related to dynamic analysis. Static analysis is the process of verifying that your code meets certain expectations without actually running it. Unlike unit and integration testing, static analysis can be performed on raw source code without the need for a web server or build process. Static analyzers typically parse your code and turn it into what is known as an abstract syntax tree. This tree is then traversed and the pieces are checked based on the rules dictated by the static analyzer. Most static analyzers also include a way for developers to write their own custom rules, but that varies from tool to tool. Static analysis is most commonly used to: + - Ensure consistent style and formatting - Check for common mistakes and possible bugs - Limit the complexity of code @@ -22,7 +24,7 @@ We'll look into some of the most commonly used tools, that we recommend you shou ## ESLint -[ESLint](https://eslint.org/) is probably the most used static analysis tool for JavaScript. It is mainly a tool for [linting](https://en.wikipedia.org/wiki/Lint_(software)), as in a tool that programmatically scans your code with the goal of finding issues that can lead to bugs or inconsistencies with code health and style and sometimes even fix those issues automatically. +[ESLint](https://eslint.org/) is probably the most used static analysis tool for JavaScript. It is mainly a tool for [linting](), as in a tool that programmatically scans your code with the goal of finding issues that can lead to bugs or inconsistencies with code health and style and sometimes even fix those issues automatically. ESLint is very easy to [setup](https://www.section.io/engineering-education/node-eslint/) and also comes with many [predetermined rules](https://eslint.org/docs/rules/) that you can configure for your project. It also gives the option to extend a set of rules prepared by another reliable company or developer, so that we don't have to list down all the rules from scratch. You can ovverride a few rules if required from the extended set. @@ -46,6 +48,7 @@ These will ensure that the rules from your project's `eslintrc` and `prettierrc` ## Executing static analysis We can run our static analysis tools just like we executed our unit tests using the command `npm test` which was possible by defining the test script in our `package.json` files. + ```js { ... @@ -58,6 +61,7 @@ We can run our static analysis tools just like we executed our unit tests using ``` We can add a script to run ESLint as: + ```js "lint": "eslint ." ``` @@ -65,11 +69,13 @@ We can add a script to run ESLint as: And then the command `npm run eslint` checks all JS files in our code for lint errors. However, we need some JS files to be ignored by ESLint such as those in `node_modules` or maybe if we have a `build` folder then those too. In that case, we can reuse the `.gitignore` file which already tell git to ignore tracking certain set of files and folders and modify our script to: + ```js "lint": "eslint --ignore-path .gitignore ." ``` Similarly, we can write another script to run prettier formatting as: + ```js "format": "prettier --ignore-path .gitignore --write \"**/*.+(js|json)\"" ``` @@ -77,6 +83,7 @@ Similarly, we can write another script to run prettier formatting as: And voila, `npm run format` will now use prettier config rules to apply formatting corrections on al js and json files in the project, except those that should be ignored. We can also have a joint script for both lint and format as: + ```js "validate": "npm run format && npm run lint" ``` @@ -85,4 +92,4 @@ Now we can execute `npm run validate` before pushing any major code change to Gi Using a common set of linting and formatting rules enforced by ESLint and Prettier boost team productivity and ensure that all developers in the team are writing clean and consistent code in a shared codebase. We will try to use these tools in most assignments going forward and strongly recommend that you use them in your own projects as well. The feeling of looking at clean and readable code can often be therapeutic, given that this job can otherwise get very stressful stuck in the land of debugging. A combination of static analysis and dynamic testing leads to well-maintained and robust code! - \ No newline at end of file +![](../assets/clean-code.jpeg) diff --git a/module6-architecture-and-best-practices/r1-introduction-to-architecture/README.md b/module6-architecture-and-best-practices/r1-introduction-to-architecture/README.md index c50207f..78e8896 100644 --- a/module6-architecture-and-best-practices/r1-introduction-to-architecture/README.md +++ b/module6-architecture-and-best-practices/r1-introduction-to-architecture/README.md @@ -64,7 +64,8 @@ Microservices allow for small dedicated teams working on specific services of th It all starts with a set of architecture diagrams. Although there are many different types and layers of architecture diagrams, usually a representation of all the different high-level logical components of the system is the most frequently referred to and used diagram. Take a look at this backend architecture diagram demonstrating the different logical components of the Netflix backend: - + +![](../assets/netflix-architecture.jpeg) We will try to utilize architecture diagrams during our capstone projects, of course with the caveat that our architectures will not be very complex since we will only be developing MVP-level projects. It is very difficult to cover architecture diagrams in the scope of this curriculum, but we believe it is best understood in practice with senior engineers on the job. When you start working as a backend developer, a senior technical member on your team will definitely walk you through an architecture diagram to get you up to speed with the system architecture you will be working on. This is the best learning experience for system architecture. diff --git a/module6-architecture-and-best-practices/r1.2-nodejs-best-practices/README.md b/module6-architecture-and-best-practices/r1.2-nodejs-best-practices/README.md index 6760900..f2414ce 100644 --- a/module6-architecture-and-best-practices/r1.2-nodejs-best-practices/README.md +++ b/module6-architecture-and-best-practices/r1.2-nodejs-best-practices/README.md @@ -78,7 +78,7 @@ The concept of separation of concerns is just a reiteration of the different lay It is good practice to write dedicated error and response handler functions or classes that can be reused throughout the codebase. This also ensures following a consistent error messaging and response structure approach for our APIs and is a continuation of writing modular code managed and modified from a single place. The handling of the request-response flow following this approach can be visualized as below: - +![](../assets/3re-architecture.png) ### 4. Simple deployability @@ -94,7 +94,7 @@ This is a reiteration of everything we learned in the Authentication and Securit - Consider mandating API keys even for public API endpoints - Consider setting up throttling and rate-limiting on your APIs - +![](../assets/api-security-structure.png) And finally here are some other good practices which we will learn about in detail in upcoming lessons: diff --git a/module6-architecture-and-best-practices/r2.1-caching-with-redis/README.md b/module6-architecture-and-best-practices/r2.1-caching-with-redis/README.md index a022ae3..deeb489 100644 --- a/module6-architecture-and-best-practices/r2.1-caching-with-redis/README.md +++ b/module6-architecture-and-best-practices/r2.1-caching-with-redis/README.md @@ -374,11 +374,11 @@ To understand the implementation details of other imported files, refer to the [ We can use the Network tab on our browser console to monitor the time taken for a request the first time when there's no data in the cache and then a second time when data has been cached. - +![](../assets/api-call-time.png) As you can see, when we request the banks' data for the first time, since it hasn't been cached yet our API talks to the Paystack API to fetch all banks. So, the request takes about 890ms. But it also saves the fetched data in cache for subsequent requests. - +![](../assets/cache-read-time.png) In the second request, this time our API knows that the data exists in the cache so it reads it directly from there. As a result, the response time is reduced to about 270 ms. diff --git a/module6-architecture-and-best-practices/r3-websockets/README.md b/module6-architecture-and-best-practices/r3-websockets/README.md index 57e6338..1b07901 100644 --- a/module6-architecture-and-best-practices/r3-websockets/README.md +++ b/module6-architecture-and-best-practices/r3-websockets/README.md @@ -23,7 +23,7 @@ HTTP and WebSocket both are communication protocols used in client-server commun So HTTP is a stateless protocol that runs on top of TCP which is a connection-oriented protocol it guarantees the delivery of data packet transfer using the three-way handshaking methods and re-transmits the lost packets. - +![](../assets/http-geeks-for-geeks.png) **WebSocket**: WebSocket is bidirectional, a full-duplex protocol that is used in the same scenario of client-server communication. However, unlike HTTP, it starts with `ws://` or `wss://`. @@ -31,7 +31,7 @@ It is a stateful protocol, which means the connection between client and server Let's take an example of client-server communication, the client is a web browser and we have a server, whenever we initiate the connection between client and server, the client-server makes the handshaking and decides to create a new connection and this connection will be kept alive until terminated by any of them. When the connection is established and alive the communication takes place using the same connection channel until it is terminated. In a way, you can say that the client and server are both actively listening to each other while the WebSocket connection is open. - +![](../assets/websocket-geeks-for-geeks.png) ## How is WebSocket different than HTTP polling, HTTP streaming, and server-sent events? @@ -94,12 +94,12 @@ After this reading, we'll get some hands-on practice with WebSockets by building The name might sound quite similar to WebSockets, however, they are not necessarily related. As a backend developer, you may often find yourself integrating with third-party APIs and services. Your API can integrate with another API by making requests. But sometimes you'll find the use of webhooks instead. Let's take a closer look at this and how it is beneficial for our backend applications. - +![](../assets/stripe-webhooks.png) Webhooks enable services like Stripe, GitHub, or Google to push data to you, instead of you having to pull data from them. When some event occurs (e.g. someone buys something from your store), the service sends you an HTTP request with data about that event. You don't have to run a script to poll the API for new events; they'll tell you when they happen, as soon as they happen. - +![](../assets/stripe-webhooks-2.png) GitHub for example can send your API a request each time someone opens a new issue in your repo. They'll tell you when a new branch is created, or even when a repo is starred. GitHub calls these as events. diff --git a/module6-architecture-and-best-practices/r6-microservices/README.md b/module6-architecture-and-best-practices/r6-microservices/README.md index 17bdc69..0c876e1 100644 --- a/module6-architecture-and-best-practices/r6-microservices/README.md +++ b/module6-architecture-and-best-practices/r6-microservices/README.md @@ -45,7 +45,7 @@ Theis architecture pattern significantly impacts the relationship between the ap Some APIs are also exposed to mobile, desktop, and web apps. The apps don't, however, have direct access to the backend services. Instead, communication is mediated by an intermediary known as an API Gateway. The API Gateway is responsible for tasks such as load balancing, caching, access control, API metering, and monitoring. - +![](../assets/microservices-example.png) The two main characteristics of microservices are: @@ -126,7 +126,7 @@ Best practices are the Do's and then there are commonly agreed anti-patterns whi Here is a visual example of a microservices architecture for an e-commerce application. - +![](../assets/microservices-example-2.png) What would this look like in practice using Node.js? Firstly, it is important to understand why Node.js is beneficial for microservices architecture. Microsoft, PayPal, and Uber are leading companies actively using Node.js application development for their projects.