1
00:00:00,000 --> 00:00:07,440
It's actually something we started to talk about on that failed recording, which is that the...

2
00:00:07,440 --> 00:00:16,320
where it's come from is, as I've been working on this packages page update for Swift.org,

3
00:00:16,320 --> 00:00:24,800
it's made me think a lot about how we pick and recommend and discuss packages. And there was

4
00:00:24,800 --> 00:00:29,500
there was a bit in that failed recording where we talked about a package

5
00:00:29,500 --> 00:00:34,000
and I ended up talking myself out of recommending it halfway through.

6
00:00:34,000 --> 00:00:40,400
Well you talked yourself out of it, you immediately said you shouldn't be using it.

7
00:00:40,400 --> 00:00:44,200
You didn't give yourself much of a chance to be honest.

8
00:00:44,200 --> 00:00:53,100
And afterwards we were discussing the failed episode and you said it was a bit of a shame that that got lost

9
00:00:53,100 --> 00:01:01,900
because it is actually an interesting thing. Like there's value in

10
00:01:01,900 --> 00:01:09,220
talking about things that you wouldn't automatically... like a recommendation is a

11
00:01:09,220 --> 00:01:13,460
funny thing because a recommendation it almost makes no sense because what might

12
00:01:13,460 --> 00:01:18,020
fit my use case might not fit your use case and it might not fit everybody's

13
00:01:18,020 --> 00:01:21,500
use case but there will be some people who find something in everything right?

14
00:01:21,500 --> 00:01:28,780
So recommendations are a little odd in that way, but also there's value, I

15
00:01:28,780 --> 00:01:35,600
think, in talking about things that you wouldn't necessarily use, and there's

16
00:01:35,600 --> 00:01:38,860
still value in that. And it's something I've been thinking about,

17
00:01:38,860 --> 00:01:43,420
like I say, over the last few weeks as I've been putting the final touches on

18
00:01:43,420 --> 00:01:47,800
the packages page and that process that we're going to put in of people

19
00:01:47,800 --> 00:01:54,140
suggesting packages to recommend and then having a kind of editorial

20
00:01:54,140 --> 00:01:58,720
process of picking some packages to feature on Swift.org temporarily. And

21
00:01:58,720 --> 00:02:05,380
that they shouldn't be pitched as like, "these are the best packages ever." It's

22
00:02:05,380 --> 00:02:10,360
just, here are some packages. They may do interesting things.

23
00:02:10,360 --> 00:02:15,400
They may do interesting things and not be for you. They may, you know, they may be

24
00:02:15,400 --> 00:02:20,440
something that you can learn something from or get inspiration from or there's many many reasons

25
00:02:20,440 --> 00:02:25,160
to look at a package. Yeah absolutely yeah yeah I agree and and you can learn something from

26
00:02:25,160 --> 00:02:31,080
having a package discussed that is clearly not your use case but still it's well valuable in

27
00:02:31,080 --> 00:02:37,320
knowing that's just not right for me it's too big for me it doesn't do it quite the way I would need

28
00:02:37,320 --> 00:02:41,880
it it's you know it's too complex because of the yeah trade-offs it makes you know lots of things

29
00:02:41,880 --> 00:02:46,040
are just trade-offs, right? There isn't the perfect package because the perfect package

30
00:02:46,040 --> 00:02:52,600
is effectively almost, you know, often something you would have to write yourself because that's

31
00:02:52,600 --> 00:02:56,520
the only way to guarantee it's actually tailored to your requirements. I mean...

32
00:02:56,520 --> 00:03:03,320
>> Can I suggest Foundation? >> Yeah, but is that a package in the sense that, I mean,

33
00:03:03,320 --> 00:03:08,680
obviously at some point it'll be a package in the... Although actually that's a great point,

34
00:03:08,680 --> 00:03:13,480
because many people will argue Foundation isn't a good choice for what they're doing.

35
00:03:13,480 --> 00:03:16,040
You know, they might be on resource constrained devices.

36
00:03:16,040 --> 00:03:22,680
Many Linux folks say, "I don't want to pull Foundation in because it makes my binary bigger,

37
00:03:22,680 --> 00:03:30,840
compile times are bigger." That sort of thing. But compile times isn't going to be an issue

38
00:03:30,840 --> 00:03:37,080
if it's a library like that. But once it's a package, that'll have an effect. Although I think

39
00:03:37,640 --> 00:03:45,000
on Linux, it is even part of it. Swift core foundation is binary. I'm not 100% sure.

40
00:03:45,000 --> 00:03:52,680
But either way, you'll bloat your binary. You have more complexity if you pull in a dependency like

41
00:03:52,680 --> 00:03:59,480
that. And in other cases, of course, you're going to import foundation because when you're building

42
00:03:59,480 --> 00:04:05,320
an app, there's so much you need. You're eventually codable, all that stuff. You need foundation.

43
00:04:05,320 --> 00:04:10,840
that's almost unavoidable. But it is a trade-off, you know, not every environment is the same,

44
00:04:10,840 --> 00:04:16,600
not every system is the same. For some people it's a natural thing to pull in, for others it's

45
00:04:16,600 --> 00:04:23,160
the last thing they want to touch. Yeah, it's a complicated subject to talk about because

46
00:04:23,160 --> 00:04:29,400
you don't want to, or certainly I don't want to ever upset anyone if I talk about somebody's

47
00:04:30,360 --> 00:04:40,040
open source work here and end up even implicitly saying, "Well, I wouldn't use it," then I don't

48
00:04:40,040 --> 00:04:44,840
want to upset anyone. That has the potential to upset someone, but I think that discussion is

49
00:04:44,840 --> 00:04:50,520
really valuable. Maybe we should just not call them recommendations because that implies some

50
00:04:50,520 --> 00:04:56,840
degree of experience or testing or usage of a package that you're saying, "Well, I've used this,

51
00:04:56,840 --> 00:05:02,680
and I therefore recommend it, which is certainly not what I do when we look through these packages.

52
00:05:02,680 --> 00:05:06,360
I skim the packages, I look at the ones that look interesting, and then we talk about them.

53
00:05:06,360 --> 00:05:12,600
Yeah, my process is a bit different, but I think that's also valuable that we don't do it the same

54
00:05:12,600 --> 00:05:16,680
way, because that leads us to pick different packages for different reasons. Are you saying

55
00:05:16,680 --> 00:05:24,920
you test every package you recommend? I actually do, yes. Just today, my pick today, I tried it,

56
00:05:24,920 --> 00:05:30,760
it. I found a bug. I reported it. It's already been fixed. There's a new release. But I feel like,

57
00:05:30,760 --> 00:05:37,000
I mean, that isn't always the case, but most of the time I pick packages that I'm really curious

58
00:05:37,000 --> 00:05:44,920
about. And part of that curiosity is trying it out. And that's why I often mention that stuff

59
00:05:44,920 --> 00:05:50,920
works in trying a playground because that's how I try it. That's the easiest way to try it. And

60
00:05:50,920 --> 00:05:55,180
And that's a huge, that's a huge help in trying them, but today's package that

61
00:05:55,180 --> 00:06:00,640
didn't work and I created a little package, which actually I realized I do in a

62
00:06:00,640 --> 00:06:05,300
complicated way, so what I normally do is create a directory in terminal, the Swift

63
00:06:05,300 --> 00:06:08,300
package, init, type executable, type library.

64
00:06:08,300 --> 00:06:11,640
Actually today I just did an Xcode project new package.

65
00:06:11,640 --> 00:06:12,660
It's so much easier.

66
00:06:12,660 --> 00:06:16,660
It sets everything up that I had to fiddle around with and it's

67
00:06:16,660 --> 00:06:18,360
immediately there in Xcode.

68
00:06:18,360 --> 00:06:25,360
Sometimes you have these Jordan paths, you keep going down and you never reevaluate what you're actually doing.

69
00:06:25,360 --> 00:06:33,360
But yes, I often do try it because I'm interested in those aspects of it.

70
00:06:33,360 --> 00:06:36,360
How does it actually work? And that's later on.

