WEBVTT

1
00:00:00.680 --> 00:00:02.960
<v Speaker 1>Imagine for a second that you are opening up the

2
00:00:03.040 --> 00:00:06.480
<v Speaker 1>back of one of those vintage mechanical pocket watches. You know,

3
00:00:06.519 --> 00:00:08.279
<v Speaker 1>you take the casing off and you just see this

4
00:00:08.480 --> 00:00:11.640
<v Speaker 1>incredibly complex web of tiny golden gears.

5
00:00:11.679 --> 00:00:14.199
<v Speaker 2>Oh yeah, those are I mean, as a piece of engineering,

6
00:00:14.439 --> 00:00:16.600
<v Speaker 2>they are an absolute marvel to look.

7
00:00:16.519 --> 00:00:19.239
<v Speaker 1>At it right exactly, But if you turn just one gear,

8
00:00:19.280 --> 00:00:22.280
<v Speaker 1>it instantly turns three others, and then those turn ten more,

9
00:00:22.600 --> 00:00:25.600
<v Speaker 1>which is great for a watch, but as a metaphor

10
00:00:25.640 --> 00:00:28.920
<v Speaker 1>for software architecture, it is an absolute nightmare.

11
00:00:28.600 --> 00:00:30.800
<v Speaker 2>One hundred percent. It's a total disaster.

12
00:00:30.519 --> 00:00:33.439
<v Speaker 1>Because, you know, when you're dealing with traditional object oriented

13
00:00:33.479 --> 00:00:37.560
<v Speaker 1>programming or OOP, mutating state in one place often triggers

14
00:00:37.600 --> 00:00:41.719
<v Speaker 1>this like cascade of hidden changes across your entire application.

15
00:00:41.880 --> 00:00:45.479
<v Speaker 2>Yeah, you change a user's status over in this one module,

16
00:00:45.520 --> 00:00:50.119
<v Speaker 2>and suddenly, completely out of nowhere, a totally unrelated billing

17
00:00:50.119 --> 00:00:51.520
<v Speaker 2>object just breaks over there.

18
00:00:51.719 --> 00:00:55.280
<v Speaker 1>Exactly. You've basically built a web of change, and trying

19
00:00:55.320 --> 00:00:58.039
<v Speaker 1>to keep the entire state of that mechanical machine in

20
00:00:58.079 --> 00:01:00.280
<v Speaker 1>your head, I mean, it just becomes impossible as the

21
00:01:00.320 --> 00:01:01.960
<v Speaker 1>code based scales up, which is.

22
00:01:01.960 --> 00:01:04.599
<v Speaker 2>You know why we spend so much time chasing obscure

23
00:01:04.599 --> 00:01:08.040
<v Speaker 2>state bugs instead of actually building new features. We tend

24
00:01:08.040 --> 00:01:10.359
<v Speaker 2>to think we are so neatly categorizing our systems into

25
00:01:10.400 --> 00:01:15.079
<v Speaker 2>these rigid classes and objects, but those implicit connections between

26
00:01:15.120 --> 00:01:18.640
<v Speaker 2>the objects, they eventually just create total architectural gridlock.

27
00:01:18.879 --> 00:01:21.519
<v Speaker 1>And that gridlock is exactly what we are unpacking in

28
00:01:21.560 --> 00:01:24.000
<v Speaker 1>this deep dive because today we are looking at Michael

29
00:01:24.040 --> 00:01:26.120
<v Speaker 1>Fogus's book Functional JavaScript.

30
00:01:26.200 --> 00:01:28.079
<v Speaker 2>Yeah, it's such a great text, it really.

31
00:01:27.920 --> 00:01:33.799
<v Speaker 1>Is, and Focus uses the underscore dot js library to

32
00:01:34.000 --> 00:01:37.719
<v Speaker 1>basically demonstrate a completely different mental model for handling that

33
00:01:37.760 --> 00:01:40.599
<v Speaker 1>complexity we just talked about. Right, we are moving away

34
00:01:40.680 --> 00:01:44.159
<v Speaker 1>from focusing on nouns, you know, the rigid objects and

35
00:01:44.159 --> 00:01:47.280
<v Speaker 1>classes that hold state, and we're shifting our focus entirely

36
00:01:47.319 --> 00:01:49.719
<v Speaker 1>to verbs, pure isolated.

37
00:01:49.159 --> 00:01:50.799
<v Speaker 2>Function, which is a huge mental shift.

38
00:01:51.000 --> 00:01:54.000
<v Speaker 1>Huge And even if you're writing in modern E six

39
00:01:54.120 --> 00:01:57.959
<v Speaker 1>or typescript today, the architectural philosophies that Focus lays out

40
00:01:57.959 --> 00:02:00.879
<v Speaker 1>about data transformation, I mean, they are going to completely

41
00:02:01.000 --> 00:02:03.560
<v Speaker 1>change how you approach system design.

42
00:02:03.519 --> 00:02:06.400
<v Speaker 2>Well in the environment. Here is crucial to understand too,

43
00:02:06.760 --> 00:02:10.280
<v Speaker 2>because JavaScript is multi paradigm. It doesn't force your hand

44
00:02:10.319 --> 00:02:11.159
<v Speaker 2>one way or the other.

45
00:02:11.280 --> 00:02:13.919
<v Speaker 1>Right, it's very flexible, extremely flexible.

46
00:02:13.919 --> 00:02:17.479
<v Speaker 2>I mean you can write imperative step by step state mutations.

47
00:02:17.639 --> 00:02:21.560
<v Speaker 2>You can build these massive, prototype heavy object oriented webs

48
00:02:21.759 --> 00:02:26.439
<v Speaker 2>You can even lean heavily into metaprogramming by manipulating the

49
00:02:26.439 --> 00:02:30.639
<v Speaker 2>execution model itself with proxies and reflection. Yeah. But and

50
00:02:30.719 --> 00:02:34.159
<v Speaker 2>this is the key. It also provides the foundational tools

51
00:02:34.199 --> 00:02:37.879
<v Speaker 2>for functional programming right out of the box, specifically through

52
00:02:37.919 --> 00:02:39.120
<v Speaker 2>how it treats functions.

53
00:02:39.240 --> 00:02:41.719
<v Speaker 1>So rather than that mechanical watch where every gear is

54
00:02:41.800 --> 00:02:45.319
<v Speaker 1>locked into the adjacent gear, Fogus frames functional programming as

55
00:02:45.360 --> 00:02:46.879
<v Speaker 1>like an industrial assembly line.

56
00:02:46.919 --> 00:02:48.319
<v Speaker 2>I love that analogy me too.

57
00:02:48.719 --> 00:02:51.599
<v Speaker 1>So raw materials, which is your data, go in one end,

58
00:02:52.039 --> 00:02:54.400
<v Speaker 1>and as they move down the configor belt, they are

59
00:02:54.439 --> 00:02:59.479
<v Speaker 1>transformed by these discrete single purpose machines right the verbs exactly.

60
00:02:59.680 --> 00:03:03.439
<v Speaker 1>And a huge constraint of this assembly line is immutability.

61
00:03:03.879 --> 00:03:06.840
<v Speaker 1>So the original raw materials are never destroyed and they're

