1
00:00:00,000 --> 00:00:02,400
We have shipped a new feature since we last spoke, right?

2
00:00:02,400 --> 00:00:03,600
Indeed we have.

3
00:00:03,600 --> 00:00:06,240
Well, kind of. I say we.

4
00:00:06,240 --> 00:00:10,720
It's neither of us that shipped the feature.

5
00:00:10,720 --> 00:00:19,200
So what we're talking about is the feature that went live on the site, was it last week,

6
00:00:19,200 --> 00:00:27,120
I think it was, which is to explain our internal package score on the page that we currently have

7
00:00:27,120 --> 00:00:31,520
for package maintainers that shows you various little bits of metadata about your package.

8
00:00:31,520 --> 00:00:39,760
And it now includes a breakdown of how we are representing packages with our internal score

9
00:00:39,760 --> 00:00:45,840
that goes towards the search result placement. So our search results are not entirely ordered

10
00:00:45,840 --> 00:00:52,720
by package score, but package score goes into the mix as well as relevance of the query,

11
00:00:52,720 --> 00:00:58,640
of course. And the most significant part about this feature that's gone live is that it was

12
00:00:58,640 --> 00:01:05,360
developed by Cindy Chin, who did it as part of this year's Swift Mentorship Program.

13
00:01:05,360 --> 00:01:10,640
I think we've talked about the fact that Cindy was working on this on the podcast in previous

14
00:01:10,640 --> 00:01:18,880
episodes, but it's nice to mention that it's now shipped. The Mentorship Program is finished for

15
00:01:18,880 --> 00:01:26,240
this year. It's been an absolute pleasure working with Cindy, just from start to finish, amazing

16
00:01:26,240 --> 00:01:34,240
attitude, incredible coding skills, just a great experience start to finish. And the nice thing

17
00:01:34,240 --> 00:01:42,720
about it is that this feature has now shipped on the site and is live for everyone to look at.

18
00:01:42,720 --> 00:01:48,400
And one thing, just to talk about the Mentorship Program for a second before we dig into the

19
00:01:48,400 --> 00:01:52,720
feature, which we do want to talk about, but to dig into the Mentorship Program for a second,

20
00:01:52,720 --> 00:01:59,760
it was really nice this year because in our initial call that we had to kind of define

21
00:01:59,760 --> 00:02:08,160
the scope of what Cindy was going to tackle for this project, she was very keen to tackle one

22
00:02:08,160 --> 00:02:16,320
feature end to end. And so that meant, like, obviously we picked something together that

23
00:02:16,320 --> 00:02:21,600
was either, it was actually ended up being from the current list of issues, because this has been

24
00:02:21,600 --> 00:02:28,320
on our minds for a little while. But we didn't, we hadn't really designed the feature. And so

25
00:02:28,320 --> 00:02:34,160
the Mentorship Program this year started with, well, let's have a think about what this package

26
00:02:34,160 --> 00:02:40,160
score, how do we actually represent it? Where do we put this information? How do we make people,

27
00:02:40,160 --> 00:02:45,600
because package score has been a little bit of a sensitive subject in the past, but there's been a

28
00:02:45,600 --> 00:02:54,080
few conversations around whether, you know, how, whether you even should be ranking packages by

29
00:02:54,080 --> 00:03:00,000
some kind of internal score. And so when approaching the feature of exposing this data,

30
00:03:00,000 --> 00:03:07,840
we definitely talked quite a lot about how to make it obvious what was happening, but also

31
00:03:07,840 --> 00:03:13,600
being aware that some people might actually disagree with the whole idea about package

32
00:03:13,600 --> 00:03:18,960
scores. So we did some design, first of all, and thought about how the feature would work.

33
00:03:18,960 --> 00:03:26,880
And then Cindy kind of went ahead and made several modifications. So not only exposing

34
00:03:26,880 --> 00:03:34,160
the package score, but also adding two new factors to the package score. So two new metrics

35
00:03:34,160 --> 00:03:40,640
that packages will be scored on, or are currently now scored on. So adding two of those, and then

36
00:03:40,640 --> 00:03:46,160
visualizing that package score on the maintainers page. Finally, obviously, including testing and

37
00:03:46,160 --> 00:03:52,160
all the rest of it, finally designing the front end side of it. So she wanted to do some HTML and

38
00:03:52,160 --> 00:03:59,440
CSS work. So that was representing the score on the page. And then finally, and I really do mean

39
00:03:59,440 --> 00:04:07,200
end to end when I say it, she wanted to write the blog post that launched the feature. So that blog

40
00:04:07,200 --> 00:04:13,440
post went live last week, written by Cindy, and the feature went live as well. So it's been an

41
00:04:13,440 --> 00:04:18,880
absolute pleasure working with her this year. And I think we've actually got a great feature out of

42
00:04:18,880 --> 00:04:24,720
the end of it. We absolutely did. And I'd add, finally, finally, she also got featured in one

43
00:04:24,720 --> 00:04:32,480
of the most popular, if not the most popular, IRIS newsletters last week, didn't it? So it was really

44
00:04:33,600 --> 00:04:35,680
how on earth did that happen? Yeah, that's amazing.

45
00:04:35,680 --> 00:04:42,960
Well deserved, because I think that's a great feature. And I think I love the whole approach of

46
00:04:42,960 --> 00:04:53,200
wanting to do it end to end and doing it in that time frame. And not as your main thing, she has

47
00:04:53,200 --> 00:04:58,400
other work to do, right? So this is a side project. So it's quite amazing. Really nice, really well.

48
00:04:58,400 --> 00:05:05,920
Yeah, she works at Mozilla, working on Firefox. I mean, she has a full time job. And so yeah,

49
00:05:05,920 --> 00:05:13,840
this is 12 weeks of, you know, a couple of hours a week to get this done, which is remarkable work.

50
00:05:13,840 --> 00:05:19,920
Really nice. I'd love to see that come together. And really just across the whole spectrum with

51
00:05:19,920 --> 00:05:26,560
everything. Really, really nice. And it's been well received. I actually got some questions.

52
00:05:27,360 --> 00:05:35,360
Yesterday afternoon, I believe it was about the feature, which shows how interested people are in

53
00:05:35,360 --> 00:05:42,560
the score and wanting to know, you know, how it's computed now that they can see it. The next thing

54
00:05:42,560 --> 00:05:48,480
that's happening is, well, why does this package have this score? Right. And so this is what we

55
00:05:48,480 --> 00:05:53,840
expected. Yeah. And I think these are fair questions. Yeah. We mentioned this in the

56
00:05:53,840 --> 00:06:01,600
blog post, actually, but this score has technically, and I'm going to lean on the

57
00:06:01,600 --> 00:06:07,200
word technically very heavily here, it's technically always been open because the score has actually

58
00:06:07,200 --> 00:06:13,280
been isolated in one class in our code since the beginning. We launched day one, this score

59
00:06:13,280 --> 00:06:19,040
was there in some form. And so technically, that score has always been transparent.

60
00:06:21,200 --> 00:06:25,200
It's just that it's unreasonable for us to expect people to go and look at the source code.

61
00:06:25,200 --> 00:06:32,720
And that's what this really does. But we knew that this issue would come up as soon as we ship it.

