Flavours of busy, restrained features, and variable static views
Hi. I'm Michael Dyrynda.
And I'm Jake Bennett.
And welcome to episode 178 of the North
Meets South Web Podcast. [rock music]
Nailed it. Good job, dude. How's it going?
Nice. Going well. Going, uh, yeah. Going
well.
-Busy-
-Good
-... but but well. How about you?
-Great. Yeah. No. Same. Same. I [sighs]
I've tried recently.
I I catch myself saying the same answer
that you just gave a lot, which is busy,
-right?
-Mm-hmm.
And and i- it's true. Like, it's not a
lie. I mean, we are. We are busy.
-We're all busy.
-But I realized after a while that I would
ask people the same question, they would
say the same thing. And it's like, you
know what? We're all busy. All of us,
we're all busy.
-Yeah.
-Like, so-
All busy all the time.
Yeah. I tried to stop saying that, but it
doesn't work very well 'cause it's still
typically my answer. "How are things
going?"
-Yeah.
-"Oh, you know, bus- pretty busy. But busy
work, but the good. Things are good.
Things are good." You know, so whatever.
-So-
-I mean, I don't, I don't know how else to
-answer the question because that's-
-I know.
-That's how I am.
-There's so many things going on. It's like
-I have to pick one thing to talk about.
-Mm-hmm.
Uh, it's like I I could talk about a lot
of things, but there's a lot of things
-going on, so I'm busy.
-Yeah.
-There's a lot, you know?
-Yeah.
-We all are.
-Busy.
-We all-
-Busy, busy
... are.
You reach that certain stage in life where
you, you think... Uh, I remember thinking
when our kids were little, like, "Man,
once my kids can feed themselves and tie
their own shoes, then things will probably
slow down." And it's like and then they
get older, and it's like then it's
friends-
-Gets harder
-... and sports.
-Yeah.
-And you're like, "Man, after basketball
season is over, then then things are gonna
slow down a little bit." And it doesn't.
-It just keeps going faster-
-Yeah
-... and faster and faster and faster.
-We're we're just moving into that phase
-now with Eli playing sport and soccer.
-Mm-hmm.
-And now it's-
-Mm-hmm
Liv has decided that she doesn't always
want to... I think more often than not,
she doesn't want to go to the soccer
games, which is fair enough-
-Mm-hmm
-... 'cause it's cold-
-Yes
-... and she's sitting around and she's
-bored. And-
-Sure. Yeah. Yeah
... she's not really interested in it. So
because she's not participating, she
doesn't doesn't really wanna be involved.
And so one week, I'll take Eli to soccer.
-One week, Ria will take him. And so-
-Oh, nice. There you go
... it's back and forth, and then, like,
figuring out who's going where. And and
now that the kids are a little bit more
independent and it's a bit easier to do
things. Like, before, when we'd, like,
bath the kids, we want all hands on deck
'cause someone will be washing one,
someone will be drying the other one,
-getting them ready for bed-
-Yep.
-And all that kind of stuff.
-Yep. [laughs]
Now
now both of them can basically wash
themselves, except when it comes time to
washing their hair. And Eli can dress
himself, so it's like you... Uh, we just
watch them get in and out to make sure
that they don't-
-Get in there
-... slip on the bath.
-Yep. Yep.
-You know, so that makes it easier to,
like, go out during the week so that, you
know, Mum can put one of them to bed or I
-can put one of them to bed, feed them-
-Yeah
... all that kind of stuff. And and it's
not like this overwhelming chore of of
having to do all of that stuff because
they're quite independent
already. Um, and so that that makes life a
lot easier, so that we don't have to have
two people here all the time. It makes it
easier for for Rhea to go to the gym or
for me to go out and and grab a bite or
something like that, so-
-Yeah. Yeah. Very true.
-It's just a-
-That is true.
-But it's a different kind of busy, as you
-say.
-It is different.
-You know?
-Yeah. That's right.
-It's just phases-
-Yep
... of busy. And then, you know, once they
get to-
-Exactly
-... the age of your kids, at at the other
end, it's, like, more professional sport
kind of commitments. Not not professional,
-but, like, higher level of of sport-
-Yeah
... commitments, where
it's training multiple times a week. It's
playing multiple times a week. It's all of
-this kind of moving around-
-Right. Right
-... where we now-
-They're trying to get better. Like, when
they're younger, it's like they're just
trying to play. They just, they're happy
-to just play.
-Yeah. Mm-hmm.
And, like, at this level, they have to
kinda decide if they wanna be... If this
-is what they wanna do, if they don't.
-Yeah.
And if they do, it's like they've gotta
commit to practicing outside of the
-practices and games and stuff.
-Yeah. That's right. Yeah.
And so it's like if you actually wanna get
playing time and be good, you gotta do
stuff outside.
-Mm-hmm.
-So coordinating those times as well and
-whatever. So...
-Yeah.
It's all lots of fun, man. It is all lots
of fun.
-It's good though.
-But those, for like, for Graham right now,
he's 14, so it feels like the clock is
starting.
-Mm-hmm.
-The countdown is on. You know what I mean?
-It's kinda-
-The countdown to college because it's very
-different for-
-Give as much time as we can with him
-... for you guys over there. Mm-hmm.
-Yeah.
-'Cause what's-
-Yep.
Over there, very, very common for, you
know, um, kids to to pack up and go off to
-college and not-
-Yep. Yep
-... not stay at home and-
-Totally
... and be away for for months at a time
between breaks and things like that.
Whereas here, they, they, generally,
people will still go to university
where they grew up.
-Mm-hmm.
-And and it's like you'll catch a bus to
the city to, like, go, and then you'll
come back home at the end of the day. So
it's it's very different, you know,
hearing those perspectives. I see Abigail,
you know, tweeting about it, that they're
they're running out of summers with the
kids at home and the kids being around and
all that kind of stuff. And it's just not
something that really
crosses our... my mind because
short of going to the
join the army, you know, like my my nephew
did, you don't really... Like, most
people kind of tend to stay where they are
until they finish study. Not a lot of
people will travel interstate for study.
Um, I think that's fairly uncommon here.
-Interesting. Yeah.
-Yeah.
-Yeah. That is a cultural thing.
-Or is this, like-
-I think-
-... part of the course for you guys?
I think... Very, very common. Yeah.
Exactly.
-Mm-hmm.
-And a lot of kids see it as their first
opportunity to sort of escape their
hometown. You know what I mean? It's like
-they wanna get outta here.
-Mm-hmm.
They wanna go experience the world, live
somewhere different, live apart from their
parents and family. Kinda have their their
leap into adulthood, if you will. So-
-Yeah
-... which comes with the pros and cons,
you know, because they're only 18, so
they're still kids, man.
-Yeah.
-It's like-
-Yeah.
-... you can make really stupid decisions
as 18-year-olds. You can make really
stupid decisions as a 40-year-old too.
-But-
-Yeah
... got a little bit more life experience
behind you. So, anyway, yeah. It's, uh,
it's fun, man. It's, it's been a good
start to the summer, and
things are going good.
Um,
last show, when we were talking, um, we
came up with, like, a bunch of things that
we wanted to talk about, and so I wrote
them down. And we talked about how we
wanted to sort of have a little bit
more... What did you call it? Like, not
-consistency, but, like-
-Continuity.
-Continuity. That's it.
-Yeah.
That's the word. Continuity between the
shows. And so last time, we were talking
about
Wistia, talked about the new Wilber Jobs
website and how-
-Mm-hmm
-... that w- that was pretty cool. Um, I've
got a couple things we could talk about
with that. Staggered CSS animations, live
photos, we could talk about that. Or we
could talk about where to store values for
templates in static sites. That's an
interesting one.
-Mm-hmm.
-Or defensive programming.... or time
bombed feature flags. All right, which one
sounds the most interesting to you?
Hmm. Time bomb feature flags I've played
with in the past, and they've bitten me-
-Yes
-... because they don't, they don't work-
-Ooh
-... quite as, quite the way that I thought
they would.
All right, let's dive in. Let's dive into
time bomb feature flags. Okay.
-Should I set the stage real quick?
-Mm-hmm.
You wanna tell me what Pennant is? Tell
us, tell all the people what Pennant is.
Pennant is a Laravel first party
implementation for f- feature flagging,
uh, in, in your Laravel apps, right? So
Tim McDonald-
-Yeah
-... built, built that one out, hmm, not
last year, the year before, I think. So
it's a couple of, couple of years-
-Yeah
-... it's been around now. And, yeah, it's
a, it's a first, first party, you know,
it, it feels like a Laravel implementation
of feature flags.
Yeah, it's, um, it's a really good,
um, it's a really good library, and it's
very simple. Um, so it's,
you know, it's basically the minimum
amount of code that you would need in
order to be able to run feature flags is
kinda how I think of it. So
it's really, um,
wonderfully simple. Uh, the couple of
things that we, the way that we use it is
you have...
You can either have a closure
that helps to give it a name. You can name
the feature and then have a function that
accepts a scope and then resolves the
truthiness of that feature.
So
you say, let's say, um, the feature is,
I don't know,
Ken Call Michael. It's Ken Call Michael.
The, you know, one of our support people
gets a emergency button on their
dashboard, which if they need help, they
can call Michael. And only certain people
get access to this because, you know,
there's people who have abused this in the
past. And so we wanna start out with only
giving it to managers, because managers
are the ones who, uh, can escalate calls
to Michael. So what we're gonna do is
we're going to thi- name this feature Ken
Call Michael, and, uh, the way that I'm
going to do it is I'm going to implement
it inside of a class called Ken Call
Michael Feature. And, um, inside of that,
I have a resolve function, or sorry,
resolve method, which accepts a scope, and
I think typically that's just a generic,
it's mixed $scope. But you can specify
things like user. So I know that I'm
passing a user into that scope, and it
will fail if I pass anything else. So I'll
pass a user in as that scope, and then I
can say user hasRole manager, something
like that. And I return that, return the
truthiness of that statement. So if that
statement returns as true, when that
person visits the page that, uh, checks
that feature, right, where that feature is
actually on the page, it will grab that
class. It will resolve that feature,
resolve that method, and then it will
return a truthy or falsey, um, value. And
then that will get stored. Depending on
what driver you're using for Pennant,
it'll either get stored in the database,
or it'll get stored, you know, in Redis or
other places, wherever you might have it.
-Mm-hmm.
-And then at that point, it is resolved. It
is not stored. It will not ever resolve
again unless you delete or, or, uh, purge
that feature for that person, which is
great.
So that's the idea, right? I can turn
features on or off. I can also launch it
as, like, nobody gets it. I can just, from
that resolve function, return false. And
then I can go into the database, and I can
say only I get it, right? Or I can
release it to a beta group of users. So I
can test it in production without having
any fear of breakages occurring because
nobody can see it except for me. So if it
breaks, it's only gonna break for me, or
it's gonna break for a very small group of
users. So really, really nice. Now,
after having explained that, Michael, I
want to hear your idea or explanation of
time bombs,
why you might use them, and how you
implemented them and how they bit you.
Mm-hmm.
Yeah. Well, I think it's, it's the, the
fact that they are resolved once and
persisted that has bitten me because-
-Mm-hmm
-... the, the time bomb nature is that I
would expect that a feature flag applies
or doesn't apply depending on how you've
got your code wrapped by that feature flag
at some point in the future.
-Mm-hmm.
-So the way that I wanted to use them,
rightly or wrongly, last year when, when I
looked at it, was to time bomb the
-display of speakers for Laricon AU.
-Hmm.
So, like, on some day in the future, we
want this speaker to appear on the
-website.
-Yeah, yeah.
So I don't have to remember to do it. So I
don't have to be at the computer to, you
know, tick a box or whatever. So I
thought, yes, I will, I will time bomb
that feature flag,
uh, so that that speaker appears at some
point in the future.
Now, the problem with that was, because
that was resolved once, when it resolved
-the first time that it was loaded-
-Mm-hmm.
-It was false
-... it was like... It was false. So it
went into the database, and that was it.
It was just false forever. So I would have
to then go in, [laughs] on that time, on
that day, to then remove that flag, which-
Yeah
-... kind of defeated the purpose of it.
-Defeats the purpose.
-So that's-
-Totally.
That's where, that's where I got bitten by
them. Other than that-
-So-
-... I think they work fantastic.
Okay. So, so
it's probably helpful to talk about
definitions of what a time bomb is. So
what you've explained there is not
necessarily a time bomb. A time bomb, as
Martin Fowler describes it when he's
talking about features and toggling, is a
way for you to make sure that feature
flags don't stick around for forever,
-right?
-Mm-hmm.
So you could think of a time bomb more as
an expiration date than a... Only to show
-it at this time. Now-
-Mm-hmm
... I think it's worth discussing how we
would actually approach your particular
-problem that you're talking about.
-Mm-hmm.
And
maybe,
I don't know. I- I'm actually not sure how
I would solve that with Pennant. I think
I would honestly, in that instance, I
would literally just put a
timestamp check or something [laughs] like
that.
-Yeah. All right.
-I would wrap it with a conditional if that
-says-
-Yeah
... if, if, uh, now is passed and then
pass in the date-
-Mm-hmm. Yeah
-... and then I would... Then that's how I
-would do that probably.
-... yeah, this year. This year, we put all
of the, the speakers into the database,
so now we just have a, like, publish date
-is in the past.
-Ah, so- oh, perfect
-That works fine this time
-... there you go.
Yeah. Which is the sensible way of doing
it, but last year, we kind of... The, it
was all static HTML really, so we, we put
all the spon- uh, the, all the speakers on
-the page that way. And so we're-
-Yeah
... just expecting, like, for each one to
then,
t-to, to appear effectively when, when the
time is in the past, but didn't work out
that way. Uh, but this year, yeah. It's
just a, just a field on the database
that's an announced at or something like
that, and we just return all of the
speakers where announced at is less than
or equal to now, which is much-
-That makes sense
-... easier way of doing it.
-Great way to do that
-Don't use feature flags for that. Yeah,
-no.
-Absolutely. Great way to do that. So,
so if we're approaching this idea of time
bombs as this, as more of, like, an
expiration date, um, I, I would love to
talk about that just for a little bit.
And, and essentially, I'll give you the
scenario that
we faced that had me looking back into
this, which was we had a feature flag that
was,
you know, gate, gating a feature that we
had written
and I pushed it out on a Friday
-and promptly forgot.
-It's time to push down
-About that feature.
-Yeah. Just want to push down
Totally forgot about it. It didn't matter.
It was like, "Okay, hey, whatever." So,
uh, I enabled it for a couple users and
the users of us who had it just
looked at it and figured, "Well, everybody
must have this," right? We totally forgot
-that we did not release it for everyone.
-Yeah.
And so six months later, somebody's like,
"Yeah, I don't know how to see, like, if
this file is timed up or not." Like, well,
just use the, you know, just use the
-timed up, you know, thing at the top.
-Yeah.
They're like, "I've never seen that." And
they're like, "Well, like, certainly.
Like, it's right up here. Here's where you
should see it." Go into the features
table. Yup, not enabled for anybody except
for us. Like, ah, crap. And so what
happened is
we had this feature flag that was not
supposed to be around forever. It was only
supposed to be for this beta testing sort
of idea. And once it was good, then we
needed to remove it. So the question is,
how do you inform yourself when
you should, you know, how do you basically
put an expiration date and say, "Hey, by
the time a month has passed, we should
have figured out if we want this feature
-or not for everybody."
-Mm-hmm.
It should be general release to everybody,
or it shouldn't be.
-Yeah.
-And, you know, we kinda need to pull the
trigger on one way or the other.
So I asked Tim McDonald. I was like, "How
would you do this?" We had a couple ideas
for how we would do it, but the way that
he did it was very, uh, clever. And so I
wanted to share the idea that he had,
which is,
uh, to put on each one of your feature
classes, which again, is the way that I
really prefer to do it, is to use a
class-based resolution because you get all
the other things you can do, this
behavior, these traits that you can put on
it and whatnot. But you make a trait
called is, like, concerned with
expiration, you know, maybe something like
that. And inside of there, um, you have a
contract essen- or sorry, maybe it's a
contract, not a trait. But it's, uh, a
contract that specifies that you need to
have a
is expired
method that returns a Boolean.
And then what you can do is, uh, in that
is expired, you can do a date. You could
say now is past a particular time, or you
can do other things, right? You can,
there's other things you could do. It
doesn't have to just be a date, but you
just return a Boolean from there.
And then what you can do
is
you can, in your service provider, you can
say there's an event that says feature
resolved, I think is what it is. So what
this does is any time that a feature gets
resolved, even if it's out of the
database, if it's grabbing it,
it will look and say,
um, is this an instance of,
you know, or does this extend the contract
or implement the contract of, uh,
you know, can expire or something,
whatever. Like, what, you know, I'm using
bad names here, but that's the idea,
right?
-Sure. Yeah, yeah, yeah.
-And if it is, if it does extend that
contract or implement that contract, then
what you do is you check to see is it
-expired.
-Yeah.
And if it is expired, then you can do a
couple things. So, um,
you know, you could log, warn yourself,
something like that. Um, but the thing
that Tim did, which I thought was really
cool, is there's this way that you can
check to see if you're running tests
currently. Have you ever seen this before?
-So it's like-
-The other container that's, like, is
-running-
-Yeah
... running unit tests or something like
that.
Yeah. If app dot op running unit tests. So
you can do this conditional. You should
say, "If we're running tests
and it's expired,
then we want to throw a runtime exception
that says feature has expired." So what
that does then is if you're ever running a
test that encounters this feature, and
the feature is expired, it's going to
force you to make a decision one way or
-the other.
-Yeah.
-You either need to extend-
-Extend it
... the amount of time that you have until
it expires.
-Or remove it. Mm-hmm.
-Or get rid of it. And I love that because
it does... It's not destructive. It
doesn't ever mess you up in production.
Uh, you can have it log if it's in
production if you want.
-Mm-hmm.
-Instead of throwing that runtime
exception. Um, but it's a great way to
ensure that any of your features that
you're putting in place have a reasonable
expira- uh, expiration timestamp on them
and that you're forced to deal with them
at some point in the future.
-Um, so I thought that was pretty cool.
-I like that.
-Yeah.
-That is a very Tim thing to do. [laughs]
Mm-hmm.
To put a thing in there. I've,
-I've-
-So he wa- so he did... So here's the deal.
He hasn't actually, like, this is not...
This does not exist. You have to just add
it on yourself.
-Yeah.
-Right?
-Yeah, exactly. Yeah.
-That's why I was like, "It would be cool
if it was first party." He's like, "I
mean,
I didn't feel like there was a good..." He
said, "I didn't feel like there was a
good generic option to put on top of it."
So-
-Yeah
-... I built the tools. A lot of the users
to decide how they wanna handle it, but
it's not, it's not difficult to implement
-it.
-Yeah.
-Right? You could see how you would do so.
-Yeah. It demonstrates a lot of restraint
on, on his part and on, I suppose, on
Laravel's part in general about where you
draw the line in the sand for, for what
you do offer as part of the library and
for what you say, "The tools are there. Go
and implement it."And, and I think this
is, this is a fairly good
case, use case of the tools that go and
implement it yourself. I've, I've gone
back and forth over the years about
whether or not
using those kind of conditionals in
application code is a good idea or a bad
-idea, you know?
-Mm-hmm.
Doing an, like an environment check or
doing a, are we running unit tests? Or, or
that kinda stuff to then trigger things
because you're, you're putting
test logic inside of your application code
to do this kind of stuff.
Erm,
I think it's fine, in general. I don't, I
don't really see any reason to do that. I
know that in parallel testing and things
like that, we will have all kinds of
conditionals that check, like, if the
parallel testing token is set, then we
need to go and do this stuff. And then
somewhere else we go, "Okay, don't do this
stuff because we are parallel testing,"
and, and things like that. So
there's definitely cases, I think, where
doing that kind of runtime, testing time
logic is good. I think
forcing you to, you know, blow up your...
[sighs] It depends on how strict you are
on your continuous integration. Like, if
you're running this in CI and it fails
because somewhere between where you pushed
a pull request
-into GitHub and some-
-Mm-hmm.
And, and when the CI ran, your, your test
suite is now failing
because of this expired token or this
expired check,
but it's unrelated to the pull request
that, that was pushed up. So I think
that's, like,
that's the one thing that, that sticks to
me. It's like, okay, yes, we need to do
something about it. It is now impacting on
this unrelated thing,
and it's, you know, a team decision. What
do you do with that? Is someone now tasked
with going immediately and, and updating
that? Do we... You know, it, it may not be
a decision that gets resolved straight
away, depending on the size of the
organization. It, it might be, like, you
as a developer or as a founder, you can go
like, "Yeah, I'll just kick that can down
the road a week," or, "I'll go and remove
all of those feature flags, and this is
now just a feature that's part of the
platform." So yes, it does prompt you to
do that, but sometimes that decision
-involves committees. It involves-
-Yeah
... product teams, product managers,
things like that. You've gotta go ask.
You've gotta go wait. They don't have an
answer. They've gotta go chase it up with
-someone else.
-So now you have a blocked PR, yeah.
And meanwhile you've got a blocked PR and
a failing test suite, and all of that
-kinda stuff. So, you know-
-In fact, every PR is blocked, right? If
you had multiple PRs out there, all of
them are blocked.
-Mm-hmm. Yeah.
-And every single person is trying to
scramble to figure out what do we need to
do with this.
Yeah, yeah. And everyone's going, "Oh,
this is failing. Retry fail tests." Like,
'cause they're like, "Oh, this wasn't
supposed to fail," you know? Es-
especially, like, we get into situations
at work where the, the test suite will
just be flaky.
Erm,
and it's just over time, the, the
construct of, of the application has
changed where, you know, you've got
factories that, that are resolved in a
certain way. Which is okay when you've got
100 tests, but when you've got 500 tests
or 1,000 tests, those factories can, like,
step on each other. You might not have
something that's unique, so
over
enough iterations, you end up with
collisions and things because you don't
have the, like, fake, faker Unique applied
in there. So there's, like, all these
different
cascading
arbitrary failures that you might not even
look at it for a couple of days-
-Yep
-... until someone goes, "Hey, this is,
this is failing." So
I like the idea in
theory.
-Mm-hmm.
-I think
whether or not it works depends on
the kind of company that you're in and how
quickly they respond to that. Like, if
you,
and, like, whether you put that in there
at all,
uh, really comes down to how quickly
someone is going to respond
when... It may be a case that you log,
you know, for two weeks or something
before the failure,
erm, even if you are running in test so
that something bubbles up somewhere that
hopefully someone would see.
Erm,
but yeah.
-That's a l-
-Yeah, you're, you're-
... long-winded way of saying that, like,
I think in general, I agree with the idea.
I like, I like the idea of putting
something [laughs] that explodes in, in
test. Because that's something that
at some point in your release cycle,
whether it's during development locally or
as part of CI or deployments, like,
something will blow up because of that.
-Yeah.
-Erm, and, and what you have in place to
work around it. You know, okay, we can
just merge this PR anyway knowing that
this is,
erm,
-unrelated to that pull request.
-Yeah.
If you do, if you do automated deploys,
it's a bit trickier. Erm,
it depends on, like, if you do... I know
with, erm, Laravel's testing stuff, you
-can --fail on your test.
-Mm-hmm, mm-hmm.
And, like, it will f- after the first
fail- like, if that's the first failure
and it doesn't get to something else-
-There's just stuff there.
-Yeah. Yeah, okay, so this is unrelated to,
to my failure. I'm gonna, you know, ship
this anyway. Oh, whoops. There was a, some
error further down in the test suite that
didn't get picked up 'cause we bailed out
on this thing. So...
-Yeah.
-You know?
-I'll say that the-
-Rest reward, I guess.
Yeah. The,
the concerns that you bring up are the s-
very same concerns that Andy Hinkle had
when we were going to implement this. He
was like, "I don't like the fact that
other developers are gonna have to deal
with a feature flag before they can merge
their stuff." So we came up with some
ideas and some solutions. The one thing I
will say too, though, is that this, I feel
like, follows the convention that has
been brought about in many
different... You know, like we talked
about Nuno's, um, thing where it's, like,
just here's the best practices applied to
the app service provider.
-Mm-hmm.
-Where it's like, disallow n+1 queries or
disallow lazy loading or, you know, those
assignment overflow things or whatever.
Like, those, those sorts of things that
only fail if you're in local, if you're in
your local environment. You know what I'm
talking about?
-Yeah. Yeah, yeah.
-So, like, it'll check those things. It's
not gonna blow up in production. It's not
gonna blow up in your face. If you happen
to ship it to production, it's gonna be
like, "Eh, okay. Just let it go." But if
you're in local dev or in testing, it's
gonna blow up in your face and say like,
"Yeah, you can't do that." You, you can't-
-Mm-hmm
-... you know, do that lazy load stuff. So
this sort of falls in line with that to
me. Um...However, it's not a
yes or a no, or an always or a never.
It's, it's only based on some time-based
thing a lot of times, which is... So it's
not a right or wrong. It's just like if
you happen to be the guy who runs it just
before it expires, or right after it
expires, then you're screwed. You're the
one who has to deal with it. So
okay, so how do we address this? Well,
two couple... Two, two different ways I
think we could deal with it. Um, one is
that you could, if you're running,
uh, your CI on a regular enough basis, you
could start dropping warnings a month in
advance of the expiration, right? So you
could say, "If it expires in the next 30
days, throw a warning on the tests. If it
expires in the next..." You know, if it's,
if it's in the past, then go ahead and
throw a failure. You know, something like
that. So that would allow you to be
notified of it ahead of it actually
expiring, so that you could fix it. Um,
and like, you know, you see it, it's, it's
erroring, or not erroring but it's
throwing a warning, and you're like, "Oh,
okay. I should probably make an issue for
that so somebody can fix that or make a
decision." We have 30 days to do so. The
other thing that we talked about is making
a command that runs once a day at like
6:00 AM, something like that, that runs
through the features, checks if any of
them are expired and if they are, sends
off an email or sends it or creates an
issue, or whatever you might have that
says, "Hey by the way, these features are
expiring within the next 30 days or the
next 7 days," or whatever. Uh, or they are
expired and these need to be addressed,
and that's it. You know, so there was...
That was, there was a couple options
there. You could say it doesn't ever fail
tests, it just sends out a warning to let
somebody know that this needs to be
addressed. Um, so there's a couple
different ways you could do that there
that I could see being effective that
would not necessarily block the team, but
could inform a project manager that these
are something that we need to prioritize
within the next cycle.
Kind of, you know, deprecation warnings I
guess for features.
Yes, exactly that.
-Mm-hmm.
-Yes, correct. Yep, yep.
Yeah, and I think realistically that's the
only way to, to deal with it. And if, if
no one's gonna pick up the deprecation
warnings
for the feature flags like that
on a, you know, across a team, across an
organization, you know, if you're
involving all these different p-
all these different people, then
probably have bigger concerns to, to worry
about. You know, at least sending that
email or that notification in Dislike or
whatever else
that happens to be from that scheduled
job, scheduled task, is...
You know, you've got to address it in some
way. Um, and if it goes to enough people,
someone... Well actually, if it goes to
too many people everyone's gonna be like,
"I thought someone else was gonna deal
with it," and then you've got to be
-careful there as well.
-Yeah.
So
yeah, keep the, keep the list small but
make sure it gets actioned, I guess is the
-main thing.
-Exactly.
But again, comes down to the team and,
like, someone actually taking ownership o-
over that. So
-yeah.
-Yep.
-Good, uh-
-Yep, you got it.
Good, good problem. Um, I think good, good
solution to that problem as well.
Awesome. Yeah, thanks. I, it was, it was a
fun one to kind of run down and it was...
Uh, yeah. A couple different approaches
there, a couple different concerns, but I
was happy with where we landed on it, so
yeah. Stoked about that.
-Mm-hmm.
-Okay. Since you talked about your, um,
your speakers on Laracon, um, I think this
is a good transition into this other part
which is this,
where do you store values
for
templates in a static
view? Okay, so let me pitch it to you this
way. Let's say you didn't have a database
for those team members, or not another
team members, for those speakers, right?
Um, because locally you are going to do it
and you don't want to have to like... How
do you, how do you populate your database
locally and then push that up to
production without having to have access
to the production database? You can't
really do that. It's like I know what the
values need to be, they're not necessarily
dynamic, it's just I- I don't... Where do
I store them, right? Do I... What are my
options? If I, if I can't put them in a
database, where are the other places that
I could put them? So I actually came up
with one just as we were talking here, but
there was a couple options here that,
that were thought about, right?
One is you could literally just dre- like
create a component and then in Blade, just
you don't even bother doing a loop. You
just put in the values.
-Yeah.
-Right? That's it. Create a component, put
the values in, that is your database
essentially, right? You just-
-Mm-hmm
-... write them all out in the blade, and
that works. That's fine. Like you just
basically, your component is going to have
locations or values, like the values that
you would normally store in the database
are gonna be essentially like arguments to
that component, right? So like name,
image source, um,
title, announcement date, right, all those
things.
Right? Those are gonna be, those are gonna
be stored like in the Blade file.
-Yeah.
-That's one way to put it.
-Yeah.
-That's one spot to put it.
-Yeah.
-Um, can you think of any other spots you
might, you might put these things?
I can because this is what we did last
year was-
Ooh, okay. I wanna hear, I wanna hear. I
want wrong answers only.
-We, uh-
-Wrong answers only.
-Wrong answers only [laughs]. Yeah.
-Yes. What were the other places you could
-put it?
-We created, we created a YAML file that we
-hosted in GitHub that you had to-
-Okay
... in a JS, it was a secret JS... No
[laughs], I'm joking.
-I was gonna say, oh dang. Okay.
-You said wrong answers only.
-That's crazy [laughs].
-You said wrong answers only.
I- I, at first I thought you were being
serious. I was like wait a second, do you
really? Okay. All right, all right. A YAML
file in-
-No, we-
-... a JS that you were pulling in R.
-In a JS.
-Fair enough.
-That's right, yeah.
-Yeah.
-So if anyone wants to go and-
-And then you used Sushi.
... uh, and scan. Sushi. Yeah, to use as
an-
Used, uh, Caleb Porzio's Sushi package,
yeah.
... eloquent database. That's right. Uh,
no we just, I just put all that stuff
-inside of like a config Laracon.php.
-Okay.
And it was just an array of speakers which
was keyed by...
Actually, I don't think it was keyed. I
think it was just an, an array that we
then pulled out and we, you know, we
collected it. We put it in a collection.
We sorted it by announced. We filtered
ones that were not, you know, didn't have
an announced in the, in the past and that
was it. That's, that's how we did it.
-Yeah.
-Um, and then I think w- we just used, you
know, Cloudflare to cache that so we
didn't... Well, you know, obviously the
page gets cached so it doesn't have to hit
the origin server to, to resolve that in
the future. So yeah, that was, that was it
really.
Yeah. Uh, that works pretty good. So,
like, you could put it in the config. You
also, if you're being a little bit crazy,
you could just chuck it into the
-controller. Like, if you wanted to-
-Mm-hmm. Yeah
... just inline an array in the
controller, you-
-Yeah. Sure
-... could kinda put it in there. Uh,
that's one way to do it as well. Um, so,
uh, my,
my junior-ish developer, he's actually...
He's Landon. Landon is his name. Um, he
played basketball a little bit last year
at Laracon with me right afterwards. There
was a couple dudes that we all played.
Me, David, Hemphill, Landon, and then
three other dudes that absolutely smoked
us. It was really fun, but kinda crazy.
-[laughs]
-Landon's a great basketball player, junior
developer though, and he's, he's figuring
stuff out. And so for him, he ini- or
initially just put it, like, in the
controller. Like, he actually had
a method for each. Like, so we had, like,
four locations that we were trying to,
like, you know, deal with. And so what he
did is he put,
uh, a method in, in the controller.
So you would have, like, a, a value being
passed into the controller, um,
like, uh, you know, in the, like, the
array that gets passed in to the, to the
-view. I'm sorry, to the view.
-Yep. Mm-hmm.
And he would say, like, "Location one, Fat
Arrow,
this.get('location1')." And then say,
"Location two-"
-Yep.
-"... this.FatArrow.get('location2')." So
he was just calling private methods inside
the controller that were sort of then
-returning these arrays. And I was like-
-Yep
..." Hmm,
that is fin-" Like, it works. It's
probably not how I would do it, but it
-works. And so I-
-Yeah
... was like, "I'm wondering..." You know,
config file is the first thing that came
to mind. But for some reason, I remember
when looking at it, there were some
reasons why it wouldn't have really worked
in a config file. And I think partly
because he was doing some PHP stuff inside
of that config file, and, like, it
would've been weird to do it there. Um,
but
the other thing that I'm wondering here is
this. If you didn't want to store it in a
config, what if you just put it in a
SQLite database and then shipped the
-database up?
-Yeah. Yeah,
-totally.
-If you put that in somewhere? Like, could
you... Where would you put that, though?
Would you... You'd put it in the storage
file or something? I don't know how that
typically works. If you put it in the
storage, you have to, like, symlink it or
something weird like that if you're using
-Envoyer.
-Yeah. I would just, just put it in the
database, 'cause that's, that's where the
SQL files go by default.
-If-
-Okay
... you know, if you, if you, if you do a
Laravel new and you say you wanna use
SQLite, it will create a
database/database.sqlite file inside of
storage. Uh, inside of the database
folder, and then you just commit that to
-version control and off you go.
-Yeah, 'cause I'm... As, I'm sure initially
it's probably.gitignored maybe?
Hmm, not a... Oh, yeah, maybe
database.sqlite specifically, but you
-could just remove it from there, like-
-Totally. You could.
Just because Laravel puts it there by
default doesn't mean you can't change it.
-Um-
-Absolutely.
Yeah. Yeah, shipping, shipping sqlite is
fine. Um, who, who was it? Like, was it
Aaron Francis was talking about that for,
for, um...
I think for his aaronfrancis.com. He's, he
ships an sqlite file or something like
-that, so.
-It seems like the right place to do it,
-right? I mean, like-
-[laughs]
... you literally have, you have the
structure in there. You can pull it using
-your, uh, you know, using models and-
-Mm-hmm
-... all that good stuff.
-And, you know-
So it's like, I don't really see a reason
why you wouldn't or why you couldn't.
SQLite is, is made to be small and
portable like that.
-Every, you know-
-Mm-hmm
-... the, these things, every-
-I mean, the problem is it can fill up
-... everyone's iPhones-
-It's just a flat file, yeah.
Everyone's Android file. Yeah, it's just,
just shove it all in there. Yeah.
-Yeah.
-Um-
-Yeah, so I think-
-I mean, the other thing you could probably
-do is like a-
-... that's, that's an interesting third
-option. Yeah
-... a document store. You know, something
that writes JSON to a file, and
-do that, I guess, with, like-
-Yeah, but the SQLite thing seems way
better to me. Yeah, as long as you have...
I mean, as long as you can set up... You
know, you just have to make sure that
every person, each person that's looking
at it,
uh, when they're trying to develop stuff,
uh, that they map... Uh, you know, they
can open TablePlus to that sqlite file or
whatever, right? So-
Yeah. Yep.
Yeah, that seems like a good way to do it
though. Seems like a pretty good way to do
it. Um, portable, light. It's still a mi-
it's still a, uh, you know, queryable
-entity. Um, you don't have to write-
-You could be-
You don't have to write, like, factories
or anything for it. You could just... You
know, you just ship it. You ship the
actual data up.
-Yeah.
-Yeah.
You could open up TablePlus and use that
as your, you know-
-Totally
-... as your admin interface-
-Yeah
-... to put stuff in there.The only-
-Absolutely, and you've got-
-... the only other thing that, th-
... version control on and everything, you
know?
Yeah, yeah. I mean, the only other thing
that you might do that's probably a little
bit more approachable in terms of version
control is just a, like, a CSV file,
-and then use-
-Yeah
... Switchy to, to, to manage that.
-Yeah. But I like the-
-Because then-
-... SQLite. I like the SQLite option.
-Yeah. The ISQL-
-And I, I'm not pushing that direction
-... is definitely nicer from a, from a dev
perspective. If, if you needed, like,
someone else,
you know, someone from product or someone
from sales or marketing, whatever, to be
putting data in their CSV would be fine.
And just like, "Here's the updated file."
Yeah.
-Yeah.
-"Drop it in, overwrite, replace it." You
-know?
-Yeah, it's only developers working on this
one, so I think SQLite's gonna be the
solution there. And I think that's, um,
that's a really great way to do that. So,
uh, we're gonna move towards that,
actually. That's w- exactly what we're
gonna do. We're gonna end up doing that
precisely.
Love it.
Love it. Awesome.
Okay, um, what else we have here?
Live photos, staggered CSS animation,
defensive programming.
What do you think? Hmm.
So, uh, Matias...
I can't say his last name. Starts with a
G. Guimaraes, I think. Uh, he's got a
defensive Laravel
course coming to Laracasts at some point,
so it should be cool.
I saw Jeffrey tweeted about that, like,
today, I think. Yeah.
Yeah. Yeah, he, um... De- definitely check
that out if you're a Laracasts
subscriber. I, uh, I watched his...
-It was Event Sourcing Tour- uh, series-
-Mm, yes
... that he had on Screencast. That was,
that was really good. He did a, a good job
of that, so I'm, uh, I'm keen to see
his, um,
his defensive Laravel stuff. Because he,
he works at, like, a payment provider or
-something over, over there-
-Oh, interesting
... where he lives in,
pretty sure, Brazil.
-One of the-
-Okay
... Portuguese slash and/or
Spanish-speaking nations. Sorry, Matias.
-But, uh, yeah, he, um-
-That's right, that's Portuguese, right?
-Yeah. I-
-Yeah, he's a-
Did I tell you about that, right? When I
said-
-Yeah, yeah
-... when I thought
But I couldn't remember if he was from
Spain or from Brazil. But I know in
-Brazil-
-Oh, gotcha
-... they speak Portuguese. Yeah. So-
-Yes, indeed.
Um,
yeah, he...So, he does some very intense
things, uh, in terms of, like, the
extremes of what you can do with Laravel,
so I can't... You know, he'd be a, he'd be
a... You'd be hard-pressed to find a
better teacher for that kind of Laravel at
scale type of thing. So, yeah, keen to
check-
-Yeah
-... that one out when it drops.
That'll be really good. I'm sure he'll
have some excellent sort of tips on using
Laravel tools in order to be sure that you
can catch things if they happen terribly,
if they happen to go terribly wrong.
We had something today where,
um,
it was, it was the sequence in which
something was working, so we were reading
an email from an email inbox,
we were creating a record for it, and on
that database we had a unique column for
the ID of that item from that inbox. So
that item from that inbox was given a
unique, like, Outlook message ID.
And so it's, you know, it's a GUID. And so
it's, it's unique. You cannot create
another one with that same GUID.
However, the step after we created it was
to move it from that location, that
folder, to another location.
If that failed,
right? So you'd move it from the inbox to
a folder called Processing or something
like that, right? So we create the record,
and then we start to process that email.
We read the body. We read the subject. We
do some, you know,
guessing as to where we think it needs to
go and basically have our own really
intelligent rule system that we can build
up off of that database record, right? So
you create the record, and then you send
it to processing. Well, if that sending to
processing fails for some reason, which
sometimes is this weird race, race
condition, if it fails, then the email
doesn't move, and when the inbox gets
scanned in the next minute, it tries to
pick that up again and create the record.
Well, since you have a unique ID, it
fails. So
yeah. It, it's like just using simple
things like a database transaction around
those two pieces, right? Create it, and
then move it. And if it fails while
moving, roll back the creation so that it
can try it again next time without hitting
a unique constraint. So those are the
sorts of things that we're talking about
here, right? These, you can't anticipate
everything that's going to happen. You
don't know all the different failure
points, but you can certainly wrap
something into database transaction and
roll back if something fails. You can do
that. And that's, you don't have to know
everything. You just have to know if
anything fails in here, roll back. Don't
leave this unfinished, weird state, um,
that you're gonna have to contend with
later, especially if you have-
-Yeah
-... constraints around unique values. So I
hope in, in, you know, in his course he,
he covers some of those things or, you
know, like the rescue function in Laravel
is so insanely awesome. Where if there is
a failure while you're attempting to do
something, you can provide a default
return value and just continue the program
running as if nothing failed, right?
Those, that's incredibly helpful. So
Laravel has a ton of tools to help make it
more resilient and more bulletproof if
you know they exist. So I'm sure he'll-
-Yeah
-... cover all that stuff and do a great
-job doing so.
-Yeah. One, one thing I've been caught out
with by that Rescue helper in the past is
typically I'm wrapping something in Rescue
because I don't wanna know about it, and
I always-
-Yeah
-... I, I have on more than one occasion
forgotten to set the report flag to, to
false.
Uh-huh.
So I still, I still get the exception to
bubble up, and then I go like, "What is
this?" And then I, I, like, I put the
Rescue in there, and I go, "Ah, I forgot,
forgot the, to report." Because the, the
place that we mainly use it is when we are
trying to parse dates using Carbon or
the-
-Oh
-... or the date facade. Because, you know,
you guys use, um, month, day, year, and
we use day, month, year.
-But-
-Ah, yes. Right
... if you take something that's
day/month/year
and you throw that at date parse, because
that's how we would re-enter it into a UI.
Yeah.
When you take day/month/year and put it
into PHP, PHP assumes that it is
-month/day/year.
-Yeah.
And so what you end up with is something
that's, like, 13/3/25.
-Yeah.
-And then Carbon goes, "Thanks."
Freaks out.
Um, so yeah. We, we've got in a number of
places where we're handling that, you
know, a date create from format, and then
we explicitly tell it, like, "This is
-day/month/year." So that-
-Yeah
... it goes, "All right. Yeah, this is,
this is the right way round." Um,
and then we fall back to just doing, like,
a date pass in case something comes
through as year-month-day or whatever else
and then, then gets picked up that way.
But yeah. When it, when it hits that first
Rescue, uh, callable
and you don't have the report, then we
still get the exception bubble up into,
um, our observability tooling. And it's
like, "Oh, yep. I don't really care about
-that," because-
-Yeah
... it's, it's... Like, it will, it will
catch the exception from the Rescue,
report it, and then go to the f- the
fallback, so you're, like-
-Then it'll continue on, but yeah
-But, and then you go, "But this worked.
Why am I...? Oh, okay. Yep. Gotcha."
-So don't, uh-
-Yeah, exactly
-... don't miss that one. [laughs]
-I'm surprised that there's no, like,
localization thing for Carbon where you
can basically just tell it at the top
level, "Hey, we're in Australia. Please
handle dates accordingly."
Yeah, yeah.
Probably. Probably is and we just miss it,
but, um-
-Yeah. Maybe
-... no, 'cause this is an underlying PHP
thing as well.
-Like-
-Oh, gotcha
... if you were to do... Yeah, if you were
to do, like, a create, whatever the
underlying
PHP function is, it will do the same
thing.
-Got it.
-The, the-
-Yeah
-... the correct approach for that is to
-use hyphens instead of slashes.
-Ah, interesting.
But no one, no one here is going to enter
the dates with hyphens instead of slashes,
-because that's just not what we do, so.
-Yeah.
-Like, that is-
-Yeah
-... I mean, I assume that's-
-We don't, we don't do hyphens either.
Yeah. I assume that's, like, the
workaround in, at the language level. To
be like, "Oh, yeah, you can do this as
long..." But you, you're not gonna tell,
you know, users of your platform who have
become accustomed to using slashes to use
hyphens in your application wherever else
-it's just handled, so.
-Yeah.
Yeah.
Absolutely.
Well, hey, dude. I think we have a couple
things left to talk about next time. Um,
we could probably talk a little bit more
about defensive programming and some
examples that we have. We could talk
about...... staggered CSS animations,
which is
interesting to me. This is when you go
onto a page and you want, like, this
effect of when you hit a certain
observability point, and there's a, what's
that called?
Interaction observer? It will animate
something in into view.
But if you have, like, three paragraphs of
text or something like that right
following each other and you scroll down
really fast, you don't want that whole
block to animate and at the same time. You
want them to animate in, like, a
-PowerPoint-
-One after, yeah
-... like, one, two, three. Yeah.
-Mm-hmm.
Which is a little bit tricky to do. And
so, um, I think, uh, motion.dev allows you
to do that. We figured out how to do
that. I still have to implement it. Uh,
and then this idea of how do we, how do we
accomplish live photos on the web, where
if you roll over something, it kind of
moves the photo. It kind of gives you this
motion, where it changes from a photo to
a video while you're rolled over it, and
-then-
-Yeah
... and then when you roll off it, it, it
stops doing that.
-Interesting.
-So found some interesting stuff about
that. It'd be, uh, I'd love to kind of
talk that through with you and see what
-your thoughts are-
-Mm-hmm
... on that. So
-next show, folks. Come on back and-
-Sure
... um,
you know, hey, uh, to go along with the,
uh, the news of, uh, Steve and Erin
breaking up, I, I gotta let you guys know
that, um, Michael said he's leaving the
podcast, and it's, he's just leaving it to
me. He said, he said he's giving me
-everything. Just take it.
-[laughs]
I'm paying, I'm paying him 50% of what
it's worth.
-So [laughs]-
-50% on anything is nothing.
-Since we haven't had a sponsor.
-[laughs] Sorry.
-[laughs]
-We are, we-
-Since we haven't had a sponsor in, like-
-[laughs]
... years, I'm getting a steal on this
thing.
-That's right. I said, I said to Aaron-
-Oh, man
... that, uh, that the, the unsponsorable,
the unsponsorable comment was ruthless.
It was fair, but it was ruthless. [laughs]
-Oh, so funny. So funny. Oh, my.
-He'll be fine.
-Well, anyway.
-I think, I think he's for himself.
Yeah, I agree. I agree. No, totally,
totally. He'll do great. And I think Steve
will do well too. I mean, I think people
knowing that he's available, I mean, heck,
when I heard that he was available, I'm
like, "Oh, geez. I have a couple things I
could have him do actually." Like,
actually-
-I said how-
-... one specific thing that I thought of
that I was like, "I would love for Steve
to do this," but I knew he wouldn't have
-time.
-Yeah.
-So maybe now he does.
-Maybe. Get into it. 'Cause I said, "How
long before he'll... How, how long before
he lands on the Lara ship?" So...
-[laughs] Right.
-Get him before it's too late.
May- Who knows? Maybe that was, uh, maybe
that was part of his, his calculation.
Maybe he was like, "You know what?
I can have a job over here if I really
wanted one."
-Mm-hmm.
-"So maybe I'll just do the job thing for a
-bit." Who knows?
-Yeah.
Not making any, uh, assumptions here. Hey,
folks, also if you have not bought your
Laracon tickets yet, it's might be too
late. But if it's not, you should
definitely go buy them because Michael and
I would love to see you there. We're
gonna doing some interviews there. We're
gonna be enjoying the show, watching all
the talks, and we would love for you to
say hi. So please stop by and say hey.
Look for, uh, the really tall guy and look
for the handsome Australian with the, uh,
other cursing Australian next to him.
That will be Aaron. Uh, OG, OG Aaron.
-[laughs]
-OG Aaron.
[laughs] OG Aaron making an appearance
again at Laracon US.
-Yeah.
-He's gonna be a riot. I can't wait to see
him.
Fun.
-It'll be good fun.
-Awesome.
Episode 178, folks. Thanks for tuning in.
You can find us at North Meets
South.audio/178. Hit us up on X or on
BlueSky at Jacob Bennett, at Michael
Dorando, or at North South Audio. And, uh,
if you liked the show, rate it up in your
podcast app of choice. Five stars would
be amazing. Thanks, folks. If you'd like
to sponsor us,
also talk to us on those channels. It
won't happen. But if you'd like to, we'd
love for you to. But until next time,
we'll see you.
Oh.
Creators and Guests


