1
00:00:01,070 --> 00:00:04,020
<v Jonas>Modules are a super important part</v>

2
00:00:04,020 --> 00:00:06,020
of software development.

3
00:00:06,020 --> 00:00:07,540
And so in this lecture,

4
00:00:07,540 --> 00:00:10,530
we're gonna talk about modules in more depth

5
00:00:10,530 --> 00:00:13,143
and learn how they work behind the scenes.

6
00:00:14,800 --> 00:00:17,070
So essentially, a module

7
00:00:17,070 --> 00:00:19,370
is a reusable piece of code

8
00:00:19,370 --> 00:00:22,120
that encapsulates implementation details

9
00:00:22,120 --> 00:00:25,370
of a certain part of our project.

10
00:00:25,370 --> 00:00:28,120
Now that sounds a bit like a function

11
00:00:28,120 --> 00:00:29,640
or even a class,

12
00:00:29,640 --> 00:00:31,840
but the difference is that a module

13
00:00:31,840 --> 00:00:35,290
is usually a standalone file.

14
00:00:35,290 --> 00:00:37,500
Now that's not always the case,

15
00:00:37,500 --> 00:00:40,170
but normally when we think of a module

16
00:00:40,170 --> 00:00:42,750
we think of a separate file.

17
00:00:42,750 --> 00:00:46,910
So of course a module always contains some code

18
00:00:46,910 --> 00:00:51,040
but it can also have imports and exports.

19
00:00:51,040 --> 00:00:53,920
So with exports, as the name says,

20
00:00:53,920 --> 00:00:57,110
we can export values out of a module

21
00:00:57,110 --> 00:01:01,420
for example, simple values or even entire functions.

22
00:01:01,420 --> 00:01:04,070
And whatever we export from a module

23
00:01:04,070 --> 00:01:06,710
is called the public API.

24
00:01:06,710 --> 00:01:08,890
So this is just like classes

25
00:01:08,890 --> 00:01:11,850
where we can also expose a public API

26
00:01:11,850 --> 00:01:14,420
for other codes to consume.

27
00:01:14,420 --> 00:01:16,490
Now, in the case of modules,

28
00:01:16,490 --> 00:01:19,490
this public API is actually consumed

29
00:01:19,490 --> 00:01:23,060
by importing values into a module.

30
00:01:23,060 --> 00:01:25,630
So just like we can export values

31
00:01:25,630 --> 00:01:28,600
in modules, we can usually also import values

32
00:01:28,600 --> 00:01:30,470
from other modules.

33
00:01:30,470 --> 00:01:33,570
And these other modules from which we import

34
00:01:33,570 --> 00:01:35,610
are then called dependencies

35
00:01:35,610 --> 00:01:37,370
of the importing module

36
00:01:37,370 --> 00:01:39,660
because the code dead is in the module

37
00:01:39,660 --> 00:01:43,380
dead is importing cannot work without the code,

38
00:01:43,380 --> 00:01:47,860
that it is importing from the external module, right?

39
00:01:47,860 --> 00:01:50,510
And this entire logic that I just described

40
00:01:50,510 --> 00:01:52,510
is true for all modules

41
00:01:52,510 --> 00:01:54,760
in all programming languages.

42
00:01:54,760 --> 00:01:58,490
So this is not specific to only JavaScript.

43
00:01:58,490 --> 00:02:01,840
In fact, modules are a pattern that developers

44
00:02:01,840 --> 00:02:05,570
have been using in all languages for decades.

45
00:02:05,570 --> 00:02:09,300
Now, of course we can write code without modules,

46
00:02:09,300 --> 00:02:11,320
and actually we've been doing that

47
00:02:11,320 --> 00:02:12,780
up until this point.

48
00:02:12,780 --> 00:02:14,760
but that's because our applications

49
00:02:14,760 --> 00:02:16,890
have been very simple.

50
00:02:16,890 --> 00:02:20,180
However, when a code base grows bigger and bigger,

51
00:02:20,180 --> 00:02:22,230
there start to be many advantages

52
00:02:22,230 --> 00:02:23,910
of using modules.

53
00:02:23,910 --> 00:02:26,270
And the first one is that modules make it

54
00:02:26,270 --> 00:02:29,640
really easy to compose software.

55
00:02:29,640 --> 00:02:31,480
So we can think of modules

