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.