62
00:03:06.879 --> 00:03:10.319
<v Speaker 1>never mutated in place. You are always producing a brand

63
00:03:10.360 --> 00:03:13.319
<v Speaker 1>new version of the data at every single station on

64
00:03:13.360 --> 00:03:13.800
<v Speaker 1>the line.

65
00:03:13.879 --> 00:03:16.479
<v Speaker 2>So let's look at how that actually changes the developer's

66
00:03:16.560 --> 00:03:20.319
<v Speaker 2>day to day approach in the real world. Fogus introduces

67
00:03:20.360 --> 00:03:23.479
<v Speaker 2>a really practical example early on with this parsiage function. Right,

68
00:03:23.719 --> 00:03:26.400
<v Speaker 2>the goal is super simple. You take a user input

69
00:03:26.400 --> 00:03:29.479
<v Speaker 2>string and you parse it into an integer. In a

70
00:03:29.520 --> 00:03:32.560
<v Speaker 2>standard imperative approach, you might write a function that parses

71
00:03:32.560 --> 00:03:36.800
<v Speaker 2>the string. Sure, but it also probably contains hard coded

72
00:03:36.800 --> 00:03:40.560
<v Speaker 2>console dot log statements for debugging oh always yeah, or

73
00:03:40.719 --> 00:03:43.439
<v Speaker 2>maybe direct DOM manipulations to show warning banners on the

74
00:03:43.439 --> 00:03:45.039
<v Speaker 2>screen if the input is malformed.

75
00:03:45.159 --> 00:03:47.759
<v Speaker 1>I see that pattern all the time. The developer tightly

76
00:03:47.840 --> 00:03:50.599
<v Speaker 1>couples the business logic, which is parsing the age, with

77
00:03:50.719 --> 00:03:52.000
<v Speaker 1>the reporting logic.

78
00:03:51.840 --> 00:03:55.879
<v Speaker 2>Exactly, and that coupling makes the code incredibly brittle. Think

79
00:03:55.919 --> 00:03:58.240
<v Speaker 2>about it if your environment changes. Say you want to

80
00:03:58.240 --> 00:04:01.120
<v Speaker 2>move that exact same parsiage function from a browser environment

81
00:04:01.400 --> 00:04:02.599
<v Speaker 2>to a no JS.

82
00:04:02.240 --> 00:04:03.520
<v Speaker 1>Server where there is no dom.

83
00:04:03.840 --> 00:04:06.879
<v Speaker 2>Right, there is no dom to manipulate, so the function

84
00:04:07.000 --> 00:04:10.120
<v Speaker 2>just completely breaks. Or say you decide you want to

85
00:04:10.159 --> 00:04:13.759
<v Speaker 2>send your errors to a telemetry service like data dog

86
00:04:14.280 --> 00:04:15.719
<v Speaker 2>instead of just a browser console.

87
00:04:15.879 --> 00:04:18.480
<v Speaker 1>You basically have to rip open the core business logic

88
00:04:18.519 --> 00:04:20.839
<v Speaker 1>of your application just to update your logging sets.

89
00:04:21.360 --> 00:04:22.040
<v Speaker 2>It's a mess.

90
00:04:22.319 --> 00:04:26.839
<v Speaker 1>But focuses functional alternative abstracts all of those actions. He

91
00:04:26.920 --> 00:04:30.360
<v Speaker 1>pulls the concepts of warnings and errors and notes out

92
00:04:30.439 --> 00:04:33.399
<v Speaker 1>into their own isolated single purpose.

93
00:04:33.079 --> 00:04:34.759
<v Speaker 2>Functions be hindy verbs.

94
00:04:34.720 --> 00:04:37.360
<v Speaker 1>Right, things like a fail function or worn function, and

95
00:04:37.399 --> 00:04:40.319
<v Speaker 1>then the parsiage function just takes those verbs in as arguments.

96
00:04:40.639 --> 00:04:42.839
<v Speaker 1>So if you want to change how the system logs data,

97
00:04:43.240 --> 00:04:46.759
<v Speaker 1>you literally just inject a different worn function into the pipeline.

98
00:04:46.839 --> 00:04:49.800
<v Speaker 1>The actual parsing logic is never ever touched.

99
00:04:49.920 --> 00:04:53.439
<v Speaker 2>It's basically a textbook application of inversion of control, but

100
00:04:53.959 --> 00:04:56.879
<v Speaker 2>done through functional composition rather than relying on one of

101
00:04:56.879 --> 00:05:00.360
<v Speaker 2>those really heavy op dependency injection frame works.

102
00:05:00.560 --> 00:05:01.879
<v Speaker 1>Yeah, this can get so glowed.

103
00:05:02.120 --> 00:05:06.600
<v Speaker 2>They really can't here. Functions just become these perfect hermetically

104
00:05:06.639 --> 00:05:10.160
<v Speaker 2>sealed units of abstraction. They don't know anything about the

105
00:05:10.199 --> 00:05:12.319
<v Speaker 2>outside world, they don't care about the outside world. They

106
00:05:12.319 --> 00:05:14.800
<v Speaker 2>only know what is passed directly into them.

107
00:05:14.839 --> 00:05:18.439
<v Speaker 1>But to build an entire system out of these isolated verbs,

108
00:05:19.040 --> 00:05:22.279
<v Speaker 1>the language has to support them natively, right like this

109
00:05:22.360 --> 00:05:27.279
<v Speaker 1>hinges entirely on JavaScript treating functions as first class. Yes, now,

110
00:05:27.319 --> 00:05:29.920
<v Speaker 1>I know you listening are probably familiar with the concept

111
00:05:29.920 --> 00:05:32.680
<v Speaker 1>of first class functions, but let's just look at the

112
00:05:32.759 --> 00:05:36.120
<v Speaker 1>mechanical implications of it really quick. Because a function in

113
00:05:36.240 --> 00:05:39.480
<v Speaker 1>JavaScript is literally just an object under the hood. It

114
00:05:39.480 --> 00:05:41.920
<v Speaker 1>can be assigned to a variable, it can be stored

115
00:05:42.000 --> 00:05:44.319
<v Speaker 1>in an array, or like we just saw, it can

116
00:05:44.399 --> 00:05:45.560
<v Speaker 1>be passed as an argument.

117
00:05:46.000 --> 00:05:49.879
<v Speaker 2>And that capability is basically the engine of applicative programming.

118
00:05:50.120 --> 00:05:52.120
<v Speaker 1>Applicative programming, Yeah, which.

119
00:05:51.959 --> 00:05:55.199
<v Speaker 2>Sounds fancy, but it's simply the practice of a function

120
00:05:55.279 --> 00:05:57.720
<v Speaker 2>calling another function that was passed to it. It's the

121
00:05:57.759 --> 00:06:00.879
<v Speaker 2>core mechanism that powers the functional obstrc actions we use

122
00:06:01.240 --> 00:06:03.240
<v Speaker 2>to replace traditional control.

123
00:06:02.879 --> 00:06:05.879
<v Speaker 1>Flow, right, you mean the holy trinity of map, reduce,

124
00:06:06.000 --> 00:06:09.759
<v Speaker 1>and filter. We use these constantly to replace clunky forour loops.