62
00:06:32,720 --> 00:06:36,320
It's kind of like in Hitchhiker's Guide to the Galaxy, where the demolition of Earth

63
00:06:36,320 --> 00:06:39,440
was published ahead of time on Alfred Centauri or somewhere.

64
00:06:39,440 --> 00:06:43,600
People could have protested, but you know, just didn't get around it.

65
00:06:43,600 --> 00:06:49,600
Yeah, I mean, and it's fair to ask these questions. And it's great to have them,

66
00:06:49,600 --> 00:06:56,160
just keep them coming. If there's anything you want to ask us about, let us know. I love that

67
00:06:56,160 --> 00:07:01,120
I got this question ahead of time and that we can address it now, rather than me typing some

68
00:07:01,120 --> 00:07:06,800
back and forth answers. This is much nicer to be sort of broadcasting it to more people,

69
00:07:06,800 --> 00:07:11,680
which probably, you know, some of you might have the same question. So one question was obviously,

70
00:07:11,680 --> 00:07:17,680
and this is an example of one metric, what's the rationale to give zero points for eight

71
00:07:17,680 --> 00:07:24,640
dependencies? So this package has eight dependencies and in the listing, it then has

72
00:07:24,640 --> 00:07:31,760
no points for the number of dependencies because the, you know, I think five or less get some

73
00:07:31,760 --> 00:07:39,280
points and two or less or fewer, rather, you get some more points. And, you know, that's obviously,

74
00:07:39,280 --> 00:07:45,360
if you have eight dependencies, you know, you get no points. If you had fewer, you'd get some

75
00:07:45,360 --> 00:07:52,160
points. And the question is, well, I can't really shed the dependencies. How did we arrive at those

76
00:07:52,160 --> 00:07:58,080
points? I should rather say and direct the questions towards you, because I think, I know

77
00:07:58,080 --> 00:08:02,240
you came up with these figures. What was your rationale around those?

78
00:08:02,240 --> 00:08:05,440
Dave Yes, all of the scoring has been,

79
00:08:05,440 --> 00:08:07,200
you can lay all the blame at my door here.

80
00:08:07,200 --> 00:08:10,080
Mason Praise you can include me,

81
00:08:10,080 --> 00:08:11,280
the blame goes to Dave.

82
00:08:11,440 --> 00:08:21,520
Right. Okay, sure. So yes. So before I answer this question, I would be much more comfortable

83
00:08:21,520 --> 00:08:28,480
with this metric if we were able to exclude test only dependencies, but we cannot. And therefore,

84
00:08:28,480 --> 00:08:36,000
we do the best with what we can, what we have, sorry. I think it's valid. So generally,

85
00:08:36,800 --> 00:08:43,920
the way that I think about score is that it should be all positive things. There shouldn't be really,

86
00:08:43,920 --> 00:08:50,000
there should be no penalties included in the score. And in fact, the way that it works is

87
00:08:50,000 --> 00:08:55,280
that everything is just an addition to the score. It's just that it happens to be dependencies

88
00:08:55,280 --> 00:08:59,600
calculation is where it's less than something instead of greater than something. So it's kind

89
00:08:59,600 --> 00:09:08,720
of inverting the positivity really. But so generally, it's all ways, adding on something

90
00:09:08,720 --> 00:09:14,080
for doing something that makes your package better. And that also is a very important part of

91
00:09:14,080 --> 00:09:22,640
this is what I always hope will happen with the score and we live in an imperfect world. And so

92
00:09:22,640 --> 00:09:27,840
we can't be guaranteed, you know, we can't be absolutely correct with this. But what I hope

93
00:09:27,840 --> 00:09:31,760
that if anyone tries to gain their score and increase it artificially by looking at the

94
00:09:31,760 --> 00:09:39,360
rules and doing things to kind of increase their score, that actually that just makes a better

95
00:09:39,360 --> 00:09:47,040
package because that's ultimately what we're trying to do here is put higher quality and

96
00:09:47,040 --> 00:09:52,880
better maintained packages higher in the search results. That is the intention of this score.

97
00:09:54,000 --> 00:10:02,960
So things like having many releases, that's one of the factors that we score packages on.

98
00:10:02,960 --> 00:10:06,800
If a package has been around for a long time, it's more likely to have more releases.

99
00:10:06,800 --> 00:10:11,200
And therefore, we give more points, not based entirely on how many releases,

100
00:10:11,200 --> 00:10:14,400
but there are some thresholds. So I forget what the numbers are. But if you go over

101
00:10:14,400 --> 00:10:18,160
two releases, you get a couple of points. And if you go over five releases, you get some more,

102
00:10:18,160 --> 00:10:20,640
and you go over 50, you get some more or something like that.

103
00:10:20,640 --> 00:10:23,840
Mason So in terms of those, in terms of those

104
00:10:23,840 --> 00:10:29,280
thresholds, specifically for the dependencies, like five and two, did you look at the distribution?

105
00:10:29,280 --> 00:10:35,440
Or did you just sort of eyeball the numbers? Did you just come up with a number? How did you come

106
00:10:35,440 --> 00:10:40,720
up with the numbers? It's a mix, right? Yeah. So I certainly do look at the data when I'm coming up

107
00:10:40,720 --> 00:10:45,040
with these numbers. And don't forget, a lot of these numbers were come up with three years ago.

108
00:10:45,040 --> 00:10:54,480
So I forget exactly how I came up with some of them. But certainly, one approach that I definitely

109
00:10:54,480 --> 00:10:59,280
use is that, like, I don't even know whether those numbers I gave were correct, but I would

110
00:10:59,280 --> 00:11:04,720
imagine they would be something like that. Because what I tend to do is, you'll get a few points for

111
00:11:04,720 --> 00:11:12,160
just kind of doing anything towards that metric, a few more when you go over, you know, a medium

112
00:11:12,160 --> 00:11:16,480
amount. And then the more releases, like if you have 1000 releases, you're not going to get any

113
00:11:16,480 --> 00:11:21,440
more points than if you had 50 releases or something like that. Generally, it's diminishing

114
00:11:21,440 --> 00:11:28,960
returns as we go up. So certainly, if you look at the, like the metric that we give points for

115
00:11:28,960 --> 00:11:36,960
number of stars, so you only get zero additional points if you have less than 25 stars on a

116
00:11:36,960 --> 00:11:42,240
repository. From 25 to 100 stars, you get 10 points, which is actually quite a large amount of

117
00:11:42,240 --> 00:11:53,760
points. 100 to 500, you get 20. 500 to 5000, you get 30. 5000 to 10,000, you get 35. And then if

118
00:11:53,760 --> 00:11:59,680
you have more than 10,000, you get 37. So you're getting two points for potentially 20,000 stars

119
00:11:59,680 --> 00:12:06,640
at the end there. So certainly, it definitely takes into account diminishing returns. Generally,

120
00:12:06,640 --> 00:12:18,640
I like to also factor in how important the metric is in terms of how, what the maximum score for it.

121
00:12:18,640 --> 00:12:23,600
So it's not like every metric has the same maximum score. They do have different maximum scores.

122
00:12:23,600 --> 00:12:27,760
And in the case of dependencies, which is what the original question was around, we could finally

