WEBVTT

1
00:00:00.080 --> 00:00:04.440
<v Speaker 1>Picture this. The company website isn't technically down, but every

2
00:00:04.480 --> 00:00:07.559
<v Speaker 1>single alarm on the operation's dashboard is just flashing red.

3
00:00:07.639 --> 00:00:11.160
<v Speaker 2>Oh man, the absolute worst nightmare for any software developer, right.

4
00:00:11.240 --> 00:00:14.720
<v Speaker 1>Support calls are just flooding in expensive, angry calls from

5
00:00:14.759 --> 00:00:18.760
<v Speaker 1>frustrated customers, And the root cause is that someone made

6
00:00:18.760 --> 00:00:22.120
<v Speaker 1>a change to a third party API and it's causing

7
00:00:22.160 --> 00:00:23.920
<v Speaker 1>this massive data corruption on your.

8
00:00:23.920 --> 00:00:26.519
<v Speaker 2>End, which is terrifying, especially when you consider the system

9
00:00:26.559 --> 00:00:31.359
<v Speaker 2>talking to that API is usually some massive legacy beasts exactly.

10
00:00:30.920 --> 00:00:33.520
<v Speaker 1>In this case, it's a five hundred thousand line Java

11
00:00:33.640 --> 00:00:37.759
<v Speaker 1>enterprise system, and of course the one developer who actually

12
00:00:37.799 --> 00:00:41.640
<v Speaker 1>understands it is sitting on a beach somewhere completely unreachable.

13
00:00:41.840 --> 00:00:44.679
<v Speaker 2>Yeah, naturally, and normally, just tracking down a bug like

14
00:00:44.759 --> 00:00:47.399
<v Speaker 2>that in a massive Java code base, compiling a fix,

15
00:00:47.520 --> 00:00:50.799
<v Speaker 2>running tests, and deploying it, I mean that takes days.

16
00:00:51.320 --> 00:00:53.920
<v Speaker 1>But according to the opening of the book we're exploring today,

17
00:00:54.359 --> 00:00:59.399
<v Speaker 1>the author Michael Bevelocklyn faced this exact scenario and he

18
00:00:59.479 --> 00:01:00.719
<v Speaker 1>fixed it in an hour.

19
00:01:00.600 --> 00:01:03.520
<v Speaker 2>Which honestly borders on science fiction for anyone who's ever

20
00:01:03.560 --> 00:01:05.560
<v Speaker 2>wrestled with legacy enterprise code.

21
00:01:05.599 --> 00:01:08.920
<v Speaker 1>It really does. But The kicker is he didn't use

22
00:01:09.040 --> 00:01:12.560
<v Speaker 1>Java to fix it. He spun up a closure RIPL

23
00:01:12.920 --> 00:01:16.159
<v Speaker 1>to bypass all those usual deployment delays. And we should

24
00:01:16.159 --> 00:01:18.640
<v Speaker 1>probably explain what that is, because it's totally crucial to

25
00:01:18.719 --> 00:01:20.760
<v Speaker 1>understanding how you move so fast.

26
00:01:21.040 --> 00:01:24.439
<v Speaker 2>Yeah. So RPL stands for read evil print loop. It's

27
00:01:24.480 --> 00:01:28.879
<v Speaker 2>this interactive programming environment. So instead of the slow traditional

28
00:01:29.000 --> 00:01:33.040
<v Speaker 2>Java cycle where you write code, compile the whole massive project,

29
00:01:33.239 --> 00:01:36.519
<v Speaker 2>restart the server, and just cross your fingers, which takes forever, right,

30
00:01:36.560 --> 00:01:39.040
<v Speaker 2>it takes forever, But a RPL lets you interact with

31
00:01:39.079 --> 00:01:43.040
<v Speaker 2>a live running system. You type a command, the environment

32
00:01:43.120 --> 00:01:46.400
<v Speaker 2>evaluates it instantly against the live data, and it prints

33
00:01:46.400 --> 00:01:47.719
<v Speaker 2>the result right back to you.

34
00:01:47.920 --> 00:01:50.680
<v Speaker 1>So he used that live immediate connection to the data

35
00:01:50.760 --> 00:01:53.640
<v Speaker 1>to write a custom domain specific language and then wrote

36
00:01:53.640 --> 00:01:57.000
<v Speaker 1>a functional data transformation to clean up the corrupted mess instantly.

37
00:01:57.120 --> 00:01:58.159
<v Speaker 2>It's brilliant And.

38
00:01:58.120 --> 00:02:00.920
<v Speaker 1>A week later, at an all hands meeting, the boss

39
00:02:00.959 --> 00:02:03.200
<v Speaker 1>thanked him for the Java program that saved the day,

40
00:02:03.640 --> 00:02:06.560
<v Speaker 1>and he just smiled and said, that wasn't Java. I

41
00:02:06.599 --> 00:02:09.639
<v Speaker 1>love that start so good. So welcome to the deep dive.

42
00:02:10.400 --> 00:02:14.199
<v Speaker 1>Today we were exploring Bevel Acolen's book Functional programming patterns

43
00:02:14.199 --> 00:02:17.599
<v Speaker 1>in Skala enclosure, and the mission of this deep dive

44
00:02:17.879 --> 00:02:20.080
<v Speaker 1>is to help you cross the bridge from the traditional,

45
00:02:20.360 --> 00:02:24.439
<v Speaker 1>kind of bulky, object oriented programming world into the lean,

46
00:02:24.840 --> 00:02:27.319
<v Speaker 1>highly expressive world of functional programming.

47
00:02:27.439 --> 00:02:31.759
<v Speaker 2>Yeah, because functional languages like Scala enclosure, they fundamentally flip