71
00:06:36,360 --> 00:06:40,360
That's actually a big part of what I want to highlight in that package.

72
00:06:40,360 --> 00:06:43,360
How does that actually work? I was really curious about that.

73
00:06:43,360 --> 00:06:48,000
And that's often the case, not always but often I want to see how it actually

74
00:06:48,000 --> 00:06:54,560
works in practice. Well now you're making me feel terrible and like an amateur.

75
00:06:54,560 --> 00:06:57,840
Which is exactly why I brought it up.

76
00:06:57,840 --> 00:07:02,840
I'm not saying, although I did notice that halfway through your thing that you

77
00:07:02,840 --> 00:07:06,240
said at the beginning you said I test all packages and then halfway through it

78
00:07:06,240 --> 00:07:15,020
switched it off. And I'm not saying that I don't test any packages but it's

79
00:07:15,020 --> 00:07:19,380
certainly, in fact I can give you a little preview, none of my packages that

80
00:07:19,380 --> 00:07:25,320
I'm going to talk about today I haven't tested any of them. Shame on you.

81
00:07:25,320 --> 00:07:31,200
Shame on me, absolutely. Well I think the ones that I don't test explicitly are

82
00:07:31,200 --> 00:07:37,380
often ones I have used in the past. I'd have to check. I mean, I'm sure there's been one

83
00:07:37,380 --> 00:07:42,000
or the other where I picked it for other reasons and I didn't actually run it, but...

84
00:07:42,000 --> 00:07:46,320
You get a gold star then I will get one printed and send to you.

85
00:07:46,320 --> 00:07:49,800
Oh, excellent. Excellent. What material is it going to be? Is it like valuable metal

86
00:07:49,800 --> 00:07:53,800
or something? Is it an Apple-like trophy?

87
00:07:53,800 --> 00:07:57,240
Oh, Apple-like. Yeah. Okay. We'll give you one of those little pens that Apple...

88
00:07:57,240 --> 00:08:01,160
Little, there we have it. Little, little is the value of my work.

89
00:08:01,160 --> 00:08:07,800
Right. But I think that's interesting though. I think that's definitely an interesting

90
00:08:07,800 --> 00:08:16,120
discussion to have about what would be alternative labels for instead of recommendations, highlights.

91
00:08:16,120 --> 00:08:24,280
Yeah. We've been talking about this with that pull request and the word that we've settled on there,

92
00:08:25,480 --> 00:08:27,480
which I quite like is Showcase.

93
00:08:27,480 --> 00:08:28,400
- Oh, right, yeah.

94
00:08:28,400 --> 00:08:29,880
Yeah, it's a show, yeah, that's good.

95
00:08:29,880 --> 00:08:30,920
I think that's really good

96
00:08:30,920 --> 00:08:33,960
because that implies it doesn't have to be ready.

97
00:08:33,960 --> 00:08:37,780
A showcase is often a prototype or a proof of concept

98
00:08:37,780 --> 00:08:39,320
or just something interesting.

99
00:08:39,320 --> 00:08:40,900
I think that's good, yeah.

100
00:08:40,900 --> 00:08:42,160
- It can be a preview.

101
00:08:42,160 --> 00:08:45,080
It can be, yeah, it's like here is a selection of things

102
00:08:45,080 --> 00:08:45,920
that might be interesting.

103
00:08:45,920 --> 00:08:47,600
- Yeah, no, I like that.

104
00:08:47,600 --> 00:08:49,800
Yeah, I hadn't actually,

105
00:08:49,800 --> 00:08:53,000
didn't remember what the final version actually was, yeah.

106
00:08:53,000 --> 00:08:57,000
And we've also been talking this week about a blog post, right?

107
00:08:57,000 --> 00:08:58,000
Yes, we have.

108
00:08:58,000 --> 00:09:00,600
And that's a really interesting blog post that we came across.

109
00:09:00,600 --> 00:09:04,320
It's called "Worrying about the NPM ecosystem."

110
00:09:04,320 --> 00:09:07,080
And it's a blog post by Sam Bleckley.

111
00:09:07,080 --> 00:09:11,080
It's actually quite, well, old in internet terms.

112
00:09:11,080 --> 00:09:15,400
So this is three years old from June 29, 2020.

113
00:09:15,400 --> 00:09:19,640
And this is really interesting for us in particular,

114
00:09:19,640 --> 00:09:26,120
working on the Swift ecosystem and creating a package index on the ecosystem.

115
00:09:26,120 --> 00:09:32,440
Because what Sam has done is analyze the NPM ecosystem through the lens of, of

116
00:09:32,440 --> 00:09:37,240
what packages there are, you know, statistics of the package index.

117
00:09:37,240 --> 00:09:38,400
And that's really interesting.

118
00:09:38,400 --> 00:09:42,960
I mean, obviously there are many things that are different between NPM and

119
00:09:42,960 --> 00:09:48,200
Swift, size being probably the most critical part of it.

120
00:09:49,360 --> 00:09:52,280
- Well, it did strike me actually as,

121
00:09:52,280 --> 00:09:54,820
it did strike me as I was reading through it again

122
00:09:54,820 --> 00:09:56,980
before today's recording.

123
00:09:56,980 --> 00:10:00,560
One of the, well, so first of all, actually,

124
00:10:00,560 --> 00:10:04,560
I think it's really nice to see somebody step back

125
00:10:04,560 --> 00:10:08,320
and look at a package ecosystem like this for the long term.

126
00:10:08,320 --> 00:10:11,560
And we've got lots of history to look back on.

127
00:10:11,560 --> 00:10:16,960
This is, the Swift package ecosystem is obviously something

128
00:10:16,960 --> 00:10:20,580
that we're both very intimately connected with

129
00:10:20,580 --> 00:10:21,780
and passionate about,

130
00:10:21,780 --> 00:10:25,500
but there have been a great many package ecosystems

131
00:10:25,500 --> 00:10:28,520
to learn from, NPM being one, of course,

132
00:10:28,520 --> 00:10:30,180
but even back before then, CPAN

133
00:10:30,180 --> 00:10:33,400
and lots and lots of package ecosystems.

134
00:10:33,400 --> 00:10:36,820
And it's really nice to see somebody taking a long-term look

135
00:10:36,820 --> 00:10:38,540
at like, well, what are the problems?

136
00:10:38,540 --> 00:10:41,980
How is the reality of this ecosystem

137
00:10:41,980 --> 00:10:43,920
compared to an expectation?

138
00:10:45,340 --> 00:10:50,560
did strike me as I was rereading it that maybe we should put a limit on the

139
00:10:50,560 --> 00:10:53,860
number of packages in the package ecosystem. So you know once that last

140
00:10:53,860 --> 00:10:58,240
once that fifty thousandth package is in that's it we're full. Yeah some old ones

141
00:10:58,240 --> 00:11:04,360
need to go. That's right yeah something it's not that that's it can never change

142
00:11:04,360 --> 00:11:08,980
and I'm not really being serious about this but but there is actually there is

143
00:11:08,980 --> 00:11:15,400
actually an interesting point to be at least considered of like, is there a

144
00:11:15,400 --> 00:11:19,780
point where a package ecosystem, once it goes over a certain point, these problems

145
00:11:19,780 --> 00:11:26,480
are unavoidable? I think so to some degree, but also there's inevitably a

146
00:11:26,480 --> 00:11:32,040
layer of cruft that'll accumulate over time. I mean we see this already, right,

147
00:11:32,040 --> 00:11:36,340
there are packages that are effectively unmaintained and have been unmaintained

148
00:11:36,340 --> 00:11:37,540
for years and years and years.

149
00:11:37,540 --> 00:11:41,940
They probably don't even compile on any, on any of the versions that we test,

150
00:11:41,940 --> 00:11:44,940
you know, they stopped with Swift 4.2 or something like that.

151
00:11:44,940 --> 00:11:50,660
I'm sure there are some, um, that we just ended up with and, you know, there's,

152
00:11:50,660 --> 00:11:55,940
there's no process by which we would go through and drop them.

153
00:11:55,940 --> 00:11:58,660
So we carry them forward probably forever.