123
00:12:27,760 --> 00:12:35,680
get him back to the original question. The total number of points you can get for having a low

124
00:12:35,680 --> 00:12:44,560
number of dependencies is five compared to 10 for having 25 stars, which 25 stars is a relatively

125
00:12:44,560 --> 00:12:51,280
low number of stars. So just to put that into context, and this was deliberately because this

126
00:12:51,280 --> 00:12:57,520
metric is first of all, not ideal because it includes test only dependencies. And secondly,

127
00:13:00,480 --> 00:13:07,120
I certainly do think there's a case to be made that a package with a zero or very low number

128
00:13:07,120 --> 00:13:16,000
of dependencies is a mark of a package that I would want to consider using. So I think having

129
00:13:16,000 --> 00:13:22,320
that metric in there is valid. But the fact that that metric isn't quite perfect in how we are able

130
00:13:22,320 --> 00:13:28,000
to calculate it right now is why it has a lesser score. And when we're able to do test only

131
00:13:28,000 --> 00:13:35,200
dependencies or exclude test only dependencies, we may also increase the total, the kind of the

132
00:13:35,200 --> 00:13:39,280
weighting of that score. So there's a follow up question. But that's an interesting question.

133
00:13:39,280 --> 00:13:43,520
Would you agree? Well, actually, before we move on to the follow up, would you agree

134
00:13:43,520 --> 00:13:49,360
with my defense of that? Yeah, yeah, yeah, definitely. I mean, plus, I think people

135
00:13:49,360 --> 00:13:55,520
sort of focus on the score quite a bit, I would say perhaps a bit too much, because

136
00:13:56,240 --> 00:14:00,960
what you need to bear in mind, this is a tiebreaker in search results. If you search for

137
00:14:00,960 --> 00:14:05,200
something, you have a name match or, you know, the term, your search terms are good. Right.

138
00:14:05,200 --> 00:14:10,720
Your readme has the terms, you'll show up in the list. And this is just, you know, give you a bit

139
00:14:10,720 --> 00:14:16,640
of a higher ranking in that list. It's, you know, we don't have recommendations or discovery or that

140
00:14:16,640 --> 00:14:22,960
sort of stuff where that would otherwise appear and have an impact. So the best thing to actually

141
00:14:22,960 --> 00:14:29,600
do is have a package that has proper keywords and stuff and, you know, a readme that explains what

142
00:14:29,600 --> 00:14:36,800
it is and then make sure that terms that people would search for to find it are referenced there

143
00:14:36,800 --> 00:14:42,240
in these in these places. And then you show up and we show 20 results on the first page. And,

144
00:14:42,240 --> 00:14:50,160
you know, with given the number of metrics we have in this score, maybe in one of them,

145
00:14:50,160 --> 00:14:55,600
it won't be ideal. But, you know, if it's a good package and has a lot of the other metrics right,

146
00:14:55,600 --> 00:15:02,880
you know, having a few points fewer there isn't going to destroy your discovery on that page,

147
00:15:02,880 --> 00:15:06,000
I think. So I think that's something to bear in mind there.

148
00:15:06,000 --> 00:15:07,520
Toby Cunningham But Cindy and I had an interesting

149
00:15:07,520 --> 00:15:16,560
conversation around one of the new metrics that Cindy added was, does the repository have a readme

150
00:15:16,560 --> 00:15:24,160
file? Because that certainly is a mark of a, you know, a package which I would want to look at. If

151
00:15:24,160 --> 00:15:29,360
a package doesn't have a readme file, I think it should certainly have less points than one that

152
00:15:29,360 --> 00:15:35,760
does. And of course, most packages do. But the scoring on that check of does the package have

153
00:15:35,760 --> 00:15:41,920
a readme, not looking at the content of the readme, not trying to evaluate how long the readme is or

154
00:15:41,920 --> 00:15:47,760
how much information there is in there, but which we can and may also do in the future. But just

155
00:15:47,760 --> 00:15:55,040
does it have a readme? We scored that at 15 points, which is the exact same score as does the

156
00:15:55,040 --> 00:16:03,280
package have documentation. So initially, my gut feeling when we were talking about having it at 15

157
00:16:03,280 --> 00:16:09,680
points was well, documentation should be more important than a readme because clearly someone's

158
00:16:09,680 --> 00:16:15,040
put some time and effort into documenting their package. But actually, I think I feel really

159
00:16:15,040 --> 00:16:20,800
comfortable in the end with what we decided on to have them at the same score. Because again,

160
00:16:20,800 --> 00:16:27,680
the documentation, we're not giving any kind of measurement of documentation quality with this.

161
00:16:27,680 --> 00:16:33,360
This is just a Boolean. Does it have documentation? Does it have a readme? And actually,

162
00:16:33,360 --> 00:16:38,800
I think those, the reason we actually decided on 15 points for both is that some people use

163
00:16:38,800 --> 00:16:44,720
their readme as documentation. And so they are almost fulfilling the same thing. Now, if you have

164
00:16:44,720 --> 00:16:50,000
both a readme and documentation, then you're going to get double points, which I think is also fair

165
00:16:50,000 --> 00:16:56,960
because it's more work that you've done towards creating a better package. But that's why

166
00:16:56,960 --> 00:17:02,640
initially my feeling was to say the readme should be less points than documentation.

167
00:17:02,640 --> 00:17:05,200
But the more we thought about it, the less that made sense.

168
00:17:05,200 --> 00:17:08,400
Mason Mendez Yeah. Yeah. I think also the readme often

169
00:17:08,400 --> 00:17:13,840
fulfills the role of sort of a getting started page in the documentation. Sometimes it's even,

170
00:17:13,840 --> 00:17:18,480
you know, it's a duplicate of that, which is fine. I think it's great to have it in both places. But

171
00:17:18,480 --> 00:17:23,520
the readme sort of serves that purpose more of explaining what it is about and what the entry

172
00:17:23,520 --> 00:17:30,960
points are into the package. Whereas documentation often is at first, especially at the first pass of

173
00:17:30,960 --> 00:17:35,760
the documentation is just API reference documentation, which is useful, but not

174
00:17:35,760 --> 00:17:39,600
great if you want to understand how to use a package, how to get started with it.

175
00:17:39,600 --> 00:17:41,600
You said we had a follow up question.

176
00:17:41,600 --> 00:17:47,680
We do. Yes. And that's quite specific to that package. But I think there's a couple in that

177
00:17:47,680 --> 00:17:53,120
area. And the question is, it's tough for a Swift on server package to achieve this,

178
00:17:53,120 --> 00:17:59,760
because Neo, a very common foundational server side Swift library already has four dependencies.

179
00:17:59,760 --> 00:18:06,080
So by using Neo, which you almost certainly will be when you're writing or publishing a

180
00:18:06,080 --> 00:18:11,760
server side Swift package, you start off at a, you already passed the two that gives you

181
00:18:11,760 --> 00:18:17,920
maximum points. You're very close to the five that gives you the next step. And you're almost

182
00:18:17,920 --> 00:18:25,920
out of the scoring range with that. And those are real dependencies, not test only dependencies.

183
00:18:25,920 --> 00:18:31,920
So they would not be fixed by if we at some point will detect test dependency. So this is a real