48
00:02:31.759 --> 00:02:34.199
<v Speaker 2>how we structure software. I mean, they treat functions as

49
00:02:34.199 --> 00:02:38.599
<v Speaker 2>first class citizens. They strictly favor immutability over changing state,

50
00:02:39.000 --> 00:02:40.639
<v Speaker 2>and they're inherently declarative.

51
00:02:40.879 --> 00:02:44.080
<v Speaker 1>Okay, let's unpack this because if you're listening to this

52
00:02:44.159 --> 00:02:46.919
<v Speaker 1>and wondering why you should even care about a programming

53
00:02:46.919 --> 00:02:50.479
<v Speaker 1>paradigm shift, it's really about eliminating the sheer exhaustion of

54
00:02:50.520 --> 00:02:54.479
<v Speaker 1>writing endless boilerplate code. Absolutely, it's about understanding how modern

55
00:02:54.560 --> 00:02:58.960
<v Speaker 1>JVM applications are evolving to handle incredible scale without crashing.

56
00:02:59.240 --> 00:03:01.919
<v Speaker 1>So let's start with how these two paradigms handle aptions.

57
00:03:02.159 --> 00:03:04.759
<v Speaker 1>We're essentially moving from a world ruled by nouns to

58
00:03:04.800 --> 00:03:05.960
<v Speaker 1>a world power by verbs.

59
00:03:06.280 --> 00:03:10.280
<v Speaker 2>Right, in strict object oriented programming, everything has to be

60
00:03:10.319 --> 00:03:14.080
<v Speaker 2>an object. Everything is a noun. So verbs, you know,

61
00:03:14.120 --> 00:03:16.360
<v Speaker 2>the actual actions, the functions that do the work, they're

62
00:03:16.439 --> 00:03:17.120
<v Speaker 2>kind of trapped.

63
00:03:17.199 --> 00:03:18.319
<v Speaker 1>You're trapped in the classes.

64
00:03:18.400 --> 00:03:20.479
<v Speaker 2>Exactly. They can't exist on their own. They have to

65
00:03:20.520 --> 00:03:22.439
<v Speaker 2>be permanently attached to a class.

66
00:03:22.840 --> 00:03:27.080
<v Speaker 1>The book uses this hilarious real world analogy to point

67
00:03:27.120 --> 00:03:30.719
<v Speaker 1>out the absurdity of this, specifically looking at the functional

68
00:03:30.759 --> 00:03:34.599
<v Speaker 1>interface pattern in Java. Like, imagine if you couldn't just

69
00:03:34.840 --> 00:03:37.759
<v Speaker 1>run because run is a verb.

70
00:03:37.719 --> 00:03:38.960
<v Speaker 2>Right, you can't just do the thing.

71
00:03:39.159 --> 00:03:42.520
<v Speaker 1>Yeah, Instead, to execute the action of going for a run,

72
00:03:43.039 --> 00:03:46.560
<v Speaker 1>you would have to invent like a runner object, and

73
00:03:46.639 --> 00:03:49.319
<v Speaker 1>a shoe putter on her object, and a door opener object.

74
00:03:49.319 --> 00:03:51.360
<v Speaker 2>Which sounds ridiculous when you say it out loud, but

75
00:03:51.400 --> 00:03:54.680
<v Speaker 2>we do this constantly in traditional object oriented languages, I

76
00:03:54.719 --> 00:03:56.479
<v Speaker 2>really do. Like, if you want to pass a single

77
00:03:56.599 --> 00:03:59.400
<v Speaker 2>simple action around, say just a custom sorting rule, you

78
00:03:59.400 --> 00:04:01.080
<v Speaker 2>can't just pass the rule itself. You have to wrap

79
00:04:01.080 --> 00:04:04.840
<v Speaker 2>it in a class. You write five lines of boilerplate

80
00:04:04.919 --> 00:04:09.000
<v Speaker 2>code just to create a comparator class, instantiate an object

81
00:04:09.039 --> 00:04:11.319
<v Speaker 2>of that class, and then pass that object into your

82
00:04:11.360 --> 00:04:12.199
<v Speaker 2>sorting algorithm.

83
00:04:12.439 --> 00:04:15.680
<v Speaker 1>It's a massive amount of syntactic overhead just to tell

84
00:04:15.719 --> 00:04:19.240
<v Speaker 1>the computer, hey, sort these people by their first name

85
00:04:19.279 --> 00:04:20.319
<v Speaker 1>instead of their last name.

86
00:04:20.480 --> 00:04:24.480
<v Speaker 2>Exactly. So functional programming relies on higher order and anonymous

87
00:04:24.480 --> 00:04:25.800
<v Speaker 2>functions to strip all that.

88
00:04:25.839 --> 00:04:28.839
<v Speaker 1>Away, which is where the first class citizen thing comes in,

89
00:04:28.920 --> 00:04:29.920
<v Speaker 1>right right, When we.

90
00:04:29.879 --> 00:04:32.040
<v Speaker 2>Say a function is a first class citizen, it just

91
00:04:32.079 --> 00:04:34.680
<v Speaker 2>means the language treats the function exactly the same way

92
00:04:34.720 --> 00:04:36.560
<v Speaker 2>it treats a string or an integer. You don't need

93
00:04:36.560 --> 00:04:39.720
<v Speaker 2>a wrapper class. You just write a tiny anonymous function

94
00:04:39.879 --> 00:04:42.639
<v Speaker 2>right there in line and pass it directly into the

95
00:04:42.680 --> 00:04:43.639
<v Speaker 2>sorting algorithm.

96
00:04:44.240 --> 00:04:47.519
<v Speaker 1>You've turned five lines of class bureaucracy into one line