154
00:11:58,660 --> 00:12:03,660
I mean, unless we decide at some point, right, this, this isn't passing any, any

155
00:12:03,700 --> 00:12:08,200
any compatibility checks never has or hasn't in the last X years.

156
00:12:08,200 --> 00:12:09,580
Is that a reason to drop it?

157
00:12:09,580 --> 00:12:10,320
I don't know.

158
00:12:10,320 --> 00:12:12,920
Is it who's what's what's the

159
00:12:12,920 --> 00:12:17,740
it's a good question that I don't really have a good answer for, but also we're in

160
00:12:17,740 --> 00:12:23,180
a actually a much better position than we really should be because there was a point

161
00:12:23,180 --> 00:12:25,580
I can't remember which Swift Swift version it was.

162
00:12:25,580 --> 00:12:30,360
There was a point where we just had to say that anything, I think it was anything

163
00:12:30,360 --> 00:12:32,840
three and below just had to go.

164
00:12:32,840 --> 00:12:35,980
Like even though there was package manager support

165
00:12:35,980 --> 00:12:39,420
for those, they were so old and it just didn't work anymore.

166
00:12:39,420 --> 00:12:42,940
So we kind of had a reset around Swift 4, I think.

167
00:12:42,940 --> 00:12:45,280
- I believe package dump failed to work

168
00:12:45,280 --> 00:12:47,880
on very old packages, yes, or something like that.

169
00:12:47,880 --> 00:12:51,820
And package dump really is central to how we gather

170
00:12:51,820 --> 00:12:55,220
the very basic metadata for a package.

171
00:12:55,220 --> 00:12:59,580
So if that fails, there's really very little to glean

172
00:12:59,580 --> 00:13:02,320
from a package, yeah, that might have been the reason.

173
00:13:02,320 --> 00:13:04,540
And so we had that reset and you're right

174
00:13:04,540 --> 00:13:06,100
that there are definitely packages in there

175
00:13:06,100 --> 00:13:08,100
that are so old that they don't compile

176
00:13:08,100 --> 00:13:10,060
on any of the versions that we test with

177
00:13:10,060 --> 00:13:12,900
and will probably never be updated again.

178
00:13:12,900 --> 00:13:14,900
- Yeah, and what's to happen with them?

179
00:13:14,900 --> 00:13:19,900
And you can imagine NPM is going to have a lot of that.

180
00:13:19,900 --> 00:13:22,260
How old is NPM?

181
00:13:22,260 --> 00:13:23,780
- Tens of thousands, yeah.

182
00:13:23,780 --> 00:13:28,540
Oh, NPM is, I don't know, 10, 15 years old.

183
00:13:28,540 --> 00:13:34,300
I mean, so in, in many regards, it's a glimpse of the future of

184
00:13:34,300 --> 00:13:35,780
the Swift package ecosystem.

185
00:13:35,780 --> 00:13:41,000
To some degree, I'm not sure size wise it's ever going to approach anything like it.

186
00:13:41,000 --> 00:13:46,660
We should mention like in the blog post, Sam lists 1.3 million packages in the

187
00:13:46,660 --> 00:13:51,720
NPM ecosystem, which is obviously more than two orders of magnitude, more than

188
00:13:52,500 --> 00:14:00,340
we track right now, which is 6,000 packages and a few. I guess we're also not tracking all of them.

189
00:14:00,340 --> 00:14:04,340
I mean, clearly we're not because those are just the open source ones, which is also true for NPM.

190
00:14:04,340 --> 00:14:12,020
But we also are probably much less established as the source where everyone goes to register

191
00:14:12,020 --> 00:14:18,500
the new packages. That's probably more true for NPM than it is for Swift package index.

192
00:14:20,340 --> 00:14:22,460
So that's certainly a difference.

193
00:14:22,460 --> 00:14:25,180
I mean, the size is just, I mean, imagine two orders of

194
00:14:25,180 --> 00:14:26,480
magnitude, what that changes.

195
00:14:26,480 --> 00:14:32,440
Um, and there are some other interesting aspects that he lists that he looked at

196
00:14:32,440 --> 00:14:34,160
that I found really quite surprising.

197
00:14:34,160 --> 00:14:42,960
So he looked at a, um, a thing, circular dependencies of packages, and that

198
00:14:42,960 --> 00:14:46,120
is something I did not really expect.

199
00:14:46,120 --> 00:14:51,120
So there are 1,700 packages that are directly dependent

200
00:14:51,120 --> 00:14:53,960
on themselves.

201
00:14:53,960 --> 00:14:55,040
- Yes.

202
00:14:55,040 --> 00:14:58,480
- Which I can't quite grasp how that works.

203
00:14:58,480 --> 00:15:03,480
- Well, he even says in his post, he says,

204
00:15:03,480 --> 00:15:08,200
yeah, they depend directly on themselves,

205
00:15:08,200 --> 00:15:10,480
either perfectly circularly or a different version

206
00:15:10,480 --> 00:15:11,600
of the same package.

207
00:15:11,600 --> 00:15:13,720
I have no explanation for that.

208
00:15:13,720 --> 00:15:16,020
- So the other example I can understand

209
00:15:16,020 --> 00:15:23,700
like 2,500 packages depend on themselves via two steps. And he gives an example that is quite,

210
00:15:23,700 --> 00:15:27,380
well, it's still strange, but at least it makes a little more sense how it could happen.

211
00:15:27,380 --> 00:15:33,300
There's Babel Core that depends on Babel register and that again depends on Babel Core.

212
00:15:33,300 --> 00:15:40,900
But given that they're all related to Babel, you'd think, I mean, how would you build a dependency

213
00:15:40,900 --> 00:15:45,700
tree where that can actually happen? I found that really strange. I wonder if there's something

214
00:15:45,700 --> 00:15:53,540
particular about NPM that makes that possible. So we should say that the blog post is also

215
00:15:53,540 --> 00:16:01,780
interesting for us because we want to do some of the same analysis for the Swift ecosystem soon.

216
00:16:01,780 --> 00:16:05,780
We're not in a position right now to do it because we're not actually gathering all the

217
00:16:05,780 --> 00:16:11,060
underlying information yet that we would be able to make that same analysis. But I'm really curious

218
00:16:11,860 --> 00:16:18,300
that can actually happen. I think part of this is

219
00:16:18,300 --> 00:16:23,420
is actually a little bit specific to JavaScript the language. We talked about

220
00:16:23,420 --> 00:16:28,940
Foundation earlier and JavaScript is a very very lightweight language and

221
00:16:28,940 --> 00:16:33,020
doesn't have anything like Foundation and so yeah part of the reason that are

222
00:16:33,020 --> 00:16:38,300
1.3 million packages is that a hundred people have all tried to solve all the

223
00:16:38,300 --> 00:16:41,220
basic problems and they've all put a package out for all the basic problems

224
00:16:41,220 --> 00:16:47,820
And those packages get deeply, deeply ingrained in those dependency

225
00:16:47,820 --> 00:16:53,980
graphs. And I think that's a lot of these circular references are caused at least

226
00:16:53,980 --> 00:16:59,100
in part by that problem. Yeah, that's actually in one of my first notes about

227
00:16:59,100 --> 00:17:07,220
what are potential lessons. I think that's really it because a lot of the

228
00:17:07,220 --> 00:17:13,100
analysis that Sam is doing is, you know, highlighting his surprise at how many,

229
00:17:13,100 --> 00:17:17,060
how deep the dependency trees are and how wide they are.

230
00:17:17,060 --> 00:17:19,700
So how many dependencies get pulled in?

231
00:17:19,700 --> 00:17:26,740
There's, there's, um, many packages that have 250 dependencies and no, actually

232
00:17:26,740 --> 00:17:29,060
2,500 dependencies is the maximum.

233
00:17:29,060 --> 00:17:35,100
And, and I think, uh, 2,500, 2,500.

234
00:17:35,100 --> 00:17:35,620
Yes.

235
00:17:35,620 --> 00:17:36,100
Yeah.

236
00:17:36,100 --> 00:17:36,460
Sorry.