184
00:18:31,920 --> 00:18:36,320
problem. Yeah. Well, is it? I think that actually comes. Is it though? Because, well, so I think

185
00:18:36,320 --> 00:18:41,520
that actually comes back to the same thing that I said earlier, which is the total number of points

186
00:18:41,520 --> 00:18:48,080
that you are gaining or losing in this case here is only five points. This is ranked,

187
00:18:48,080 --> 00:18:53,600
you know, it's a third of a readme file. Yeah. But I think there's also another reason why

188
00:18:54,800 --> 00:19:00,160
this isn't that important because these scores are relative. We're using them in ranking search

189
00:19:00,160 --> 00:19:05,440
results for a thing. And if you're searching for a server side Swift package, all these packages

190
00:19:05,440 --> 00:19:11,040
will have Neo as their dependencies pretty much because it's such a foundational library. So I'm

191
00:19:11,040 --> 00:19:17,280
pretty sure if you made a survey across the Swift package index across server side libraries,

192
00:19:17,280 --> 00:19:22,080
none of them will have points for dependencies because they're all up in the

193
00:19:22,080 --> 00:19:27,600
five, 10 range because they're very much, you know, if you use Vapor as a dependencies,

194
00:19:27,600 --> 00:19:33,040
you're done. You're way past any of the limits there. But that's true for all your

195
00:19:33,040 --> 00:19:38,480
in quotes, competitive, you know, competitors in the package ranking space. They all have,

196
00:19:38,480 --> 00:19:44,320
you know, Neo or Vapor or, you know, a package like that. So you're still being compared on

197
00:19:44,320 --> 00:19:50,720
equal terms and, you know, compared to an iOS package, yes, you'll have a lower score,

198
00:19:50,720 --> 00:19:56,240
but that doesn't really matter because someone shopping for a server side library won't be

199
00:19:56,240 --> 00:20:01,920
looking at iOS libraries. It's not going to go, well, actually the score of this is less. So I'm

200
00:20:01,920 --> 00:20:05,280
going to use SwiftUI instead of server side Swift. Yeah, yeah, exactly. I mean, you're

201
00:20:05,280 --> 00:20:11,440
looking for something different. Yeah. And this goes back to, you know, the most important thing

202
00:20:11,440 --> 00:20:19,040
is going to be your search terms. Have something that is sure to be referenced in your readme

203
00:20:19,920 --> 00:20:25,040
keywords and stuff. You know, if it's an important thing that describes your package well,

204
00:20:25,040 --> 00:20:32,480
has very strong association with your package, put that in somewhere and you'll land at the

205
00:20:32,480 --> 00:20:36,480
top or near the top, certainly on the first page. And that's the most important thing, really.

206
00:20:36,480 --> 00:20:44,160
Were there any more questions? No, that's the two that I got. We'll see if we have some follow-ups.

207
00:20:45,120 --> 00:20:50,240
So the last thing that we should mention here is, because I don't think we actually said how

208
00:20:50,240 --> 00:20:54,800
to find this feature. So the first thing you should do actually is read Cindy's blog post

209
00:20:54,800 --> 00:20:58,880
on the Swift Package Index blog, which you can get to just by hitting the blog link on the home

210
00:20:58,880 --> 00:21:03,600
page of the package index. And it does explain in that post how to find the feature, but I'll also

211
00:21:03,600 --> 00:21:09,200
just quickly say it here. So if you go to any package page on the right-hand side, underneath

212
00:21:09,200 --> 00:21:13,920
the versions, the current versions of the package, there's a little bit of small text that says,

213
00:21:14,480 --> 00:21:18,960
are you this package's maintainer or something like that. And there's a link there, which goes

214
00:21:18,960 --> 00:21:24,160
through to a specific page for package maintainers, which has information like how you can add those

215
00:21:24,160 --> 00:21:31,920
badges to your readme to display your platform and Swift version compatibility, how to add

216
00:21:31,920 --> 00:21:37,120
documentation if you have documentation in your package. And then at the bottom of that page is

217
00:21:37,120 --> 00:21:43,680
now this new package score page. So that's where it is. And the other thing that I want to mention

218
00:21:43,680 --> 00:21:51,280
is that we are absolutely not saying that this is a complete and total representation of package

219
00:21:51,280 --> 00:21:56,800
score. In fact, I would describe this as the bare minimum of a package score. For example, we're

220
00:21:56,800 --> 00:22:03,600
not doing any analysis of how documented or how good a readme file is or anything more than the

221
00:22:03,600 --> 00:22:08,800
total number of dependencies or anything like that. All of these, there's a metric for does

222
00:22:08,800 --> 00:22:14,480
the package include tests and the trigger for that metric is does the package include a test target,

223
00:22:14,480 --> 00:22:21,200
which is a fairly low bar for passing that metric. So what we're saying here is that this is what we

224
00:22:21,200 --> 00:22:30,480
have currently. And we are actively listening to ideas for amendments and additions to this. And

225
00:22:30,480 --> 00:22:36,000
in fact, at the bottom of that page, just underneath the package score, there is a link to

226
00:22:36,000 --> 00:22:44,480
a always open discussion thread on our repository where this is already being discussed. And so

227
00:22:44,480 --> 00:22:52,640
just a declaration that we don't believe this is a completed package score feature.

228
00:22:52,640 --> 00:23:00,960
This is always going to be a work in progress and that we are listening if you have ideas and

229
00:23:00,960 --> 00:23:08,640
opinions on new metrics, how we could make it better. Exactly. A living score. And it always

230
00:23:08,640 --> 00:23:14,960
will be. Yeah. Yeah. Do we have anything else or should we do some packages? I think that's it. In

231
00:23:14,960 --> 00:23:20,880
terms of news, we should do some package recommendations. I can start us off this week

232
00:23:24,800 --> 00:23:34,000
with a package called DirectJSON by Mertol Kasanan. And this is a package that makes use

233
00:23:34,000 --> 00:23:44,160
of the Swift function dynamic member lookup. And what it does is it allows you to access on

234
00:23:44,160 --> 00:23:52,560
extend the string. And if that string includes JSON content, like if the contents of the string

235
00:23:53,280 --> 00:24:00,400
is a JSON object, it allows you just to basically dot into the properties and navigate through

236
00:24:00,400 --> 00:24:08,480
the JSON in that way. So, for example, the example from the readme here is a string

237
00:24:08,480 --> 00:24:15,280
called the cars of 2023, which is a potential list of cars or something like that. It doesn't

238
00:24:15,280 --> 00:24:22,400
actually have the data in the readme. And so it says the cars of 2023 dot JSON, which looks to

239
00:24:22,400 --> 00:24:30,160
see if the property is JSON, like it is the string JSON dot EV dot popular bracket zero dot brand.

240
00:24:30,160 --> 00:24:39,520
So you're effectively saying no, no codable, no JSON parsing, just access properties inside JSON

241
00:24:39,520 --> 00:24:49,680
as if they were already parsed. And then the dynamic member lookup will turn those method

242
00:24:49,680 --> 00:24:56,800
calls into lookups inside the JSON and there we go, return the values. And I think this is an

243
00:24:56,800 --> 00:25:03,680
interesting package, but it's probably not one that I would suggest using in actual production.

244
00:25:03,680 --> 00:25:03,680
Stuart Jensen Here we go again.