97
00:04:47.560 --> 00:04:50.600
<v Speaker 1>of pure logic. Yes. I am going to push back

98
00:04:50.600 --> 00:04:54.399
<v Speaker 1>on this though, because classes do more than just hold methods, right,

99
00:04:54.720 --> 00:04:58.800
<v Speaker 1>They hold state, They have properties and variables. So if

100
00:04:58.839 --> 00:05:01.040
<v Speaker 1>a function is just a flow vading verb in the ether,

101
00:05:01.800 --> 00:05:04.759
<v Speaker 1>how does it remember anything? Don't we lose the context

102
00:05:04.759 --> 00:05:05.839
<v Speaker 1>that a class provides.

103
00:05:06.079 --> 00:05:09.519
<v Speaker 2>Well, what's fascinating here is the mechanism functional language is

104
00:05:09.600 --> 00:05:12.759
<v Speaker 2>used to solve that exact problem. It's called a closure.

105
00:05:13.120 --> 00:05:13.600
<v Speaker 1>A closure.

106
00:05:13.759 --> 00:05:17.160
<v Speaker 2>Yeah, when you create a function in Scala or closure,

107
00:05:17.519 --> 00:05:20.879
<v Speaker 2>it automatically bundles itself with the scope and context was

108
00:05:20.920 --> 00:05:24.920
<v Speaker 2>created in it physically like closes over the variables that

109
00:05:24.920 --> 00:05:27.360
<v Speaker 2>were present in memory at the exact moment of its birth.

110
00:05:27.399 --> 00:05:31.199
<v Speaker 1>Oh wow, so it's basically carrying an invisible backpack of data.

111
00:05:31.319 --> 00:05:34.480
<v Speaker 1>Wherever it goes, it remembers what it needs without us

112
00:05:34.560 --> 00:05:36.879
<v Speaker 1>wiring up class properties and constructors.

113
00:05:37.199 --> 00:05:38.959
<v Speaker 2>That's a great way to put it. In fact, the

114
00:05:39.000 --> 00:05:42.879
<v Speaker 2>text mentions this classic programmer joke. Classes are a poor

115
00:05:42.920 --> 00:05:46.399
<v Speaker 2>man's closure and closures are a poor man's class ah,

116
00:05:46.480 --> 00:05:49.319
<v Speaker 2>because they essentially solve the exact same problem of marine

117
00:05:49.319 --> 00:05:52.639
<v Speaker 2>state and behavior. The difference is that closures achieve it

118
00:05:52.680 --> 00:05:54.800
<v Speaker 2>with virtually zero extra curd.

119
00:05:55.160 --> 00:05:57.560
<v Speaker 1>Wait, if a closure can hold on to state without

120
00:05:57.600 --> 00:06:00.240
<v Speaker 1>needing a class, does that completely invalidate? How how we

121
00:06:00.279 --> 00:06:04.319
<v Speaker 1>design larger enterprise patterns like I'm looking at you command pattern?

122
00:06:04.399 --> 00:06:06.920
<v Speaker 2>Oh? The command pattern is a perfect casualty of this shift.

123
00:06:07.120 --> 00:06:10.160
<v Speaker 2>I mean, in enterprise software you use the command pattern

124
00:06:10.279 --> 00:06:13.759
<v Speaker 2>to turn a method invocation into an object, usually so

125
00:06:13.800 --> 00:06:16.519
<v Speaker 2>you can queue it up, log it, or undo it later.

126
00:06:16.360 --> 00:06:18.639
<v Speaker 1>Write the classic undue button exactly.

127
00:06:18.879 --> 00:06:23.000
<v Speaker 2>But traditional object oriented design requires a massive bureaucracy to

128
00:06:23.040 --> 00:06:26.160
<v Speaker 2>make it happen. You need a client to create the command,

129
00:06:26.319 --> 00:06:29.600
<v Speaker 2>an invoker to run it, a receiver to act on it,

130
00:06:29.680 --> 00:06:32.439
<v Speaker 2>and a command interface to tie all those pieces together.

131
00:06:33.079 --> 00:06:35.759
<v Speaker 1>And the book illustrates this with a cash register example.

132
00:06:35.839 --> 00:06:36.600
<v Speaker 2>Right, yes, it does.

133
00:06:36.839 --> 00:06:40.360
<v Speaker 1>In Java, just to record a simple purchase and keep

134
00:06:40.360 --> 00:06:43.600
<v Speaker 1>a history for those undue capabilities, you have to build

135
00:06:43.639 --> 00:06:47.560
<v Speaker 1>a purchase command class, a cash register receiver class, and

136
00:06:47.600 --> 00:06:50.240
<v Speaker 1>a purchase invoker class. I mean it feels like you're

137
00:06:50.240 --> 00:06:52.439
<v Speaker 1>setting up a corporate committee just to buy a cup

138
00:06:52.480 --> 00:06:52.959
<v Speaker 1>of coffee.

139
00:06:53.040 --> 00:06:56.000
<v Speaker 2>It really does. But in Skala, because of closures and

140
00:06:56.040 --> 00:06:59.759
<v Speaker 2>higher order functions, you bypass the interface and the invoker entirely.

141
00:07:00.079 --> 00:07:01.360
<v Speaker 2>You just write a simple make.

142
00:07:01.240 --> 00:07:03.399
<v Speaker 1>Purchase function just a function, just a function.

143
00:07:03.600 --> 00:07:06.240
<v Speaker 2>It takes the register and the purchase amount, and it

144
00:07:06.279 --> 00:07:09.199
<v Speaker 2>returns another function that performs the actual addition.

145
00:07:09.439 --> 00:07:12.959
<v Speaker 1>And because that return function is a closure, its invisible