237
00:17:36,460 --> 00:17:40,900
I was quoting from Crates, from Rust comparison.

238
00:17:40,900 --> 00:17:46,140
So there's very, very, very, very deep dependency trees.

239
00:17:46,140 --> 00:17:49,820
And I thought about how or why that is.

240
00:17:49,820 --> 00:17:51,460
And I think you're exactly right.

241
00:17:51,460 --> 00:17:57,180
That's why what I thought as well, a strong and good standard library probably

242
00:17:57,180 --> 00:18:04,180
trims that tree by a lot because it literally prunes the tree of all these

243
00:18:04,180 --> 00:18:08,520
packages that other ecosystems don't need.

244
00:18:08,520 --> 00:18:13,640
And I think the other one is UI libraries that are practically always

245
00:18:13,640 --> 00:18:17,260
OS libraries that aren't part of the Swift ecosystem per se.

246
00:18:17,260 --> 00:18:23,060
Like, like we're not tracking Swift UI as a package that has sub dependencies

247
00:18:23,060 --> 00:18:26,020
or anything like it, UIKit equally.

248
00:18:26,020 --> 00:18:31,320
That that's all platform libraries, which NPM really doesn't have, right?

249
00:18:31,320 --> 00:18:37,000
any, any web framework and there are lots of them needs to ship all this as a

250
00:18:37,000 --> 00:18:40,200
dependency, right, that you then pull in and use.

251
00:18:40,200 --> 00:18:46,700
I think an area where you see the same issue is web development.

252
00:18:46,700 --> 00:18:48,800
And, and we are actually the, that's interesting.

253
00:18:48,800 --> 00:18:53,320
The SPI server package is the package with the most dependencies and it's 56.

254
00:18:53,320 --> 00:18:59,220
Uh, and that's mostly, um, the vapor and friends because that's a very rich

255
00:18:59,220 --> 00:19:08,180
framework with lots of dependencies. Vapor has everything nicely broken down into individual

256
00:19:08,180 --> 00:19:15,140
things. If you use a database, you by nature use the foundational Postgres library, then

257
00:19:15,140 --> 00:19:21,060
I think there's even a separate one for the Neo stuff and then there's a fluent layer.

258
00:19:21,060 --> 00:19:27,220
I think so I have at least three, maybe four database libraries that you pull in when you

259
00:19:27,220 --> 00:19:29,140
use Postgres as the database in vapor.

260
00:19:29,140 --> 00:19:33,040
And that is the case for quite a number of other packages.

261
00:19:33,040 --> 00:19:37,360
I should also add in our defense, those 56 includes def dependencies.

262
00:19:37,360 --> 00:19:44,120
So it's not, it's not entirely that, uh, that bad in the, in the shipping binary.

263
00:19:44,120 --> 00:19:52,280
But I think we are sort of an example of a more typical NPM package in that sense.

264
00:19:52,520 --> 00:19:57,480
in that a lot of stuff isn't OS library stuff.

265
00:19:57,480 --> 00:20:01,960
I mean, I don't think, I'm not even sure the Postgres,

266
00:20:01,960 --> 00:20:04,180
I think the Postgres stuff might need libraries.

267
00:20:04,180 --> 00:20:06,560
I need to check what we actually need in our Docker image.

268
00:20:06,560 --> 00:20:11,560
But a lot of the stuff we build to run is very foundational

269
00:20:11,560 --> 00:20:14,560
in the sense there's very little that the OS

270
00:20:14,560 --> 00:20:17,960
actually provides as underlying libraries that get used.

271
00:20:17,960 --> 00:20:20,920
A lot of it is just straight up code

272
00:20:20,920 --> 00:20:25,680
that is built on purpose to provide the functionality itself.

273
00:20:25,680 --> 00:20:28,720
What I also found interesting,

274
00:20:28,720 --> 00:20:30,720
and I'm not sure if you've followed that link,

275
00:20:30,720 --> 00:20:33,860
there was a follow-up post where Sam looks

276
00:20:33,860 --> 00:20:36,720
at the same analysis for Rust,

277
00:20:36,720 --> 00:20:38,000
and that was quite interesting.

278
00:20:38,000 --> 00:20:40,160
Did you see that one as well?

279
00:20:40,160 --> 00:20:41,120
- As I skimmed that one,

280
00:20:41,120 --> 00:20:42,720
but I didn't read it in full, full depth.

281
00:20:42,720 --> 00:20:45,540
- Yeah, it's a bit interesting and particular for our case,

282
00:20:45,540 --> 00:20:47,300
because it's sort of in between.

283
00:20:47,300 --> 00:20:50,480
So Rust at the time, this was July, 2020,

284
00:20:50,480 --> 00:20:54,400
had 50,000 packages. So we're just an order of magnitude away now from us.

285
00:20:54,400 --> 00:21:01,200
It also includes cycles, dependency cycles, so that might indicate that it's just something

286
00:21:01,200 --> 00:21:04,640
that happens. CB; This is the ghost of Christmas future.

287
00:21:04,640 --> 00:21:12,400
MG; Yeah. And a lot fewer dependencies. And I think that is to our point that a strong

288
00:21:12,400 --> 00:21:19,360
standard library probably prunes that tree quite a bit. And he mentioned that, Sam,

289
00:21:19,360 --> 00:21:25,600
It's very likely due to a few very popular packages with few dependencies that early on

290
00:21:25,600 --> 00:21:32,240
caught on and were crystallization points for all the work.

291
00:21:32,240 --> 00:21:39,120
I think Swift is in a good position, especially with many of the packages in backend development

292
00:21:39,120 --> 00:21:45,040
and Swift server group, SSWG packages. Swift Neo, for instance, is taking care of a lot of the

293
00:21:46,960 --> 00:21:57,520
plumbing in terms of networking, where Swift benefits from having packages in lots of areas,

294
00:21:57,520 --> 00:22:04,320
but not multiple different implementations. So there's typically one good library that does it,

295
00:22:04,320 --> 00:22:10,400
and all the effort to maintain it is focused on that one library. And then it gets used a lot and

296
00:22:10,400 --> 00:22:16,560
battle tested and sort of often they have good dependency trees in the sense that there are

297
00:22:16,560 --> 00:22:22,400
few dependencies that they themselves have, or it's the same ones again and again. So I think all

298
00:22:22,400 --> 00:22:30,320
of this helps a bit in keeping this growth in check. But obviously it's going to be interesting

299
00:22:30,320 --> 00:22:34,400
to see if that changes and how that changes as the index ecosystem grows.

300
00:22:34,400 --> 00:22:37,120
Stay Forever It will certainly be something we have to keep

301
00:22:37,120 --> 00:22:44,400
an eye on. While you were just talking, I had a suspicion and I just double checked it.

302
00:22:45,840 --> 00:22:52,480
So we have actually two dependency trees in SPI Server. As you say, our Swift dependency tree is

303
00:22:52,480 --> 00:22:57,840
quite large because of vapor in the database dependencies that we bring in through that.

304
00:22:57,840 --> 00:23:08,320
We also have a JavaScript dependency tree because we have a front-end process and that has its own

305
00:23:08,320 --> 00:23:15,680
build process and we use the standard JavaScript dependency manager that we've been talking

306
00:23:15,680 --> 00:23:22,320
about today. And I did pick our dependencies very carefully with the front end and I've

307
00:23:22,320 --> 00:23:31,280
just double checked. We have three top level dependencies and those dependencies have

308
00:23:31,280 --> 00:23:37,920
zero second level dependencies. Oh nice, I was sort of racing myself for a big number there.

309
00:23:37,920 --> 00:23:44,080
No, so it's actually we're the opposite, we're living in opposite world.

310
00:23:45,440 --> 00:23:53,120
Wow. We do have, so I should just mention, we do have a much bigger results file because

311
00:23:53,120 --> 00:24:00,240
in production we only have three dependencies but our build environment gets into that whole messy

312
00:24:00,240 --> 00:24:08,000
NPM tree. So we have some development dependencies and we have some production dependencies and our