245
00:25:03,680 --> 00:25:06,880
Jason Kilgore Yeah, this is my thing, right? Here's a

246
00:25:06,880 --> 00:25:14,000
package. Don't use it. Well, let's see if you agree, right? Let me say what I'm going to say

247
00:25:14,000 --> 00:25:20,400
about it. And then again, we'll see if you agree. But I think the reason I wanted to highlight this

248
00:25:20,400 --> 00:25:25,680
package is not because it would go into a production application. But actually, if you

249
00:25:25,680 --> 00:25:32,960
want to write some Swift code, and just very quickly look at the contents of some JSON,

250
00:25:32,960 --> 00:25:37,520
you actually end up having to do quite a bit of work with codable. And yes, you could decode it

251
00:25:37,520 --> 00:25:45,040
into a dictionary and do it that way. And that's fine. But if you want it in a typed way, then

252
00:25:45,040 --> 00:25:51,280
you're going to be doing quite a lot of typing to get that. If you just want to very quickly

253
00:25:51,280 --> 00:25:55,200
just see what's there, experiment with something before it goes in properly.

254
00:25:55,200 --> 00:26:01,200
And so I think that's where this package potentially lives is for experimentation.

255
00:26:01,200 --> 00:26:06,400
I think that the downside of this is potentially that if you did ship something with this,

256
00:26:06,400 --> 00:26:14,400
and your JSON ever changes, then that's going to be harder to work with than it would be with

257
00:26:14,400 --> 00:26:19,440
something like codable. It reminds me of Ruby, actually, because the first time I came across

258
00:26:19,440 --> 00:26:27,200
this kind of approach was with Ruby, which has a method called method missing, which is the same

259
00:26:27,200 --> 00:26:32,560
as dynamic member, whatever it's called, dynamic member lookup, where it turns the method name

260
00:26:32,560 --> 00:26:38,320
into a parameter on method missing. And that's the first time I came across this approach.

261
00:26:38,320 --> 00:26:45,680
So would you agree? Would you agree with my assessment of this package?

262
00:26:45,680 --> 00:26:48,880
Mostly, yes. Although the first thing I thought of was actually Ruby is a good point,

263
00:26:48,880 --> 00:26:54,720
because I thought this is going to be nice for scripting, right? And I have been using Swift

264
00:26:54,720 --> 00:27:01,200
more and more for scripting. And I do love codable there, because it's very easy even to drill into

265
00:27:02,080 --> 00:27:07,680
structs, because you don't need to spell them out completely, right? If you drill into a nested

266
00:27:07,680 --> 00:27:12,160
JSON, all you need is the container types. You don't need to spell out all the properties you're

267
00:27:12,160 --> 00:27:18,720
not interested in, right? So I wouldn't necessarily agree that you have to do that much typing

268
00:27:18,720 --> 00:27:26,960
to unpack a JSON into codable. However, if you don't know what the structure is,

269
00:27:26,960 --> 00:27:32,720
or the structure is perhaps dynamic, then you're out of luck with codable. You have to use JSON

270
00:27:32,720 --> 00:27:36,960
serialization. And I guess that's what this is using under the hood. And then this certainly

271
00:27:36,960 --> 00:27:43,680
is a much nicer API to unpack something that is dynamic. And it certainly is. It doesn't need any

272
00:27:43,680 --> 00:27:49,520
typing, right? You don't need any struct or declaration to decode. You can just drill in.

273
00:27:49,520 --> 00:27:52,720
I think that's really nice for that kind of purpose.

274
00:27:52,720 --> 00:27:59,440
I actually came across a situation, it was with codable on a YAML file rather than a JSON file.

275
00:27:59,440 --> 00:28:06,800
But I had a situation this week where the same key in the YAML file could be either a string

276
00:28:06,800 --> 00:28:15,520
or an array of strings. So I had to write a custom decoder for that, which first attempted

277
00:28:15,520 --> 00:28:20,080
to decode an array. And then if not, then it attempted to decode a string.

278
00:28:20,800 --> 00:28:27,840
Yeah. On that note, one of the features I love most about recent Xcodes, I think it might be 15,

279
00:28:27,840 --> 00:28:34,400
is that you can generate a codable implementation. Because writing your own codable

280
00:28:34,400 --> 00:28:40,720
implementation always, I have like snippets lying around to look it up. Or I used to, because now

281
00:28:40,720 --> 00:28:46,480
it's so much easier because you can just generate it and then modify it to do what you need it to do.

282
00:28:46,480 --> 00:28:48,880
That's such a great feature.

283
00:28:48,880 --> 00:28:53,120
That would have been useful. I didn't know about that. Where is that feature? Is it in refactor?

284
00:28:53,120 --> 00:29:00,160
Yeah, it's in the refactoring stuff. You can generate a codable implementation.

285
00:29:00,160 --> 00:29:02,480
You learn something new every day of the school day.

286
00:29:02,480 --> 00:29:03,200
So there you go.

287
00:29:03,200 --> 00:29:09,840
My first pick is a really interesting package that I came across a couple of weeks ago,

288
00:29:09,840 --> 00:29:17,200
and it's called Swift Summarize by Stef Kors. Did you know about

289
00:29:17,920 --> 00:29:26,080
Core Services Framework Search Kit, and in particular in there, the SK Summary type?

290
00:29:26,080 --> 00:29:27,920
Only because I also read about this.

291
00:29:27,920 --> 00:29:38,400
I had no idea this existed. So what this does, effectively, it gives you like a local version of

292
00:29:38,400 --> 00:29:44,960
one of the aspects of chat GPT. You can, with this thing and with this package, give it a string,

293
00:29:45,760 --> 00:29:52,160
and then offline and on device have it summarize that string you put in.

294
00:29:52,160 --> 00:30:01,200
I tried this with a couple of paragraphs from our blog post about the Apple announcement

295
00:30:01,200 --> 00:30:14,240
when we had our sponsorship. And the result I got was, so these are like two, four, six

296
00:30:14,240 --> 00:30:19,200
very short paragraphs. I don't know how many characters that is, but it's the meat of our

297
00:30:19,200 --> 00:30:24,640
blog posts. And the summary is, Apple support and the community support we already enjoy via our

298
00:30:24,640 --> 00:30:30,000
GitHub sponsorships have set us on a path where the Swift package index can be a project that

299
00:30:30,000 --> 00:30:36,960
fully supports our work financially. And I think we can just have much shorter blog posts in the

300
00:30:36,960 --> 00:30:46,640
future because this is the meat of it. I did not realize that this was a framework that you can use

301
00:30:46,640 --> 00:30:54,880
and that it's on device, it runs offline. So that's a really interesting framework that I

302
00:30:54,880 --> 00:30:59,600
discovered via this package. And it's great to have this as a little Swift package. I could just

303
00:30:59,600 --> 00:31:04,720
stuck it in a playground without trying to playground feature. And that was a great way

304
00:31:04,720 --> 00:31:10,320
to play around with this and see how it does. Yeah. So I also tried this actually, because

305
00:31:10,320 --> 00:31:17,760
it was going to be one of my package recommendations today, but it didn't make

306
00:31:17,760 --> 00:31:26,080
it into the final cut. I did try this and you're right that having it not need a network connection,