146
00:07:13.000 --> 00:07:16.560
<v Speaker 1>backpack remembers the purchase amount and the specific register it's

147
00:07:16.560 --> 00:07:17.399
<v Speaker 1>supposed to act.

148
00:07:17.240 --> 00:07:20.160
<v Speaker 2>On exactly, and to keep track of the history and

149
00:07:20.240 --> 00:07:23.439
<v Speaker 2>execution function just takes that returned closure and drops it

150
00:07:23.480 --> 00:07:25.839
<v Speaker 2>into a standard list before running it. Boom, you have

151
00:07:25.879 --> 00:07:26.639
<v Speaker 2>your history log.

152
00:07:26.759 --> 00:07:29.439
<v Speaker 1>That's amazing, and closure strips it down even further, doesn't it.

153
00:07:29.480 --> 00:07:32.160
<v Speaker 2>Oh yeah, you don't even need a cash register object.

154
00:07:32.439 --> 00:07:35.920
<v Speaker 2>Closure uses a concept called an atom to manage the

155
00:07:35.959 --> 00:07:39.439
<v Speaker 2>total an atom, yeah, and atom is a functional construct

156
00:07:39.480 --> 00:07:42.680
<v Speaker 2>specifically designed to manage a piece of changing states safely,

157
00:07:43.319 --> 00:07:45.439
<v Speaker 2>so you don't build a class around it. You just

158
00:07:45.879 --> 00:07:48.639
<v Speaker 2>manipulate the atom directly with your purchase functions.

159
00:07:48.839 --> 00:07:51.040
<v Speaker 1>So if someone is listening to this and wondering what

160
00:07:51.079 --> 00:07:53.759
<v Speaker 1>the actual day to day impact is for them, it

161
00:07:53.800 --> 00:07:56.519
<v Speaker 1>really comes down to cognitive load. Com Lately, you are

162
00:07:56.560 --> 00:08:01.319
<v Speaker 1>getting enterprise grade undue replay and logging capabilities, but with

163
00:08:01.399 --> 00:08:03.720
<v Speaker 1>a fraction of the code. Like when you open that

164
00:08:03.759 --> 00:08:06.480
<v Speaker 1>file six months from now, you aren't hunting through four

165
00:08:06.480 --> 00:08:09.079
<v Speaker 1>different class files just to figure out what a purchase does.

166
00:08:09.480 --> 00:08:12.839
<v Speaker 1>It's all right there, localized and just vastly.

167
00:08:12.560 --> 00:08:16.000
<v Speaker 2>Easier to read, right, because we have essentially replaced heavy

168
00:08:16.079 --> 00:08:19.600
<v Speaker 2>classes with lightweight functions and closures. But you know that

169
00:08:19.680 --> 00:08:22.560
<v Speaker 2>naturally brings up the data itself. What are these functions

170
00:08:22.600 --> 00:08:27.399
<v Speaker 2>actually operating on? Well, in functional programming, data doesn't change.

171
00:08:27.480 --> 00:08:31.160
<v Speaker 2>It is strictly immutable. Once a piece of data is created,

172
00:08:31.519 --> 00:08:33.639
<v Speaker 2>it is locked in stone forever.

173
00:08:33.519 --> 00:08:36.399
<v Speaker 1>Which, coming from the object oriented world, that concept can

174
00:08:36.440 --> 00:08:40.840
<v Speaker 1>sound incredibly restrictive. I mean, in Java, building truly immutable

175
00:08:40.840 --> 00:08:44.840
<v Speaker 1>objects is painful. It leads to the whole telescoping constructor problem.

176
00:08:44.919 --> 00:08:46.399
<v Speaker 2>Oh yeah, you see this all the time you have

177
00:08:46.440 --> 00:08:48.720
<v Speaker 2>a person object, sometimes you only have a first and

178
00:08:48.799 --> 00:08:51.240
<v Speaker 2>last name. Sometimes you have a middle name or a title.

179
00:08:51.600 --> 00:08:54.519
<v Speaker 2>So you end up writing like ten different constructors to

180
00:08:54.519 --> 00:08:58.399
<v Speaker 2>cover all the possible combinations of defaults, or you abandon

181
00:08:58.440 --> 00:09:01.080
<v Speaker 2>constructors entirely and use the fluent builder pattern.

182
00:09:01.240 --> 00:09:03.360
<v Speaker 1>Right, and the builder pattern requires you to create a

183
00:09:03.399 --> 00:09:07.440
<v Speaker 1>whole separate builder class with individual methods to set each property,

184
00:09:07.639 --> 00:09:11.799
<v Speaker 1>which finally returns the lockdown immutable object. Trying to keep

185
00:09:11.879 --> 00:09:13.960
<v Speaker 1>data immutable in Java is like trying to build a

186
00:09:14.000 --> 00:09:16.399
<v Speaker 1>ship in a bottle using tweezers.

187
00:09:16.159 --> 00:09:17.559
<v Speaker 2>That is painfully accurate.

188
00:09:17.879 --> 00:09:21.679
<v Speaker 1>Yes, it's beautiful and totally secure once it's done, but

189
00:09:21.759 --> 00:09:24.720
<v Speaker 1>the construction process is just absolutely exhausting.

190
00:09:24.840 --> 00:09:28.399
<v Speaker 2>Well, Scala bypasses this entirely with something called case classes.

191
00:09:28.799 --> 00:09:32.279
<v Speaker 2>Case classes give you named parameters and default arguments right

192
00:09:32.279 --> 00:09:34.320
<v Speaker 2>out of the box. So if you want a person

193
00:09:34.360 --> 00:09:37.000
<v Speaker 2>to have a default empty middle name, you declare it