313
00:24:08,000 --> 00:24:12,160
development dependencies are much messier than our production ones. Right, right. Yeah, I need to

314
00:24:12,160 --> 00:24:17,200
to check, I'm actually curious how many Swift production dependencies we actually have.

315
00:24:17,200 --> 00:24:23,120
I mean, it's not going to be a lot because we have snapshot testing and that sort of

316
00:24:23,120 --> 00:24:28,320
stuff, but there aren't. I can't think of a lot of specific test dependencies that we're

317
00:24:28,320 --> 00:24:29,320
pulling in.

318
00:24:29,320 --> 00:24:35,400
Toby

319
00:24:35,400 --> 00:24:38,840
Obviously we'll put it in the show notes, but I would thoroughly recommend reading this

320
00:24:38,840 --> 00:24:42,120
blog post if you have even the slightest interest in what we've been talking

321
00:24:42,120 --> 00:24:46,120
about because it's fascinating. Well written, it'll make you laugh a couple of

322
00:24:46,120 --> 00:24:50,080
times. It's a great blog post. Yeah, really good and I'm curious. So we'll

323
00:24:50,080 --> 00:24:56,880
definitely endeavor to produce the same numbers, same statistics for Swift

324
00:24:56,880 --> 00:25:00,800
Package Index. We're just not in a position to do that yet because we're

325
00:25:00,800 --> 00:25:05,560
not tracking the full dependency trees but it is coming. Well I think

326
00:25:05,560 --> 00:25:10,200
it's also good that we're thinking about this while the package ecosystem is this

327
00:25:10,200 --> 00:25:16,920
size. Yeah. Because I think one of the ways that you stop it happening is by

328
00:25:16,920 --> 00:25:23,080
showing it happen. Well the question is can you really? I mean how?

329
00:25:23,080 --> 00:25:27,160
Like we were saying earlier I mean I do believe there probably is a size at

330
00:25:27,160 --> 00:25:33,080
which this becomes inevitable but certainly there are things you know I

331
00:25:33,080 --> 00:25:40,360
I think we're in pretty good shape to delay that inevitability at least a little bit.

332
00:25:40,360 --> 00:25:42,760
Let's see how it goes.

333
00:25:42,760 --> 00:25:45,700
So should we showcase some packages?

334
00:25:45,700 --> 00:25:50,680
Let's showcase some packages.

335
00:25:50,680 --> 00:25:52,160
You can kick us off this week.

336
00:25:52,160 --> 00:25:53,440
All right, I'll kick us off.

337
00:25:53,440 --> 00:25:58,500
So my first package is actually two packages in a trench coat.

338
00:25:58,500 --> 00:26:02,160
And I do suspect one of them might appear.

339
00:26:02,160 --> 00:26:06,640
depend on each other, right?

340
00:26:06,640 --> 00:26:08,080
Actually they do, but it's

341
00:26:08,080 --> 00:26:10,080
unidirectional.

342
00:26:10,080 --> 00:26:12,080
I suspect they might also be in iOS Dev

343
00:26:12,080 --> 00:26:14,960
Weekly later this week,

344
00:26:14,960 --> 00:26:15,600
but I'm calling first dibs. And it's

345
00:26:15,600 --> 00:26:18,640
from our

346
00:26:18,640 --> 00:26:19,520
good friends Point Free. It's Swift

347
00:26:19,520 --> 00:26:22,880
macro testing

348
00:26:22,880 --> 00:26:25,120
and Swift snapshot testing.

349
00:26:25,120 --> 00:26:26,880
Disclaimer, Point Free Co. are a sponsor of

350
00:26:26,880 --> 00:26:29,920
the Swift Package Index,

351
00:26:29,920 --> 00:26:31,120
but I just can't resist. I'll

352
00:26:29,920 --> 00:26:32,000
always recommend them. They're good packages, Bront.

353
00:26:32,000 --> 00:26:37,920
I saw both of these in the RSS feeds and as soon as I saw them, I just skipped over them

354
00:26:37,920 --> 00:26:45,280
because I needed to pick them up. You left them for me, nice. Yeah, they're really great. What

355
00:26:45,280 --> 00:26:52,560
I love about them is that they are useful, but also useful in interesting new ways. And they

356
00:26:52,560 --> 00:26:58,480
really build on top of each other. So, right, let me explain what they do. So, the first one,

357
00:26:58,480 --> 00:27:07,120
Swift macro testing is about macros which is a new feature in Swift 5.9 and Swift 5.9 obviously comes

358
00:27:07,120 --> 00:27:12,960
with the ability to implement macros. It also has some facilities to actually test your

359
00:27:12,960 --> 00:27:21,920
implementation and what it does effectively is it adds an assert macro expansion and then you can

360
00:27:21,920 --> 00:27:27,840
inline, you know, have a literal string that is your expectation of what it should look like and

361
00:27:27,840 --> 00:27:34,480
the macro definition itself and then it compares that the macro expands into what you wanted it to

362
00:27:34,480 --> 00:27:44,400
expand to. And the Swift macro testing package expands on that, no pun intended,

363
00:27:44,400 --> 00:27:50,800
by giving you more capabilities because the assert macro expansion test, while nice,

364
00:27:50,800 --> 00:27:57,520
is fairly basic. So it only allows you to compare the strings and you sort of have to manage that

365
00:27:57,520 --> 00:28:06,700
yourself, what this, their, uh, assert does is it actually puts the expanded

366
00:28:06,700 --> 00:28:09,700
expectation into your source code in line.

367
00:28:09,700 --> 00:28:14,760
So you don't need to prepare something and then copy paste it in.

368
00:28:14,760 --> 00:28:19,700
You, you write an assert with the macro definition in it, as you call it.

369
00:28:19,700 --> 00:28:21,580
Then you run the test.

370
00:28:21,580 --> 00:28:24,780
You know, if you know how snapshot tests work, you normally run the

371
00:28:24,780 --> 00:28:26,500
test and then it writes out a file.

372
00:28:26,500 --> 00:28:31,400
And then you confirm, yeah, the file looks like, like, you know, as I expect.

373
00:28:31,400 --> 00:28:34,900
And then when you run run it the next time and the file is there, it just compares the

374
00:28:34,900 --> 00:28:36,400
next snapshot against the file.

375
00:28:36,400 --> 00:28:37,100
Right.

376
00:28:37,100 --> 00:28:43,600
What it does here is it, it is not file-based, but it actually places the expansion into

377
00:28:43,600 --> 00:28:48,500
your source code in Xcode and it uses Swift syntax under the hood to understand your

378
00:28:48,500 --> 00:28:53,100
test structure and does effectively a live live source edit of Xcode.

379
00:28:53,100 --> 00:28:57,860
source edit of Xcode, so it as if you were typing out the expectation itself.

380
00:28:57,860 --> 00:29:01,200
So that's quite nice because you don't need to fiddle with the expectation.

381
00:29:01,200 --> 00:29:04,900
And obviously, once you've done it the first time, it'll then, if it's different,

382
00:29:04,900 --> 00:29:06,260
it'll highlight a difference, right?

383
00:29:06,260 --> 00:29:08,400
It only does that if there's nothing there yet.

384
00:29:08,400 --> 00:29:12,700
So this is your first capture of the difference.

385
00:29:12,700 --> 00:29:18,100
And it goes beyond that because it doesn't just snapshot your expansion,

386
00:29:18,100 --> 00:29:22,460
it also snapshots diagnostics and fixits, which is something that the built-in

387
00:29:22,460 --> 00:29:24,780
certain macro expansion doesn't do.

388
00:29:24,780 --> 00:29:27,540
So this is only for testing the expansion itself

389
00:29:27,540 --> 00:29:32,540
and Point Free Co's tool also allows you to test

390
00:29:32,540 --> 00:29:36,500
all the edge cases, like diagnostics when there's something

391
00:29:36,500 --> 00:29:40,820
wrong with your macro call or fix-its when you want to test

392
00:29:40,820 --> 00:29:42,860
what your suggestions are, how to fix issues

393
00:29:42,860 --> 00:29:43,980
with the macros.