307
00:31:26,080 --> 00:31:32,240
not need API calls that cost money is a huge advantage to it. But in the examples that I

308
00:31:32,240 --> 00:31:36,880
tried, because we've been doing some work with summarization of package information,

309
00:31:36,880 --> 00:31:43,840
using chat GPT. And so this is a subject that I've spent a bit of time looking at. And

310
00:31:43,840 --> 00:31:52,240
in the testing I did, it's impressive what it does, but it's not a patch on what you get out

311
00:31:52,240 --> 00:32:00,560
of GPT for the same input text. So it is good. And it's certainly the fact that it is an on device

312
00:32:01,120 --> 00:32:10,160
calculation, an on device summarization tool is a huge difference. And so they shouldn't really

313
00:32:10,160 --> 00:32:16,560
be compared, but we do live in a world where chat GPT exists. Another thing that I really liked,

314
00:32:16,560 --> 00:32:21,200
I'm not sure if I mentioned that already, is that the results seem to be stable. So I've run this,

315
00:32:21,200 --> 00:32:25,520
you know, multiple times, right. I left some time in between in case there's some caching going on,

316
00:32:25,520 --> 00:32:29,920
but you do, apparently you are getting the same result back, which is a nice feature,

317
00:32:29,920 --> 00:32:32,720
actually, because the way we've been using it...

318
00:32:32,720 --> 00:32:34,640
Which is a disadvantage of GPT.

319
00:32:34,640 --> 00:32:39,280
Yeah, we the way we've been using that is sort of, you know, you run it again,

320
00:32:39,280 --> 00:32:42,480
you get something different, you sort of have to pick a result at some point.

321
00:32:42,480 --> 00:32:53,120
Yeah. Although I did, I don't know whether you you listened to or watched the recent keynote from

322
00:32:53,120 --> 00:33:00,480
OpenAI. But they're talking about now in the current latest version of the API, you can also

323
00:33:00,480 --> 00:33:07,600
specify a random, a consistent random seed to get the same output from the same input again.

324
00:33:07,600 --> 00:33:09,040
Okay, that's nice.

325
00:33:09,040 --> 00:33:11,360
I don't know whether that's shipped yet, but that was something they talked about.

326
00:33:11,360 --> 00:33:15,600
Right. So that was Swift summarized by Steph Kors.

327
00:33:17,680 --> 00:33:27,840
So my next package is Memberwise Init by Galen O’Hanlon. And this is a Swift 5.9 macro package

328
00:33:27,840 --> 00:33:34,720
for automatic memberwise init statements. So if you create a struct, you want to generate a

329
00:33:34,720 --> 00:33:40,480
memberwise init for it, rather than having to type out that or use any kind of automation to

330
00:33:40,480 --> 00:33:44,320
create it. I know there are lots of ways to automate the creation of these things. This

331
00:33:44,320 --> 00:33:49,920
takes it and puts it in a macro. So above your, for example, if you're doing on a struct, if you

332
00:33:49,920 --> 00:33:55,440
above your struct, you add the attribute memberwise init. And then in this case,

333
00:33:55,440 --> 00:34:00,880
the example is dot public, and it will create you a public init that takes every property and gives

334
00:34:00,880 --> 00:34:08,960
you an initializer that adds that. And so nice little time saver is something that you end up

335
00:34:08,960 --> 00:34:17,680
doing quite a lot in Swift. But again, I must stop recommending packages that I then recommend not

336
00:34:17,680 --> 00:34:26,960
using. It is definitely becoming a habit of mine. I certainly, this package made me think more about

337
00:34:26,960 --> 00:34:36,160
macros than I have done in the past. And it's certainly a nice little time saver to not have

338
00:34:36,160 --> 00:34:42,480
to generate and not have to write a memberwise init for your struct. But at the same time,

339
00:34:42,480 --> 00:34:50,320
and this was always the problem with C macros is it hides what's happening. And so for some things,

340
00:34:50,320 --> 00:34:54,240
where there's a lot of code that you might want to generate or something complex that you want to do,

341
00:34:54,240 --> 00:34:58,400
maybe that, although, I mean, do you want to hide complexity? I don't know. I think there's,

342
00:34:58,400 --> 00:35:03,200
I think there's a genuine question about macros that this made me think about, which is,

343
00:35:04,080 --> 00:35:08,640
are they actually a good idea? And I'm not saying they're not a good idea before anyone,

344
00:35:08,640 --> 00:35:14,000
or anyone thinks that's what I'm saying. But I certainly, it makes me think about like how much

345
00:35:14,000 --> 00:35:21,760
would I import a package that has a macro to generate a memberwise init when the amount of

346
00:35:21,760 --> 00:35:27,760
typing in a memberwise init is actually not that much really. Yes, it's repetitive, and it's not

347
00:35:27,760 --> 00:35:33,280
something we really want to have to do. But at least once you've typed it, it's there and you

348
00:35:33,280 --> 00:35:37,760
can see it. And I know that Xcode can expand the macro and show you the code that it generates. And

349
00:35:37,760 --> 00:35:44,240
there are definite pros and cons to this whole approach, but it did make me wonder of like where

350
00:35:44,240 --> 00:35:52,880
that line lies in terms of would I add a macro to do this job or that job or some other job? And

351
00:35:52,880 --> 00:35:58,480
I think this is an interesting package. I think I'm sure it will save some people some time,

352
00:35:58,480 --> 00:36:04,960
but I'm not sure that I would bring it in. Would you? I think I would. And here's why,

353
00:36:04,960 --> 00:36:10,960
because we have actually, we have this problem in a couple of places. Vapor uses,

354
00:36:10,960 --> 00:36:18,320
Vapor models, most of the properties are, or many of them are optional just due to the way

355
00:36:18,320 --> 00:36:27,600
it's often set up. And you do need to specify initializers for all these. And they often

356
00:36:27,600 --> 00:36:32,880
default to nil. And we had a couple of cases where we, and you can very easily generate the

357
00:36:32,880 --> 00:36:38,240
initial initializer, right? There's a, again, under the refactoring tools, you can right click

358
00:36:38,240 --> 00:36:42,880
on your name. That one I do know about. Yeah. And then it generates that and it does that,

359
00:36:42,880 --> 00:36:48,000
but it only does that the first time, right? The next time you add a new member or remove one,

360
00:36:48,000 --> 00:36:55,040
you have to remember to update your initializers. And that is something that you can't forget if

361
00:36:55,040 --> 00:37:01,040
you have a, if you add an optional property, then you don't need to initialize it and to spell it

362
00:37:01,040 --> 00:37:07,840
out in that list. And there can be drift in what members you have and which ones you actually

363
00:37:07,840 --> 00:37:13,520
initialize. And I guess the big advantage of something like this is that it would track

364
00:37:13,520 --> 00:37:20,320
and always have a fully specified initializer. There's no missing of members and making sure

365
00:37:20,320 --> 00:37:26,800
they're all assigned. And the way this bit does was, if I recall correctly, we ended up, you know,

366
00:37:26,800 --> 00:37:31,520
saving stuff to the database. It wasn't actually saved because we never updated the initializer

367
00:37:31,520 --> 00:37:35,520
where that field was passed through and actually written to the database, which is, you know,