194
00:09:37.039 --> 00:09:40.759
<v Speaker 2>exactly once in the class definition and the compiler handles

195
00:09:40.799 --> 00:09:43.399
<v Speaker 2>the rest, no extra constructors needed.

196
00:09:43.519 --> 00:09:46.919
<v Speaker 1>Okay, but if the data is completely immutable, what happens

197
00:09:46.919 --> 00:09:49.840
<v Speaker 1>when that person gets married and changes their last name? Right, Like,

198
00:09:50.039 --> 00:09:51.240
<v Speaker 1>we can't mutate the object.

199
00:09:51.320 --> 00:09:53.480
<v Speaker 2>We already have, right, so you use the built in

200
00:09:53.639 --> 00:09:57.759
<v Speaker 2>dot copy method. It instantly clones the existing case class

201
00:09:57.799 --> 00:10:00.759
<v Speaker 2>in memory, but it allows you to pass send just

202
00:10:00.960 --> 00:10:02.720
<v Speaker 2>the new attribute you want to change.

203
00:10:02.759 --> 00:10:03.440
<v Speaker 1>Oh that's clever.

204
00:10:03.639 --> 00:10:07.320
<v Speaker 2>Yeah, it generates a brand new updated person object, leaving

205
00:10:07.320 --> 00:10:11.159
<v Speaker 2>the original completely untouched. It's lightning fast and completely safe.

206
00:10:11.360 --> 00:10:14.159
<v Speaker 1>I know Scale relies heavily on its static type system

207
00:10:14.200 --> 00:10:18.559
<v Speaker 1>to enforce those case classes, but Closure is completely different structurally. Right,

208
00:10:18.799 --> 00:10:20.519
<v Speaker 1>it doesn't use case classes at all, does it.

209
00:10:20.840 --> 00:10:24.679
<v Speaker 2>No. Closure embraces dynamic simplicity. So for a lot of

210
00:10:24.720 --> 00:10:28.840
<v Speaker 2>exploratory programming, Closure relies on simple maps, which are essentially

211
00:10:28.960 --> 00:10:32.519
<v Speaker 2>just generic key value pairs in memory. But when you

212
00:10:32.559 --> 00:10:35.399
<v Speaker 2>need to lock that data down, perhaps to ensure certain

213
00:10:35.440 --> 00:10:40.720
<v Speaker 2>fields exist for polymorphism, Closure seamlessly transitions those maps into records.

214
00:10:40.840 --> 00:10:43.240
<v Speaker 1>Wait, how does that transition actually work out of the hood,

215
00:10:43.559 --> 00:10:45.639
<v Speaker 1>Like from a map to a record.

216
00:10:45.440 --> 00:10:48.279
<v Speaker 2>It's quite elegant. Actually, a map is just a generic

217
00:10:48.360 --> 00:10:51.720
<v Speaker 2>hash table. But when you define a record enclosure, the

218
00:10:51.759 --> 00:10:55.600
<v Speaker 2>compiler generates a fast, concrete Java class with specific fields

219
00:10:55.600 --> 00:10:58.320
<v Speaker 2>for your data. Yet to the rest of your closure code,

220
00:10:58.440 --> 00:11:01.360
<v Speaker 2>that record still behaves exact like a standard map.

221
00:11:01.440 --> 00:11:03.679
<v Speaker 1>So you get the strict memory structure of a class

222
00:11:03.720 --> 00:11:07.000
<v Speaker 1>with the fluid flexibility of a dynamic map exactly. But so,

223
00:11:07.120 --> 00:11:10.559
<v Speaker 1>why go through all this effort, why make immutability such

224
00:11:10.559 --> 00:11:13.080
<v Speaker 1>a foundational pillar of these languages in the first place.

225
00:11:13.480 --> 00:11:16.320
<v Speaker 2>Well, if we connect this to the bigger picture, immutability

226
00:11:16.360 --> 00:11:20.200
<v Speaker 2>isn't just some functional purity exercise for academics. It solves

227
00:11:20.200 --> 00:11:23.399
<v Speaker 2>one of the most expensive system crashing problems in modern

228
00:11:23.559 --> 00:11:26.159
<v Speaker 2>software development, race conditions.

229
00:11:26.519 --> 00:11:30.440
<v Speaker 1>Because our modern world runs on multiicore processors, we have

230
00:11:30.559 --> 00:11:33.759
<v Speaker 1>dozens of threads running simultaneously within a single application.

231
00:11:34.039 --> 00:11:37.960
<v Speaker 2>Exactly, A massive class of bugs occurs when thread A

232
00:11:38.120 --> 00:11:40.559
<v Speaker 2>is trying to read a piece of data and thread

233
00:11:40.600 --> 00:11:44.440
<v Speaker 2>B unexpectedly mutates that same data in the background. It

234
00:11:44.519 --> 00:11:48.559
<v Speaker 2>leads to corrupted states and just unpredictable crashes. But by

235
00:11:48.679 --> 00:11:53.399
<v Speaker 2>enforcing strict immutability, that entire class of bugs just ceases

236
00:11:53.480 --> 00:11:56.559
<v Speaker 2>to exist. You can share your data across a thousand

237
00:11:56.559 --> 00:12:00.360
<v Speaker 2>concurrent threads safely because you know with absolute certainty that

238
00:12:00.559 --> 00:12:02.720
<v Speaker 2>none of them possess the ability to alter it.

239
00:12:03.159 --> 00:12:05.840
<v Speaker 1>Knowing our data is safe from sneaky background changes is

240
00:12:05.840 --> 00:12:09.000
<v Speaker 1>a huge relief. But I mean it introduces a major

241
00:12:09.039 --> 00:12:12.840
<v Speaker 1>mechanical problem. If our data is immutable and we cannot