394
00:29:43,980 --> 00:29:45,100
So that's quite nice.

395
00:29:45,100 --> 00:29:52,100
- So I think I did see the macro in the first place

396
00:29:52,100 --> 00:29:58,140
macro package fly pass, but I didn't look into it in much detail yet. Like I say, I

397
00:29:58,140 --> 00:30:04,340
knew you would take it. But what I did see was, I think, what you're about to talk about,

398
00:30:04,340 --> 00:30:09,500
which is the other side of this, which is an enhancement to Swift snapshot testing,

399
00:30:09,500 --> 00:30:16,580
which added support for inline testing this week. And even now I understand why they added

400
00:30:16,580 --> 00:30:21,420
that. But that feature, even on its own, is invaluable. We use snapshot

401
00:30:21,420 --> 00:30:27,500
testing in a couple of different ways. We have HTML snapshot testing, which takes

402
00:30:27,500 --> 00:30:33,300
fully rendered HTML files of hundreds and hundreds of lines of HTML

403
00:30:33,300 --> 00:30:38,820
and snapshots those. And those obviously suit file-based snapshot testing really

404
00:30:38,820 --> 00:30:43,140
well. But then we also have a whole load of other uses of snapshot testing. Like

405
00:30:43,140 --> 00:30:48,180
snapshot tests and SQL queries and we snapshot test even just a bit of like

406
00:30:48,180 --> 00:30:52,740
JSON like in a fragment of JSON somewhere or even just a string like we

407
00:30:52,740 --> 00:30:56,340
you know we render a date or something maybe we'll just snapshot test that and

408
00:30:56,340 --> 00:31:01,780
currently all those live also on disk which is it's okay it's not terrible but

409
00:31:01,780 --> 00:31:06,940
I really liked the idea of being able to have those snapshots just in line in the

410
00:31:06,940 --> 00:31:11,700
in the code and and now finding out that they will automatically update if you if

411
00:31:11,700 --> 00:31:15,100
if you ask them to, that's just the icing on the cake.

412
00:31:15,100 --> 00:31:18,100
- Yeah, that's really nice because you always have to

413
00:31:18,100 --> 00:31:19,600
sort of make the decision.

414
00:31:19,600 --> 00:31:22,860
I mean, it still doesn't make sense to do an inline snapshot

415
00:31:22,860 --> 00:31:25,060
for hundreds of lines of output.

416
00:31:25,060 --> 00:31:27,460
That's clearly something you want to stick in a file.

417
00:31:27,460 --> 00:31:28,300
- Of course.

418
00:31:28,300 --> 00:31:31,740
- But many smaller ones are just really nice to have inline

419
00:31:31,740 --> 00:31:34,260
because you don't need to go hunting through the file system

420
00:31:34,260 --> 00:31:35,940
to actually look at the snippet, right?

421
00:31:35,940 --> 00:31:39,180
It's really nice if a three-liner, four-liner

422
00:31:39,180 --> 00:31:40,980
is actually inline there in the test.

423
00:31:40,980 --> 00:31:44,980
And that's this amazing new feature of the inline testing.

424
00:31:44,980 --> 00:31:47,380
Not only that you can have it in there,

425
00:31:47,380 --> 00:31:50,400
but it actually automatically manages

426
00:31:50,400 --> 00:31:53,900
that representation inline and you just,

427
00:31:53,900 --> 00:31:55,800
effectively you just look at it,

428
00:31:55,800 --> 00:31:58,160
yeah, looks all right, run it.

429
00:31:58,160 --> 00:32:01,020
And then if it fails, it gives you the same message

430
00:32:01,020 --> 00:32:02,860
as if it was a file.

431
00:32:02,860 --> 00:32:05,460
And obviously also you can always see the diff

432
00:32:05,460 --> 00:32:10,460
in your source tree, even if you were to save it.

433
00:32:10,940 --> 00:32:14,700
That's great. It sounds like a real, um, a real, uh, enhancement to, to,

434
00:32:14,700 --> 00:32:16,260
to the Snapchat testing library.

435
00:32:16,260 --> 00:32:20,700
Really great couple of packages, um, and, and really nice, um, combined,

436
00:32:20,700 --> 00:32:24,100
um, yeah, release of those.

437
00:32:24,100 --> 00:32:29,980
So my first, um, completely untested and, and experimented with package

438
00:32:29,980 --> 00:32:37,380
is, um, is, I mean, so, okay. So, so it's, the package is cloud's

439
00:32:37,380 --> 00:32:38,900
cloud kit sync monitor.

440
00:32:39,220 --> 00:32:41,060
So in order for me to have tested this,

441
00:32:41,060 --> 00:32:43,220
I would have had to set up a CloudKit project.

442
00:32:43,220 --> 00:32:46,340
And you know, there's a lot of testing in that.

443
00:32:46,340 --> 00:32:48,740
It's by Grant Gruninger,

444
00:32:48,740 --> 00:32:51,620
and it monitors the state

445
00:32:51,620 --> 00:32:54,980
of an NS Persistent CloudKit container

446
00:32:54,980 --> 00:32:56,380
synchronization process.

447
00:32:56,380 --> 00:32:59,460
So I think this,

448
00:32:59,460 --> 00:33:02,140
if it does what it says on the same,

449
00:33:02,140 --> 00:33:03,240
which I'm sure it does,

450
00:33:03,240 --> 00:33:06,540
I think this is a potential,

451
00:33:07,500 --> 00:33:11,540
a package that potentially every CloudKit application should include because one

452
00:33:11,540 --> 00:33:14,100
thing, one area where CloudKit is a little weak,

453
00:33:14,100 --> 00:33:18,420
certainly in the operating system and in also in applications that use it,

454
00:33:18,420 --> 00:33:23,580
is feedback on what's happening with CloudKit sync. Has it finished?

455
00:33:23,580 --> 00:33:25,820
Is it still going on? What's happening? Did it error?

456
00:33:25,820 --> 00:33:31,580
And this allows you to hook into all of the notifications sent out by the

457
00:33:31,580 --> 00:33:36,100
persistent CloudKit container and translate them into some published properties

458
00:33:36,100 --> 00:33:39,580
that you can then monitor in SwiftUI and update some UI

459
00:33:39,580 --> 00:33:44,580
or keep whatever tabs on it you would like in an easy way

460
00:33:44,580 --> 00:33:46,540
without having to subscribe

461
00:33:46,540 --> 00:33:48,620
to all those different notifications.

462
00:33:48,620 --> 00:33:52,980
And it doesn't come with any pre-built UI

463
00:33:52,980 --> 00:33:54,020
as I believe it shouldn't.

464
00:33:54,020 --> 00:33:56,560
I think that's something that you should,

465
00:33:56,560 --> 00:33:57,940
each application should determine

466
00:33:57,940 --> 00:34:02,500
how to surface this information if they choose to.

467
00:34:02,500 --> 00:34:05,460
But it does kind of tame all those notifications

468
00:34:05,460 --> 00:34:09,520
and give you a nice way to just take a look

469
00:34:09,520 --> 00:34:12,020
at what's happening with your sync state.

470
00:34:12,020 --> 00:34:13,400
It's got a great read me file.

471
00:34:13,400 --> 00:34:16,460
It's actually been in development for a couple of years,

472
00:34:16,460 --> 00:34:18,900
but I've not come across it before.

473
00:34:18,900 --> 00:34:19,740
- Nice.

474
00:34:19,740 --> 00:34:23,080
Yeah, I mean, that's super hard to test.

475
00:34:23,080 --> 00:34:24,440
Actually, as you were saying it,

476
00:34:24,440 --> 00:34:27,580
I realized I did not test the macro testing package.

477
00:34:27,580 --> 00:34:28,420
So there you go.

478
00:34:28,420 --> 00:34:29,860
It's immediately--

479
00:34:29,860 --> 00:34:32,460
- See, I knew it wasn't.

480
00:34:32,460 --> 00:34:36,900
I knew your virtue wasn't as complete as you claimed.

481
00:34:36,900 --> 00:34:39,520
- But snapshot testing I have, I've tried.