56
00:02:31,480 --> 00:02:33,070
as small building blocks

57
00:02:33,070 --> 00:02:35,100
that we can then put together

58
00:02:35,100 --> 00:02:38,430
in order to build really complex applications.

59
00:02:38,430 --> 00:02:40,320
And I think it might be helpful

60
00:02:40,320 --> 00:02:42,880
to look at a more real world example,

61
00:02:42,880 --> 00:02:46,520
to understand all the benefits of modules.

62
00:02:46,520 --> 00:02:49,350
So let's take this digital camera.

63
00:02:49,350 --> 00:02:51,940
You can see that this specific camera

64
00:02:51,940 --> 00:02:55,123
is basically made up of all these modules

65
00:02:55,123 --> 00:02:56,930
that we can see here.

66
00:02:56,930 --> 00:03:00,030
And this is exactly how we can compose software

67
00:03:00,030 --> 00:03:02,420
using modules as well.

68
00:03:02,420 --> 00:03:05,610
Another big advantage of these camera modules

69
00:03:05,610 --> 00:03:07,300
is that each of them can be

70
00:03:07,300 --> 00:03:10,350
developed in complete isolation.

71
00:03:10,350 --> 00:03:13,980
So you can have one engineer working on the lens

72
00:03:13,980 --> 00:03:16,380
and another one on the screen

73
00:03:16,380 --> 00:03:19,870
and even another one on the controller module.

74
00:03:19,870 --> 00:03:22,950
And the best part of this is that each engineer

75
00:03:22,950 --> 00:03:25,640
can actually work on their own module

76
00:03:25,640 --> 00:03:27,330
without even understanding

77
00:03:27,330 --> 00:03:29,420
what the other engineers are doing.

78
00:03:29,420 --> 00:03:31,410
And also without understanding

79
00:03:31,410 --> 00:03:35,010
how the entire final camera works itself.

80
00:03:35,010 --> 00:03:37,330
And so isolating components

81
00:03:37,330 --> 00:03:41,200
is another huge advantage of using modules.

82
00:03:41,200 --> 00:03:43,450
And again, isolating components

83
00:03:43,450 --> 00:03:45,860
essentially means that each module

84
00:03:45,860 --> 00:03:48,000
can be developed in isolation

85
00:03:48,000 --> 00:03:50,280
without the developer having to think

86
00:03:50,280 --> 00:03:52,400
about the entire code base.

87
00:03:52,400 --> 00:03:55,030
He doesn't even need to understand all of it,

88
00:03:55,030 --> 00:03:56,450
which makes it really easy

89
00:03:56,450 --> 00:03:59,660
to collaborate on a larger team.

90
00:03:59,660 --> 00:04:02,240
Next up modules make it very easy

91
00:04:02,240 --> 00:04:04,440
to abstract or code.

92
00:04:04,440 --> 00:04:05,930
And we already talked about

93
00:04:05,930 --> 00:04:07,810
what abstraction means,

94
00:04:07,810 --> 00:04:10,410
but basically we can use modules

95
00:04:10,410 --> 00:04:13,240
to implement low level code

96
00:04:13,240 --> 00:04:14,420
then other modules,

97
00:04:14,420 --> 00:04:15,830
which don't really care

98
00:04:15,830 --> 00:04:17,920
about these low level details

99
00:04:17,920 --> 00:04:21,720
can import these abstractions and use them.

100
00:04:21,720 --> 00:04:24,500
And back to our camera, the screen module,

101
00:04:24,500 --> 00:04:26,620
for example, does not care

102
00:04:26,620 --> 00:04:29,470
about the low level implementation details

103
00:04:29,470 --> 00:04:31,410
of the controller module.

104
00:04:31,410 --> 00:04:33,940
It can simply import the controller,

105
00:04:33,940 --> 00:04:36,070
but without knowing how it works

106
00:04:36,070 --> 00:04:39,600
and use it to control other parts of the camera.

107
00:04:39,600 --> 00:04:43,730
And so that's essentially the power of abstraction.

108
00:04:43,730 --> 00:04:46,000
Modules also naturally lead

109
00:04:46,000 --> 00:04:48,820
to a more organized code base.

110
00:04:48,820 --> 00:04:50,900
Because when we break up our code

111
00:04:50,900 --> 00:04:55,010
into separate isolated and obstructed modules,