125
00:06:10.199 --> 00:06:12.439
<v Speaker 1>But I want to push back on the architectural cost

126
00:06:12.519 --> 00:06:13.399
<v Speaker 1>of this for a second.

127
00:06:13.560 --> 00:06:14.360
<v Speaker 2>Okay, laid on me.

128
00:06:14.639 --> 00:06:17.680
<v Speaker 1>If we are strictly following this functional assembly line model,

129
00:06:17.959 --> 00:06:21.759
<v Speaker 1>we are constantly passing functions around, We're creating closures. We

130
00:06:21.800 --> 00:06:25.920
<v Speaker 1>are allocating memory for brand new arrays every single time

131
00:06:25.959 --> 00:06:28.680
<v Speaker 1>we call map or filter, all because we refuse to

132
00:06:28.759 --> 00:06:30.360
<v Speaker 1>mutate the original array.

133
00:06:30.160 --> 00:06:31.519
<v Speaker 2>Right, to maintain immutability.

134
00:06:31.600 --> 00:06:34.240
<v Speaker 1>Yeah, but if I just write a standard imperative for

135
00:06:34.439 --> 00:06:37.439
<v Speaker 1>loop that mutates an array in place, I am mathematically

136
00:06:37.519 --> 00:06:41.800
<v Speaker 1>utilizing way fewer CPU cycles and I'm allocating way less memory.

137
00:06:42.079 --> 00:06:46.759
<v Speaker 1>So at scale, doesn't treating everything as this immutable assembly

138
00:06:46.800 --> 00:06:51.120
<v Speaker 1>line of tiny functions just absolutely tank the application's performance.

139
00:06:51.199 --> 00:06:54.800
<v Speaker 2>It's a totally valid architectural concern, and honestly, historically, in

140
00:06:54.879 --> 00:06:58.720
<v Speaker 2>older runtime environments, you would be absolutely right. The overhead

141
00:06:58.720 --> 00:07:01.600
<v Speaker 2>of the call stack alone plus the garbage collection from

142
00:07:01.639 --> 00:07:04.560
<v Speaker 2>all those new arrays would be a massive bottleneck, right.

143
00:07:04.439 --> 00:07:05.680
<v Speaker 1>It would just choke the system.

144
00:07:05.959 --> 00:07:10.079
<v Speaker 2>But the mechanics of modern JavaScript engines, particularly Googles V

145
00:07:10.199 --> 00:07:12.439
<v Speaker 2>eight engine, you know, the one that powers Chrome and Node,

146
00:07:13.240 --> 00:07:17.600
<v Speaker 2>they drastically alter that math through runtime compilation strategies.

147
00:07:17.920 --> 00:07:20.319
<v Speaker 1>Okay, walk me through the mechanics of that, because how

148
00:07:20.319 --> 00:07:25.160
<v Speaker 1>does vight actually compensate for the overhead of hundreds of

149
00:07:25.240 --> 00:07:26.160
<v Speaker 1>tiny function calls.

150
00:07:26.199 --> 00:07:28.199
<v Speaker 2>Well, it all comes down to how just in time

151
00:07:28.480 --> 00:07:32.360
<v Speaker 2>or JIT compilation works. You see, V eight doesn't just

152
00:07:32.439 --> 00:07:36.199
<v Speaker 2>blindly execute your code line by line. It actually watches

153
00:07:36.279 --> 00:07:39.800
<v Speaker 2>the code execute, it gathers profiling data, wall it runs,

154
00:07:40.079 --> 00:07:42.000
<v Speaker 2>and then it dynamically optimizes it.

155
00:07:42.079 --> 00:07:44.839
<v Speaker 1>Wait, it optimizes it on the fly exactly.

156
00:07:45.000 --> 00:07:46.839
<v Speaker 2>And one of the main tools it uses to do

157
00:07:46.879 --> 00:07:49.560
<v Speaker 2>this is called inline caching. So if V eight sees

158
00:07:49.600 --> 00:07:52.639
<v Speaker 2>that a specific tiny function like say our isolated warn

159
00:07:52.680 --> 00:07:55.240
<v Speaker 2>function from earlier. If it sees that function being called

160
00:07:55.240 --> 00:07:57.759
<v Speaker 2>repeatedly with the same exact types of arguments, it will

161
00:07:57.759 --> 00:08:00.480
<v Speaker 2>eventually just stop executing it as a separate function call.

162
00:08:00.560 --> 00:08:02.920
<v Speaker 1>Wait, so it actually rewrites the execution path.

163
00:08:03.120 --> 00:08:07.639
<v Speaker 2>Yes, literally, it performs what's called code inlining. The compiler

164
00:08:07.720 --> 00:08:10.639
<v Speaker 2>takes the actual machine code instructions of that tiny worn

165
00:08:10.720 --> 00:08:15.680
<v Speaker 2>function and pastes them directly into the calling functions execution block.

166
00:08:15.800 --> 00:08:16.480
<v Speaker 1>Oh wow.

167
00:08:16.720 --> 00:08:19.240
<v Speaker 2>Yeah, so the overhead of the function call, the context switching,

168
00:08:19.279 --> 00:08:21.800
<v Speaker 2>pushing of popping variables from call stack, all of that

169
00:08:21.920 --> 00:08:26.399
<v Speaker 2>is entirely eliminated. V eight essentially flattens your beautiful, modular

170
00:08:26.480 --> 00:08:31.199
<v Speaker 2>functional code into this highly optimized, imperative machine code block

171
00:08:31.279 --> 00:08:31.879
<v Speaker 2>under the hood.

172
00:08:32.000 --> 00:08:35.120
<v Speaker 1>That completely changes the perspective on performance. So their argument

173
00:08:35.159 --> 00:08:38.279
<v Speaker 1>that a massive fore loop is always faster that completely

174
00:08:38.360 --> 00:08:41.159
<v Speaker 1>ignores how the modern engine actually optimizes the code.

175
00:08:41.200 --> 00:08:44.039
<v Speaker 2>Well yeah, and in fact, a massive forur loop that

176
00:08:44.159 --> 00:08:46.919
<v Speaker 2>does like five different things and mutates variables of all

177
00:08:46.919 --> 00:08:50.919
<v Speaker 2>different types can actually confuse the GI compiler. Oh really yeah.

178
00:08:51.200 --> 00:08:54.039
<v Speaker 2>Vight relies heavily on what are called hidden classes, which

179
00:08:54.080 --> 00:08:59.000
<v Speaker 2>are basically predictable object shapes to optimize property access. If

180
00:08:59.039 --> 00:09:01.919
<v Speaker 2>your imperative loop is constantly altering the shape of your objects,

181
00:09:02.000 --> 00:09:05.360
<v Speaker 2>you know, adding or deleting properties dynamically, vight will actually

182
00:09:05.360 --> 00:09:08.279
<v Speaker 2>de optimize that block of code. It kicks it back down, exactly,

183
00:09:08.320 --> 00:09:12.279
<v Speaker 2>It kicks it back down to slow, unoptimized execution. But

184
00:09:12.759 --> 00:09:17.279
<v Speaker 2>by writing small, pure functions that always return predictable data shapes,