482
00:34:39,520 --> 00:34:42,580
- Well, we've all used snapshot testing.

483
00:34:42,580 --> 00:34:43,780
- All right, we all have.

484
00:34:43,780 --> 00:34:46,020
(laughing)

485
00:34:46,020 --> 00:34:54,720
Right, my second pick is called Lighter by Helge Hess.

486
00:34:54,720 --> 00:34:58,060
And this is a really interesting package.

487
00:34:58,060 --> 00:35:02,300
It's not new, I've known about it for a while,

488
00:35:02,300 --> 00:35:06,260
but there was a release in the last week

489
00:35:06,260 --> 00:35:08,260
or last couple of weeks.

490
00:35:08,260 --> 00:35:12,260
And this is the package I was alluding to earlier

491
00:35:12,260 --> 00:35:13,740
when I said I was curious

492
00:35:13,740 --> 00:35:15,640
about how it's actually implemented.

493
00:35:15,640 --> 00:35:19,100
So Lighter is a very interesting SQLite database

494
00:35:19,100 --> 00:35:20,220
access package.

495
00:35:20,220 --> 00:35:23,120
And this is probably an area where there are quite

496
00:35:23,120 --> 00:35:24,840
a few candidates in the package index

497
00:35:24,840 --> 00:35:27,120
that is well serviced.

498
00:35:27,120 --> 00:35:28,000
There's a rich field.

499
00:35:28,000 --> 00:35:31,860
Like for instance, there's GRDB by Gwen Del Roy.

500
00:35:31,860 --> 00:35:36,160
That's probably the most widely known and used representative of the package,

501
00:35:36,160 --> 00:35:39,720
of a SQLite database access package.

502
00:35:39,720 --> 00:35:45,260
But Lighter is really interesting in its approach and its use case, effectively.

503
00:35:45,260 --> 00:35:52,160
It is a package that source generates SQLite library bindings.

504
00:35:52,160 --> 00:35:53,720
And it can do that in two ways.

505
00:35:53,720 --> 00:35:59,960
One is just straight up a layer that directly interfaces with the C library.

506
00:35:59,960 --> 00:36:02,000
So it's dependency free what you get out of it.

507
00:36:02,000 --> 00:36:07,700
And the other one is a, it generates an additional layer on top, which is a lighter

508
00:36:07,700 --> 00:36:13,100
layer, so it gives you a nicer high level API to talk to your database.

509
00:36:13,100 --> 00:36:20,900
But what's really interesting is the, so the marketing, if I can call it that of the

510
00:36:20,900 --> 00:36:23,420
packages, it's, it's really, really fast.

511
00:36:23,460 --> 00:36:33,940
And it has a performance test suite where it calls some numbers that are quite remarkable.

512
00:36:33,940 --> 00:36:37,140
So in some of the tests, it's six times faster than GRDB.

513
00:36:37,140 --> 00:36:44,340
And it's three times faster than GRDB if GRDB is sort of manually tweaked,

514
00:36:44,340 --> 00:36:51,380
effectively by avoiding codable, which is apparently a very big price to pay there.

515
00:36:51,380 --> 00:36:56,740
So it is quite fast in the tests that Helge is running. But I was really curious about some of

516
00:36:56,740 --> 00:37:04,580
the things he's doing in his examples because he has an example how you filter on a query. So,

517
00:37:04,580 --> 00:37:10,500
you know, as you can imagine, you run a database, get me all the records from a table and filter,

518
00:37:10,500 --> 00:37:15,940
you know, like a typical where clause. But it's written like a Swift filter with a closure.

519
00:37:15,940 --> 00:37:24,660
you have, for instance, I loaded up a music, there's a Chinook, I think it's called a test

520
00:37:24,660 --> 00:37:30,340
SQLite database that you can download, which has sample data in it and has tracks like music tracks

521
00:37:30,340 --> 00:37:35,860
in it. And you do db.tracks.filter, and then you pass in a closure where you can apply

522
00:37:35,860 --> 00:37:45,060
a filter on the tracks individually, right? You do $0.length, like the track length,

523
00:37:45,060 --> 00:37:48,960
And then I queried for all the tracks that are longer than 300 seconds.

524
00:37:48,960 --> 00:37:53,100
And that runs, I mean, obviously with the number of tracks in it, I wasn't

525
00:37:53,100 --> 00:37:57,160
able to tell if it's fast or, or anything, but I did actually check how it's

526
00:37:57,160 --> 00:37:59,920
implemented and that was really interesting because what it does

527
00:37:59,920 --> 00:38:07,200
effectively, it binds the, the closure as a C function pointer into, to

528
00:38:07,200 --> 00:38:08,920
the, to the SQLite library.

529
00:38:08,920 --> 00:38:13,060
So the library actually runs your closure directly, like as a function

530
00:38:13,060 --> 00:38:14,920
in inside the database, you know?

531
00:38:14,920 --> 00:38:24,280
it's as if in a Postgres database you had shipped your code as an extension and then called into it.

532
00:38:24,280 --> 00:38:29,400
You had all this done ahead of time and then you were calling into it. It can actually do that with

533
00:38:29,400 --> 00:38:35,000
straight up Swift code. I was really surprised that that works. I mean, obviously there's some

534
00:38:35,000 --> 00:38:40,360
unsafe pointer stuff going on to make that work, but that explains how that interface works and

535
00:38:41,320 --> 00:38:47,160
how the claims can be made that this works without having to translate all sorts of variants of Swift

536
00:38:47,160 --> 00:38:52,200
code into where clauses, right? That's not happening. It's actually just executing the

537
00:38:52,200 --> 00:39:00,920
predicate directly in C in the library. And that's remarkable. So yeah, it's a really interesting

538
00:39:00,920 --> 00:39:07,240
package. I tried it out with the Chinook database works as advertised. It code generates. So there's

539
00:39:07,240 --> 00:39:13,400
a build plugin that comes with it that auto generates your database access layer. You

540
00:39:13,400 --> 00:39:18,280
give it an input database and it looks at the schema and pulls out all the stuff. And

541
00:39:18,280 --> 00:39:22,840
that worked fine for that database. Well, it worked fine actually. That's the thing

542
00:39:22,840 --> 00:39:30,120
I pointed out earlier. There was a formatting issue in the underlying database and that

543
00:39:30,120 --> 00:39:35,400
broke the generated code and Helga fixed that really quick. And that's the one thing I had

544
00:39:35,400 --> 00:39:41,720
in my notes when you adopt that sort of library that generates code, there's a slightly bigger

545
00:39:41,720 --> 00:39:48,280
risk that things might not go 100% if the code generation doesn't work right. So yeah, you have

546
00:39:48,280 --> 00:39:53,880
a bit of an extra risk there in your dependency. On the other hand, if you don't regenerate right,

547
00:39:53,880 --> 00:39:59,960
what you already have is going to keep working. So at least there's some safety there, but it's

548
00:39:59,960 --> 00:40:03,280
It's something to bear in mind for packages like this.

549
00:40:03,280 --> 00:40:05,440
But I believe if you need a really fast

550
00:40:05,440 --> 00:40:09,680
SQLite database access and you don't want to deal with

551
00:40:09,680 --> 00:40:12,320
the C aspects of the SQLite database,

552
00:40:12,320 --> 00:40:14,120
which is a database library,

553
00:40:14,120 --> 00:40:16,760
which is probably not something you want to be doing,

554
00:40:16,760 --> 00:40:18,740
this looks like a really great option.

555
00:40:18,740 --> 00:40:21,260
- That's great.

556
00:40:21,260 --> 00:40:24,280
And I like how in the description of the package,

557
00:40:24,280 --> 00:40:26,360
it ends with dependency free.

558
00:40:26,360 --> 00:40:28,400
So it says Swift APIs for SQLite,

559
00:40:28,400 --> 00:40:30,820
type safe down to the schema, very, very fast

560
00:40:30,820 --> 00:40:31,840
dependency free.

561
00:40:31,840 --> 00:40:33,800
I think, you know, the fact that it's made it

562
00:40:33,800 --> 00:40:36,520
into the description of the package is obviously,

