Jake Bennett and Michael Dyrynda conquer a 14.5 hour time difference to talk about life as web developers
-Hey. I'm Michael Dyrynda.
-And I'm Jake Bennett.
And welcome to episode 182 of the North
Meet South Web podcast.
-Chuka, chuka, chuka.
-Let's j-
-Hey.
-Let's just assume you heard it. I don't
know why you don't hear it anymore, but it
definitely played.
I have no idea. It's, yeah, it's fine.
It's fine. Hey, everybody. Welcome to
episode 182. We're going to skip the chit
chat. Do you know why? Do you wanna know
why? I'll tell you why. I'm starting the
chit chat, but we're gonna skip it.
-Do it.
-I am... Um,
I think I'm entering that stage of life
where you're just perpetually tired, all
the time.
-Mm-hmm.
-I think it's just how it is. I think
there's... I don't think there's any
coming back from it. I think it is just
called life, and I think that's where I'm
at right now. And so I'm like, "You know
what? Let's just get into it." Like,
no need to, uh, you know, pretend like,
uh, we've got limitless energy here. Like,
let's get down to the nuts and the bolts.
But
that'd be missing one of my favorite parts
of the show-
This has been two weeks in a row that this
has-
... which is catching up with you,
Michael. How are things going, my friend?
This is, this is two weeks in a row that
you've been, like, tired, tired. Which is
-very unusual. So-
-Dude, it is. I think it... Well, I think
-it's going back to the school thing.
-It could be something, like, it could be
-seasonal.
-I think it's the changing of the weather.
-Yeah.
-Yeah. I think that may be what it is.
-Yeah, that's what it is.
-I am... We, we had like this pocket... So,
we're heading into spring now, and, uh,
Australians, we just say like the first of
September is spring. We don't, we don't
hang around for like the spring equinox or
whatever the heck. You know, it's not the
22nd of September. We start all of our
seasons on the 1st of the month. When
they- You know, on the q- on the quarter
that they roll around in.
-Respect. Respect.
-So we're heading into spring now, and, um,
we... Because it's spring, it's like sun
but it's also rainy. But then it's cold,
but then it's sunny, but it's not warm.
And so I had this pocket of time on the
weekend where I was like, "I gotta mow the
lawn now 'cause the weeds are getting out
of control." And
I'm gonna do it so that when the lawn
stuff... Which I just shared a photo of
the, the box that this came in in, in the
cash money. From that-
-Oh, okay then.
-It's a local company called Lawn Hub.
-Mm, nice.
-Which sounds-
-Good name
-... similar to another thing that is also
-a hub, and their branding-
-Oh, sure. Yeah, GitHub.
-Their branding-
-Yeah, sure. Yeah.
Yes. Yes, definitely. Um, and their
branding matches color. Like, all of the
-naming of stuff is-
-Oh my
... is very much in line with the other
hub.
-Mm, mm.
-And so, lawnhub.com.au. So I've, I've got
their stuff
had come in today, and so I had to mow the
lawn because you're not supposed to,
like, spray... I've got this spray stuff.
You're not supposed to fertilize the lawn
or do any of that kinda stuff within 48
hours, or 24 hours, whatever it is, of
-mowing 'cause you wanna catch the weeds-
-Okay
-... as they're in their growth cycle.
-Gotcha. Sure.
So I did this on Saturday thinking I
better do it now 'cause it's gonna rain
-on Sunday.
-Yep.
And then it didn't rain on Sunday, and it
didn't rain on Monday, and it hasn't so
far rained today but it's supposed to rain
this afternoon and all night today and
-then tomorrow and Thursday. So I've got-
-Gotta put... Yep. You're playing the game.
And, and it's like, okay, so I wanna do
this, and you're supposed to do all of
this lawn care, you know,
in September ahead of the growth period.
And it's like, I need to mow the lawn to
get it ready so that the weeds are growing
to then hit it with not the, not the weed
-killer but this is like a growth stuff.
-Okay, sure.
That is supposed to, like... It's a
wetting agent and, and a fertilizer that's
supposed to
spring the lawn into growth. And of course
the weeds-
-Okay
-... which are also there, and then as the
weeds are growing on day 10, you then hit
it with the weed killer. Now, I don't
-know-
-Interesting
... I don't know how you're supposed to
plan this because how do I know in 10
days, especially with the fits and starts
of spring-
-Yeah, yeah
-... when the rain is gonna come? Because
-you're not supposed to apply this stuff-
-Right before rain or anything like that,
-yeah.
-Um, right before rain, you're not supposed
-to, you know-
-You want it to be dry for a couple of
-days, yeah.
-So I don't know.
-It's tough, right? It's tough.
-So I'm just hoping it works out right.
Yeah. We've got a buddy, I've got a buddy
who does like... He's really big into
lawns and he's like, he goes out in the
spring and he measures his ground soil
temperature.
-Right.
-And so he'll like... If it's before, you
know, if it's before the... You know, you
wanna get your pre-emergent weed control
down between 58 and 61 or something like
that, and if you go, you know, I don't
-know. So anyway-
-Not to that extreme
... I just tell him like, "Hey dude, text
me when you're putting your stuff down."
-That's what I always say.
-Yeah, and I'll do it.
"Just text me when you're putting your
stuff down." And then I'll do it too.
'Cause he lives you know, you know, five
miles away, so I'm like, all right.
-Yeah.
-Chances are if it's, if his soil
temperature is all right, it's, mine's
going to be about there too.
-It'd be about the same, for sure.
-Yeah. Anyway, it's, that's a big help.
-But, uh, anyway.
-So yeah. So, so doing that at the moment,
but like trying to fit it in with, with
the weather is ridiculous.
-Yep, yep.
-And so, because I mowed the lawn even
though it was wet it was still enough to
kick up the pollen and so now hay fever
-season is upon me.
-Oh, hay fever it is. Yep. Here it is.
So, right. So this is my thing. You know,
I wake up in the morning, morning feeling
terrible, not wanting to get out of bed
because my head hurts and my nose is
congested and, and you know, we're back in
that. Fortunately, I know because I did
mow the lawn
and it is that time of year that I'm like
it is just hay fever.
That's what it is, yeah. It's not
something else. Yeah. Yeah, yeah, yeah.
I'm not playing the, the COVID or hay
fever game. So I feel rubbish in the
-morning but Re-
-The COVID or hay fever game.
... Re just
had
septoplasty because she's, like, she's
always had bad sleep. Like she will sleep
-for 12 hours, wake up and still be tired.
-Mm-hmm.
And so, you know, gets to a point where
you finally want to do something about
this. You're not gonna just accept that
this is
what it is. And so she went and saw an
ENT, an ear, nose and throat specialist
and they said, "You know, you are waking
as you sleep
but it's not enough
that you need to start looking at a CPAP."
You know, face mask while you sleep kind
of thing.
-Yep, yep.
-This option of the septoplasty was to go
in and to realign her turbinates because
she had a deviated septum in her nose.
-Ah, okay.
-So they go in there and... Like day
surgery, they go in there with a drill and
they go, you know?
-Oh.
-Do whatever they do and sort it all out.
Oh, nope, nope, nope, nope, nope, nope,
nope.
So it was like day surgery but she was,
you know, she was under for it, of course.
They don't do this while you're awake and
she woke up with-You know, like, no
bruising. They they do it pretty pretty
good these days. Because, you know, we
needed to start mucking around in there
around the place, it's like Oh, yeah. ...
right near the surface. So you would
assume there'd be bruising and stuff, and
I'd have questions to answer for a for a
few days after. Why has your wife got
black eyes and all that kind of stuff.
But, um-
Just stay home, honey. Just stay home.
I'll go do-
-Yeah. So-
-... I'll go do other stuff that you need
-to focus on something else.
-Yeah. So she was like ... She had a week
off work which was which was nice, you
know, took care of the kids. And it was
funny though because I said to her
halfway through Saturday, like, she had
this surgery on on Thursday, and I said to
her halfway through Saturday, I said,
"Look, I know that you had the kids for a
whole week while I was in Denver. However,
you had the kids for a whole school
week where you get them up in the morning,
you take them to school."
-And then you say goodbye. Yes. Yes.
-And you say bye bye, and then you and then
you see them again in the afternoon.
Which, don't get me wrong-
-You have them for a week
-... don't get me wrong, it's still ...
Yeah. But don't get me wrong, it's still
hard work. But there's seven hours out of
the day where they're not there.
-Agreed. Yeah. That's okay. Yeah.
-I had them Saturday. Right? I took them
grocery shopping in the morning. We we got
home at lunchtime, and I'm like, crap. It
is only lunchtime, and they're still
going. Like, they wanna keep going. I'm
like, I
I was so tired at the end of that weekend,
like, more tired than I've ever been.
-That's fine.
-But long, long winded way of saying, like,
maybe you've got sleep problems, and this
is why you're feeling tired.
Maybe. Maybe I do. Yeah. Or or maybe it's
just a seasonal thing too. I don't know.
I'm not sure. That's a that is a fair
question. Um, I do see-
Just don't be telling me it's still a
seasonal thing come December or come March
-if you like.
-Yeah. Okay. Fair enough. Let's let's keep-
You've gotta look into it.
Let's keep checking in. Yeah. Let's keep
checking in on this. We'll see we'll see
what's going on here, and I think that's a
this is a good you know, we'll we'll make
this a recurring section of the of the
show here. So
hey, with that out of the way, I am
actually really interested to hear about
something you've been chatting about with
me recently,
which is some of these fake HTTP stuff.
So, you know, we've talked about this on
the show a number of times, this idea of,
like, this gateway pattern and how we
structure it at Wilbur where, to give you
a quick rundown, we will create a gateway
class which is responsible for newing up a
client, setting up the base URL, any
tokens that would need to be retrieved or
pulled from the config to set up that
client. And then we will have methods that
make calls to endpoints and handle any
specifics around that endpoint, whether
it's caching or whether it's rate limiting
or whether it's, you know, massaging a
response that we get back or have it
handling an erroneous response and all
those things, which is great. But then
what we'll do is we'll, uh, bind that into
in the container, um, and we'll bind that
to, you know, an an interface. Right? And
that interface will be implemented not
only on the HTTP side of things, but also
we'll have a fake that returns
data that we have pulled probably from the
API, gotten a real response, and then
we'll sort of load that into the fake. And
we'll have, um, different responses a la
magic tokens. Right? So, you know, stripe
back in the day, you'd have 4242 gives you
a valid response and 4141 gives you an
invalid CVV, whatever. So we do something
similar to that. But I know that you guys
are big Saloon users, which if you don't
know what that is, listener, uh, you
should definitely go check that out. Sam
Carrey has an amazing package called
Saloon. Very popular nowadays. And I'm
interested to hear kind of what you've
been kicking around with that. So you've
been chatting about it a little bit, and I
wanna get a clear picture of what exactly
it is you're talking about
and if it solves some of the same problems
or or what you got. So go. It's all it's
-all you, my friend.
-Yeah. So, yeah, I
we
we're doing this integration at the moment
where we had, like, some old, old library
that was like, it's long since been
deprecated, no longer maintained. So we
had copied the vendor code into our
application code to integrate with
Salesforce.
And that was, you know, to to push leads
in there, to pull contacts out, things
-like that.
-So it's like a PHP Salesforce SDK sort of
-idea?
-Yeah. Basically. Yeah.
-Is that what it was? Okay. Okay. Sure.
-But it was you know, it was like PHP very,
very PHP
5 code.
-Okay.
-But, yeah, long since unmaintained. And at
some point in the last 18 months, I
think, like, fairly recently, we moved to
using this other library called Forest, f
o r r e s t,
and it allowed us to directly run SOQL, so
Salesforce object query language, I think
-it is.
-Interesting.
-Which is like the the version of SQL, uh-
-Okay
... that you can use to query Salesforce.
And we thought
-Customize the Salesforce. Yeah.
-This'd be a great solution. You know, we
can write the queries ourselves. We can do
it. Um, but there was not really a good
testing layer for it to the point where we
were using mockery and we were creating
mock expectations that, you know, this
method would be called with these
arguments. It would return this stuff. And
the problem with that I mean, number 1,
don't test what you don't own kind of
-thing.
-Oh, yep.
But but number 2, mocks and I know that,
um, JMack has been on an adventure trying
to improve this in, uh, I think, Laravel
specifically,
um, and he's gone off and he's been doing
other things that have come up in the
meantime. But he's been trying to improve
the messaging around when a mock
expectation fails. Because when a mock
expectation fails, it just tells you,
like, mockery underscore some, like, hash
or whatever that it's generated for this
thing. It's saying, expected this, but it
didn't happen.
-Yeah. Yeah. And it's very
-And that's it. Like-
It's not it's not clear at all. The the
error message itself is is horrible. Yeah.
It's horrible. It tells you that the
expectation is not correct, but you don't
know why. And so then what you end up
doing is, like, if you're a, quote
unquote, rule developer, you will go and
fire up xdebug and you would follow
through and look at all these things. If
you're a Laravel developer, you go and
start digging all over the place to see,
like, what was actually in this object.
And and then you're looking, like, what is
diff and whether you're using xdebug or
you're using DD, you still have to look
at, like, what is my expectation and what
is in the thing. And some of these
Salesforce objects are quite large. So
we've got 20 or 30
things in here, and you've got to look at,
like, what's missing, what's added,
what's different. Is it in a different
order? Is it somewhere else in the
-response?
-Yeah. Right. Yeah.
It's it's a whole thing. And so I was I
was poring through the... Saloon docs
a while back for some stuff, and I saw in
there that someone had written
a Salesforce
SDK using Saloon. I thought, "Great. I'm
pulling that in immediately. I don't even
have to read the doc, so I don't need to
know any more about it. It's written with
-Saloon, it's gonna be good."
-Yep.
And what that has
enabled us to do, uh, obviously is to use
Saloon under the hood, which makes testing
so much better because we can use Saloon
fake. We can say, "I'm expecting these
res- requests to go out, I'm expecting
these responses to come back." We can do
Saloon fakes, we can... Like, you know, we
can record fixtures-
-So in the testing layer, you can, yeah-
-In the testing layer
... record pictures and replay them back
out.
-Fantastic.
-Mm-hmm. Yep.
It has improved things a great deal to the
point where like, "Okay, we're gonna
replace this Forest library with the
Saloon SDK." But as part of this, I've
been doing some exploration, which is
like, I guess three-fold into, how do we,
how do we do this kind of stuff with, um,
local development? Like, I don't-
-Yeah, that's the question
-... want to be handing out-
-That is the big question.
-I don't wanna be handing out keys to
people to access Salesforce. Um, we, we
spin up and spin down Salesforce
test environments as needed. Like, we
don't typically keep them around. So, you
-might have-
-Sure
... credentials to do something now, but
that, that environment might be gone at
some point in the future when you come
back to it. Um, obviously we don't wanna
test in production 'cause you end up
littering your Salesforce instance with
all of these test accounts and things like
that. And so I, I started going down the
path of, okay, what does this look like to
actually create a fake? And you and I
have spoken about this, as you said
previously, where maybe you can just call
Saloon fake inside a service provider
somewhere and record some fixtures and do
all this kind of stuff. And so this, this
then led to my second point of ex-
exploration, which was using AI. 'Cause
yeah, I'm a big AI boy now, and I like to
I like to play with stuff. So I've been
using
Claude and I've been, you know, with open
code, which is from the SST guys, um, Dax
and, and Adam who are part of the, the
Terminal Coffee, uh, empire, um, have been
building out this open code thing. Which
is kind of like, it's like Claude Code.
It's a, a Terminal application, but it
allows you to hook into different
providers and access different models
through those providers. So we use GitHub
Copilot, um, which means we can't use
Claude as, as I understand it. Claude is
to access the Anthropic, I think, the
OpenAI, whichever it is, their Claude
-service using their Claude-
-Yeah
... CLI. And then I think Cursor's got one
and, you know, all these other companies
have got one. So what open code allows us
to do is to authenticate against GitHub,
and then we have access to whatever models
we have access to inside of GitHub
Copilot. So I can use Claude to then do
this stuff. So I've been in-
-Interesting
-... planning mode. I spend like 45 minutes
just going through, like, "I wanna do
this, I wanna do this." Like, blah, blah,
blah. You know, come up with whatever we
wanna do. Switch to build mode and say,
"Okay, now go build that." And so what
I've been doing, and it's been literally
days 'cause I'm like feeling my way
through it. I'm not necessarily liking the
output or it's, it's partially
implementing things. So, you know, which I
think anyone that's been using AI for any
period of time knows that this is kind of
the process. Treat it as a junior
developer that you're pairing with, and
that's typically how you're gonna go. So
we have been building out a, a fake
gateway,
as you've done with Stripe, where
in some instances, like if we wanna do a
search for a contact or an account,
there's like, here are the, here are the
key phrases that you pass through. You
know, search for Michael and you'll get
like three results back that are like
-Michael A, Michael B, Michael C.
-Sure.
If you search for Michael Dorinda, it will
return a single result, Michael Dorinda.
Um, and so we've done this. Uh, I, I
reached out to Sam Curry, the author of
Saloon, and I said, "What is the approach?
Like, how do we do this?" And he said,
"You know, there's a few people that have
asked about this recently." And like a day
after I'd asked about it, Alex Six from,
um, Zillow who spoke at Arc on US,
um, he, he had pinged Sam
on X and was like, "Hey,
is this possible?" And so, you know, we
had this conversation about, yeah, we're
exploring this at the moment. And what it
essentially boils down to
is hooking into Saloon's global middleware
and, and putting our own handler in there
that basically looks at, okay, is this
enabled? Is our fake gateway enabled? So
with an environment variable and a conf-
uh, environment variable and a config
switch, you know, if this is enabled-
-Yeah, yeah
-... everything should go through our
-Salesforce mock handler.
-Yeah.
And then the, I've iterated on this a few
times where I've landed with like this
registry patent approach where we just
register all of the, the response handlers
we want. And each response class is then
responsible for providing its own should
handle method. And it will look at the
pending request and say, "Okay, is this to
an endpoint that I'm in of interest of?"
And so we've got 20 or 30 of these at the
moment, and it would just like spin
through them all and go, "Okay, this is a
post request to the contact standard
object endpoint. I'm gonna intercept that
request and I'm gonna return this
response." And so we're then using Faker
to just send back fake data. Um,
and then where you can, you can seed Faker
-with a, with a value, right?
-Okay.
So that you get deterministic
fake data back. So what we do is take all
of-
-I never heard of this.
-Okay. So deterministic data
is where like you are, it's pseudo-random.
Like it is random data, but it will
always be the same random data based on
that seed. So you pass it a number from
like one to whatever the upper limit is
that it supports, and then it will see the
random number generator so that when you
call Faker whatever,
it-Internally, it will process that. You
know, it'll go through its array of 50
names, and if you've got a seed of 3, it
will always return the seventh value from
that list of 50 names for first name.
And then the next time you call it, it
will always return the same value and
then... So then when you are developing
things, if you search for Michael, you're
going to get the same Michael back every
single time on every single machine.
-Because if you-
-Interesting
... are searching for Michael and you get
a different fake value back, you know, in
the UI context, it doesn't make sense, you
know?
-Yeah. Yeah, yeah, yeah.
-But with deterministic seeding, it means,
okay, here is, here is the value that I
want to base all of my random data on, and
it will always do that. So what we do is
we look at the body of that pending
request. We take all of the inputs,
we join them together, and then PHP has
this function called CRC32, which will
take a string and it will compute an
integer value that represents what that
is. And then we pass that value into, um,
into Faker's seed method
so that we're always getting this data
back. And so-
-Interesting
-... we've, we've now built out a fairly
robust, um, implementation that will
always give us, like, pseudo-random data,
but in a consistent way. So, like, if
we're searching for something, you know,
we can, we can build our expectations on
it, we can build tests on it 'cause we
know that, like, the fake data won't
change every time we run the test. We know
that we're always gonna get the same set
of data back. So we can actually write
tests against all of these endpoints with
the fake gateway enabled, knowing that
we're gonna get back this specific data.
That then extends-
-So when you say you seed it, you're not-
-Yes
-... seeding a database.
-We're not seeding a database, no.
'Cause they're not models in your
application.
-No.
-You're seeding the responses that are
gonna come back from your mock handler for
Salesforce.
-Correct. Yeah.
-Yeah, yeah, yeah.
-Uh-huh.
-So it's basically like with Faker, you're
almost creating... I mean, it's not a
database, but it's almost a database
because it's pseudo-random. I mean, it's
deterministic, right? So you're-
-Mm-hmm.
-When I'm hearing you say, like, you're
referencing, like, an ID, it's basically
like you're referencing an ID in a
database that actually does not exist
because it's just seeded-
-Correct. Yeah.
-You know, seeded fake data, essentially.
-So-
-Wow. Yeah
... you could think of it almost as a
sort of database, I suppose. I mean, it's
not a database, but, like,
same idea, right? Where it's
deterministic, you can write tests against
-it 'cause it's not gonna change.
-Right.
So it's almost seeded data, but you don't
have models backing this stuff.
-Correct.
-So you have to use some other sort of
-mechanism to do so.
-Yeah.
-Okay.
-So you're, you're seeding the random
number generator that PHP uses, which is
using, like-
-Yep. Yep, yep
-... MT Rand or whatever under the hood.
Yeah. MT... Like, it's a PHP function
under the hood. So if you always want to
get the... This is quoting from the Faker
docs. "If you want to always get the same
generated data, for instance, when using
Faker for unit testing purposes, the
generator offers a seed method which seeds
the random number generator." And the
crux of that is that calling the same
script twice with the same seed produces
the same results.
-Interesting. Okay.
-And this, and this-
-Okay
-... is then why it becomes helpful in, in
the... Like, in a, in a UI context where
if you are seeding based on the inputs, no
matter what you put in there... Like, if
I put Jake in there
or I put Michael in there or I put Eric in
there or I put Sam in there or whatever,
as long as the inputs match, you will
always get the same results back, which
makes the testing a bit more predictable.
If you hand that off to a QA team or, you
know, for testing, or manual whatever, you
know that you, that it's... Like, it's
not gonna make people stop and think,
"Wait, what happened there? 'Cause I got
two different results back." It's like,
no, if I search for Jake-
-Yeah, I guess, yeah
-... the same set of results come back.
Right. So it's like you only... The only
benefit that you lose of fake data is that
the randomness of it is sometimes a bit
of a fuzz test against, you know, can your
code handle values that are not typical
sort of deal?
-Yeah.
-Right?
-Yeah.
-And so that, that's part of the idea of,
like, Faker, which is like, "Hey, it
should be able to generate any value and
it should always work." But it's like,
there are other considerations to be made
too, and so you're just making a
trade-off. You're saying, "Well, we're
okay with losing some of the benefit of
that randomness for the predictability of
having deterministic values that are
getting seeded in here," and for all the
other me- reasons you mentioned.
Interesting.
-Yeah.
-I've never actually heard of this, so
-I'll, I'll check into that.
-Yeah.
-That sounds really cool.
-And so in, in the context of, like,
actually opening up the application in the
browser and, like, using it, I think it
-makes-
-Yeah, yeah
... much more sense than having totally
random data.
-Mm-hmm.
-Because if you think about it, if I'm, if
I'm hitting Salesforce and searching for
Jake, well, I expect-
-Yeah
-... Jake's data to always come back. I
-wanna see-
-Absolutely, yeah
... the same results. And so that's where
this comes in. And, like, this stuff has
been in Faker, I don't know, since
forever. And the reason that, like, I'm,
I, I know this fancy word, deterministic,
is 'cause I built this, um, avatar
generator for Laracon AU, where I wanted
it to be random, but I wanted it to always
be the same for a given input. So if I'm
gonna generate an image-
Yeah, it's, it's almost like functional,
right? I mean, it's f- it's almost like
functional programming where it's like
given the same inputs, you should expect
-to get the same outputs every time. Yeah.
-Yeah. Yeah.
Um, and so, yeah, that, that, that has
worked really well in that context and
provides us, like, much more useful
output. I'm, I'm not sure... I still need
to do a little bit of finagling to make
sure that I'm actually happy with
-what has been built. Because-
-Yeah
... largely it has been just, like,
driving the AI and letting it come up-
-Yep, yep
-... with stuff and fixing things as they
come. But it's, it's been pretty good in
terms of
building the code,
finding problems. Like, I've got it into
this loop now where we put into our Claude
file,
um,
you know, make sure that you always run
PHP unit on the test. Make sure you always
run CS Fixer. Make sure you always run
Stan, so if you've introduced any
violations, like, it'll go back and fix
those things as well, which has been very
helpful. Um, so I think the, the code is
robust. I think the, the... Then the third
exploration is, okay, we've built
this thing. Is this something that we
can... I don't know if we can package it
up or if we produce a set of guidelines or
something that go, "Okay, now for the
other things that we want it to
have..."... mock gateways for. You know,
for a lender integration with a bank or
for a provider of, like, you know, Equifax
or something like that where we're doing
these lookups. Well, we- we want the- the
same data to always come back, but we
don't wanna hit Equifax 'cause that cost
-money every time you do that.
-Again, and it will... And like you said,
it's deterministic in a sense. You don't
have to spin up an Equifax-
-Right
-... non-production environment sort of
-deal.
-Correct.
Like, it's like you just get all those
benefits that you're talking about. Now,
there are, you know, there does end up
being some drawbacks, but, I mean, you
know, there's drawbacks with the current
approach. So you just have to... It's the
-trade-off, right?
-Yeah.
-Um, you know.
-So in- in our tests, right, in our tests,
we would still want to- to do this kind of
stuff with actual fake data. And that's
where we'd dip into the Saloon fakes, and
we would use our fixtures and all of that
kinda stuff. In terms of actually using it
-by hand-
-Yeah, yeah
... in the browser, yeah. Then, but- so
then the exploration was, okay, how do I
build this
infrastructure
where I've got, like, a config file? Okay,
okay, here is Salesforce, but now here is
Equifax, here is bank A, here is bank B,
here is lender A, all of these kinda
things. And I just configure them in
there, and they'll register themselves,
and then they'll find, you know, okay,
this is the thing that needs to hit this.
And it all goes into Saloon's global
middleware and whatever needs to- to deal
with any given request. And we can build
these over time. So I think I'm happy
enough with it that I think that it will
work,
and it seems to cover all of the scenarios
that exist currently
until we start using it in practice and
figuring out, okay, how do we
create the next gateway, the next mock,
the next mock, you know, and actually
using it. That will be the determining
factor about if this approach is actually
robust enough to be that flexible across
the board, so.
-Yeah, yeah.
-We'll see. We- we might revisit that in a,
in a few episodes and see if we've made
any progress on it.
Yeah, it's like you're trying to look into
the crystal ball and determine what the
-future's gonna hold, right? It's like-
-Yeah.
It's- it's so funny, like, I... We talked
to... We talked to the dev team about
this, and they're totally on board with
that- that approach where it's like
sometimes you just gotta ship it and see.
You know what I mean? Like, just- just
push the button and, like, you're not
gonna have the final answer. But, like,
we're not building pianos here. Like, we
can go in and change the code. Like, it's
not a big deal. You know what I mean? It's
like it doesn't have to be perfect the
first time. It just has to be good enough
that it's not gonna break everything. And
if it's good enough, then it's like you
can make modifications as you go, right?
Um, but trying to make predictions about
how it's going to be used everywhere, it's
just impossible. And I feel like my IT
team, they are on that train. They're
like, "We have to have all the variables
solved before we push the button." It's
-like, you don't.
-Mm-hmm.
-You don't.
-Mm-hmm.
You just need to have enough information
to make a good decision and then push it
and see what happens and then learn and
move from there. But you can make
decisions and make changes a lot faster
that way than you can hemming and hawing
and waiting around and trying to get the
perfect answer. And it's like you won't
have the perfect answer until you actually
start moving, then you're gonna figure it
out. So, um, but the other part I was
gonna say is, like, this registration
piece that you're talking about where,
like, you're registering all the different
responses and things like that. And I'm
sure you'll find a way to organize this
well, but, like, right now, two things.
Number 1, they're probably tied to actual
-endpoints, I'm guessing.
-Yeah, so the... Each response has its own
should-handle method, and it gets past
the- the pending request object. So it
goes and looks like it... You c- 'cause
then you've got access to the request
itself, and you can figure out, do I need
to intercept this or not? And
depending on what it is, you know,
sometimes it's- it's enough to just look
at
the endpoint. Sometimes we wanna look at
the endpoint and the body and go...
Because then we've got for authentication,
for example, we've got an email, like a
specific email address for a successful
login. We've got a specific email address
for a failed login, a specific email
address for, like, a- an account that
doesn't exist, like all of these kind of
things. So some of it gets a bit grim. Um,
some of these methods have got some
creative regexes that Claude has written
in there.
-Yeah.
-Which may or may not be the most
-appropriate course of action.
-Yeah.
But you... I mean, in- within the context
of each of those response classes, you can
do whatever you want to determine if it
should be handled.
Yeah. And so I guess that's what I'm
trying to figure out is, like, how do you
co-locate the code that's going to be
handling or that's gonna be responsible
for figuring all that out? And I'm sure
it's, like, you can have, like, some class
double, you know, dot op generate or a
class dot op register handlers or
something like that, where you can kind of
just say, like-
-Right
-... for this particular type of response,
we're gonna have a class named this that's
going to be, you know, by convention,
it's gonna match the naming like this, but
it's gonna be called, you know, blah,
blah, blah, response register handlers
class.
-Yeah. Yeah.
-And then, you know, you just call that,
-and there you go. And, and so you can-
-Yeah
... break it up so it's not like some
massive
just config file, essentially. You know,
there's actually some testability even
around your- your registrations and things
like that, if you needed it to be as, uh,
-as sophisticated as that. But-
-Yeah.
-Maybe not.
-At- at the moment, this, like, registry
that we have, it just, like, you
pass it a, a namespaced path, like
app/gateway/sales floor-
salesforce/fake/responses, right? And it
will go and look in there, and it will
look through... Like, it just looks
through all of the files in there. And if,
if it's a non-abstract class and it
implements an interface that we've got on
there, it will then register it
as a, as a handler. And then it will...
And then the
Saloon is then responsible for passing all
of those
things through and figuring out, should I
be intercepting this request? So it is-
-Mm-hmm, mm-hmm
-... it has been done in such a way where,
like, the registry will go and just, like,
discover all of these things
automatically and then just slot them in
there. So definitely don't run it in
-production.
-Right, right.
Because you could be registering, like,
you know...... dozens to hundreds of
classes for all of your Saloon
implementations. Um, but locally, like, it
doesn't matter too much. Our machines are
so overpowered and over-provisioned that-
Totally
... having this do it. No, and especially
if you're just enabling them one by one.
So there's, like, the top level
is this thing that spins through the
config and then registers all the
handlers, and then each handler is
responsible for then going and registering
all of its responses. So if you've got
them all disabled, it'll just spin through
that top level four or five or ten or
however many integrations you've got
fairly quickly, and it'll just do nothing.
Like, we just filter them out of the
collection.
-So-
-Yes
... I would like to share some code in
time once I've-
-Yeah, absolutely
-... you know, happy that it is, it is
actually a sensible approach. But, you
know, early indications, um,
with, like, just the Salesforce
mock, uh, seems to be good. The proof will
be in the pudding of whether or not it
actually extends to other handlers. And
I've been trying to kind of guide the AI
to make sure that this is extensible. And
anytime we start duplicating things, it's
like, "Okay, let's pull this out, let's
hoist this up to the top-level namespace,
let's, you know, make sure this is all
possible." 'Cause it is something that is,
in my mind, that, like, we need to be
able to do this. So, I think the, the main
thing is just... Salesforce is a very
large thing. Like, there's a big surface
area of things that you can do. And so
there's lots of overlap to the same
endpoints. But when you've got discrete
endpoints, it's much easier to have, like,
a common thing that just, like, injects
fake data based on the request kind of
thing, so. I, I, I feel good about it, but
I'm still, um, cautious about
how well that works as we start
integrating more. So we'll see how that
-goes in time.
-That's exciting, dude. Yeah, I'm excited
to hear about that. That's, um, that
sounds really cool. Uh, yeah, so we'll
follow up on that in future shows. A
couple of things I wanted to share real
quick before we wrap this one up. Bond is
a new thing by Filip
Gagnik, Gagniks. I don't know how to say
his last name. Anyway, he's a Livewire and
Alpine dude, and he just released this
library, Bond, uh, which is this
interesting way
to
give you essentially, like, fully
reactive, optimistic UIs on the front end
that are also Livewire-aware. So you get
the best of front-ends, like with
modern JavaScript tooling, like being able
to do includes and things like that,
um, and bundling and
all those, all those pieces,
and then also all the benefits of
Livewire. And so in his demo, that he put
out a video today about this,
um, he goes through and shows with this
counter component, it's fully reactive,
and it's like he can plus, plus, plus,
plus, plus, plus, plus on this counter.
And then in the bottom he has like,
"Here's what the Livewire server rendered
-value is." And you can see-
-Hm
... that on the front end he's able to
click it as fast as he wants and the front
end stays reactive and it doesn't make
those back-end calls, and then it sort of,
like, lazily updates that background,
that background, um, amount. And then when
it makes a round trip, it ends up
updating that, that thing on the front end
as well. Um, but your front end allows
you to continue to go just as fast as the
browser front end will allow you to, as
long
-Yeah
-... as long as the, you know, user's
machine is able to catch up or, you know,
keep up with your JavaScript, uh, front
end interactions. It will take care of
sort of eventually syncing in the back end
-which is really, really cool.
-Mm-hmm.
We've needed this in a couple projects,
and, um, he's got some, uh... It's just
very interesting. It's got TypeScript
support, um,
-super, super cool.
-Interesting.
-So Vite basically will pull out-
-Do you wanna-
-Go ahead.
-You'll have to send me a link so I can put
-it in the show notes.
-Yeah.
-It sounds interesting.
-Yeah, absolutely, I will. And I'll, I'll
send you the, uh, the video that he made
here.
-Mm-hmm.
-It's really, really good. Uh, Wilbur
Powery, uh, talked about it, um, today in
our, in our dev chat. So there's the video
and then I will send you the open source
repo as well. Both look really, really
cool. It's a nine-minute video. You should
definitely check it out. Really well
done. Uh, he seems like he, he essentially
manuscripted his video that he was gonna
do. It's, it's nine minutes and it's just
pure code. Like-
-Nice.
-... doesn't stumble over one word. It's so
well rehearsed. It's the best video on a
new thing that I've seen people, you know,
started to put out in a while. It's
really, really good. So
shout out, Philip. Good job. Secondly, uh,
we've been talking about our journey, uh,
at our company of restructuring a lot of
our roles and permissions and things like
-that.
-Mm-hmm.
And how we've sort of split the
responsibilities between, uh, basically
saying our application's only
responsibility is to check permissions
-with gate checks.
-Yes.
And then what we've done is we have bound
those particular abilities to AD groups.
And we've done that using... In AD, I mean
active directory. We've done that using,
uh, enums and enum attributes, which I
swear is one of the most productive secret
ninja combinations ever. Enums with
attributes is just-
-Mm-hmm
-... awesome. It's so cool. Um, it allows
you to have, like, type safety and also to
bind additional pieces of information
directly next to enums, which I just
absolutely love. So really, really cool
combination. I'm liking that. And I feel
like we've arrived at some conclusions,
um, about how we've found to best
structure some of those things,
specifically regarding, like, departments,
job titles, and stuff like that. So, um,
I'm interested to share some of those
maybe in a couple weeks and-
-Mm-hmm
-... talk about that and some of the
discoveries we've made, and maybe talk
about this Bond thing too. We are-
-Yeah
-... right now in the process of creating a
two-way interactive texting experience
through SMS. So people who wanna get hold
of our agents, they can do so through SMS.
We're using Twilio Conversations.
But...... we're pulling a lot of the
Twilio Conversation stuff local. We're
-saving records on our side.
-Mm-hmm.
Um, Twilio's, like, the source of truth,
but we'll pull those down to our side, so
we have database records then can- can
basically enrich that data with our own
data. Um, and we're using a LiveWire front
end. We're building on a LiveWire front
end, which is great, but this idea of,
like, the optimistic UI is very
-attractive-
-Mm-hmm. Yeah
... because sometimes it does, it can feel
a little bit laggy. You know what I mean?
If you're doing, like, high volume
interactions back and forth, or you're
trying to say, like, "Who's..." You know,
"Which one of our team members is
currently in this conversation?" How are
we able to, you know, using presence
channels or some of those things.
Sometimes it can feel a little bit laggy,
or notifications if a new thing comes in.
You know, you have to kind of loop over-
-Yeah
-... a bunch of stuff in the background.
Anyway, um, I'm interested to see if this
is something we can start using and, um,
since Wilbur Power is the lead on that
project, and he's the one who discovered
this library, I'm interested to see if
this is something we might actually use in
the next couple of weeks as well. So,
looking forward to that in the next show,
-I suppose.
-Yeah. Yeah, so, um, Ash Allen, I think it
was, tweeted something out about putting
methods on enums.
-Okay. Yeah, yeah.
-Um, to, like, to- to return a label for
something. Because, you know, your cases
and your names don't always match up with
what or how you wanna present that to the
user, so he was talking about, you know,
having a ToLabel method for things that
would then return
something that you could just put into
your UI as opposed to what you're storing
in the database. And then someone had put-
mentioned in there that, yeah, you can
create attributes here that target, um,
like, the constants but, you know, enum
members in that case, where you could put
like a pound square bracket label
whatever, and then you've got labels
available through that as well. So, I
think that's a, a, a, as you say, a really
powerful combination and it gives you a
lot of flexibility
across enums, not just... Like, I don't
have to create an, you know, a label
method here or ToLabel and then a map and
then, you know, match the value to
whatever. You can just put it straight
there on the, um,
on the- the enum member itself, and then
you can do it on a case by case basis.
Like, you would expose the label method
directly and would say, like, "Hey, is
there an attribute here?" or return the
value of the attribute. Otherwise, you
might do, like, a string snake or a string
title or whatever it is to, you know,
have some fallback where you wanna do it
that way. So, yeah, I- I-
-Yep. Yep. Really, really powerful combo.
-I do- I do think enums and attributes go
-together like lamb and tuna fish.
-Yeah. Lamb and tuna fish. I've not heard
that. That is a new one on me, and, uh, I
love it. I- I will add it to my list-
-Pretty sure it was from Big Daddy
-... of things that I tell my friends.
-I- I will tell my friends when-
-Big Daddy originals
... when we talk about Australian
colloquialisms. So this is not a, this is
not an Australian thing? Lamb and tuna
fish?
-No.
-Oh.
Lamb and tuna fish was a, it was a
character... Uh, it was Big Daddy. It was
a character that, um,
-uh, Rob Schneider played in that movie.
-Okay, okay.
Where he was... Yeah, he was, he played,
like, you know, as Rob Schneider did back
then, he played like a foreign, non-
nondescript-
-Sure
-... foreign character. And he, yeah-
-It's hilarious.
-I'll put a link in the show notes.
All right, I'll have to check it out. Hey,
what episode are we on? 182?
-That's right.
-182, folks. Thanks so much for hanging out
with us. You can find show notes for this
episode at northmeetsouth.audio/182. Hit
us up on
X or on BlueSky at jacobbennett and
michaeldrinda, or at North Meets... Or,
North South Audio. And of course, if you
liked the show we would really appreciate
it if you'd rate it up in your podcatcher
of choice. Five stars would be incredible.
Thanks, folks. Until next time, we will
see you. Bye-bye.
Bye.