185
00:09:17.639 --> 00:09:20.639
<v Speaker 2>you are actually feeding the V eight engine exactly what

186
00:09:20.720 --> 00:09:23.720
<v Speaker 2>it needs to optimize your code to near native speeds.

187
00:09:24.080 --> 00:09:25.480
<v Speaker 1>That is fascinating.

188
00:09:25.639 --> 00:09:28.360
<v Speaker 2>Do you get the developer experience of highly modular code

189
00:09:28.440 --> 00:09:30.519
<v Speaker 2>without having to sacrifice the run time performance?

190
00:09:30.639 --> 00:09:32.799
<v Speaker 1>Okay, so the engine basically has our back on the

191
00:09:32.799 --> 00:09:35.559
<v Speaker 1>performance side, But let's look at the developer experience of

192
00:09:35.600 --> 00:09:38.879
<v Speaker 1>actually snapping these functions together. Because you know, in the

193
00:09:38.879 --> 00:09:41.399
<v Speaker 1>real world they rarely fit perfectly out of the box.

194
00:09:41.519 --> 00:09:42.440
<v Speaker 2>No, they definitely do not.

195
00:09:42.759 --> 00:09:44.879
<v Speaker 1>So what do we do when two systems need to

196
00:09:44.960 --> 00:09:49.519
<v Speaker 1>talk but their function signatures are completely mispatched. Fogus dives

197
00:09:49.559 --> 00:09:52.919
<v Speaker 1>into this problem by looking at JavaScript's native array sorting mechanism,

198
00:09:53.000 --> 00:09:54.840
<v Speaker 1>which is notoriously quirky.

199
00:09:54.919 --> 00:09:57.919
<v Speaker 2>Oh it is a perfect case study and weird API design.

200
00:09:58.000 --> 00:10:02.080
<v Speaker 2>If you take an array of integers, say two, three,

201
00:10:02.399 --> 00:10:06.000
<v Speaker 2>negative six, zero, negative one oh eight, and forty two, okay,

202
00:10:06.080 --> 00:10:08.360
<v Speaker 2>and you just call the native dot sort method on

203
00:10:08.399 --> 00:10:11.440
<v Speaker 2>that array. It doesn't actually sort them numerically, right.

204
00:10:11.279 --> 00:10:15.639
<v Speaker 1>Which drives beginners crazy. It sorts them lexicographically. It coerces

205
00:10:15.679 --> 00:10:18.000
<v Speaker 1>everything to a string first, so negative one oh eight

206
00:10:18.039 --> 00:10:20.600
<v Speaker 1>comes before negative six, because the character one comes before

207
00:10:20.600 --> 00:10:24.720
<v Speaker 1>the character six in unicode. It's this bizarre historical artifact

208
00:10:24.879 --> 00:10:28.360
<v Speaker 1>from JavaScript's early days, when it was mostly just dealing

209
00:10:28.399 --> 00:10:31.639
<v Speaker 1>with string data from HTML forms, and so to get

210
00:10:31.639 --> 00:10:35.039
<v Speaker 1>a mathematical sort, the API forces you to pass in

211
00:10:35.120 --> 00:10:37.159
<v Speaker 1>a very specific comparator function.

212
00:10:37.440 --> 00:10:41.360
<v Speaker 2>And the contract for that comparator function is incredibly rigid, right.

213
00:10:41.440 --> 00:10:44.840
<v Speaker 2>It expects exactly two arguments, and it must return a

214
00:10:44.879 --> 00:10:48.000
<v Speaker 2>negative number if the first is smaller, a positive number

215
00:10:48.000 --> 00:10:51.639
<v Speaker 2>if it's larger, and zero if they're totally equal.

216
00:10:51.480 --> 00:10:55.399
<v Speaker 1>Which means usually developers just write this messy inline anonymous

217
00:10:55.440 --> 00:10:58.759
<v Speaker 1>function with some subtraction math or like an i false

218
00:10:58.840 --> 00:11:01.120
<v Speaker 1>block jammed directly inside the torque call.

219
00:11:01.200 --> 00:11:02.679
<v Speaker 2>Yeah, we've all written that code.

220
00:11:02.519 --> 00:11:05.840
<v Speaker 1>Oh totally. But Fogus abstracts this to show the power

221
00:11:05.879 --> 00:11:08.919
<v Speaker 1>of functional composition. He starts by writing a super generic

222
00:11:08.960 --> 00:11:12.120
<v Speaker 1>predicate function called less equal. It just takes two numbers

223
00:11:12.120 --> 00:11:13.639
<v Speaker 1>and returns a boolean just true.

224
00:11:13.519 --> 00:11:16.360
<v Speaker 2>Or false, right, and a predicat being any function that

225
00:11:16.399 --> 00:11:19.120
<v Speaker 2>takes a value and just returns a boolean. It is

226
00:11:19.200 --> 00:11:22.120
<v Speaker 2>basically the simplest, most reusable piece of logic you can

227
00:11:22.159 --> 00:11:23.000
<v Speaker 2>possibly write.

228
00:11:23.159 --> 00:11:25.200
<v Speaker 1>But the SARDAPI doesn't want a boolean.

229
00:11:25.480 --> 00:11:26.120
<v Speaker 2>No, it does not.

230
00:11:26.240 --> 00:11:28.399
<v Speaker 1>It will completely fail if you just pass it less

231
00:11:28.480 --> 00:11:31.919
<v Speaker 1>or equal. So Fogus writes a higher order function, which

232
00:11:31.960 --> 00:11:34.159
<v Speaker 1>is a function that returns another function, and he calls

233
00:11:34.159 --> 00:11:37.919
<v Speaker 1>it comparator. This comparator function takes any boolean predicate as

234
00:11:37.960 --> 00:11:40.799
<v Speaker 1>its argument, and it returns a brand new function that

235
00:11:40.879 --> 00:11:44.120
<v Speaker 1>maps the true false output into the negative one, zero

236
00:11:44.360 --> 00:11:47.519
<v Speaker 1>or one format that the dot sort API demands.

237
00:11:47.639 --> 00:11:50.759
<v Speaker 2>The mechanism there is what's really fascinating, Yeah, because you

238
00:11:50.840 --> 00:11:56.000
<v Speaker 2>are physically decoupling the core business logic, you know, evaluating

239
00:11:56.039 --> 00:11:59.000
<v Speaker 2>if a is less than b from the arbitrary framework

240
00:11:59.039 --> 00:12:02.080
<v Speaker 2>requirement of those nig one, zero one return values.

241
00:12:02.200 --> 00:12:04.360
<v Speaker 1>It's exactly like a travel adapter. That's a good way

242
00:12:04.360 --> 00:12:05.600
<v Speaker 1>to look at it, right, Like if I take my

243
00:12:05.679 --> 00:12:08.519
<v Speaker 1>laptop to Europe, the wall socket, which is the dot

244
00:12:08.600 --> 00:12:12.600
<v Speaker 1>sort API, it demands a specific three prong shape my

245
00:12:12.720 --> 00:12:15.519
<v Speaker 1>laptop charger, which is my less equal predicate. It only

