You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: Readme.md
+51-27Lines changed: 51 additions & 27 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -20,7 +20,7 @@ To master a new concept, it's often best to begin from the ground up. This isn't
20
20
21
21
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.
22
22
23
-
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)
23
+
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)
24
24
25
25
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.
26
26
@@ -261,29 +261,53 @@ The repo for our backend framework- [Velocy](https://github.com/ishtms/velocy).
261
261
-[Improving the `Router` API](/chapters/ch06.3-improving-the-router-api.md)
262
262
-[The need for a `trie`](/chapters/ch06.4-the-need-for-a-trie.md)
263
263
-[What is a `Trie` anyway?](/chapters/ch06.4-the-need-for-a-trie.md#what-is-a-trie-anyway)
264
-
-[Exercise 1 - Implementing a `Trie`](/chapters/ch07-ex-implementing-a-trie.md#exercise-1---implementing-a-trie)
-[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)
> 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.
6
6
>
@@ -14,7 +14,7 @@ Here's an illustration that shows how does a `Trie` look like in theory:
14
14
15
15
Here's how you can visualize the Trie above based on the words "OK", "TO", "CAR", "CAT", and "CUP":
16
16
17
-
## Root Node
17
+
###Root Node
18
18
19
19
The Trie starts with a root node that doesn't hold any character. It serves as the starting point of the Trie.
20
20
@@ -32,7 +32,7 @@ The Trie starts with a root node that doesn't hold any character. It serves as t
32
32
- "A" further branches to "R" for "CAR" and "T" for "CAT".
33
33
- "U" further branches to "P", completing the word "CUP".
34
34
35
-
## End of the word
35
+
###End of the word
36
36
37
37
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.
38
38
@@ -44,16 +44,16 @@ Here's an another illustration to explain the "end-of-word" (EOW):
44
44
45
45

46
46
47
-
## Challenge 1: Basic Trie with `insert` Method
47
+
###Challenge 1: Basic Trie with `insert` Method
48
48
49
49
In this first challenge, your task is to implement a Trie data structure with only one functionality: inserting a word into the Trie.
50
50
51
-
### Requirements
51
+
####Requirements
52
52
53
53
1. Create a class called `Trie`.
54
54
2. Implement an `insert(word)` method that takes a string `word` and inserts it into the Trie.
55
55
56
-
### More details
56
+
####More details
57
57
58
58
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.
59
59
@@ -104,7 +104,7 @@ Great. You just implemented a `Trie` which is a Tree data structure. You've also
104
104
105
105
> 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.
106
106
107
-
### Solution
107
+
####Solution
108
108
109
109
```js
110
110
classTrie {
@@ -219,7 +219,7 @@ The previous code looks fine. However, as our backend library/framework prioriti
219
219
220
220
The code above is acceptable, and not a bad implementation. But we can do better.
221
221
222
-
### Using a `for` loop instead of recursion
222
+
####Using a `for` loop instead of recursion
223
223
224
224
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.
225
225
@@ -259,16 +259,16 @@ class Trie {
259
259
}
260
260
```
261
261
262
-
## Challenge 2: Implement `search` method
262
+
###Challenge 2: Implement `search` method
263
263
264
264
Now that we have a Trie with insertion capabilities, let's add a `search` method.
265
265
266
-
### Requirements
266
+
####Requirements
267
267
268
268
1. Add a `search(word)` method to the `Trie` class.
269
269
2. The method should return `true` if the word exists in the Trie and `false` otherwise.
270
270
271
-
### More details
271
+
####More details
272
272
273
273
1.**Start at the Root**: Begin your search at the root node.
274
274
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.
@@ -292,7 +292,7 @@ Go ahead and implement the `Trie.search` method. Don't read anything below befor
292
292
293
293
If you are having trouble or are stuck, here are some hints to help you with the implementation -
294
294
295
-
### Hints
295
+
####Hints
296
296
297
297
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.
298
298
@@ -312,7 +312,7 @@ If you are having trouble or are stuck, here are some hints to help you with the
312
312
313
313
Good luck!
314
314
315
-
### Solution
315
+
####Solution
316
316
317
317
Again, I chose to implement tree traversal using a for loop instead of recursion.
318
318
@@ -345,4 +345,4 @@ search(word) {
345
345
346
346
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.
# Exercise 2 - Implementing our Trie based `Router`
3
+
##Exercise 2 - Implementing our Trie based `Router`
4
4
5
5
> 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.
6
6
7
7
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.
8
8
9
9
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.
10
10
11
-
## Challenge 1: Implementing the `addRoute` method
11
+
###Challenge 1: Implementing the `addRoute` method
12
12
13
-
### Requirements
13
+
####Requirements
14
14
15
15
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.
16
16
17
-
### More details
17
+
####More details
18
18
19
19
1.**Class Definition**: Define a class named `TrieRouter`. This class should contain:
20
20
@@ -110,7 +110,7 @@ class RouteNode {
110
110
}
111
111
```
112
112
113
-
### Hints
113
+
####Hints
114
114
115
115
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.
116
116
@@ -125,7 +125,7 @@ class RouteNode {
125
125
6. To deal with trailing slashes, and repeated slashes, you could write utility functions that normalize the path before processing it.
126
126
7. You should throw an error if the path contains any whitespace.
127
127
128
-
### Solution
128
+
####Solution
129
129
130
130
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.
131
131
@@ -213,7 +213,7 @@ Output:
213
213
```bash
214
214
$node trie_router.js
215
215
216
-
# OUTPUT
216
+
## OUTPUT
217
217
-home
218
218
-user
219
219
--status
@@ -222,7 +222,7 @@ $node trie_router.js
222
222
223
223
Looks perfect. Let's go through the code and understand what's going on.
224
224
225
-
### Explanation
225
+
####Explanation
226
226
227
227
```js
228
228
classRouteNode {
@@ -319,13 +319,13 @@ After the loop completes, the handler function is associated with the last node
319
319
320
320
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.
321
321
322
-
## Challenge 2: Implementing the `findRoute` method
322
+
### Challenge 2: Implementing the `findRoute` method
323
323
324
-
### Requirements
324
+
#### Requirements
325
325
326
326
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.
327
327
328
-
### More details
328
+
#### More details
329
329
330
330
1. **Method - `findRoute`**: Add a method to your `TrieRouter` class called `findRoute`.
331
331
@@ -361,7 +361,7 @@ console.log(trieRouter.findRoute("/user/status/play")); // Should return null
361
361
362
362
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.
363
363
364
-
### Starting Boilerplate
364
+
#### Starting Boilerplate
365
365
366
366
Feel free to use the starting boilerplate below. If you are comfortable, you may proceed without it.
367
367
@@ -381,13 +381,13 @@ class TrieRouter {
381
381
}
382
382
```
383
383
384
-
### Hints
384
+
#### Hints
385
385
386
386
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.
387
387
388
388
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.
0 commit comments