368
00:37:35,520 --> 00:37:39,680
that is not something you discover like weeks after. It's just something you discover at an

369
00:37:39,680 --> 00:37:45,040
inopportune time, like an hour later. It's not a huge problem, but it's a bit of a nuisance. And

370
00:37:45,040 --> 00:37:52,400
it's a lot of silly updating of initializers that isn't really interesting work, right? I love,

371
00:37:52,400 --> 00:37:59,280
yeah, taking stuff out of the picture that is just busy work. And there's nothing, you're right,

372
00:37:59,280 --> 00:38:07,440
hiding complexity is a problem, but I don't think this is complexity that is bad. Like this is just

373
00:38:07,440 --> 00:38:13,280
noise, really, because everyone will understand what this initializer does and why it's there.

374
00:38:13,280 --> 00:38:16,560
You know, sometimes you need it. You don't often don't even need it, right? If you are

375
00:38:16,560 --> 00:38:21,200
internal to a package, you don't need to write the initializer. So, and it's still there, right? Swift

376
00:38:21,200 --> 00:38:26,560
still generates that internal one that you never even see, but you can initialize your type fully,

377
00:38:26,560 --> 00:38:31,520
you know, with all the properties. Why is that? Well, it's because it's all internal and it's not

378
00:38:31,520 --> 00:38:35,840
exposed. You don't see it, but it's still there. How is this different? All it does, it gives you

379
00:38:35,840 --> 00:38:42,400
a way of having that same automated way of generating it and you can make it public and

380
00:38:42,400 --> 00:38:47,120
then it works across module boundaries and that. So in that sense, I think it just, you know,

381
00:38:47,120 --> 00:38:53,200
elevates that to a different access level. And I think in that respect, it's absolutely fine as a

382
00:38:53,200 --> 00:38:58,640
complexity. In fact, I think the only complexity is that you need to import that as a package.

383
00:38:58,640 --> 00:39:05,520
And I know that there's been a pitch to have something like that as a language extension. And

384
00:39:05,520 --> 00:39:10,480
I think, I don't recall where that discussion ended. I'm pretty sure it came up in the discussion

385
00:39:10,480 --> 00:39:16,400
where that should just be a macro. And I'm very sure that there will be a set of macros that

386
00:39:16,400 --> 00:39:22,080
eventually end up in either in the standard library or in a, you know, Apple foundation

387
00:39:22,080 --> 00:39:26,800
package or something where these things will become commonplace and I use just like any other

388
00:39:26,800 --> 00:39:32,800
annotation that we use right now, you know, like observable and whatnot. And it'll be one of those

389
00:39:32,800 --> 00:39:39,120
where it offers that and we will use it and forget about it. All right. Yeah. Yeah. I mean, all very

390
00:39:39,120 --> 00:39:45,280
good points. And I should just say as well, that there are lots of options with this macro for you

391
00:39:45,280 --> 00:39:50,160
to customize various bits that you talked about there. So you can specify that a property should

392
00:39:50,160 --> 00:39:55,600
be escaping or public or give it a different label or, you know, and combine those things.

393
00:39:55,600 --> 00:40:01,280
You could have a customized label and the fact that it's public and things like that. So I should

394
00:40:01,280 --> 00:40:06,480
say that there's good support for creating the member wise initializer that you would like to

395
00:40:06,480 --> 00:40:15,680
create rather than just the same one for every type. So, yeah, I think it's, and that's the reason

396
00:40:15,680 --> 00:40:21,760
I didn't hesitate to talk about it here because we call these recommendations and they are of

397
00:40:21,760 --> 00:40:29,200
sorts, but actually what they really are is as with any real world dependency situation where

398
00:40:29,200 --> 00:40:34,640
you're considering adding a dependency is it's actually, it's a decision that comes down to

399
00:40:34,640 --> 00:40:40,080
trade-offs in the real world. And so when we talk about them, we should talk about those trade-offs

400
00:40:40,080 --> 00:40:51,520
too. Yeah. I mean, mine are recommendations. Yours are mentions. That's not how I want them

401
00:40:51,520 --> 00:40:57,840
to be. I just think, well, you got to try harder, Dave. You got to try harder. Yeah, I do. You're

402
00:40:57,840 --> 00:41:02,000
right. I do have to try harder. That's right. Because you wait till you hear my last one.

403
00:41:02,000 --> 00:41:08,960
Oh God, here we go. All right. I'm bracing myself. All right. Let me, let me squeeze in a

404
00:41:08,960 --> 00:41:15,840
recommendation before we get to that one then. And this next one is called Typhoon by Nikita

405
00:41:15,840 --> 00:41:23,040
Vasilev. And that's a really nice retry library. And I came across this because I actually had

406
00:41:23,040 --> 00:41:28,800
need of something like this recently. I have my own version of it, which is a little module that

407
00:41:28,800 --> 00:41:33,680
I'm using. And if I had discovered this before, I might've actually jumped on it. It looks really

408
00:41:33,680 --> 00:41:40,000
nice. So what this does, it gives you an API where you can pass in an async throws closure

409
00:41:40,000 --> 00:41:45,680
and it'll retry it as the name of the package says, or the description says. I'm not sure

410
00:41:45,680 --> 00:41:52,160
of the name Typhoon, how that ties to retrying, but that's what it's called. The nice thing is

411
00:41:52,160 --> 00:41:57,520
you can set retry policies. So there's a couple of things that are listed. I'm not sure how

412
00:41:57,520 --> 00:42:04,000
extensive it is, but obviously you can specify the number of retries, whether they are just,

413
00:42:04,000 --> 00:42:09,040
you know, on a constant time. And it also supports exponential backoff where

414
00:42:09,040 --> 00:42:16,240
subsequent retries will be at a longer period. You know, it'll do one second, two second, four

415
00:42:16,240 --> 00:42:20,720
second, eight seconds. And you typically do that to avoid hammering a service. You know, for instance,

416
00:42:20,720 --> 00:42:27,280
if you're running on a network, you don't want to constantly hammer the service at the same time.

417
00:42:28,240 --> 00:42:32,960
I'm not sure if it has random jitter, but it would be a nice extension if it doesn't.

418
00:42:32,960 --> 00:42:37,040
Looked really nice. Also something you can test in a playground to get a feel for it.

419
00:42:37,040 --> 00:42:42,720
One really nice thing I found is it didn't actually work in our Try in a Playground feature

420
00:42:42,720 --> 00:42:49,200
because it was referencing Vision OS in the platforms, Preamble and Arena. The underlying

421
00:42:49,200 --> 00:42:55,440
tool didn't manage to pass the manifest, but by the time you listen to this, or actually already

422
00:42:55,440 --> 00:43:01,680
it's fixed. So we have shipped an update. I saw this pull request go through. Yeah. I'm so keen

423
00:43:01,680 --> 00:43:07,520
to try these packages that whenever they don't work, I get really annoyed and I need to fix it

424
00:43:07,520 --> 00:43:19,760
straight away if I can. So that's Typhoon, a retry package by Nikita Vasilev. So my third package is,

425
00:43:21,120 --> 00:43:29,200
I love this package and I love what it says about the Swift package ecosystem, which is that we are,