246
00:12:15.519 --> 00:12:18.480
<v Speaker 1>has a two prong shape. I don't rewire my laptop

247
00:12:18.559 --> 00:12:20.080
<v Speaker 1>charger to fit the European socket.

248
00:12:20.399 --> 00:12:22.240
<v Speaker 2>No, that would ruin it for when you go back

249
00:12:22.240 --> 00:12:23.159
<v Speaker 2>home exactly.

250
00:12:23.480 --> 00:12:25.679
<v Speaker 1>Instead, I just plug my charger into an adapter, and

251
00:12:25.720 --> 00:12:28.960
<v Speaker 1>then I plug the adapter into the wall. Focus's comparator

252
00:12:29.000 --> 00:12:30.320
<v Speaker 1>function is that travel adapter.

253
00:12:30.480 --> 00:12:34.559
<v Speaker 2>And by not rewiring the core logic, that lesser equal

254
00:12:34.600 --> 00:12:39.080
<v Speaker 2>predicate remains completely pure and completely reusable. You can use

255
00:12:39.120 --> 00:12:42.159
<v Speaker 2>it tomorrow inside a filter function or a su function,

256
00:12:42.240 --> 00:12:45.399
<v Speaker 2>which actually do expect boolean returns. If you had buried

257
00:12:45.399 --> 00:12:48.960
<v Speaker 2>that logic inside of bespoke comparator, it would be locked

258
00:12:49.000 --> 00:12:52.840
<v Speaker 2>away forever and totally useless to the rest of your application.

259
00:12:53.679 --> 00:12:57.120
<v Speaker 2>And that is really the essence of functional composition, right.

260
00:12:57.159 --> 00:13:01.279
<v Speaker 2>You build complex behavior just by snapping the gether these tiny, generic,

261
00:13:01.320 --> 00:13:02.159
<v Speaker 2>re usable verbs.

262
00:13:02.279 --> 00:13:03.919
<v Speaker 1>But let's look at the other side of the equation,

263
00:13:04.080 --> 00:13:07.240
<v Speaker 1>because if our verbs are these tiny decoupled adapters, what

264
00:13:07.360 --> 00:13:10.720
<v Speaker 1>happens to our nouns? I mean, the prevailing philosophy in

265
00:13:10.879 --> 00:13:14.759
<v Speaker 1>most enterprise software is object oriented design, where the data

266
00:13:14.799 --> 00:13:16.679
<v Speaker 1>and the methods that operate on that data are all

267
00:13:16.720 --> 00:13:20.080
<v Speaker 1>bundled together into these massive classes. If we are decoupling

268
00:13:20.120 --> 00:13:22.559
<v Speaker 1>all the verbs, do we just toss out the classes entirely.

269
00:13:22.840 --> 00:13:26.279
<v Speaker 2>Well, this is where Fogus introduces a concept called data thinking,

270
00:13:26.759 --> 00:13:30.919
<v Speaker 2>and it aggressively challenges standard op doctrine. He actually quotes

271
00:13:31.000 --> 00:13:33.559
<v Speaker 2>Alan Perlis, you know, one of the pioneers in computer

272
00:13:33.639 --> 00:13:37.519
<v Speaker 2>science who famously said it is better to have one

273
00:13:37.559 --> 00:13:41.080
<v Speaker 2>hundred functions operate on one data structure than ten functions

274
00:13:41.120 --> 00:13:42.279
<v Speaker 2>on ten data structures.

275
00:13:42.320 --> 00:13:45.159
<v Speaker 1>Wow. That completely flies in the face of how most

276
00:13:45.200 --> 00:13:48.000
<v Speaker 1>developers are taught to model their domains. Oh, completely, because

277
00:13:48.039 --> 00:13:49.600
<v Speaker 1>we're taught that if you have a user, you build

278
00:13:49.600 --> 00:13:52.159
<v Speaker 1>a user class. If you have an invoice, you build

279
00:13:52.200 --> 00:13:53.200
<v Speaker 1>an invoice class.

280
00:13:53.279 --> 00:13:56.000
<v Speaker 2>And the fundamental problem with that approach is that you

281
00:13:56.039 --> 00:14:01.039
<v Speaker 2>are basically inventing a brand new, highly specific micro language

282
00:14:01.600 --> 00:14:05.480
<v Speaker 2>for every single entity in your entire Systemma. Well, a

283
00:14:05.559 --> 00:14:08.360
<v Speaker 2>user class might have a dot get role method, but

284
00:14:08.440 --> 00:14:11.559
<v Speaker 2>an invoice class has a dot calculatol method. If you

285
00:14:11.600 --> 00:14:14.480
<v Speaker 2>want to write a utility function to format some data,

286
00:14:15.440 --> 00:14:18.159
<v Speaker 2>it has to be custom tailored to understand the specific

287
00:14:18.200 --> 00:14:21.159
<v Speaker 2>bespoke methods of the user class or the invoice class.

288
00:14:21.559 --> 00:14:24.320
<v Speaker 2>Your logic becomes completely coupled to the arbitrary shape of

289
00:14:24.320 --> 00:14:25.440
<v Speaker 2>that specific class.

290
00:14:25.720 --> 00:14:28.480
<v Speaker 1>Ah I see, So Fogus argues that we should just

291
00:14:28.519 --> 00:14:31.399
<v Speaker 1>strip all of that away and rely on bare fundamental

292
00:14:31.519 --> 00:14:32.399
<v Speaker 1>data primitives.

293
00:14:32.519 --> 00:14:36.960
<v Speaker 2>Yes, just plain JavaScript objects, which are essentially just associative

294
00:14:37.039 --> 00:14:39.919
<v Speaker 2>arrays of key value pairs and standard arrays.

295
00:14:40.360 --> 00:14:43.879
<v Speaker 1>He demonstrates this with this lame CSV parsing example. So

296
00:14:44.480 --> 00:14:48.600
<v Speaker 1>imagine a simple data set of employees. They've got names, ages,

297
00:14:48.639 --> 00:14:53.159
<v Speaker 1>and departments. A traditional OP approach would parse that CSV

298
00:14:53.559 --> 00:14:56.600
<v Speaker 1>and instantiate like a table class, which then holds an

299
00:14:56.679 --> 00:15:00.879
<v Speaker 1>array of row classes which are mapped to individual employees classes.

300
00:15:00.519 --> 00:15:03.080
<v Speaker 2>Which creates a massive memory footprint, not to mention the

301
00:15:03.120 --> 00:15:05.559
<v Speaker 2>sheer amount of boilerplate code required just to define all

302
00:15:05.600 --> 00:15:06.600
<v Speaker 2>this classes in the first place.

303
00:15:06.720 --> 00:15:09.960
<v Speaker 1>Right, It's exhausting. But Fogus bypasses all of it. He

304
00:15:10.080 --> 00:15:13.399
<v Speaker 1>just parses the CSV directly into an array of plane

305
00:15:13.440 --> 00:15:16.639
<v Speaker 1>JavaScript objects, and that's it. That's the entire data model,

306
00:15:16.639 --> 00:15:18.960
<v Speaker 1>an array of objects. But okay, here is where I

307
00:15:19.000 --> 00:15:21.919
<v Speaker 1>have a major issue with this data thinking concept. If