242
00:12:12.919 --> 00:12:14.840
<v Speaker 1>mutate state, how do we loop?

243
00:12:15.120 --> 00:12:18.240
<v Speaker 2>Yes. This is often the biggest mental hurdle for developers

244
00:12:18.240 --> 00:12:21.360
<v Speaker 2>moving from object oriented to functional programming.

245
00:12:21.080 --> 00:12:23.039
<v Speaker 1>Because if you think about a traditional forour loop or

246
00:12:23.080 --> 00:12:25.600
<v Speaker 1>a four reach loop in Java under the hood, those

247
00:12:25.639 --> 00:12:28.360
<v Speaker 1>loops relying on an iterator. They rely on mutating a

248
00:12:28.399 --> 00:12:31.080
<v Speaker 1>state variable like iplus plus just to keep track of

249
00:12:31.080 --> 00:12:34.120
<v Speaker 1>their exact position in a list. If we can't mutate state,

250
00:12:34.200 --> 00:12:35.360
<v Speaker 1>we can't iterate like that.

251
00:12:35.720 --> 00:12:39.120
<v Speaker 2>We have to shift our thinking from imperative iteration to

252
00:12:39.240 --> 00:12:44.320
<v Speaker 2>declarative transformation. Instead of writing code that micromanages every single

253
00:12:44.360 --> 00:12:46.840
<v Speaker 2>step of a loop, we declare what we want the

254
00:12:46.879 --> 00:12:47.840
<v Speaker 2>final outcome to be.

255
00:12:48.200 --> 00:12:51.600
<v Speaker 1>Okay, let's use the text specific scenario here to ground

256
00:12:51.720 --> 00:12:54.440
<v Speaker 1>this the lambda bar and grill. We have a massive

257
00:12:54.519 --> 00:12:58.360
<v Speaker 1>database list of people. We're opening a new restaurant, and

258
00:12:58.399 --> 00:13:01.519
<v Speaker 1>we want to send grand opening ands, but only to

259
00:13:01.600 --> 00:13:04.759
<v Speaker 1>the people who live in specific nearby zip codes. Right.

260
00:13:04.879 --> 00:13:07.919
<v Speaker 2>So, in an imperative object oriented language, you tell the

261
00:13:07.960 --> 00:13:11.200
<v Speaker 2>computer exactly how to do this. You create a temporary

262
00:13:11.240 --> 00:13:14.200
<v Speaker 2>empty mutable list, You set up a loop counter, You

263
00:13:14.279 --> 00:13:17.360
<v Speaker 2>check person one zip code if it matches, you mutate

264
00:13:17.399 --> 00:13:20.399
<v Speaker 2>your temporary list by appending them to it, You increment

265
00:13:20.440 --> 00:13:21.879
<v Speaker 2>your counter, you check person two.

266
00:13:22.080 --> 00:13:23.759
<v Speaker 1>It's incredibly tedious, very.

267
00:13:23.799 --> 00:13:26.960
<v Speaker 2>But in functional programming we use sequence comprehensions.

268
00:13:27.399 --> 00:13:29.639
<v Speaker 1>Let's break down how Scala does this, because it reads

269
00:13:29.679 --> 00:13:33.399
<v Speaker 1>almost like natural English. Use a Scala for comprehension, but

270
00:13:33.480 --> 00:13:36.159
<v Speaker 1>it is not a traditional loop. You declare that you

271
00:13:36.200 --> 00:13:38.399
<v Speaker 1>are pulling people from the original list, and then you

272
00:13:38.480 --> 00:13:40.960
<v Speaker 1>embed a guard directly inside the comprehension.

273
00:13:41.200 --> 00:13:44.320
<v Speaker 2>And the guard is basically an inline if statement, right

274
00:13:44.399 --> 00:13:46.159
<v Speaker 2>like if zip code is close.

275
00:13:46.000 --> 00:13:50.200
<v Speaker 1>Yeah, exactly. That guard seamlessly filters the original list and

276
00:13:50.320 --> 00:13:53.639
<v Speaker 1>yields a brand new, immutable list containing only the matching

277
00:13:53.720 --> 00:13:57.399
<v Speaker 1>people you didn't manage a single counter or a temporary array.

278
00:13:57.919 --> 00:14:01.639
<v Speaker 2>Enclosure approaches it similarly, but he uses a macro closure

279
00:14:01.799 --> 00:14:05.960
<v Speaker 2>pairs a four macro with a when clause. The logic

280
00:14:06.159 --> 00:14:09.799
<v Speaker 2>is identical, give me the people from this sequence when

281
00:14:10.039 --> 00:14:12.759
<v Speaker 2>this zip code condition is met, which.

282
00:14:12.559 --> 00:14:14.600
<v Speaker 1>Is so clean. So if we're asking what the day

283
00:14:14.639 --> 00:14:17.360
<v Speaker 1>to day impact is for a developer, it's about elevating

284
00:14:17.399 --> 00:14:20.360
<v Speaker 1>your code from low level micromanagement to high level delegation.

285
00:14:20.720 --> 00:14:23.759
<v Speaker 1>You start thinking in terms of data pipelines. You filter, map,

286
00:14:23.799 --> 00:14:26.440
<v Speaker 1>and reduce rather than holding the computer's hand through every

287
00:14:26.480 --> 00:14:28.200
<v Speaker 1>microstep of constructing a list.

288
00:14:28.000 --> 00:14:30.440
<v Speaker 2>And it drastically reduces off by one errors.

289
00:14:30.519 --> 00:14:33.639
<v Speaker 1>Definitely, I love an elegant data pipeline. But let's bring

290
00:14:33.639 --> 00:14:36.120
<v Speaker 1>this back down to the messy real world. Because data