426
00:43:29,200 --> 00:43:35,120
we have everything from something that will generate you a member-wise initializer for

427
00:43:35,120 --> 00:43:40,320
Astrux, which would be valid in any Swift program that you could write, pretty much.

428
00:43:40,320 --> 00:43:50,960
Two packages like this, which is called Swift ZPL by, well, I don't think it's a name,

429
00:43:50,960 --> 00:43:59,760
I think it's an abbreviation, but the abbreviation is S-C-C-H-N, but this package is a Zebra

430
00:43:59,760 --> 00:44:07,600
programming language enhancement for Swift. So it allows you to write this Zebra programming

431
00:44:07,600 --> 00:44:15,120
language faster, easier, and safer is the description of it. Now, do you know what ZPL

432
00:44:15,120 --> 00:44:21,120
or Zebra programming language is? I have no idea. I saw the package and I just briefly looked at it,

433
00:44:21,120 --> 00:44:26,320
but it didn't explain in the readme, so I didn't have the time to drill in. I just saw some

434
00:44:26,320 --> 00:44:36,960
further down, some barcode stuff. I drilled in. And so Zebra programming language is a command

435
00:44:36,960 --> 00:44:43,680
language used by a lot of printers, and it is a way to tell printers what to do, right?

436
00:44:44,000 --> 00:44:52,080
And so this is a way that you can write code to control a Zebra, a ZPL compatible printer.

437
00:44:52,080 --> 00:45:00,240
So you can say, change the alpha default font to this and have it use 50 heights. And then you can

438
00:45:00,240 --> 00:45:06,160
have a field and put some data in that field and you can define what to tell these printers to do.

439
00:45:06,880 --> 00:45:12,800
And I think, I mean, obviously this is a extremely niche package. This is not going to be

440
00:45:12,800 --> 00:45:19,360
included in many people's projects because it does a very specific thing. But actually,

441
00:45:19,360 --> 00:45:24,880
that's what I love about this package is that this is going to make somebody's day, right?

442
00:45:24,880 --> 00:45:30,800
Somebody is going to have this task. They're going to go, I wonder if package, there's a package for

443
00:45:30,800 --> 00:45:36,480
it. They're going to search Swift package index, and it's going to make somebody incredibly happy.

444
00:45:36,480 --> 00:45:41,760
It's only going to make five people happy in its entire life, but they're going to be so happy.

445
00:45:41,760 --> 00:45:49,200
And that's why I want to talk about it because I think a thriving and kind of

446
00:45:49,200 --> 00:45:54,320
comprehensive package ecosystem includes stuff like this that can

447
00:45:54,320 --> 00:45:59,200
take a ZPL compatible printer and generate a barcode in three lines of code.

448
00:45:59,200 --> 00:46:04,720
Yeah. I mean, you can see this be super useful if you have that sort of printer and need to

449
00:46:05,280 --> 00:46:11,520
output a barcode or a QR code. I mean, this looks great. There's even a Swift logo further down

450
00:46:11,520 --> 00:46:17,760
that they printed. Nice. This is a recommendation. It's just a recommendation for a small number of

451
00:46:17,760 --> 00:46:26,640
people. Yeah. Nice. And the Swift code is bang up to date. The ZPL, I would imagine, has been

452
00:46:26,640 --> 00:46:33,440
around for a very long time, but the Swift code, it uses result builders to build up the syntax for

453
00:46:33,440 --> 00:46:40,080
the ZPL programming language. So you just, you open up some braces and you start putting commands

454
00:46:40,080 --> 00:46:44,640
in there just like you would with Swift UI. Wow. That's amazing. So 37 episodes in,

455
00:46:44,640 --> 00:46:46,960
and we have a recommendation. That is fantastic.

456
00:46:46,960 --> 00:46:54,240
Yes. I need to work harder. You're right.

457
00:46:57,520 --> 00:47:08,080
My third pick is called Obfuscate Macro, and it's by our return guest, p-x9. I'm just double

458
00:47:08,080 --> 00:47:15,200
checking. No, there's still no further name. We had a package recommended before or mentioned

459
00:47:15,200 --> 00:47:22,000
before. I'm not sure whichever. Yes, I recommended one. I'm sure it was a recommendation.

460
00:47:22,000 --> 00:47:28,320
There we go. So this is obviously, as the name says, it's a macro package and it's a package to

461
00:47:28,320 --> 00:47:37,280
obfuscate strings in your binary. So you might know if you embed something in your code,

462
00:47:37,280 --> 00:47:42,720
like a static string, like a configuration variable that you don't ship from the server

463
00:47:42,720 --> 00:47:47,120
and you embed it in the library because it, for instance, never changes. But it's still something

464
00:47:47,120 --> 00:47:54,000
you don't want to leak. For instance, say you have, I don't know, some key for a symmetric

465
00:47:54,000 --> 00:48:02,720
signing or something or a passcode or something that can be found and printed. I think strings

466
00:48:02,720 --> 00:48:08,880
is the command you would use typically to see the text segments. I'm throwing around words here. I

467
00:48:08,880 --> 00:48:14,560
hope that makes sense. I've never tried it, but I know you can get it strings in a binary.

468
00:48:14,560 --> 00:48:20,160
Strings definitely does that, yeah. And so what this does, it scrambles these and you can

469
00:48:20,160 --> 00:48:28,000
just annotate your variable definition with a macro obfuscate and or rather not annotate it,

470
00:48:28,000 --> 00:48:34,720
you can use a macro command to assign it to a variable and then you can just let it do its

471
00:48:34,720 --> 00:48:41,600
thing. It picks an algorithm, I think, by random. You can also specify a specific algorithm that

472
00:48:41,600 --> 00:48:48,240
you want to use and there's a couple of quite a handful of options like bit shifting, base 64,

473
00:48:48,240 --> 00:48:57,600
AES, that sort of thing. And then it just generates some data and obviously also embeds a way to

474
00:48:57,600 --> 00:49:03,280
reverse it back into the string when you run your binary. And the result of that is there's no plain

475
00:49:03,280 --> 00:49:08,720
rendering of your string in the binary. If someone looks, they won't see it that way. They'd have to

476
00:49:10,560 --> 00:49:16,560
do more to find out what's going on. And my understanding is this isn't a foolproof way to

477
00:49:16,560 --> 00:49:24,400
actually make that operation safe. As the name says, it obfuscates the string in your binary

478
00:49:24,400 --> 00:49:29,200
and makes it harder for someone to reverse engineer it. It's still possible, but it probably

479
00:49:29,200 --> 00:49:36,480
puts up a high enough barrier to deter most folks from poking around and doing stuff with pulling

480
00:49:36,480 --> 00:49:40,800
out an API key or something for a service that you don't want them to be messing with.

481
00:49:40,800 --> 00:49:50,880
So yeah, there you go. Obfuscate macro by p-x9. Fantastic. And so I think that brings us to

482
00:49:50,880 --> 00:49:58,320
a close again. We're actually going to be back in three weeks this time and the next podcast will be

483
00:49:58,320 --> 00:50:06,160
the last one for 2023. So one more before the end of the year. But yeah, we'll be back in three

484
00:50:06,160 --> 00:50:11,680
weeks time and we will speak to you all then. All right. See you in three weeks. Bye bye. Bye bye.