308
00:15:21.960 --> 00:15:24.559
<v Speaker 1>you strip away all the classes, you are also stripping

309
00:15:24.600 --> 00:15:28.360
<v Speaker 1>away all the structural guarantees in a large code base.

310
00:15:28.840 --> 00:15:32.200
<v Speaker 1>If I pass an employee object into a function, the

311
00:15:32.279 --> 00:15:35.879
<v Speaker 1>class definition guarantees that the employee has an email property,

312
00:15:36.000 --> 00:15:38.480
<v Speaker 1>and it guarantees that the email is a string. Right

313
00:15:38.679 --> 00:15:42.200
<v Speaker 1>if we just throw raw arrays of loose objects around

314
00:15:42.279 --> 00:15:45.440
<v Speaker 1>the code base, aren't we basically just crossing our fingers

315
00:15:45.440 --> 00:15:48.159
<v Speaker 1>and hoping the data is shaped correctly? Like how do

316
00:15:48.240 --> 00:15:51.000
<v Speaker 1>you prevent the whole system from collapsing due to missing

317
00:15:51.039 --> 00:15:53.720
<v Speaker 1>properties without the strict contracts of a class.

318
00:15:53.840 --> 00:15:56.840
<v Speaker 2>So that right there is the defining trayoff between the

319
00:15:56.840 --> 00:16:01.440
<v Speaker 2>two paradigms. In an OP world, the validation happens internally

320
00:16:01.480 --> 00:16:05.399
<v Speaker 2>within the object itself. The object protects its own state exactly.

321
00:16:05.440 --> 00:16:09.080
<v Speaker 2>But in a functional data thinking world, you rely on

322
00:16:09.159 --> 00:16:11.200
<v Speaker 2>validation at the boundaries of your system.

323
00:16:11.320 --> 00:16:12.799
<v Speaker 1>Okay, what do you mean by the boundaries?

324
00:16:13.000 --> 00:16:15.879
<v Speaker 2>Think about when the data actually enters your application. Say

325
00:16:15.919 --> 00:16:18.879
<v Speaker 2>you're parsing adjason payload from an API request or you're

326
00:16:18.919 --> 00:16:21.919
<v Speaker 2>reading that CSV file from earlier. That is your boundary.

327
00:16:22.320 --> 00:16:25.000
<v Speaker 2>So you write robust validation functions right there at the edge.

328
00:16:25.080 --> 00:16:27.759
<v Speaker 2>If the data fails the schema check at the boundary,

329
00:16:27.960 --> 00:16:30.840
<v Speaker 2>you reject it immediately. But once the data passes the

330
00:16:30.840 --> 00:16:34.120
<v Speaker 2>boundary and enters your internal functional assembly line. You just

331
00:16:34.159 --> 00:16:37.039
<v Speaker 2>trust it. You don't need heavy classes to babysit the

332
00:16:37.080 --> 00:16:40.360
<v Speaker 2>data internally because you've already rigorously verified its shape at

333
00:16:40.399 --> 00:16:40.720
<v Speaker 2>the door.

334
00:16:41.039 --> 00:16:44.159
<v Speaker 1>Oh I see, So you decouple the structural validation from

335
00:16:44.200 --> 00:16:47.000
<v Speaker 1>the runtime behavior exactly. And once you do that, the

336
00:16:47.039 --> 00:16:50.600
<v Speaker 1>real power of that Alan Perliss quote really clicks into

337
00:16:50.639 --> 00:16:54.519
<v Speaker 1>place because your data is completely uniform. It's just planarrays

338
00:16:54.559 --> 00:16:57.919
<v Speaker 1>and objects, which means every single generic function in your

339
00:16:57.919 --> 00:16:59.399
<v Speaker 1>toolkit can operate on it.

340
00:17:00.000 --> 00:17:05.119
<v Speaker 2>Focus showcases this brilliantly by building an entire pseudosequal querying

341
00:17:05.160 --> 00:17:09.079
<v Speaker 2>engine using just functional concepts operating on these simple arrays

342
00:17:09.079 --> 00:17:09.680
<v Speaker 2>of objects.

343
00:17:09.880 --> 00:17:12.839
<v Speaker 1>Yeah, this part of the book is an absolute masterclass

344
00:17:13.200 --> 00:17:16.400
<v Speaker 1>because he builds the suite of functions to manipulate the

345
00:17:16.480 --> 00:17:19.400
<v Speaker 1>data as if it were an actual relational database. Like

346
00:17:19.519 --> 00:17:22.279
<v Speaker 1>he writes a project function which maps directly to a

347
00:17:22.279 --> 00:17:25.720
<v Speaker 1>seql select statement. You pass it your array of employee

348
00:17:25.720 --> 00:17:28.119
<v Speaker 1>objects and an array of keys you want, like say

349
00:17:28.240 --> 00:17:31.279
<v Speaker 1>name and department, and it just maps over the collection

350
00:17:31.519 --> 00:17:34.839
<v Speaker 1>and returns a brand new array of objects containing only

351
00:17:34.839 --> 00:17:36.000
<v Speaker 1>those specific keys.

352
00:17:36.400 --> 00:17:39.119
<v Speaker 2>And then he writes an as function which acts exactly

353
00:17:39.160 --> 00:17:42.640
<v Speaker 2>like a sequel alias mapping over the array to seamlessly

354
00:17:42.680 --> 00:17:45.000
<v Speaker 2>rename specific keys in the returned objects, and.

355
00:17:45.039 --> 00:17:48.720
<v Speaker 1>A restrict function, which is essentially just a seql wear clause.

356
00:17:49.359 --> 00:17:52.720
<v Speaker 1>It uses an underlying filter to evaluate a predicate against

357
00:17:52.759 --> 00:17:55.799
<v Speaker 1>each object, returning an array of only the objects that

358
00:17:55.880 --> 00:17:57.160
<v Speaker 1>actually pass the test.

359
00:17:57.440 --> 00:18:00.920
<v Speaker 2>But the mechanical brilliance here is the composability. The project

360
00:18:01.000 --> 00:18:03.839
<v Speaker 2>function takes an array of objects as an argument, and

361
00:18:03.880 --> 00:18:06.359
<v Speaker 2>it returns inn array of objects. The restrict function is

362
00:18:06.400 --> 00:18:09.720
<v Speaker 2>the exact same thing. Because their inputs and outputs share

363
00:18:09.759 --> 00:18:13.759
<v Speaker 2>the exact same primitive data structure. They just chain together flawlessly.

364
00:18:14.000 --> 00:18:17.039
<v Speaker 1>You can pass the result of restrict directly into project,

365
00:18:17.079 --> 00:18:19.680
<v Speaker 1>and then the result of that directly into As you

366
00:18:19.720 --> 00:18:24.079
<v Speaker 1>are executing highly complex relational queries against your data without

367
00:18:24.119 --> 00:18:27.559
<v Speaker 1>a single custom class, without a heavy RM, and critically

368
00:18:27.640 --> 00:18:30.920
<v Speaker 1>without ever mutating the original data set. It's just beautiful.

369
00:18:31.000 --> 00:18:33.839
<v Speaker 2>It's just data flowing smoothly through an assembly line of