291
00:14:36.120 --> 00:14:38.840
<v Speaker 1>pipelines are great when the data is perfect. But what

292
00:14:38.960 --> 00:14:41.960
<v Speaker 1>happens when that sequence comprehension looks for a zip code

293
00:14:42.080 --> 00:14:44.039
<v Speaker 1>and the zip code field is simply missing?

294
00:14:44.200 --> 00:14:47.200
<v Speaker 2>Ah, dealing with nothing. Tony Hohore, the computer scientist who

295
00:14:47.200 --> 00:14:51.039
<v Speaker 2>created the null reference, famously called it his billion dollar mistake.

296
00:14:51.279 --> 00:14:52.960
<v Speaker 1>Wow, billion dollar mistake.

297
00:14:53.039 --> 00:14:56.639
<v Speaker 2>Yeah, because it literally causes billions of dollars in crashes

298
00:14:56.679 --> 00:14:59.960
<v Speaker 2>and debugging time across the industry. I mean, in Java,

299
00:15:00.279 --> 00:15:04.000
<v Speaker 2>null is a constant, lingering threat. Your code becomes this

300
00:15:04.159 --> 00:15:07.799
<v Speaker 2>labyrinth of defensive null checks. If person is not null,

301
00:15:07.879 --> 00:15:10.399
<v Speaker 2>and if addresses not null, and if zip code is

302
00:15:10.440 --> 00:15:11.840
<v Speaker 2>not null, it's exhausting.

303
00:15:12.000 --> 00:15:15.720
<v Speaker 1>Or to avoid that labyrinth, object oriented developers rely on

304
00:15:15.759 --> 00:15:18.720
<v Speaker 1>the null object pattern. You create a dummy class like

305
00:15:18.759 --> 00:15:21.679
<v Speaker 1>a null person, and you hardcode their name is John

306
00:15:21.759 --> 00:15:25.159
<v Speaker 1>Do and their zip code is zero zero zero zero zero.

307
00:15:25.480 --> 00:15:27.840
<v Speaker 1>Just to ensure the program doesn't explode when it attempts

308
00:15:27.879 --> 00:15:29.480
<v Speaker 1>to call a method on an empty reference.

309
00:15:29.639 --> 00:15:33.080
<v Speaker 2>It works, but again it requires massive overhead. Scala takes

310
00:15:33.120 --> 00:15:36.679
<v Speaker 2>a deeply structural approach to this problem with its option type.

311
00:15:36.919 --> 00:15:39.240
<v Speaker 1>I find option fascinating because it acts like a type

312
00:15:39.279 --> 00:15:42.000
<v Speaker 1>safe net. Instead of a method of returning a string

313
00:15:42.039 --> 00:15:44.240
<v Speaker 1>that might secretly be a ticking time bomb of null,

314
00:15:44.639 --> 00:15:46.799
<v Speaker 1>it returns an option container, and.

315
00:15:46.879 --> 00:15:50.200
<v Speaker 2>The physical mechanism of the compiler here is key. The

316
00:15:50.200 --> 00:15:55.279
<v Speaker 2>option container explicitly holds either some value or it holds none.

317
00:15:55.360 --> 00:15:58.840
<v Speaker 2>Because of how Scala's static type system works, it physically

318
00:15:58.840 --> 00:16:01.519
<v Speaker 2>prevents your code from if you try to use the

319
00:16:01.559 --> 00:16:05.320
<v Speaker 2>value inside the option without explicitly handling the possibility that

320
00:16:05.360 --> 00:16:05.840
<v Speaker 2>it might.

321
00:16:05.720 --> 00:16:08.559
<v Speaker 1>Be none, you cannot accidentally ignore it exactly.

322
00:16:08.600 --> 00:16:11.360
<v Speaker 2>You extract the data using a method like get ls,

323
00:16:11.399 --> 00:16:13.840
<v Speaker 2>you tell the program give me the zip code, or

324
00:16:13.960 --> 00:16:18.360
<v Speaker 2>else give me this default string. It completely eliminates those

325
00:16:18.399 --> 00:16:21.159
<v Speaker 2>surprise null pointer exceptions that bring down servers at two

326
00:16:21.200 --> 00:16:22.399
<v Speaker 2>in the morning, which is huge.

327
00:16:23.000 --> 00:16:26.080
<v Speaker 1>But closure takes a much more dynamic, relaxed approach to

328
00:16:26.200 --> 00:16:30.679
<v Speaker 1>missing data. Right enclosure nil isn't a program crashing time bomb.

329
00:16:31.039 --> 00:16:34.159
<v Speaker 1>It simply evaluates to false in logic checks, so an

330
00:16:34.200 --> 00:16:37.080
<v Speaker 1>if stable won't explode if it encounters a nil correct.

331
00:16:37.399 --> 00:16:39.600
<v Speaker 2>And when you look up a value in a closure map,

332
00:16:39.759 --> 00:16:42.919
<v Speaker 2>you use the get function. The get function inherently allows

333
00:16:42.960 --> 00:16:45.559
<v Speaker 2>you to supply a default value right there as the

334
00:16:45.559 --> 00:16:48.480
<v Speaker 2>third argument. So you write, you know, get person call

335
00:16:48.519 --> 00:16:51.320
<v Speaker 2>on zip code zero zero zero zero zero. If the

336
00:16:51.399 --> 00:16:54.720
<v Speaker 2>zip code is missing or nil, the function smoothly returns

337
00:16:54.960 --> 00:16:59.080
<v Speaker 2>zero zero zero zero zero zero. No null object pattern

338
00:16:59.159 --> 00:17:00.480
<v Speaker 2>or dummy classes needed.