112
00:04:55,010 --> 00:04:57,560
this will automatically organize our code

113
00:04:57,560 --> 00:04:59,840
and make it easier to understand.

114
00:04:59,840 --> 00:05:03,720
And so this alone is a huge benefit of modules.

115
00:05:03,720 --> 00:05:07,160
Finally modules allow us to easily reuse

116
00:05:07,160 --> 00:05:09,190
the same code in a project

117
00:05:09,190 --> 00:05:12,110
and even across multiple projects.

118
00:05:12,110 --> 00:05:14,430
For example, if we use the module

119
00:05:14,430 --> 00:05:17,420
to implement a couple of mathematical functions

120
00:05:17,420 --> 00:05:19,160
in a certain project,

121
00:05:19,160 --> 00:05:21,420
and if we then need the same functions

122
00:05:21,420 --> 00:05:22,980
in the next project,

123
00:05:22,980 --> 00:05:25,800
all we need to do is to copy that module

124
00:05:25,800 --> 00:05:27,860
to the new project.

125
00:05:27,860 --> 00:05:29,950
And in our camera example here,

126
00:05:29,950 --> 00:05:33,290
this company could now use the exact same lens

127
00:05:33,290 --> 00:05:35,070
or the exact same screen

128
00:05:35,070 --> 00:05:37,130
in different camera models,

129
00:05:37,130 --> 00:05:40,580
all because they nicely abstracted these components

130
00:05:40,580 --> 00:05:43,433
into self-contained reusable modules.

131
00:05:45,120 --> 00:05:47,200
So this is how modules work

132
00:05:47,200 --> 00:05:49,630
in software design in general.

133
00:05:49,630 --> 00:05:51,880
But now let's take a look at modules

134
00:05:51,880 --> 00:05:54,023
specifically in JavaScript.

135
00:05:55,500 --> 00:05:57,470
So as of ES6,

136
00:05:57,470 --> 00:06:01,650
JavaScript has a native built-in module system.

137
00:06:01,650 --> 00:06:04,700
Now we did have modules before ES6,

138
00:06:04,700 --> 00:06:06,980
but we had to implement them ourselves

139
00:06:06,980 --> 00:06:09,600
or use external libraries.

140
00:06:09,600 --> 00:06:12,740
So ES6 modules are modules

141
00:06:12,740 --> 00:06:15,360
that are actually stored in files

142
00:06:15,360 --> 00:06:17,750
and each file is one module.

143
00:06:17,750 --> 00:06:20,743
So there is exactly one module per file.

144
00:06:21,840 --> 00:06:23,810
But now you might be thinking,

145
00:06:23,810 --> 00:06:28,470
well, scripts are usually also files, right?

146
00:06:28,470 --> 00:06:30,280
And that's of course true.

147
00:06:30,280 --> 00:06:31,720
And so let's not compare

148
00:06:31,720 --> 00:06:33,680
these two types of files

149
00:06:33,680 --> 00:06:34,583
in order to understand

150
00:06:34,583 --> 00:06:37,360
that there are actually huge differences

151
00:06:37,360 --> 00:06:41,503
between old school scripts and modern ES6 modules.

152
00:06:42,350 --> 00:06:44,560
The first difference is that in modules,

153
00:06:44,560 --> 00:06:46,200
all top level variables

154
00:06:46,200 --> 00:06:49,070
are scooped to the module.

155
00:06:49,070 --> 00:06:51,830
So basically variables are private

156
00:06:51,830 --> 00:06:53,980
to the module by default.

157
00:06:53,980 --> 00:06:57,050
And the only way an outside module can access

158
00:06:57,050 --> 00:07:00,050
a value that's inside of a module

159
00:07:00,050 --> 00:07:02,340
is by exporting that value.

160
00:07:02,340 --> 00:07:05,260
So just as we learned in the last slide.

161
00:07:05,260 --> 00:07:07,090
But if we don't export,

162
00:07:07,090 --> 00:07:11,160
then no one from the outside can see the variable.

163
00:07:11,160 --> 00:07:13,510
Now in scripts, on the other hand,

164
00:07:13,510 --> 00:07:15,050
all top level variables

165
00:07:15,050 --> 00:07:18,080
are always global and I showed you this

166
00:07:18,080 --> 00:07:21,430
in the map d project, remember?