370
00:18:33.920 --> 00:18:34.640
<v Speaker 2>pure verbs.

371
00:18:34.880 --> 00:18:38.599
<v Speaker 1>Right. And to address your earlier concern about memory overhead,

372
00:18:38.759 --> 00:18:43.640
<v Speaker 1>because JavaScript passes objects by reference, returning a new array

373
00:18:43.720 --> 00:18:47.200
<v Speaker 1>from restrict or project doesn't actually mean you are duplicating

374
00:18:47.200 --> 00:18:51.039
<v Speaker 1>the actual object data in memory over and over. Oh really, Yeah,

375
00:18:51.079 --> 00:18:53.839
<v Speaker 1>you are simply creating a new array that contains pointers

376
00:18:53.839 --> 00:18:57.960
<v Speaker 1>to the existing objects. So the memory overhead is surprisingly minimal,

377
00:18:58.359 --> 00:19:01.759
<v Speaker 1>But the architectural safety you gain by not mutating that

378
00:19:01.839 --> 00:19:04.039
<v Speaker 1>original array is just massive.

379
00:19:03.720 --> 00:19:07.839
<v Speaker 2>Which perfectly transitions into the final core concept that focus tackles,

380
00:19:08.440 --> 00:19:11.559
<v Speaker 2>which is the existential threat to all of this functional safety,

381
00:19:11.680 --> 00:19:14.119
<v Speaker 2>the big one, Because if we have this pristine assembly

382
00:19:14.160 --> 00:19:17.960
<v Speaker 2>line where data flows through isolated machines without ever being destroyed,

383
00:19:18.240 --> 00:19:21.359
<v Speaker 2>what is the single biggest danger to that factory? Mutability,

384
00:19:21.480 --> 00:19:24.319
<v Speaker 2>specifically mutability in the global scope.

385
00:19:24.359 --> 00:19:28.680
<v Speaker 1>And JavaScript is uniquely terribly vulnerable to this due to

386
00:19:28.880 --> 00:19:31.400
<v Speaker 1>how its lexical environment was originally designed.

387
00:19:31.480 --> 00:19:35.440
<v Speaker 2>Yeah, if you declare a variable without strict bindings using

388
00:19:35.480 --> 00:19:39.960
<v Speaker 2>the var keyword historically or just completely omitting a declaration

389
00:19:40.079 --> 00:19:45.359
<v Speaker 2>keyword entirely, the JavaScript engine handles that missing reference in

390
00:19:45.400 --> 00:19:46.759
<v Speaker 2>a very, very dangerous way.

391
00:19:47.160 --> 00:19:50.119
<v Speaker 1>Let's trace that execution path for a second. When the

392
00:19:50.200 --> 00:19:53.839
<v Speaker 1>interpreter hits a variable assignment that wasn't properly declared to

393
00:19:53.880 --> 00:19:57.720
<v Speaker 1>say global state equal true, it doesn't just crash.

394
00:19:57.920 --> 00:19:59.119
<v Speaker 2>No, it tries to be helpful.

395
00:19:59.200 --> 00:20:02.839
<v Speaker 1>Right. It looks at the current execution contexts environment record,

396
00:20:03.079 --> 00:20:05.880
<v Speaker 1>it doesn't find global state there, so it traverses up

397
00:20:05.920 --> 00:20:08.920
<v Speaker 1>the scope chain to the outer lexical environment, and it

398
00:20:09.000 --> 00:20:11.079
<v Speaker 1>just keeps moving up the chain until it hits the

399
00:20:11.079 --> 00:20:12.720
<v Speaker 1>global execution context.

400
00:20:13.039 --> 00:20:15.359
<v Speaker 2>And if it doesn't find it declared there either. Instead

401
00:20:15.400 --> 00:20:19.920
<v Speaker 2>of throwing a reference er, the engine quietly invisibly attaches

402
00:20:20.000 --> 00:20:21.920
<v Speaker 2>that variable directly to the global.

403
00:20:21.599 --> 00:20:23.000
<v Speaker 1>Object, which is terrifying.

404
00:20:23.079 --> 00:20:25.480
<v Speaker 2>It is in a browser, that's the window object. In

405
00:20:25.599 --> 00:20:27.119
<v Speaker 2>node it's the global object.

406
00:20:27.359 --> 00:20:31.839
<v Speaker 1>And Fogus illustrates this with a terrifyingly simple example. A

407
00:20:31.960 --> 00:20:35.720
<v Speaker 1>variable silently leaks to the global scope, so he writes

408
00:20:36.359 --> 00:20:40.480
<v Speaker 1>a global variable lavin la vida global. Now, because it

409
00:20:40.559 --> 00:20:43.640
<v Speaker 1>exists on the global object, it is fully accessible to

410
00:20:43.799 --> 00:20:48.200
<v Speaker 1>every single function, every module, and every third party script

411
00:20:48.319 --> 00:20:50.480
<v Speaker 1>running anywhere in that environment.

412
00:20:50.079 --> 00:20:53.400
<v Speaker 2>Which means literally any other piece of code may be

413
00:20:53.440 --> 00:20:56.799
<v Speaker 2>written by a completely different developer on another team can

414
00:20:56.920 --> 00:20:59.319
<v Speaker 2>execute an assignment like a global variable.

415
00:20:59.400 --> 00:21:02.279
<v Speaker 1>I drink your monad, and just like that, the state

416
00:21:02.359 --> 00:21:06.839
<v Speaker 1>is overwritten instantly without any warning whatsoever. No, and because

417
00:21:06.920 --> 00:21:11.000
<v Speaker 1>object oriented programming relies so heavily on internal state mutations,

418
00:21:11.400 --> 00:21:14.119
<v Speaker 1>if your classes depend on any external context, they are

419
00:21:14.319 --> 00:21:18.200
<v Speaker 1>highly highly susceptible to these invisible side effects. Yeah, when

420
00:21:18.200 --> 00:21:22.119
<v Speaker 1>your application inevitably crashes because a booleon suddenly became a string,

421
00:21:22.480 --> 00:21:24.519
<v Speaker 1>the stack trace isn't going to tell you who drank

422
00:21:24.559 --> 00:21:26.759
<v Speaker 1>your milkshake. It will only tell you that the code

423
00:21:26.799 --> 00:21:29.480
<v Speaker 1>failed three steps later when it tried to evaluate the string.

424
00:21:29.880 --> 00:21:32.440
<v Speaker 1>It's the broken tooth on the mechanical pocket watch all

425
00:21:32.480 --> 00:21:33.000
<v Speaker 1>over again.

426
00:21:33.279 --> 00:21:38.559
<v Speaker 2>And the functional programming heavily mitigates this exact problem through

427
00:21:38.599 --> 00:21:43.079
<v Speaker 2>the principle of referential transparency. A pure function does not

428
00:21:43.240 --> 00:21:46.519
<v Speaker 2>read from the global scope, and it absolutely does not

429
00:21:46.519 --> 00:21:49.880
<v Speaker 2>write to the global scope. Its output is derived entirely

430
00:21:49.920 --> 00:21:54.039
<v Speaker 2>and exclusively from the arguments passed explicitly into it. If