563
00:40:36,520 --> 00:40:39,300
that's how important Helga is taking it there.

564
00:40:39,300 --> 00:40:42,200
Although I would argue it does have a dependency on SQLite.

565
00:40:42,200 --> 00:40:43,040
- On SQLite, yeah.

566
00:40:43,040 --> 00:40:45,300
(laughing)

567
00:40:45,300 --> 00:40:46,720
- But I think we'll forgive him.

568
00:40:46,720 --> 00:40:49,840
- Well, on Mac OS and iOS and everywhere,

569
00:40:49,840 --> 00:40:51,000
the library's there.

570
00:40:51,000 --> 00:40:53,600
It's probably only on Linux where you--

571
00:40:53,600 --> 00:40:57,000
- So then we get into defining how do you define

572
00:40:57,000 --> 00:40:57,840
the dependency?

573
00:40:57,840 --> 00:40:59,360
(laughing)

574
00:40:59,360 --> 00:41:00,200
- What's the dependency?

575
00:41:00,200 --> 00:41:02,640
- But let's not go down that route.

576
00:41:02,640 --> 00:41:04,140
- It depends.

577
00:41:04,140 --> 00:41:07,760
- Instead, we'll go back to my un-researched,

578
00:41:07,760 --> 00:41:09,000
un-tested list of packages.

579
00:41:09,000 --> 00:41:11,200
- You really gotta have one up, won't you?

580
00:41:11,200 --> 00:41:12,900
(laughing)

581
00:41:12,900 --> 00:41:14,900
- Well, I was gonna say, actually this one,

582
00:41:14,900 --> 00:41:16,760
I haven't tested this version of it,

583
00:41:16,760 --> 00:41:18,800
but I have used this package in the past.

584
00:41:18,800 --> 00:41:23,480
It is shipping in the iOS Dev jobs app,

585
00:41:23,480 --> 00:41:28,480
which uses SwiftUI Introspect by David Roman.

586
00:41:28,480 --> 00:41:34,440
And I have a feeling we've talked about this package

587
00:41:34,440 --> 00:41:37,200
on the podcast once before right at the very beginning,

588
00:41:37,200 --> 00:41:39,840
because I think I just started,

589
00:41:39,840 --> 00:41:41,640
I just finished using it in the app

590
00:41:41,640 --> 00:41:45,440
when we were looking for packages to talk about.

591
00:41:45,440 --> 00:41:46,760
And I think I talked about it then,

592
00:41:46,760 --> 00:41:48,840
but I'm gonna mention it deliberately again,

593
00:41:48,840 --> 00:41:53,060
because it's just hit a 1.0 milestone.

594
00:41:53,060 --> 00:41:55,200
which is always worth celebrating,

595
00:41:55,200 --> 00:41:59,620
especially for a package that is so good like this.

596
00:41:59,620 --> 00:42:03,800
What it does is it allows you to get at the underlying

597
00:42:03,800 --> 00:42:08,300
UI kit or app kit controls underneath a SwiftUI view

598
00:42:08,300 --> 00:42:14,060
in a safe way so that you can,

599
00:42:14,060 --> 00:42:17,080
if there is something that the SwiftUI view

600
00:42:17,080 --> 00:42:20,180
doesn't quite do, it means you don't have to completely

601
00:42:20,180 --> 00:42:22,100
throw that SwiftUI view away.

602
00:42:22,100 --> 00:42:25,840
You can, if it is based on a UI kit or app kit control

603
00:42:25,840 --> 00:42:28,660
behind the scenes, you can get access to that,

604
00:42:28,660 --> 00:42:31,160
modify whatever properties, call whatever methods

605
00:42:31,160 --> 00:42:33,340
you would like to on that object.

606
00:42:33,340 --> 00:42:37,680
And it does it in a safe way so that if the underlying

607
00:42:37,680 --> 00:42:39,920
implementation of SwiftUI changes,

608
00:42:39,920 --> 00:42:41,460
it does not crash your application,

609
00:42:41,460 --> 00:42:43,240
it just doesn't set those properties.

610
00:42:43,240 --> 00:42:48,240
Now of course, if you do something in that code

611
00:42:48,240 --> 00:42:51,300
that you then 100% rely on later,

612
00:42:51,300 --> 00:42:54,600
That's your responsibility to make sure that

613
00:42:54,600 --> 00:42:56,280
if that code suddenly goes away,

614
00:42:56,280 --> 00:43:00,300
your application should still at least work.

615
00:43:00,300 --> 00:43:04,200
But this is a really great library

616
00:43:04,200 --> 00:43:06,340
for filling in those little gaps.

617
00:43:06,340 --> 00:43:08,940
And those gaps are getting less and less every year.

618
00:43:08,940 --> 00:43:10,740
There will be a happy day,

619
00:43:10,740 --> 00:43:13,100
and I'm sure David will agree with me

620
00:43:13,100 --> 00:43:15,900
that it will be a happy day when he can say,

621
00:43:15,900 --> 00:43:17,620
this library is no longer necessary.

622
00:43:17,620 --> 00:43:19,660
And there will definitely come that point.

623
00:43:20,980 --> 00:43:23,700
One of the things that I liked that has been added

624
00:43:23,700 --> 00:43:26,340
since I used the package,

625
00:43:26,340 --> 00:43:31,340
which is an opt-out by default to new versions.

626
00:43:31,340 --> 00:43:34,860
So when you introspect something,

627
00:43:34,860 --> 00:43:36,940
let's say you're looking for a scroll view

628
00:43:36,940 --> 00:43:40,060
inside the SwiftUI scroll view,

629
00:43:40,060 --> 00:43:45,520
you now have to say, I'm looking for it on iOS,

630
00:43:45,520 --> 00:43:48,700
version 13, 14, 15, 16,

631
00:43:48,700 --> 00:43:53,260
And then if version 17 comes out like it just did,

632
00:43:53,260 --> 00:43:55,400
you would have to manually opt in.

633
00:43:55,400 --> 00:44:00,180
You could say like I've tested this on the new version.

634
00:44:00,180 --> 00:44:01,020
I checked it.

635
00:44:01,020 --> 00:44:02,660
I'm gonna add that additional case

636
00:44:02,660 --> 00:44:07,580
so that it enables my introspection on the new platform.

637
00:44:07,580 --> 00:44:10,140
Yeah, I think it's a great library.

638
00:44:10,140 --> 00:44:14,700
It supports, there's a huge list of controls

639
00:44:14,700 --> 00:44:17,660
that it supports, everything from page controls

640
00:44:17,660 --> 00:44:23,580
scroll views, to steppers, to tables, to all the different lists and grids and

641
00:44:23,580 --> 00:44:29,660
things like that. It supports an enormous amount of the SwiftUI API. It's

642
00:44:29,660 --> 00:44:32,780
been around for a long time. It's been around for three years now, which I think

643
00:44:32,780 --> 00:44:37,980
is pretty much as long as SwiftUI has been around. Wasn't SwiftUI's first year

644
00:44:37,980 --> 00:44:43,260
2019? I think so, yeah. Isn't it SwiftUI 3.0 or something?

645
00:44:43,260 --> 00:44:48,860
Well, if it's 2019, wouldn't it be four? So yeah, maybe it was a few months after SwiftUI

646
00:44:48,860 --> 00:44:55,260
first showed up, but it's certainly been around for the vast majority of SwiftUI's lifetime.

647
00:44:55,260 --> 00:44:58,780
And I can recommend this package because I have used it.

648
00:44:58,780 --> 00:45:07,020
Nice. And with that, I think we'll call it another episode, and we will be back with

649
00:45:07,020 --> 00:45:10,140
and some more showcase packages next week

650
00:45:10,140 --> 00:45:13,020
and more news from the Swift Package Index.

651
00:45:13,020 --> 00:45:17,100
So we will speak to you in two weeks.

652
00:45:17,100 --> 00:45:19,140
- See you in two weeks, bye bye.

653
00:45:19,140 --> 00:45:20,140
- All right, bye bye.

654
00:45:20,140 --> 00:45:27,140
[ Silence ]