167
00:07:21,430 --> 00:07:23,330
And this can lead to problems

168
00:07:23,330 --> 00:07:25,820
like global namespace pollution,

169
00:07:25,820 --> 00:07:28,780
where multiple scripts try to declare variables

170
00:07:28,780 --> 00:07:30,800
with the same name and then

171
00:07:30,800 --> 00:07:32,910
these variables collide.

172
00:07:32,910 --> 00:07:34,300
So private variables

173
00:07:34,300 --> 00:07:36,310
are the solution to this problem.

174
00:07:36,310 --> 00:07:40,163
And that's why ES6 modules implemented it like this.

175
00:07:41,320 --> 00:07:44,140
Next ES modules are always executed

176
00:07:44,140 --> 00:07:47,770
in strict mode while scripts on the other hand

177
00:07:47,770 --> 00:07:51,280
are executed in sloppy mode by default.

178
00:07:51,280 --> 00:07:53,510
So with modules, there is no more need

179
00:07:53,510 --> 00:07:56,490
to manually declare strict mode.

180
00:07:56,490 --> 00:07:59,600
Also the disc keyword is always undefined

181
00:07:59,600 --> 00:08:00,980
at the top level

182
00:08:00,980 --> 00:08:05,323
while in scripts it points at the window object, right?

183
00:08:06,400 --> 00:08:08,920
Now, as we learned in the last slide,

184
00:08:08,920 --> 00:08:11,270
what's really special about modules

185
00:08:11,270 --> 00:08:13,870
is that we can export and import values

186
00:08:13,870 --> 00:08:17,030
between them using this ES6 import

187
00:08:17,030 --> 00:08:19,090
and experts syntax.

188
00:08:19,090 --> 00:08:20,630
In regular scripts,

189
00:08:20,630 --> 00:08:22,880
importing and exporting values

190
00:08:22,880 --> 00:08:25,353
is just completely impossible.

191
00:08:26,270 --> 00:08:28,290
Now, there is something really important

192
00:08:28,290 --> 00:08:31,320
to note about imports and exports,

193
00:08:31,320 --> 00:08:34,310
which is the fact that they can only happen

194
00:08:34,310 --> 00:08:35,980
at the top level.

195
00:08:35,980 --> 00:08:39,050
So as you know, outside of any function

196
00:08:39,050 --> 00:08:40,900
or any if block,

197
00:08:40,900 --> 00:08:44,520
and we will see why that is in a second.

198
00:08:44,520 --> 00:08:47,550
Also all imports are hoisted.

199
00:08:47,550 --> 00:08:49,440
So no matter where in a code

200
00:08:49,440 --> 00:08:51,260
you're importing values,

201
00:08:51,260 --> 00:08:53,030
it's like the import statement

202
00:08:53,030 --> 00:08:56,070
will be moved to the top of the file.

203
00:08:56,070 --> 00:08:58,630
So in practice importing values

204
00:08:58,630 --> 00:09:01,993
is always the first thing that happens in a module.

205
00:09:03,940 --> 00:09:07,920
Now, in order to link a module to an HTML file,

206
00:09:07,920 --> 00:09:09,760
we need to use the script tag with

207
00:09:09,760 --> 00:09:12,550
the type attribute set to module,

208
00:09:12,550 --> 00:09:14,853
instead of just a plain script tag.

209
00:09:16,140 --> 00:09:18,330
And finally about downloading

210
00:09:18,330 --> 00:09:20,620
the module files themselves.

211
00:09:20,620 --> 00:09:22,800
This always automatically happens

212
00:09:22,800 --> 00:09:25,030
in an asynchronous way.

213
00:09:25,030 --> 00:09:27,300
And this is true for a module loaded

214
00:09:27,300 --> 00:09:30,340
from HTML as well as for modules

215
00:09:30,340 --> 00:09:32,290
that are loaded by importing

216
00:09:32,290 --> 00:09:34,320
one module into another,

217
00:09:34,320 --> 00:09:36,840
using the import syntax.

218
00:09:36,840 --> 00:09:39,370
Now regular scripts on the other hand

219
00:09:39,370 --> 00:09:41,100
are downloaded by default

220
00:09:41,100 --> 00:09:43,470
in a blocking synchronous way,

221
00:09:43,470 --> 00:09:45,090
unless we use the async

222
00:09:45,090 --> 00:09:47,933
or differ attributes on the script tag.