431
00:21:54.039 --> 00:21:57.400
<v Speaker 2>a function needs configuration data, you have to pass that

432
00:21:57.480 --> 00:21:59.119
<v Speaker 2>data in as an argument.

433
00:21:59.279 --> 00:22:01.359
<v Speaker 1>You don't just reach out into the ether to grab it.

434
00:22:01.519 --> 00:22:05.279
<v Speaker 1>You enforce a very strict contract of explicit inputs and

435
00:22:05.359 --> 00:22:09.480
<v Speaker 1>explicit return values. Literally, no one can overwrite your data

436
00:22:09.519 --> 00:22:12.519
<v Speaker 1>because you never expose a mutable reference to it. You

437
00:22:12.640 --> 00:22:14.920
<v Speaker 1>only ever return a newly transformed copy.

438
00:22:15.079 --> 00:22:17.960
<v Speaker 2>And when you apply that discipline across an entire code base,

439
00:22:18.519 --> 00:22:22.079
<v Speaker 2>you just eliminate entire categories of bugs. The cognitive load

440
00:22:22.160 --> 00:22:25.759
<v Speaker 2>required to understand the system drops dramatically because you don't

441
00:22:25.759 --> 00:22:27.960
<v Speaker 2>have to keep this massive mental map of what else

442
00:22:28.039 --> 00:22:29.920
<v Speaker 2>might be secretly modifying your variables.

443
00:22:29.960 --> 00:22:31.799
<v Speaker 1>You just look at the assembly line exactly.

444
00:22:31.880 --> 00:22:34.119
<v Speaker 2>You just observe the data flowing from one station to

445
00:22:34.160 --> 00:22:34.480
<v Speaker 2>the next.

446
00:22:34.839 --> 00:22:37.599
<v Speaker 1>It really highlights how focus is functional. JavaScript is so

447
00:22:37.680 --> 00:22:40.960
<v Speaker 1>much less about learning the syntax of a specific library

448
00:22:41.039 --> 00:22:45.480
<v Speaker 1>like Underscore and way more about adopting this defensive, scalable

449
00:22:45.559 --> 00:22:49.920
<v Speaker 1>engineering mindset. For sure, we've explored how JavaScript's multi paradigm

450
00:22:50.039 --> 00:22:54.240
<v Speaker 1>nature allows us to basically shift away from rigid oop structures.

451
00:22:54.759 --> 00:22:58.319
<v Speaker 1>We unpacked how first class functions power those applicator techniques,

452
00:22:58.640 --> 00:23:02.160
<v Speaker 1>and how modern jit can like vight, make these abstractions

453
00:23:02.160 --> 00:23:03.920
<v Speaker 1>incredibly performant under the hood.

454
00:23:04.119 --> 00:23:06.680
<v Speaker 2>Yeah, and we saw how higher order functions can act

455
00:23:06.680 --> 00:23:10.680
<v Speaker 2>as adapters to decouple our logic from framework constraints, and

456
00:23:10.720 --> 00:23:13.920
<v Speaker 2>how data thinking allows us to model complex you know,

457
00:23:13.920 --> 00:23:18.440
<v Speaker 2>pseudoseqal pipelines using literally nothing but primitive rays, plane objects,

458
00:23:18.440 --> 00:23:19.759
<v Speaker 2>and highly composable verbs.

459
00:23:19.799 --> 00:23:22.880
<v Speaker 1>And ultimately we saw how enforcing a mutability and avoiding

460
00:23:22.920 --> 00:23:26.559
<v Speaker 1>the global scope chain protects our systems from unpredictable state mutations.

461
00:23:26.920 --> 00:23:29.480
<v Speaker 1>It's an entirely different way of modeling the world, which

462
00:23:29.519 --> 00:23:31.400
<v Speaker 1>actually leaves me with a final thought for you to

463
00:23:31.400 --> 00:23:33.400
<v Speaker 1>consider as you step away from this.

464
00:23:33.440 --> 00:23:34.720
<v Speaker 2>Deep dive to curious.

465
00:23:34.920 --> 00:23:37.519
<v Speaker 1>Well, we spent this whole time talking about software architecture, right,

466
00:23:38.240 --> 00:23:42.000
<v Speaker 1>but the principles of object oriented versus functional design apply

467
00:23:42.240 --> 00:23:44.920
<v Speaker 1>really heavily to how we structure human systems too.

468
00:23:45.279 --> 00:23:46.799
<v Speaker 2>Wait, how so think.

469
00:23:46.680 --> 00:23:50.559
<v Speaker 1>About corporate structures. We very often organize our teams using

470
00:23:50.680 --> 00:23:55.039
<v Speaker 1>rigid object oriented principles. We build these complex, heavy hierarchies,

471
00:23:55.079 --> 00:23:58.799
<v Speaker 1>you know, VP classes, director classes, manager classes, and we

472
00:23:58.920 --> 00:24:03.599
<v Speaker 1>lock specific responsibilities and information silos deep inside those titles.

473
00:24:03.799 --> 00:24:05.640
<v Speaker 2>That is painfully accurate.

474
00:24:05.440 --> 00:24:08.599
<v Speaker 1>Right, and then when the market shifts and a totally

475
00:24:08.640 --> 00:24:12.559
<v Speaker 1>new problem arises, our rigid human classes struggle to adapt

476
00:24:12.559 --> 00:24:15.880
<v Speaker 1>because all the communication pathways are so tightly coupled to

477
00:24:15.920 --> 00:24:16.480
<v Speaker 1>the hierarchy.

478
00:24:16.599 --> 00:24:18.720
<v Speaker 2>We end up spending months trying to rewrite the org

479
00:24:18.839 --> 00:24:20.440
<v Speaker 2>chart just to solve the new problem.

480
00:24:20.519 --> 00:24:23.920
<v Speaker 1>Exactly, Well, what if we apply data thinking to our teams.

481
00:24:24.279 --> 00:24:26.960
<v Speaker 1>What if we stripped away the rigid hierarchies and viewed

482
00:24:27.000 --> 00:24:30.920
<v Speaker 1>our organizations as functional assembly lines. The raw material is

483
00:24:30.960 --> 00:24:34.039
<v Speaker 1>the project, The verbs are the specific skills of the

484
00:24:34.039 --> 00:24:37.519
<v Speaker 1>individuals on the team completely regardless of their title.

485
00:24:38.000 --> 00:24:39.559
<v Speaker 2>That's a really powerful way to look at it.

486
00:24:39.720 --> 00:24:42.960
<v Speaker 1>Could we build more resilient, adaptable companies if we stopped

487
00:24:42.960 --> 00:24:45.839
<v Speaker 1>obsessing over managing the state of our org charts and

488
00:24:45.920 --> 00:24:49.480
<v Speaker 1>started focusing on building better pipelines for our people's skills

489
00:24:49.519 --> 00:24:52.000
<v Speaker 1>to flow through. So next time you're stuck in a

490
00:24:52.000 --> 00:24:55.440
<v Speaker 1>bureaucratic bottleneck, ask yourself, are we acting like a broken

491
00:24:55.480 --> 00:24:58.119
<v Speaker 1>pocket watch or are we building an assembly line?