339
00:17:00.679 --> 00:17:03.960
<v Speaker 1>This perfectly illustrates a point from Peter Norvig, the legendary

340
00:17:03.960 --> 00:17:06.359
<v Speaker 1>computer scientist at Google which the book references.

341
00:17:06.480 --> 00:17:09.680
<v Speaker 2>Oh, his insight is profound. He pointed out that highly

342
00:17:09.680 --> 00:17:13.519
<v Speaker 2>expressive languages actually make classic design patterns invisible.

343
00:17:13.799 --> 00:17:15.839
<v Speaker 1>You don't need to write a complex visitor pattern or

344
00:17:15.880 --> 00:17:18.559
<v Speaker 1>a null object pattern or a command pattern because the

345
00:17:18.640 --> 00:17:23.680
<v Speaker 1>language itself handles extensibility, missing data, and function encapsulation. Natively,

346
00:17:24.039 --> 00:17:26.680
<v Speaker 1>the pattern just kind of dissolves into the basic syntax

347
00:17:26.759 --> 00:17:27.359
<v Speaker 1>of the language.

348
00:17:27.440 --> 00:17:29.759
<v Speaker 2>Yeah, you stop building scaffolding and finally get to just

349
00:17:29.799 --> 00:17:30.480
<v Speaker 2>build the building.

350
00:17:30.759 --> 00:17:33.039
<v Speaker 1>I love that. Let's take a breath and look at

351
00:17:33.079 --> 00:17:35.920
<v Speaker 1>the journey we've been on by diving into the concepts

352
00:17:35.960 --> 00:17:40.839
<v Speaker 1>from Bevloquilln's book and comparing Scala and Closure to traditional Java,

353
00:17:40.960 --> 00:17:44.000
<v Speaker 1>We've seen how to shed the heavy armor of object

354
00:17:44.000 --> 00:17:45.319
<v Speaker 1>oriented design patterns.

355
00:17:45.359 --> 00:17:49.400
<v Speaker 2>We've traded noun overlords for agile verbs by embracing higher

356
00:17:49.519 --> 00:17:51.680
<v Speaker 2>order functions over bulky interfaces.

357
00:17:51.799 --> 00:17:55.279
<v Speaker 1>We've replaced the bureaucratic command pattern with lightweight closures. We've

358
00:17:55.279 --> 00:17:59.039
<v Speaker 1>swapped exhausting builders for elegant, immutable case classes and records.

359
00:17:59.079 --> 00:18:02.839
<v Speaker 1>And we've elevated our loops from imperative micromanagement to declarative

360
00:18:02.880 --> 00:18:04.240
<v Speaker 1>sequence comprehensions.

361
00:18:04.440 --> 00:18:07.640
<v Speaker 2>And the result is code that is leaner, significantly safer

362
00:18:07.640 --> 00:18:12.680
<v Speaker 2>from concurrency bugs, and just incredibly powerful for modern JVM applications.

363
00:18:12.839 --> 00:18:14.799
<v Speaker 1>I want to leave you with a final provocative thought

364
00:18:14.799 --> 00:18:18.319
<v Speaker 1>to mull Over. The text explicitly points out that Java eight,

365
00:18:18.480 --> 00:18:23.559
<v Speaker 1>which is a massive, historically strict imperative language, introduce lambda expressions.

366
00:18:23.920 --> 00:18:27.279
<v Speaker 1>They essentially bolted functional higher order functions onto the language

367
00:18:27.359 --> 00:18:31.119
<v Speaker 1>via JSR three thirty five. Why because the functional programming

368
00:18:31.160 --> 00:18:33.880
<v Speaker 1>approach is simply an undeniable win for developers.

369
00:18:34.200 --> 00:18:38.720
<v Speaker 2>Yeah, massive strictly imperative languages are actively absorbing these functional

370
00:18:38.759 --> 00:18:42.279
<v Speaker 2>features because they can no longer ignore the benefits.

371
00:18:42.519 --> 00:18:45.599
<v Speaker 1>So here is the question for you. If the biggest

372
00:18:45.599 --> 00:18:48.880
<v Speaker 1>heavyweight in the object oriented world is actively absorbing the

373
00:18:48.920 --> 00:18:53.720
<v Speaker 1>functional programming toolkit, will the historical boundary between object oriented

374
00:18:53.759 --> 00:18:58.440
<v Speaker 1>and functional programming eventually dissolve completely? Are we moving toward

375
00:18:58.559 --> 00:19:03.880
<v Speaker 1>a universal high brid programming paradigm where the old tribal

376
00:19:03.920 --> 00:19:07.079
<v Speaker 1>software wars like i'm an odev versus i'm an fp

377
00:19:07.240 --> 00:19:09.279
<v Speaker 1>dev simply cease to exist.

378
00:19:09.400 --> 00:19:12.160
<v Speaker 2>It's a fascinating future to consider as these tools continue

379
00:19:12.160 --> 00:19:12.799
<v Speaker 2>to blend together.

380
00:19:12.920 --> 00:19:14.920
<v Speaker 1>It really is. Thank you for joining us on this

381
00:19:14.960 --> 00:19:17.799
<v Speaker 1>deep dive. Keep learning, keep questioning your assumptions, and next

382
00:19:17.839 --> 00:19:20.160
<v Speaker 1>time you're staring at a broken diagnostic dashboard with the

383
00:19:20.160 --> 00:19:24.720
<v Speaker 1>alarms blaring, remember our software firefighter. With the right functional tools,

384
00:19:24.759 --> 00:19:26.960
<v Speaker 1>you might just clear those murky waters in an hour

385
00:19:27.200 --> 00:19:29.680
<v Speaker 1>and leave everyone wondering what kind of magic you just used.