223
00:09:48,860 --> 00:09:52,460
So that's a great overview of ES6 modules,

224
00:09:52,460 --> 00:09:54,540
but now let's dig a bit deeper

225
00:09:54,540 --> 00:09:56,570
and really understand how modules

226
00:09:56,570 --> 00:09:59,923
actually import other modules behind the scenes.

227
00:10:01,940 --> 00:10:04,820
And to do that, let's analyze what happens

228
00:10:04,820 --> 00:10:07,320
in this small code example.

229
00:10:07,320 --> 00:10:09,220
So here we're importing a value

230
00:10:09,220 --> 00:10:12,940
called rent from the math.js module

231
00:10:12,940 --> 00:10:15,903
and show dies from the dumb.jsmodule.

232
00:10:17,050 --> 00:10:20,760
Now, as always, when a piece of code is executed,

233
00:10:20,760 --> 00:10:24,060
the first step is to parse that code.

234
00:10:24,060 --> 00:10:28,520
Remember, so we talked about that way back.

235
00:10:28,520 --> 00:10:31,240
But remember that parsing basically means

236
00:10:31,240 --> 00:10:33,150
to just read the code,

237
00:10:33,150 --> 00:10:35,620
but without executing it.

238
00:10:35,620 --> 00:10:36,970
And this is the moment

239
00:10:36,970 --> 00:10:39,800
in which imports are hoisted.

240
00:10:39,800 --> 00:10:44,160
And in fact, the whole process of importing modules

241
00:10:44,160 --> 00:10:47,440
happens before the code in the main module

242
00:10:47,440 --> 00:10:49,223
is actually executed.

243
00:10:51,303 --> 00:10:52,770
So in this example,

244
00:10:52,770 --> 00:10:55,330
the index.js module imports,

245
00:10:55,330 --> 00:10:57,830
the dumb and math modules

246
00:10:57,830 --> 00:10:59,393
in a synchronous way.

247
00:11:00,300 --> 00:11:02,820
What that means is that only after

248
00:11:02,820 --> 00:11:06,970
all imported modules have been downloaded and executed,

249
00:11:06,970 --> 00:11:09,660
the main index.js module

250
00:11:09,660 --> 00:11:12,053
will finally be executed as well.

251
00:11:12,930 --> 00:11:14,830
Now this is only possible

252
00:11:14,830 --> 00:11:18,810
because of top level imports and exports

253
00:11:18,810 --> 00:11:22,340
that's because if we only export and import values

254
00:11:22,340 --> 00:11:26,200
outside of any code that needs to be executed,

255
00:11:26,200 --> 00:11:27,950
then the engine can know

256
00:11:27,950 --> 00:11:31,650
all the imports and exports during the parsing phase.

257
00:11:31,650 --> 00:11:34,450
So while the code is still being read

258
00:11:34,450 --> 00:11:36,920
before being executed.

259
00:11:36,920 --> 00:11:39,620
Now, if we were allowed to import a module

260
00:11:39,620 --> 00:11:41,260
inside of a function,

261
00:11:41,260 --> 00:11:43,140
then that function would first

262
00:11:43,140 --> 00:11:46,783
have to be executed before the import code happened.

263
00:11:48,020 --> 00:11:49,320
And so in that case,

264
00:11:49,320 --> 00:11:53,230
modules could not be imported in a synchronous way.

265
00:11:53,230 --> 00:11:54,890
So the importing module

266
00:11:54,890 --> 00:11:57,490
would have to be executed first.

267
00:11:57,490 --> 00:12:00,820
But you might ask why do we actually want

268
00:12:00,820 --> 00:12:03,980
modules to be loaded in a synchronous way?

269
00:12:03,980 --> 00:12:06,210
Isn't synchronous bad?

270
00:12:06,210 --> 00:12:09,910
Well, the answer is that this is the easiest way

271
00:12:09,910 --> 00:12:11,520
in which we can do things

272
00:12:11,520 --> 00:12:15,050
like bundling and dead code elimination.

273
00:12:15,050 --> 00:12:16,895
So basically deleting code

274
00:12:16,895 --> 00:12:19,760
that's actually not even necessary.

275
00:12:19,760 --> 00:12:21,060
And trust me,

276
00:12:21,060 --> 00:12:24,150
this is very important in large projects

