Skip to content

Commit

Permalink
update index
Browse files Browse the repository at this point in the history
  • Loading branch information
ishtms committed Aug 27, 2024
1 parent 99a0a5f commit 2b3fab3
Show file tree
Hide file tree
Showing 6 changed files with 410 additions and 388 deletions.
78 changes: 51 additions & 27 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ To master a new concept, it's often best to begin from the ground up. This isn't

You won't just learn how Node.js works, but also why it operates in a particular way. The guide also includes discussions on relevant data structures and design patterns.

The book also includes a wide range of exercises specifically created to challenge you, that may require commitment and consistent effort on your part. The first exercises start from [chapter 7](/chapters/ch07-ex-implementing-a-trie.md)
The book also includes a wide range of exercises specifically created to challenge you, that may require commitment and consistent effort on your part. The first exercises start from [chapter 7](/chapters/ch06.5-ex-implementing-a-trie.md)

This guide goes beyond the basics. We're focused on delivering a modular, optimized backend framework that is close to being production-ready. Topics like performance optimization, security measures, and various testing approaches will be covered to ensure the framework is both reliable and extendable.

Expand Down Expand Up @@ -261,29 +261,53 @@ The repo for our backend framework- [Velocy](https://github.com/ishtms/velocy).
- [Improving the `Router` API](/chapters/ch06.3-improving-the-router-api.md)
- [The need for a `trie`](/chapters/ch06.4-the-need-for-a-trie.md)
- [What is a `Trie` anyway?](/chapters/ch06.4-the-need-for-a-trie.md#what-is-a-trie-anyway)
- [Exercise 1 - Implementing a `Trie`](/chapters/ch07-ex-implementing-a-trie.md#exercise-1---implementing-a-trie)
- [Root Node](/chapters/ch07-ex-implementing-a-trie.md#root-node)
- [End of the word](/chapters/ch07-ex-implementing-a-trie.md#end-of-the-word)
- [Challenge 1: Basic Trie with `insert` Method](/chapters/ch07-ex-implementing-a-trie.md#challenge-1-basic-trie-with-insert-method)
- [Requirements](/chapters/ch07-ex-implementing-a-trie.md#requirements)
- [More details](/chapters/ch07-ex-implementing-a-trie.md#more-details)
- [Solution](/chapters/ch07-ex-implementing-a-trie.md#solution)
- [Challenge 2: Implement `search` method](/chapters/ch07-ex-implementing-a-trie.md#challenge-2-implement-search-method)
- [Requirements](/chapters/ch07-ex-implementing-a-trie.md#requirements-1)
- [More details](/chapters/ch07-ex-implementing-a-trie.md#more-details-1)
- [Hints](/chapters/ch07-ex-implementing-a-trie.md#hints)
- [Solution](#solution-1)
- [Exercise 2 - Implementing our Trie based `Router`](/chapters/ch08-ex-implementing-router.md#exercise-2---implementing-our-trie-based-router)
- [Challenge 1: Implementing the `addRoute` method](/chapters/ch08-ex-implementing-router.md#challenge-1-implementing-the-addroute-method)
- [Requirements](/chapters/ch08-ex-implementing-router.md#requirements)
- [More details](/chapters/ch08-ex-implementing-router.md#more-details)
- [Hints](/chapters/ch08-ex-implementing-router.md#hints)
- [Solution](/chapters/ch08-ex-implementing-router.md#solution)
- [Explanation](/chapters/ch08-ex-implementing-router.md#explanation)
- [Challenge 2: Implementing the `findRoute` method](/chapters/ch08-ex-implementing-router.md#challenge-2-implementing-the-findroute-method)
- [Requirements](/chapters/ch08-ex-implementing-router.md#requirements-1)
- [More details](/chapters/ch08-ex-implementing-router.md#more-details-1)
- [Starting Boilerplate](/chapters/ch08-ex-implementing-router.md#starting-boilerplate)
- [Hints](/chapters/ch08-ex-implementing-router.md#hints-1)
- [Solution](/chapters/ch08-ex-implementing-router.md#solution-1)
- [Explanation](/chapters/ch08-ex-implementing-router.md#explanation-1)
- [Exercise 1 - Implementing a `Trie`](/chapters/ch06.5-ex-implementing-a-trie.md#exercise-1---implementing-a-trie)
- [Root Node](/chapters/ch06.5-ex-implementing-a-trie.md#root-node)
- [End of the word](/chapters/ch06.5-ex-implementing-a-trie.md#end-of-the-word)
- [Challenge 1: Basic Trie with `insert` Method](/chapters/ch06.5-ex-implementing-a-trie.md#challenge-1-basic-trie-with-insert-method)
- [Requirements](/chapters/ch06.5-ex-implementing-a-trie.md#requirements)
- [More details](/chapters/ch06.5-ex-implementing-a-trie.md#more-details)
- [Solution](/chapters/ch06.5-ex-implementing-a-trie.md#solution)
- [Challenge 2: Implement `search` method](/chapters/ch06.5-ex-implementing-a-trie.md#challenge-2-implement-search-method)
- [Requirements](/chapters/ch06.5-ex-implementing-a-trie.md#requirements-1)
- [More details](/chapters/ch06.5-ex-implementing-a-trie.md#more-details-1)
- [Hints](/chapters/ch06.5-ex-implementing-a-trie.md#hints)
- [Solution](/chapters/ch06.5-ex-implementing-a-trie.md#solution-1)
- [Exercise 2 - Implementing our Trie based `Router`](/chapters/ch06.6-ex-implementing-router.md#exercise-2---implementing-our-trie-based-router)
- [Challenge 1: Implementing the `addRoute` method](/chapters/ch06.6-ex-implementing-router.md#challenge-1-implementing-the-addroute-method)
- [Requirements](/chapters/ch06.6-ex-implementing-router.md#requirements)
- [More details](/chapters/ch06.6-ex-implementing-router.md#more-details)
- [Hints](/chapters/ch06.6-ex-implementing-router.md#hints)
- [Solution](/chapters/ch06.6-ex-implementing-router.md#solution)
- [Explanation](/chapters/ch06.6-ex-implementing-router.md#explanation)
- [Challenge 2: Implementing the `findRoute` method](/chapters/ch06.6-ex-implementing-router.md#challenge-2-implementing-the-findroute-method)
- [Requirements](/chapters/ch06.6-ex-implementing-router.md#requirements-1)
- [More details](/chapters/ch06.6-ex-implementing-router.md#more-details-1)
- [Starting Boilerplate](/chapters/ch06.6-ex-implementing-router.md#starting-boilerplate)
- [Hints](/chapters/ch06.6-ex-implementing-router.md#hints-1)
- [Solution](/chapters/ch06.6-ex-implementing-router.md#solution-1)
- [Explanation](/chapters/ch06.6-ex-implementing-router.md#explanation-1)
- [Exercise 3 - Adding `HTTP` method support](/chapters/ch06.6-ex-implementing-router.md#explanation-1#exercise-3-adding-http-method-support)
- [Requirements](/chapters/ch06.7-ex-adding-http-methods#requirements)
- [More details](/chapters/ch06.7-ex-adding-http-methods#more-details)
- [Example](/chapters/ch06.7-ex-adding-http-methods#example)
- [Hints](/chapters/ch06.7-ex-adding-http-methods#hints)
- [Solution](/chapters/ch06.7-ex-adding-http-methods#solution)
- [Exercise 4 - Implementing Dynamic Routing](/chapters/ch06.8-ex-dynamic-routing#exercise-4-implementing-dynamic-routing)
- [Why Dynamic Routing?](/chapters/ch06.8-ex-dynamic-routing#why-dynamic-routing)
- [Flexibility](/chapters/ch06.8-ex-dynamic-routing#flexibility)
- [Better User Experience](/chapters/ch06.8-ex-dynamic-routing#better-user-experience)
- [Better Developer Experience](/chapters/ch06.8-ex-dynamic-routing#better-developer-experience)
- [Better SEO](/chapters/ch06.8-ex-dynamic-routing#better-seo)
- [Anatomy of a dynamic route](/chapters/ch06.8-ex-dynamic-routing#anatomy-of-a-dynamic-route)
- [Challenge 1: Update the `getRouteParts()` function](/chapters/ch06.8-ex-dynamic-routing#challenge-1-update-the-getrouteparts-function)
- [Requirement](/chapters/ch06.8-ex-dynamic-routing#requirement)
- [More Details:](/chapters/ch06.8-ex-dynamic-routing#more-details)
- [Solution](/chapters/ch06.8-ex-dynamic-routing#solution)
- [Challenge 2: Add the dynamic routing functionality in `Router` class](/chapters/ch06.8-ex-dynamic-routing#challenge-2-add-the-dynamic-routing-functionality-in-router-class)
- [Requirements](/chapters/ch06.8-ex-dynamic-routing#requirements)
- [More Details](/chapters/ch06.8-ex-dynamic-routing#more-details-1)
- [Steps](/chapters/ch06.8-ex-dynamic-routing#steps)
- [Solution](/chapters/ch06.8-ex-dynamic-routing#solution-1)
- [Challenge 3: Adding Wildcard (Catch-All) Route Support](/chapters/ch06.8-ex-dynamic-routing#challenge-3-adding-wildcard-catch-all-route-support) - [More Details](/chapters/ch06.8-ex-dynamic-routing#more-details-2) - [Steps](/chapters/ch06.8-ex-dynamic-routing#steps-1)
- [Solution](/chapters/ch06.8-ex-dynamic-routing#solution-2)
2 changes: 1 addition & 1 deletion chapters/ch06.4-the-need-for-a-trie.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,4 @@ Every node, including `root` will be an object that contain some necessary infor

Enough with the theory. In the next chapter, we'll dive into our very first exercise for this book: **implementing a Trie**.

[![Read Next](/assets/imgs/next.png)](/chapters/ch07-ex-implementing-a-trie.md)
[![Read Next](/assets/imgs/next.png)](/chapters/ch06.5-ex-implementing-a-trie.md)
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[![Read Prev](/assets/imgs/prev.png)](/chapters/ch06.4-the-need-for-a-trie.md)

# Exercise 1 - Implementing a `Trie`
## Exercise 1 - Implementing a `Trie`

> This exercise will motivate you to work on implementing your solution independently. Once you have completed the exercise, you can move on to the next challenge or read the solution to find a different approach.
>
Expand All @@ -14,7 +14,7 @@ Here's an illustration that shows how does a `Trie` look like in theory:

Here's how you can visualize the Trie above based on the words "OK", "TO", "CAR", "CAT", and "CUP":

## Root Node
### Root Node

The Trie starts with a root node that doesn't hold any character. It serves as the starting point of the Trie.

Expand All @@ -32,7 +32,7 @@ The Trie starts with a root node that doesn't hold any character. It serves as t
- "A" further branches to "R" for "CAR" and "T" for "CAT".
- "U" further branches to "P", completing the word "CUP".

## End of the word
### End of the word

The "end of the word" is often represented by a boolean flag at a node to signify that the path from the root of the Trie to that node corresponds to a complete word. This flag helps distinguish between a string that is merely a prefix and one that is a full word in the Trie.

Expand All @@ -44,16 +44,16 @@ Here's an another illustration to explain the "end-of-word" (EOW):

![](/assets/imgs/trie-eow.png)

## Challenge 1: Basic Trie with `insert` Method
### Challenge 1: Basic Trie with `insert` Method

In this first challenge, your task is to implement a Trie data structure with only one functionality: inserting a word into the Trie.

### Requirements
#### Requirements

1. Create a class called `Trie`.
2. Implement an `insert(word)` method that takes a string `word` and inserts it into the Trie.

### More details
#### More details

1. **Initialization**: You'll begin with a root node. This node will be the starting point for all word insertions, and it won't store any character itself.

Expand Down Expand Up @@ -104,7 +104,7 @@ Great. You just implemented a `Trie` which is a Tree data structure. You've also

> In case you were not able to figure out what to do, I would still like you to scrap the code you've written and start again from scratch. Get a pen and paper, and visualize it. That way you can convert hard problems into easier ones.
### Solution
#### Solution

```js
class Trie {
Expand Down Expand Up @@ -219,7 +219,7 @@ The previous code looks fine. However, as our backend library/framework prioriti

The code above is acceptable, and not a bad implementation. But we can do better.

### Using a `for` loop instead of recursion
#### Using a `for` loop instead of recursion

I am not a big fan of recursion, and I prefer using loops over recursion most of the time. For loop is much easier to reason about and as someone who's reading the code, it's easier to understand what's going on.

Expand Down Expand Up @@ -259,16 +259,16 @@ class Trie {
}
```

## Challenge 2: Implement `search` method
### Challenge 2: Implement `search` method

Now that we have a Trie with insertion capabilities, let's add a `search` method.

### Requirements
#### Requirements

1. Add a `search(word)` method to the `Trie` class.
2. The method should return `true` if the word exists in the Trie and `false` otherwise.

### More details
#### More details

1. **Start at the Root**: Begin your search at the root node.
2. **Traversal**: For each character in the word, traverse down the Trie, going from one node to its child that corresponds to the next character.
Expand All @@ -292,7 +292,7 @@ Go ahead and implement the `Trie.search` method. Don't read anything below befor

If you are having trouble or are stuck, here are some hints to help you with the implementation -

### Hints
#### Hints

1. **Starting Point**: Similar to the `insert` method, you'll start at the root node and traverse the Trie based on the characters in the word you're searching for.

Expand All @@ -312,7 +312,7 @@ If you are having trouble or are stuck, here are some hints to help you with the

Good luck!

### Solution
#### Solution

Again, I chose to implement tree traversal using a for loop instead of recursion.

Expand Down Expand Up @@ -345,4 +345,4 @@ search(word) {

Awesome work. Now you know the basics of the `Trie` data structure and how to implement it. In the next exercise, we'll implement our `Router` from scratch! The next exercise will be more challenging and exhaustive.

[![Read Next](/assets/imgs/next.png)](/chapters/ch08-ex-implementing-router.md)
[![Read Next](/assets/imgs/next.png)](/chapters/ch06.6-ex-implementing-router.md)
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
[![Read Prev](/assets/imgs/prev.png)](/chapters/ch07-ex-implementing-a-trie.md)
[![Read Prev](/assets/imgs/prev.png)](/chapters/ch06.5-ex-implementing-a-trie.md)

# Exercise 2 - Implementing our Trie based `Router`
## Exercise 2 - Implementing our Trie based `Router`

> This challenge is designed to push your boundaries and is considered to be more advanced than usual. It's completely okay if you don't crack it on your first attempt. The key is to persist, revisit your logic, and don't hesitate to iterate on your solutions.
Since we just built a Trie data structure that can efficiently insert and search words, we can further enhance its capabilities by extending it to implement a Trie-based router for matching URL patterns. This powerful application of `Trie` data structure is commonly utilized in web frameworks, where it plays a crucial role in efficiently routing incoming HTTP requests to their respective handler functions.

By building a `Trie`-based router, our framework can achieve optimal performance and scalability, ensuring that each request is efficiently directed to the appropriate handler for processing.

## Challenge 1: Implementing the `addRoute` method
### Challenge 1: Implementing the `addRoute` method

### Requirements
#### Requirements

Create a new class, `TrieRouter`, similar to what we had earlier - `Trie`. Add a method, `addRoute`, that takes in a URL pattern (like `/home` or `/user/status/play`) as a first parameter and a handler function as second parameter. Then insert the URL pattern into the `TrieRouter`, associating the handler function with the last node of that pattern.

### More details
#### More details

1. **Class Definition**: Define a class named `TrieRouter`. This class should contain:

Expand Down Expand Up @@ -110,7 +110,7 @@ class RouteNode {
}
```

### Hints
#### Hints

1. Remember that a Trie is a tree-like structure where each node represents a piece/segment of a URL. Understanding the hierarchy can simplify the process.

Expand All @@ -125,7 +125,7 @@ class RouteNode {
6. To deal with trailing slashes, and repeated slashes, you could write utility functions that normalize the path before processing it.
7. You should throw an error if the path contains any whitespace.

### Solution
#### Solution

Kudos to those who successfully implemented the `addRoute` function in the `TrieRouter` class. You've just completed the first difficult exercise in this book, showcasing not only your coding abilities but also your problem-solving skills.

Expand Down Expand Up @@ -213,7 +213,7 @@ Output:
```bash
$node trie_router.js

# OUTPUT
## OUTPUT
-home
-user
--status
Expand All @@ -222,7 +222,7 @@ $node trie_router.js

Looks perfect. Let's go through the code and understand what's going on.

### Explanation
#### Explanation

```js
class RouteNode {
Expand Down Expand Up @@ -319,13 +319,13 @@ After the loop completes, the handler function is associated with the last node
That's it. We now have a working implementation of our router that supports adding routes. The next challenge involves finding a route and returning the handler associated with it.
## Challenge 2: Implementing the `findRoute` method
### Challenge 2: Implementing the `findRoute` method
### Requirements
#### Requirements
You've successfully implemented the `addRoute` method to build our `Trie`-based router. Now, lets extend our `TrieRouter` class by adding another method, `findRoute`. This method should take a URL pattern (e.g., `/home` or `/user/status/play`) as its parameter. Search the `TrieRouter` and find the handler function associated with the last node that matches the pattern.
### More details
#### More details
1. **Method - `findRoute`**: Add a method to your `TrieRouter` class called `findRoute`.
Expand Down Expand Up @@ -361,7 +361,7 @@ console.log(trieRouter.findRoute("/user/status/play")); // Should return null
Feel free to share your implementation or ask for feedback in the [Github discussions](https://github.com/ishtms/learn-nodejs-hard-way/discussions) section. I'll try to review all code submissions and provide feedback if required.
### Starting Boilerplate
#### Starting Boilerplate
Feel free to use the starting boilerplate below. If you are comfortable, you may proceed without it.
Expand All @@ -381,13 +381,13 @@ class TrieRouter {
}
```
### Hints
#### Hints
1. When traversing the Trie, you may find it beneficial to break down the URL pattern into segments just like you did while inserting the route.
2. Be careful about the return values. Ensure you return the handler function if a match is found and a suitable indicator (like `null`) if no match exists.
### Solution
#### Solution
Here's the solution that I came up with:
Expand Down Expand Up @@ -433,7 +433,7 @@ class RouteNode {
}
```
### Explanation
#### Explanation
```js
findRoute(path) {
Expand Down
Loading

0 comments on commit 2b3fab3

Please sign in to comment.