277
00:12:24,150 --> 00:12:26,070
with hundreds of modules

278
00:12:26,070 --> 00:12:28,630
and that includes third party modules

279
00:12:28,630 --> 00:12:31,720
from which we usually only want a small piece

280
00:12:31,720 --> 00:12:34,130
and not the entire module.

281
00:12:34,130 --> 00:12:36,380
So by knowing all dependencies

282
00:12:36,380 --> 00:12:39,240
between modules before execution,

283
00:12:39,240 --> 00:12:41,790
bundlers like webpack and Parcel

284
00:12:41,790 --> 00:12:44,560
can then join multiple modules together

285
00:12:44,560 --> 00:12:46,770
and eliminate that code.

286
00:12:46,770 --> 00:12:49,660
And so essentially this is the reason why

287
00:12:49,660 --> 00:12:52,050
we can only import and export

288
00:12:52,050 --> 00:12:55,510
outside of any code that needs to be executed.

289
00:12:55,510 --> 00:12:58,600
So like a function or an if block,

290
00:12:58,600 --> 00:13:01,240
but now let's move on here.

291
00:13:01,240 --> 00:13:03,400
So after the parsing process,

292
00:13:03,400 --> 00:13:07,790
HIAS figured out which modules it needs to import,

293
00:13:07,790 --> 00:13:10,660
then these modules are actually downloaded

294
00:13:10,660 --> 00:13:11,733
from the server.

295
00:13:12,970 --> 00:13:15,830
And remember downloading actually happens

296
00:13:15,830 --> 00:13:17,980
in an asynchronous way.

297
00:13:17,980 --> 00:13:20,830
It is only the importing operation itself

298
00:13:20,830 --> 00:13:22,563
that happens synchronously.

299
00:13:24,454 --> 00:13:26,690
Then after a module arrives,

300
00:13:26,690 --> 00:13:30,380
it's also parsed and the modules exports

301
00:13:30,380 --> 00:13:34,760
are linked to the imports in index.js.

302
00:13:34,760 --> 00:13:35,980
So for example,

303
00:13:35,980 --> 00:13:39,800
the math module exports a function called rent.

304
00:13:39,800 --> 00:13:42,370
And this export is then connected

305
00:13:42,370 --> 00:13:46,460
to the rent import in the index.js module.

306
00:13:46,460 --> 00:13:50,660
And this connection is actually a life connection.

307
00:13:50,660 --> 00:13:54,920
So exported values are not copied to imports.

308
00:13:54,920 --> 00:13:58,490
Instead, the import is basically just a reference

309
00:13:58,490 --> 00:14:00,660
to the export at value

310
00:14:00,660 --> 00:14:02,210
like a pointer.

311
00:14:02,210 --> 00:14:03,860
So when the value changes

312
00:14:03,860 --> 00:14:05,770
in the exporting module,

313
00:14:05,770 --> 00:14:08,190
then the same value also changes

314
00:14:08,190 --> 00:14:10,570
in the importing module.

315
00:14:10,570 --> 00:14:13,020
And this is quite important to understand

316
00:14:13,020 --> 00:14:16,450
because it's unique to ES6 modules.

317
00:14:16,450 --> 00:14:19,660
Other module systems do not work like this,

318
00:14:19,660 --> 00:14:21,930
but JavaScript modules do.

319
00:14:21,930 --> 00:14:24,373
And so you need to keep that in mind.

320
00:14:25,280 --> 00:14:27,860
But anyway, next up,

321
00:14:27,860 --> 00:14:31,303
to code in the imported modules is executed.

322
00:14:32,270 --> 00:14:34,640
And with this the process of importing

323
00:14:34,640 --> 00:14:37,330
modules is finally finished.

324
00:14:37,330 --> 00:14:39,500
And so now, as I already said,

325
00:14:39,500 --> 00:14:41,860
it's time for the importing module

326
00:14:41,860 --> 00:14:44,830
to be finally executed as well.

327
00:14:44,830 --> 00:14:48,430
So index.js in this example.

328
00:14:48,430 --> 00:14:51,600
Alright. And by now you're probably tired

329
00:14:51,600 --> 00:14:53,060
of listening to me.

330
00:14:53,060 --> 00:14:54,730
And so let's quickly move on

331
00:14:54,730 --> 00:14:58,003
and actually try all this with actual code.

