Coding Blocks - The Twelve Factor App: Dev/Prod Parity, Logs, and Admin Processes
Episode Date: December 20, 2015Welcome back to the dramatic conclusion of our discussion on the 12 factor app. This time we’re talking dev/prod parity, logs, and admin processes. Oh, and Call of Duty! News Thanks for the reviews!... arathustra, lu S, Seb (from London), S Willowood, TheDarkKnight15, FreeAppsHunter Where do transforms go? UI or Middleware? Joe had surgery! Oopsy […]
Transcript
Discussion (0)
you're listening to coding blocks episode 36 subscribe to us and leave us a review on itunes
stitcher and more using your favorite podcast app visit us at codingblocks.net where you can find
show notes examples discussion and more and send your feedback questions and rants to comments
at codingblocks.net follow us on twitter at codingblocks or head to www.codingblocks.net
and find all our social links there at the top
of the page. With that, welcome. I'm Alan Underwood. I'm Joe Zach. And I'm Michael Outlaw.
And to start us off with a little bit of news, we have a winner for our t-shirt giveaway.
Winner, winner, chicken dinner! Yes, so Wade is the big winner. We have a little video of the honest pick in the raffle.
Yeah, check out our vine.
That's right.
So we'll have a link for that up there.
Also.
That's our second vine.
The what?
That's our second vine, so make sure you subscribe because we are killing it.
Yes, we are.
Two in a year.
Yeah.
That's amazing.
Hey, but they were important because they're always for a contest.
They are always giveaways. We're 100% on our contest usage of our Vine account.
Yeah, that's good stats.
In other news, we got several reviews, a couple from the UK,
which is pretty excellent.
You guys rock.
Yes, you guys are amazing.
So we got one from Aruthastra, Lou S. on Stitcher, Seb S. Willowood, TheDarkKnight15, and FreeAppsHunter.
So, guys, thank you so very much for taking the time to go over to either Stitcher or iTunes and leave us a review.
I mean, when Batman takes the time out of his busy day to leave you a review.
He's the 15th one.
Yeah, well, because the other 14 Batmans were busy.
The Joker is taking their time.
Right.
But yeah, we really do appreciate him.
I mean, it's bigger than what you guys could imagine.
So thank you for taking your time to do that.
And this isn't really news,
but I thought I'd ask a question
because this is just kind of random.
If you work with, especially web apps, I'm sure that this is the case with other things,
but if you're working with web apps, a lot of times you'll find that you're using a particular framework, right,
on the front end, be it Angular or Knockout or EXTJS or something like that, right?
And one of the things that I always struggle with,
and you always
make the decision you need to to get the job done initially, and then you circle back and you go
crazy. But let's say that your front end or your your UI tier, it requires data in a certain way.
And it has to be formatted for that particular framework, right? How do you go about handling that on your middleware?
Like if you're writing the server-side calls,
do you write your stuff?
So let's say that you have data coming out
and they're data tables typically,
but this stuff has to be massaged into a format
that that front-end framework can use.
Do you write your middle tier
so that it returns your data table
and then you wrap it with something else?
How do you go about doing that?
I feel like,
is this,
is this the same question that you,
I think you asked the other day,
like,
well,
you know,
off mic obviously,
um,
where you were talking about like,
which one do you write first?
The,
the,
your backend or,
you know,
like how,
how do you mock the data that you want for it?
If it's for a front end piece.
I don't know. Did I ask that?
I don't think that was me.
I feel like you did. I don't think that was me like you
did i don't think example if i understand correctly might be like a date like if you want a specific
date format do you return it as a string from the server or do you format that now date's probably
a bad example yeah that's kind of what if it was like a grid of data yeah like so like for instance
some components require that you wrap like a piece of metadata and give it a row count, a page count, you know, what your start number is.
But it's very specific to that framework or that component.
Let's say that you're using some sort of component that you bought, and it requires that you give this metadata back in a certain way.
And obviously, if you went and used another grid component somewhere, it would want data in a slightly different way. So if you decided at some point in time
that you needed to rip that old component out
and put a new one in,
depending on how you wrote your middle tier stuff
that actually goes and talks to the database or whatever,
you might have a lot of rewriting to do
as opposed to if you had just wrapped it somehow.
It was just one of those things that came up
that I was like...
So I don't think you're going to like my answer.
I'm curious. I don't think i'll dislike it i think uh i'm just curious as to what you guys would say well i'm gonna say it depends because i don't like your answer yeah
because let's say let's say on the one hand if you're talking about the ui has already been
well defined like like it's already been designed,
you know what the end state of it should look like, then, you know, I might, depending on the
circumstances, start all the way at the database layer, and then start building up from there,
like making the queries work and perform optimally in return what I want and what I'm going to need,
and then start building from there. Right? But if it's the case where I'm kind of exploring, like, what do I want this thing to even look like, right?
Well, I don't know what data I need.
So how can I start with the data?
I've got to start trying to decide what I want this thing to look like.
And in that case, then it's all going to be, like, hard-coded, just fake data,
just to, like, get the presentation in place to see, like, is that what I then it's all going to be like hard-coded, just fake data, just to like get the presentation in place to see like,
is that what I want it to look like?
But once you've figured that out though, at that point, do you layer it?
Like do you say, okay, the data table is obviously the data that I need,
but then all this additional metadata, how are you going to –
What was the additional metadata again?
So like let's say that you said a grid, right?
Like this grid needs particular things like a row count, a page number.
I'm trying to, like this sort of.
I feel like that's going to be like the, that's going to be like, those are going to be the
trivial kind of things that you're probably already doing elsewhere.
No, not necessarily.
Because like in the case of a grid component or something something, there could be all types of things, right?
Like what's the sorted column?
There could be several pieces of metadata that come back.
Well, what I mean, though, is that chances are probably pretty good that you're doing similar grids elsewhere in an app.
And that same kind of metadata, you've already solved that problem elsewhere too so the real the real challenge of this particular
element is trying to decide a what does it look like and b what shape does the data come back in
right and so those are the two things and that's why i'm saying like depending on the circumstance
i'm going to start from one of those two opposite ends of the spectrum and then work.
Okay, so let me put it into a more concrete example, and then I'll get Joe's take as well.
Let's say that, okay, you know that typically, let's take a web API call for C Sharp, for instance, right?
That's your endpoint that you're calling.
And typically, you get data out, and that might just be a data table,
right? Fairly simple. You called the database, you got some data and it gets returned basically,
you know, at a data table format. All right. Now you have this specific requirement for this
component that's going to be using that data. You wouldn't want to go into your web API tier
and necessarily wrap it there because anything else that needs to consume that
particular piece of data doesn't necessarily want all that extra chunk of metadata that doesn't work
for, you know, another component. And that's what I'm getting at. How do you separate that stuff
out? So I'm curious, Joe, what are you, what are your thoughts on this? Yeah, I actually had a
similar situation recently.
I was working with some charting stuff,
and you could write a data provider for it,
and you would have a column named key and a column named value.
And so I was kind of tempted to name the return from the server key and value
because I could just kind of pop this thing right in there.
But that's not descriptive.
It's not consistent with the rest of the code base,
so I ended up transforming it.
But I think that's kind of an example of the kind of stuff you're talking about where you've got a
specific format you need to meet in order to get this component to work and so where do you do that
kind of rearrangement say you've got a hash table but it needs to be an array or something like that
and uh you know i think my vote is to do it on the client, but I'd be lying if I said that I never cheated.
It's, it's kind of interesting. So like what you're saying is true. Now, in the case of what you're talking about, maybe that's something easy enough that when it gets retrieved from the server,
it's easy enough to massage on the client, right? Like you could write some sort of provider that
would automatically translate that. But in the case of something to where it actually needs
additional metadata, right? Like for instance, instance, you have some sort of search that searches through a million
records in your database, right? And this grid expects you to tell it, okay, well, we know this
is paging, and you're on page 10, you need to know that. So that's going to come back in the metadata,
you need to know exactly how many rows are work because you need to display, hey, you're displaying rows 50 through 60 of, you know, a million.
So there's all this metadata that comes back.
So now the question is, okay, you don't necessarily want to put that into that particular Web API call unless you're going to make sure that everybody knows that, hey, every one of these endpoints, these Web API endpoints here, are made specifically for this particular grid component, right?
So then that brings up, okay, well, how do you do that?
Do you funnel this through something else so that you have like a proxy endpoint
that you call that then calls some other method to go get it and then wrap it?
You know, maybe there's a parameter that you pass in that says,
hey, make this component.
And that's the thing that's always,
that kind of bounces around.
And I mean, we've been doing this stuff a while,
but these are things that you run into all the time
to where it's like, okay,
I know we're using this component today,
but in a year from now, when they say,
hey, we want to switch to the, you know,
component XYZ over here, because it is so much better.
If you wrote all your server side code to do things
specifically for that old one you now have a lot more work to go back and redo you know so it was
just one of those things that kind of came up and i was like huh i'm curious what these guys take
would be on this you know what though if you keep it consistent like let's say you had an interface
that you implemented in some sort of factory that would create it and associate that metadata then you would have a nice way of finding everywhere
that you need to change assuming that you were kind of swapping out all the grids um so so it's
a nice use of um the kind of tools if you're working in a language that has that kind of support
well that's a good point like if you made it a factory even if you didn't switch out every single
thing right it could just be another,
another instance in that factory that it creates,
right?
Like here's the old school component.
It'll create that one for you.
And here's the new,
new component.
It's a nice take on it.
It's interesting.
Hey,
so change this topic here.
I totally didn't even think to mention this before,
but you know,
this is the season i don't
even know if you realize which season this is like christmas that's what everyone would say
and you're wrong it's star wars man oh how did you not know that so so you know my my youngest
asked me this question and i thought like wow like, wow, this is so relevant.
Like, what is a software developer's favorite Star Wars character?
No one?
I'm kind of worried if someone says Han is the answer, even though it might be my answer.
No, it is Jabba the Hutt.
Oh, nice.
I was thinking, you know,
Han shoots first,
asks questions later.
He's kind of moody.
Java the Hut.
You know he gets strangled, right?
Yeah, that's true.
You're trying to, like,
overthink this thing.
No, no, no.
Java's dying.
Yeah, we'll be sure to let oracle now yeah yeah your purchase of sun was total waste of money right um but yeah so that i don't know i thought that would be fairly relevant for everybody um
because it's one of those things that comes up and you know a lot of times it's just get it done as fast as you can, right,
because you have some deadline that you have to meet.
Wow, I thought you were about to say get her done.
I could totally do that.
That's all we need.
Well, speaking of questions, if you guys have any questions,
you can hit us up at comments at codingblocks.net.
Well, let us know if you want us to keep it private, though,
because otherwise it's kind of weird sometimes
we don't necessarily know if you want us to discuss your question on the air.
So, you know, throw it out there either way.
Yep.
And Joe has some news here.
Yeah, I mentioned one of the episodes we were talking about kind of,
I forget what the word is now,
but basically keeping your posture straight, all sort of stuff ergonomic um i was having some issues with
the hands and i ended up having wrist surgery actually carpal tunnel release so i thought you
guys might be interested in it's kind of an occupational hazard at least it's common for
people in our industry so um yeah i just thought i'd kind of throw it out there i actually had it
done right around the same time that brooke shields had both of hers done oh so i'm like sitting in doctor appointments offices like watching her on
tv and she's got like this crazy cast where she she got both her hands done so you're just like
yeah i have a newfound respect for her yeah exactly and i don't know how she's wrong because
let me tell you they told me that i would be back to work like that you know that weekend if i wanted
to uh and that was bs it hurts
you know I'm still having a hard time like grabbing like uh door handles and stuff but I have been
able to work yep you had this done what like two weeks ago right no three maybe uh almost a month
now three weeks man yeah yeah I guess I guess I have Star Wars on the brain because obviously
when he said that he had surgery I was like dude did you get like a bionic arm
like Luke? Really?
Well yeah his surgery
looked a lot easier than mine although
there was no bacta tank involved which is nice.
Although the irony is
his outlaw's not going to see this movie for like another
month. Nah man I'll see it like in February.
Yeah so he's all excited about it
but by that time everybody else... Well I'm excited
because it's that much closer to February. Yeah, fair enough.
You've got to let the crowds die
down, man.
Awesome. But I will say
I haven't had any numbness or anything, and
now that I can use my mouse again,
I'm back to playing video games again.
It's not so bad. So if you have any questions or you want
to talk about it, I am very interested
in that subject. I am curious, though. Did you
change up anything? Did you change your keyboard? i know that you got the vertical mouse is there anything
else you changed yeah the vertical mouse everything else seems tiny now so i'm totally sticking with
that i have been looking at keyboards still like i just can't decide between the sculpt or a split
um you know the worst thing that came out of this actually was like i couldn't really play
you know intense clicking or even like console games because my hand just hurt.
So I started playing Warcraft again.
So I'm back on the crack.
I just didn't have to click that much for certain things.
So now I'm in trouble.
All my friends are gone.
So if you guys still play and are on the server, you should let me know so I can join you.
So you didn't go for the Swift point gt wireless ergonomic mobile mouse uh no is that the one that was like the size
of a quarter it was the it was the one yeah it was the really small one that was like the the
pen or pencil grip by the way after after we mentioned that i went back and watched some
videos on it it's actually a really cool mouse well oh yeah by the way after we had mentioned that and I was putting the show notes together for that episode,
which if you haven't already heard, that was episode 34 where we talked about it.
But then, because one of the cool things that they mentioned about this was like,
oh, it's the same, this mouse fits your hand in the same position that a pen or pencil would.
And I'm like, at first I was like, oh yeah, when we were doing the recording,
I'm like, oh yeah,
that makes total sense.
And then I remembered,
oh wait, writing sucks.
It does.
Your hand always cramp up.
It totally,
I can't write my name
more than once
without it hurting.
I'm so used to a keyboard now.
So I was like,
why would I want my mouse
to be like that?
That's a horrible idea.
I wrote a check the other day
and it was horrible
just doing that.
I was like, ugh, I gotta write out the dollar amount in words.
I actually had to ask my wife.
I'm like, I signed it on the front.
I feel like I should sign it on the back, but I can't remember.
Was it carved in stone or something?
Why?
It's doctor's offices, man.
They are ancient, and all their websites are terrible. It makes me feel really sketched out about going to these guys. It's doctor's offices man they are ancient and all their websites are terrible
it makes me feel
really sketched out
about going to these guys
it's amazing though
like you would have been
one of those guys
on the prices right
like doing the
the check thing
and they're like
you totally wrote that wrong
so you get called out
in front of a thousand people
in the audience
I totally did have to tear one up as i wrote the
wrong year on it i'm just like oh this is this sucks man i can't imagine right now i i get upset
if i go to a place and it even looks like they have some form of tap to pay and i can't tap to
pay i'm like what what why do you have that device there like you're teasing me i mean i i break down mentally inside
i don't like actually say anything first world problems that's what we have here pretty much
all right what we got next okay so i might have made a mistake or two so uh i don't even remember
i think it was episode uh 35 maybe maybe, that we were talking about.
Actually, it was probably episode 34.
And we were talking about SSDs and that new M-SATA 2, I think it is.
NVMe.
Yeah, that Samsung put out.
And I made a comment about using that in MacBook Air.
But then I was like, oh, man, I'm a moron.
The MacBook Airs don't use M-SATA.
They use like a variant of PCI Express
that looks similar to,
I don't even know the specifics of it.
It looks similar to M-SATA,
but it's actually like a variant of mini PCI Express
or something like that.
And I was like,
oh yeah,
that one gets me every time.
I forget about that.
But then also in like the, you know, change log, if we could go back and correct things,
I thought about something too.
And not to call you out, Joe.
But he's going to do it.
Yeah, here we go.
Prepare yourself.
So in episode 35, last episode, we talked about you'd had this tip of the week where you were talking about flipping the X and the Y when processing an array.
And at first, you know, like when we were recording it, I was like, oh, yeah, that makes sense.
And then, like, when it came time to put the show notes together, I was like, hold on.
I was scratching my head.
And I'm like, hey, that actually doesn't make sense.
How would that prove anything?
Because then I was thinking, okay, the whole premise was if you had a two-dimensional array
and Joe was supposing that if you were to, let's say that one of them is an X and one
of them is a Y, whichever you want and you want to choose.
Like let's say for each X element,
there's a,
it represents an array and you're going to address that as wise.
Right.
Does that make sense?
Right.
Okay.
So then,
uh,
what Joe was saying was that like,
you know,
as you're processing that,
if you were to flip that and instead of doing a four,
uh,
a four loop on and iterate through all
of your x's and then inside of that do a four loop and iterate over all your y's then instead
reverse that and do your y's first and then your x's and that would be faster and at first like i
was like okay i think i see that and then it didn't make any sense as i was putting the show notes
together and because like what i really stumbled on was I was like, wait a minute,
how can this be like any kind of performance gain?
Like, and even in the, the conversation,
like Joe mentioned like a micro performance,
I forget exactly how he worded it, but I was like, man, current Ram speeds.
Like there's no way that that can make a difference. Right.
Like even if you're reading straight off of disc, like,
unless you're reading off off of disk like unless
you're reading off some really slow disk then maybe but you know and then it had to be like a
large data structure that you're worried about but i was like what's the scenario where this really
would matter and so it took me a while and i had to research this but what it was really in reference
to that we didn't mention in the show was when it's a coordinate system like your display
so if you were processing an image on screen that's where it would matter yeah you want to
do these things sequentially right so so rather than going so if in that case, if every X represented a row on your screen and every Y represented a column, what you don't want to do is go row by row down from the top left of your screen to the bottom of your screen and then start back up at the top and then work your way down.
Instead, you want to go from the top left to the top right and then come back and go left right left right think about the 90s when you would download an image refresh
right when you download when you were when you were like looking at anything online in the 90s
right like it came in real slow like that that kind of coordinate system like if you think about
his tip in that regard then it makes sense so it wasn't complete rubbish no no
it wasn't at all it's just that the i don't feel like we described it well in that in that example
that was my worst tip ever no i didn't think it was i didn't think it was a bad tip uh you know
like like but it was just and even on allen Alan's, there was another comment, too. Oh, man.
Who was it that commented?
Somebody commented on it in the.
Oh, on Twitter.
Yeah.
Why wouldn't you just do a for loop?
Yeah, because in that same episode, you had mentioned using a for each loop.
And if you wanted to iterate over your, you're in a for each loop and you're're iterating over some collection but you need to modify that collection then instead you might do something dirty by having like another collection
that represents either the end state or the deltas that you want to you know add or remove or something
like that and and that after you break out of your 4-h loop that you would then do the do the
collection modification and i can And I don't remember.
I'd like to give credit.
I could probably find it.
But yeah, it was on Twitter.
One of the listeners commented in and said,
well, if you just used a for loop instead of a for each loop,
then you don't have that exception problem.
Because specifically the exception is collection was modified,
enumeration
operation may not execute but using a for loop you could do all that collection manipulation
it was mike mike depaul thank you yep so yeah that was excellent and it's it's absolutely true
if you do a for loop then there's no enumeration that you're stepping through there's no next and
all that kind of thing so because you're just referencing things by index at that point,
and it doesn't care.
Right.
So I felt like those were big enough, like, oops,
that should probably be mentioned.
Yep, they were good.
And you know what?
We should mention we got some really great comments,
and we're not going to talk about any or all of them,
but we even got a poem on episode 34.
So if you guys ever are bored on the internet, you should go to our website and check out the show notes and read some of the comments because they're very entertaining.
Yes.
All right.
So let's do this.
Yeah, now it's time to get into it.
The 12 Factor app.
Dun, dun, dun.
Part four. Yes. into it the 12 factor app dun dun dun part four yes so today we're going to be talking about
the last three chapters of the 12 factor app uh dev prod parody logs and admin processes
so let's start with dev prod parody who wants to who wants to intro us into Dev Prod Parity?
Sure, I can do that. So basically the idea here is to keep development, staging, and production as similar as possible. And when they say similar, this is what I thought was particularly
interesting is they didn't necessarily mean like line by line or necessarily the kind of
back-end systems you're dealing with. They actually mentioned three gaps specifically.
And we're going to talk about those right now.
The ones they mentioned first was the tools.
So that's things like, you know, if your production website is using SQL Server,
you should be using SQL Server locally.
That's kind of the common use case that you think of when you think about dev prod parity.
But the second case they mentioned was actually time. That's kind of the common use case that you think of when you think about dev prod parity.
But the second case they mentioned was actually time.
And that's in reference to there being sometimes in some environments large gaps between releases. And so the code that's out in production that you might be doing support on could be months behind the code that you're kind of doing your day-to-day work on.
And that's an example of dev and prod being different.
And the third example they gave was actually personnel,
which is cases where sometimes the people deploying the application
aren't the people writing it.
So there's kind of a disconnect between the people who kind of push it up there,
do some clicking around and verifying if stuff is working like they expect
and how they might see that differently than the people who actually built the system so so i wanted to break this apart and talk about maybe
backwards from how they had it and start with the the tools right because i found it kind of
um contradictory to some of the it seemed it felt like it was a little bit contradictory to some of
the previous chapters where like all of a sudden now as we're approaching the end and
it's saying oh yeah remember how we talked about how you could abstract everything away
before well we want you to use the exact same thing as what's in production now yeah it's
abstracted so you can do this stuff however you want to and be really flexible but don't actually
use that flexibility which which i can't argue with though because honestly like every opportunity i've ever had
i want the same environment i want my environment that i'm developing on to match as closely as
possible to what it's actually going to run on but it just felt like some of the other chapters
where it's like wait a minute didn't we talk about having everything as a backing service that you could easily swap out and like why does it matter and now all of a
sudden it's like yeah but make sure it's the exact same backing service yeah i will say like i try
and follow at least this part like if being that we do a lot of dot net stuff like i'll even try
and run the full-blown is right locally as opposed to just the development server or sql server i
mean they they've done a good job providing developers with their enterprise level SQL
server.
So you basically run a full blown enterprise database on your environment.
And that is a way to almost guarantee that when something goes from point A to point
B, it's going to be the same.
Well, when it comes to I to is i'm with you on that
but that's more of laziness on my part and that's because as much as i would like to use uh is
express or might like to use is express because you know in theory it is kind of nice but you
know a nice concept but uh the having to run you know hit f5 when i might not even want to spin up visual
studio at all right like maybe i'm only doing uh you know some javascript development and don't
want to use uh visual studio at all so like i don't want to have to open it just so i hit f5
to run is express or to kick off is express so from a laziness factor, I like to use the full-on internet server.
Yeah, I've actually had problems by doing that before
because the IIS Express is pretty good about
not having problems with different file types and MIME types,
like say like WAF font files or doing sort of downloads.
And you upload your site to a new server or version of IIS
and suddenly your downloads aren't working anymore
or you're not getting your web fonts because of that little, you know,
stuff you need to set up on the server then.
And you may totally take that for granted and not know what's going on at deploy time.
Yeah, it becomes a big deal.
Like those little tiny nuances can mean the difference between downtime or, you know, a stable running site.
Yep.
And actually there's a really great table on the 12factor.net website where they kind of talk about traditional apps and 12-factor apps and how they are different in this step.
And one thing they mention, there's three things. But the first one is the time between deployments.
In a traditional app, that can be weeks and even longer
if you're dealing with something like different versions of Windows or whatever.
I guess that's changed a lot now.
But with the 12-factor app, you're really aiming for
deploys every couple of hours, if not more often.
And so it's really important to keep your dev environment
as close to production as possible
and basically pull master often.
I'm curious, though,
and I don't know that I saw anything in here on this,
but in the case that you have a product
that's running multiple versions in different spots,
like, could you even,
like, you have a customer that has a version out here and you have a customer as
a 12 factor app at all right that's what i was gonna say like no because these are all like web
like yeah the 12 factor app like a lot of these are written in the mindset that this is just a
dot-com an internal application or something yeah maybe not maybe internal but just you know it's treated as a dot com is my
point okay but um specifically this section excuse me reminded me of a story that i remember reading
a long time ago and i went back and looked for it to find it and uh it was around how facebook
does their deployments now they have since changed greatly you know this was
an article written in 2012 so this is back when they were still doing compiled php and uh the
when they would do their releases they would do several um i think it was like i think the article
said they did uh at least a couple a day and then like the major ones were done once a week or something like that.
I'll have a link available for you.
But their releases were... One of the cool things about this was that back in 2012,
they would compile all of Facebook.com into a single file, right?
And that single file was 1.5 gig in size.
Now, your Facebook.com, you're scaled across the world,
and you've got to distribute 1.5 gig across every server in your infrastructure
in order to get your latest version out, right?
So they were using this really cool idea.
Of using BitTorrent to distribute everything.
Now specifically as it relates to the 12 factor thing.
One thing where I was trying to remember was that.
Like where was it that.
You know the whole process to put out that version of Facebook.
Was like 30 minutes in total.
But I thought I couldn't find it, but I thought there was a part where it talked about
as the developers were working on their fix, and maybe I'm thinking of an Amazon story,
but they could push out their fix right then and there as soon as they committed the ticket or whatever their ticketing system was.
But while I couldn't find that as it related to the 12-factor, this article still did relate in one way.
And that was that one of the factors here was that the authors of the code in this graph that Joe was talking about,
like the traditional versus the 12 factor, 12 factor app, the authors of the code versus the
deployers of the code in a traditional app were different people, but in the 12 factor app,
it's the same people. And specifically this article about the Facebook deployments,
they specifically talk about like the person who wrote the code
that's going out in that deployment, they own it. It's theirs. And they have to be around at the
time that the deployments are going out. And if there's any problem as a result of their, um,
their change, then they are responsible for fixing it. Like they gotta, they gotta own it.
So I liked that, that ownership part of like hey
if you're willing to if you're willing to write the code you're willing to commit it and and work
on that ticket and put it out there then you have to own it and see that it goes all the way into
production right it makes a lot of sense which is something i really like about the 12 factor app
because i really liked it i nobody i'm sure we've all been in that situation where, you know, you've
worked with someone, they write some code, but then they disappear and it comes time to do a
production deployment. And, you know, you don't, you don't know, like, well, you, you hope that
it's okay. Cause it's in, it's in, you know, whatever your master trunk is. Right. But,
you know, when it comes time to deployment, deploy it, you know, and you're like,
how do I even test this thing? Like, what is it?
It doesn't seem like it's working and you can't find this person.
Like that's a problem.
And so I really liked the ownership part of it and the fact that the 12
factor app specifically called it out as you wrote it, you deploy it.
Yeah. It makes a lot of sense because if a problem does come up,
if you're intimately familiar with it, you know exactly where to go, right?
I mean, that's a big deal.
Yeah, not only that, but you might also be aware of like,
maybe there are issues that are, how to say this,
like acceptable issues.
Edge cases or something.
That someone who's not familiar with it,
when it comes time to do the deployment,
they may be like,
oh my God, this pixel's in the wrong place.
And you're like, whoa, whoa, whoa, timeout.
Yeah, we know that it's two pixels to the right
when it should be to the left.
And we're going to fix that, right?
We already got a ticket for that.
But for right now, we don't care.
And actually, too, this article specifically called that out.
And which is why I was, you know, to your point about how did you just phrase that a moment ago when you mentioned multiple versions to different clients?
Oh, yeah.
Like you have a different version of an app deployed somewhere.
Then you can't really have development be what production
is because you have multiple versions like like specifically in in this uh facebook uh article
they had mentioned that like um you know reverting back to other versions it was for losers right
like you always roll forward and i i felt like that was really like the 12 factor app also kind
of falls in line with that too yeah right you know and i think we've mentioned that was really like the 12 factor app also kind of falls in line with that too. Right.
You know,
and I think we've mentioned that before too.
Like you just,
just roll forward and you know,
fix it there.
And so they specifically talked about like when there are those,
um,
acceptable issues,
right.
That,
you know,
rolling back a version that the,
um,
person being interviewed from Facebook in this article made the analogy that rolling back a version would be the same as pulling the brake line on the train.
Right?
You just don't do it.
Yeah.
You don't do it unless it's an emergency this brings up a little bit of a side tangent but
i've worked it and with people and at places where like the knee-jerk reaction is a rollback
and i can honestly say that in probably 95 of the time that is the wrong reaction and now you got
documentation to prove it's call them out and say they're a loser right right no but i mean in all honesty like if there is a
problem if it's something that's going to bring you down for a day and it's going to affect a lot
of you know money then maybe it's something that you consider having a rollback for right
but if it's something that you can solve in a reasonably quick amount of time and especially
if you're working with engineers you trust
and they are involved in the release cycle,
then they can probably figure out pretty quickly what's going on.
And a lot of times rolling forward is less painful than rolling back.
So, you know, taking that extra time.
It really depends on your infrastructure.
It can. It can.
It can depend on a lot of things, right?
Yeah, like what's your deployment infrastructure like?
Right. But then there's also the argument that could right? Yeah, like what's your deployment infrastructure like? Right.
But then there's also the argument that could be made, too, that like, you know, an opportunity, like let's say that Facebook has a bug, right?
Well, their monetary bug is going to be more like ad loss, you know, type of revenue, right?
As opposed to Amazon.
Versus if it's Amazon.com, then the revenue lost is huge because it's on some potential sales.
So, you know, yeah, I just thought it was interesting that their stance was, you know, rolling backwards for losers.
Yeah.
And again, you just brought up a key differentiator there.
I mean, depending on what that means to your site, right?
Like if you're Shopify, you can't have it down, right?
Like you're affecting hundreds or thousands of storefronts.
You can't screw with that.
Facebook, okay, so people can't see what their friend said, you know, 30 seconds ago.
But you know who's going to be best to be able to evaluate that problem quickly?
The guy who coded it.
Yeah, absolutely.
He should be involved in the deployment.
Yep.
So yay.
12 factor.
All right.
So sorry about that.
We're coming back from a technical difficulty there.
That's never happened.
Usually all of the bits from Florida are able to make it up here to Georgia,
but for some reason the internets didn't allow that.
And so we had to resolve that issue.
Yeah. Well, I think it was more of a problem with georgia receiving but uh that's very possible that's right but uh in the
interest of keeping things uh moving right along i just wanted to say that the key points for me
um is basically just my minding the gap here um Release early and often. Keep the programmers close to operations
and take care to make sure your
environments are as close to exact
as possible. And you know, one thing we haven't
really mentioned with this whole thing, we kind of took
for granted though, is
with this whole 12-factor act,
they're really kind of
counting on you being an agile
shop. Like, there's no room for
waterfall here oh no no
this this requires at what hourly dual every two hour releases that doesn't happen in waterfall
no you can't schedule yeah releases like that i would just be crazy you have to have like at
least 300 meetings before i release yeah this uh well well you know and that's the we've talked about this before at
the especially at the beginning where like some of these uh chapters were okay for like any type of
any type of app development right and every now and then you can see the tone that was initially
set or the intention that was initially set where,
you know,
like you were saying,
it was really for agile environments or for.com type environments.
And,
uh,
this is definitely one of those where it's like release often,
right.
Where,
you know,
that didn't happen in earlier days of an operating system,
for example,
where it's getting there though.
It is kind of getting there as,
as the pieces are
distributed more modularly but
yeah it's been a long road.
Yep. And speaking of
long roads we mentioned this
Clearly Tech article pretty much with every other
step we've done and basically they've
gone through and assigned an importance
rating to each of these steps
that we like to talk about.
And,
uh,
so what do you guys think they assigned,
uh,
for the dev prod parody?
Okay.
I may have cheated.
Yeah.
I have now only because of the technical difficulty,
but my original answer would have been high.
Like I would have thought this would have been high on the,
on the chain of things that should be,
you know,
done high as well.
Yeah. I was really surprised that this one came in as a medium and i too thought that this one was going to be treated as high but yeah they only had it a medium and their answer was that
developers feel will feel like taking shortcuts if their local environment is working well enough
and to talk them out of it
and take a hard line stance and it'll pay off in the long term but yeah that just doesn't strike
me as the right thing like one of the things that we didn't touch on and i'll just briefly say it
right now is like they said a lot of times instead of using the full-blown sql database they might
use a sqlite or something right right And that goes back into those same type of problems
that you're going to run into that you wouldn't have had
if you had been using the same type thing.
Full text indexing isn't going to be available on the Lite version.
So, I don't know.
Medium seems a little bit low for me on this one.
But if my database is in a cluster,
I'm not going to have a cluster locally, am I?
Yeah.
Yeah, you can.
You can.
You could.
I mean, it might be a little bit of work.
I think here's where the rub is for me on this one, though, yeah yeah you can you can you could i mean it might be a little bit of work but i think i think
here's where here's where the rub is for me on this one though is that this chapter there were
you know as we discussed there were three distinct parts to this right there was the the time the
personnel and the tools gap and in keeping the developers close to the deployment, that whole ownership of it,
that is very near and dear to me,
very important to me.
And so that was a big part of the reason why I was like,
I really want this one to be high.
I really want this one to be important.
Right?
And yeah, that's my opinion on it.
Yep.
But I can get behind it being medium
and there's things
I worked on
that I just could not
have a local environment
for like SharePoint farms
and just like
kind of strange environments
that I just
I'm not going to be able
to feasibly have
for a small feature
so you basically
do as best you can
to mock it
and hope QA catches
any problems
yeah
but if you've got
a QA step
then you're probably
not being very a 12 factoractor app, I guess.
There's not a whole lot of room for that here.
So I think this next one, though, I think what we're about to step into, this might be Joe's favorite thing.
Yes.
I may be wrong.
I feel like we're in a Ren and Stimpy commercial here for Log.
Yeah.
This is one of those things that I love.
It's log.
It's fun for a boy and a girl.
It's better than bad.
It's good.
Yes.
This is better than bad.
It's good.
I wasn't sure if that was going to go over well.
Oh, that's awesome.
Oh, no.
I love log.
Everyone should have log.
I mean, you know, it is star wars season you should
get one for the for all the family members oh so man let me tell you i i love logs and i hate not
having logs and uh for as much as i hate not having logs i'm terrible about actually having
the appropriate level it's either it's either too much is logged yep or not nearly enough is logged there's never a happy
medium there yeah and i've actually been in situations where i was logging too much and
it actually would slow the app down and so i would do something like you know stop stop logging and
things would dramatically speed up yeah a lot of times especially if you're running a console and
you're actually seeing things printing the screen it it can have a noticeable effect. Oh, yeah.
But it looks so good streaming, right?
You feel like you're in the Matrix.
That's right.
Tail log.
You've got like 80 of those going.
Yeah.
Yeah, like the Whopper is playing its own version of tic-tac-toe by itself
as you watch all the logs fly by.
It's guessing the random password to launch the nuke.
That's right.
But they actually had some really cool things that kind of set apart their advice on logs from kind of traditional,
or at least what I think was being traditional.
And their big point there was treating logs as event streams.
And specifically getting away from files.
They want you to log to basically your console.
So just standard error and standard out.
You just kind of do your console.log.
It's great for while you're working on it
because you see it right there in your IDE
or somewhere nearby.
And you can do all your sort of file rolling
and aggregation and streaming and writing the files
and file management and rolling logs,
all that sort of stuff can be handled
outside of your application.
Your application doesn't have to know anything
about any of that they said that but i wasn't quite on board with
it yeah i don't know and i was kind of curious especially like in the days of like apis like
a log for net right or a log for j i i'm such a fan of that i was like no wait why why do i want to get rid of that and just
write it all out the console so i thought about that actually quite a bit and one thing that they
really emphasize in some of the earlier steps is being able to have like multiple instances of your
application on one box and when you start doing stuff like that then it gets hard to have like
a you know a single place kind of configured for logs like you want to be able to to have this stuff right out there could just be like an environment variable per instance
that would define what the log path was right well like have it give it a guid or something
every time you restart the app it like goes to a different folder well it sounds like though the
difference though is what they're saying is you just log to the standard out, right?
And then in each environment, that environment decides what to do with it.
So, yeah, you're talking like log for net.
Yeah, they're talking about like, you know, redirecting it.
Redirecting, if you want to capture that out to a file, then fine.
You can redirect standard out or standard error out to, you know, your choice, right?
But you do that in the environment.
What you're talking about with like log4net or...
Log4j.
Log4j, but there was another one, LogBack, in Java.
So instead of using those libraries
to set that kind of stuff up through your app,
they're saying, no, you just do your standard out
and then you let the environment handle it, right?
And that kind of makes sense to a certain degree
because now, no matter where you put this thing, you can have that environment set up to do things a specific way for that environment, right?
As opposed to letting your application handle it, which means if you ever want to project is that based on configuration, you could have different outputs for your logs.
So if you want your application to suddenly be logging your, to do all of its logging to a database, then you just configure in the configuration configuration you configure it to write to sql
server or if you want it sending emails you configure that in the log for net configuration
or if you want it writing out to a file or if you want it writing out to the console
or if you want it writing out to console with colors all of that do all of them at the same
time again but but all yes yes you could yeah but all that was configuration driven
which doesn't break the 12 factor thing well but here they're saying don't do it but here they are
yeah no because here they're saying write it out to standard out or standard error right and so
there's only the one output ever and so you just hit on one where like if you wanted to write it
out to a console if you're running it by console and you wanted to write it out to a console if you're
running it by console and you wanted to write it out to a file or if you want to write like you
could only have the one choice right with with this option that they present yep although um
you can have a like a console appender basically so you can run through something like log4j and
still have it just write the console and then you get all the benefits of having like the different
levels of logging like debug or info and you can still have the nice
timestamp and formatting and you still end up writing the standard out yeah this one's this
is an interesting take on it like i don't know that i'd throw away logback or log4net or any of
those because they do add and like you said it's configuration driven which
i don't remember which one part of the 12 factor app was they were like hey things should be config
driven so that you can just change a config right it was chapter three yeah so so i i'm maybe
i don't know i i can't think that that these kind of libraries didn't exist when they did this
i'm not real certain maybe maybe it also has to do with speed.
Again, consider the source.
It might also have to do with speed, though.
If we think about it, if all you're doing is writing to standard out,
there's really no drag on your application.
It's now on your environment as opposed to the app.
Oh, no.
There's a drag on your application if you start writing out
to standard out while it's in the console.
Yeah, there's totally a drag on it. But it depends on how you set up your environment to do it right
there's there's no overhead in your app is what i'm saying you get what i'm saying so if you have
a log for net there's there's a bit of overhead because it's now managing how your logs get
written and that kind of information yeah but what but I guess the point that I'm, I'm trying to make those that like,
you know, you rely on those kinds of third party libraries because they're already
trying to optimize themselves for when should I flush to disk or when should
I not,
you know,
things like that versus if you're just doing a simple redirection,
then you're losing some of those performance efficiencies that that third
party API might have been doing for you. In addition to the flexibility of, okay, let me
also have the logging send out to an email on certain conditions, right? You know, so,
so that's all lost. But they have LogPlex and Fluent that that they mentioned which i'm not familiar with either
one of these things um for heroku so i would imagine that these kind of do the same type thing
but um well and this is why i was like this is why i was saying consider the source is that
okay so you know we're getting close to the end of the year here and you know as part of getting
close to the end of the year it's going to be that stupid resolution time and last year at this time i had said you know hey i should
probably like take the time and put in the effort to learn rails and i never did but the guys at heroku did and so so i don't know if maybe maybe that's where they're
coming from is that you maybe they don't have i mean i would find it crazy that there's not
you know a good logging package out there but maybe there isn't and that's why they were saying
like hey in our experience we've just found it best you know even that there might be some third
party um you know logging packages
out there just go to standard out and be done with it i don't know yeah it's interesting i mean
i don't know like i said i wouldn't stop using log4j or log4net or logback or any of those
because they add that like we said right they give you the ability through configs to set up something that
that you can easily change and stream to multiple places which might be a performance hit but you
could do it so so starting tomorrow we're gonna document the 11 factor app 11.5 with no logs
that's right no logs well at least we can all agree that they're right on about treating logs as event streams.
Yeah.
Right?
And whether that means log4j or console, sorry, standard out, then that's another point.
Yeah.
Yeah, it should be.
You should be able to retrace what happened.
That's the whole point of them.
Well, if, because they made the point about, you know,
letting some other tool route the logging and to not clutter up your app
with the file management of the log.
So if by that they include the third-party app, or I'm sorry,
a third-party library like a Log4J or Log4Net, then, you know, yeah.
One of the notes that we had here that i think is truly relevant
and people that aren't aware of them uh hopefully this will come up for you eventually is if you
have multiple servers especially like in this 12 factor app right like the whole point is to be able
to scale horizontally and so now you have logs potentially going to multiple different places
right you don't
necessarily want to have a shared server because you can't scale that properly so you might have
logs across 30 different servers well in order to actually be able to use that if you're netflix you
might not know how many servers yeah yeah it's they literally scale those up and down you know
once every couple days you know several an hour and they only stay alive for a day or two.
So these files may be all over the place. And even if you have a small web app that you might be hosting internally at your own company, even trying to go across five different servers to try
and aggregate those logs is frustrating, right? You need something like Splunk or Logstash,
which are set up to be able to suck in these logs
and aggregate them together.
So they bring them all into one searchable spot.
Splunk is amazing.
If you're not using Splunk.
I can't say Logstash because I've had no experience with it, unfortunately,
but Splunk is amazing.
Here's an example, though, that you didn't mention though like in your in your you know you have the multiple servers and you're trying to like
aggregate the data across all of them what about in the case of like security problems oh yeah
right like you're trying to trace a potential security uh vulnerability or you know a potential um you know intrusion right like if you have
n number of servers yep and you have to go through each one of them independently you'll
never find a nightmare yeah so so having it aggregated together in something like a splunk
is very helpful yeah and not to go too far into it. I mean that it, it really is amazing software.
Again,
it's not super cheap,
but you can even have it do things like alert you for like what you're
talking about with a security thing.
You have it look for particular events and you can actually have it send an
alerts out if it finds something.
Right.
So pretty amazing stuff.
I also have not used log stash,
so I'm not sure how well it fits in,
but another popular solution out there.
Yeah.
Yep.
So what do you think about the importance rating for this one?
First of all, what do you think that Clearly Tech gave it?
High is something I won't agree with.
I mean, I got to say logs are high, man.
Like, how could you not have logging in your environment?
I'm between medium and high myself because,
especially for a production-type environment
where you're not typically allowed to get hands-on into, like,
data and that kind of stuff,
how else are you going to retrace the steps, right,
in any kind of meaningful way?
And that's why, I guess guess depending on the type of environment this would definitely either be a
medium or a high for me well okay so retracing the steps from a debugging perspective but if
you're any kind of uh financial whether it be a bank or an e-commerce i would imagine that you
pretty much have to for regulation purposes.
Yeah.
Right?
Like, it's not an option.
Not having a log isn't an option.
Well, I mean, think about if you're wiring money, right?
Like, you need to know every step of the way exactly what happened.
Now, whether or not that's stored in a database.
Some of that might be traced elsewhere.
It might be databases.
I meant, like, more connectivity type of tracing.
You know, like, IP addresses that were coming in. You you know, like things that you might find in a typical log.
Vulnerabilities and stuff, yeah.
Well, like one teller is logged in from five different states and running, you know, looking up customers at a rate of like 10 per second or something.
Yep, yep.
You know.
Yeah, so that's what I'm saying.
Like I view this as like it's a high.
I don't see how it could not be. Yeah, so that's what I'm saying. Like, I view this as, like, it's a high. I don't see how it could not be.
Yeah, I guess it depends.
You're probably going to say, this is why I said, like, you're probably going to tell me it's an answer that I don't agree with, Joe.
Yep, they have as a low.
What?
And the reasoning is, basically, if you are, I'm just reading this from the site, if you are relying on logs as a primary forensic tool, you are probably already missing out on better solutions.
Be sure to consolidate your logs for convenience, but beyond beyond that don't worry about being a purist here
and they're not saying don't log and they're not saying don't aggregate but i think that they're
basically saying don't rely on logs as your primary means of debugging um which i i still
don't agree with really but uh you know i i definitely i can't see this being any lower than the medium
yeah that's what i said like depending on the the circumstance that maybe a medium's fine but i i
can't see it being any lower than that i kind of find it interesting that like in the example that
i gave and then the forensic tool was one of that you know their choices of wording in there that's
uh that's interesting.
If you take it from the perspective of duh, of course you have logs
but whether or not it's
written to standard out, then I could see
them grading this lower and getting away with it.
Definitely logs
are wonderful and if you've ever
and I'm sure you have if you've been programming for any length
of time, dealt with a situation where
you don't have any logs or you don't have good enough logs
and all you have is it's broke, figured out, and you can't reproduce the problem,
then you know how horrible that is.
All right, so that's it for logging.
And now it's time for our call to action.
So we would love for you to leave us a review if you haven't already.
And the reason is it's basically our primary way of finding new listeners.
It's really helpful to us and it's been helpful
and we would love for it to continue being helpful.
So we really appreciate it.
And also, if you already have left us a review,
please feel free to share the podcast
with your coworkers or friends.
Yeah, and you can leave us a review
by going to www.cuttingblocks.net slash review.
We made it real easy.
So you can leave it on your platform of choice,
iTunes, Stitcher, and we don't know of any other ones.
If anybody does, that'd be awesome if they told us,
but I don't know where any other review places are.
Someday we'll finish getting up on SoundCloud.
Yeah.
Did you mention Overcast?
No, I have not.
Overcast?
Well, I don't know.
There's all kinds.
Yeah.
Overcast, Player FM, Stitcher, iTunes.
Yeah.
We're all over the place.
SoundCloud.
Yep.
SoundCloud, not quite as fully as others.
But yeah, one day I'll finish uploading the rest of those episodes.
All right.
This episode is sponsored by Infragistics.
Experts in data visualization.
Infragistics developer tools drive custom app development for any data visualization
scenario on any platform.
And ReportPlus is an enterprise-ready ready self-service bi dashboard solution that
opens up your enterprise big data for end user consumption head over to infragistics.com and get
your free trial today all right so before we head into this last this uh last chapter of the 12th
factor i wanted to have a little bit of fun here um because we didn't mention the polls and we've had two episodes since this last
one and i thought you know this would be kind of interesting right because like once again we
forgot to mention like you know or even think of like what a poll could be for this episode
but when we do that and i happen to be the guy in charge of putting the show notes together
i'm like well i'm gonna have fun with it so in episode 34 i'd said well why do these guys keep forgetting to think up a survey
and the options were call of duty black ops 3 destiny the taken king or halo 5 guardians
now because i'm sure that you guys didn't cheat and don don't you dare do it now, Alex. I'm good.
I'm good.
All right.
What do you think?
What do you think it is?
Call of Duty, Destiny, or Halo 5?
Call of Duty.
Our listeners, I'm going to go with Destiny.
Wow, really?
Yeah.
Wow, from left field.
Well, Joe is right.
See, that's what I prefer.
54.5% Call of Duty Black Ops 3. Very nice. from left field well joe is right oh see that's what i prefer 54 and a half percent call of duty
black ops 3 very nice and they wouldn't be wrong that's that's the thing right i haven't bought the
game yet oh my god so well okay i felt i felt a little bit lied to about the um about the zombies
campaign because i don't remember if i read it or watch it
i definitely think i had some conversations with like local you know like uh you know game stop
store but there was supposed to be like a whole campaign mode for zombies that was supposed to be
more like the traditional campaign or like you know the gameplay was supposed to be like a normal
campaign i really didn't feel like it was.
I felt like,
I'm like,
what are they talking about?
This is like the same exact type of zombie campaign in terms of gameplay as
like what you had,
for example,
in advanced warfare.
Right.
So like redoing monotonous shooting zombies,
trying to get into the house type thing.
You're definitely thinking of like older zombies okay then then current that turned me off forever but what i'm saying is that like in okay let's let's narrow it down just to black ops 3 and
advanced warfare since those are the most recent ones. Both of those versions, if you were going to do a quote campaign
in the zombie mode, then you would start from the beginning
and it's kind of like Super Mario Brothers.
You either get to the end with your set amount of lives
or you don't and you start over.
It's not like the campaign mode in you know the normal
campaign mode where you know you're like hey you know what i want to stop here and call it a night
and i'll come back to it it's not like that right yeah it unless i miss something but
that's no i was kind of disappointed that because i was hoping for like you know
a multiple storyline but yeah and i will say i don't know like have you played
it joe have you played black ops 3 nope no okay the one thing that advanced warfare really had
that i so badly miss in black ops 3 and i can't believe they took it away was the firing range
like as you're you know putting your gun together you're customizing it, you're putting on
like, you know, what site you want on it, the grip you want on whatever, whatever options you wanted
to customize your weapon, right? You then just go over to the firing range, try it out, see if you
like it, you know, and then go shoot people in multiplayer, right? You can't do that in Black
Ops 3. It's like old school where
you know you don't know how the gun's going to perform until it's too late and you got a bullet
in your face i never did the firing range i always went straight into battle dude really i was like i
got this gun let's go use it no way man that was that was like especially no it's but especially
once you got royalty on the gun and
you're like oh cool what does this look like in gameplay mode you know i would jump into the
firing range and and just spin around like oh this is what it's gonna look like let me go ahead and
break this down for you though so so we were at a place the other day and they have a ps4 city there
oh god what's happening and they have some controllers so they have uh black ops advanced warfare advanced warfare all right so
so most normal people aka me you we'd sit down we'd be like all right let's grab one of these
built-in classes and let's rock right my god dude like 15 minutes later i was snoring i was snoring
beside outlaw as he's over there setting up his class, he's picking out the right grenades.
He's setting up his score perks, dude.
Like, I'm like, dude, are we playing today?
Do I need to come back later?
Maybe I need to hit a bio break.
I'll be back.
I know what gun I want and what options I want.
It was more like maybe two minutes.
Dude, he even spent
time like molding the person's face like it took forever i mean you know that is one of the voted
that is one of the cool things about advanced warfare you do get to like pick your outfits
dude i'm not even kidding you gotta dress him appropriately i wouldn't play the game of ping
pong and came back and was still waiting that never happened that never happened but you
know what did happen was advanced warfare and i forgot how much i loved that game though that
game's fun like when we played that game for the few minutes that we were there well we could have
been playing for like 30 minutes oh my god but it but it totally made me think like you know because
at first i like i think i wanted to like black ops a lot more than i did but it totally made me think like, you know, because at first I like, I think I wanted to like black ops a lot more than I did,
but it has definitely grown on me since.
But like you ever have that thing where like,
you don't want to be that person who doesn't like change,
right?
But sometimes you find yourself,
you're like,
Oh man,
why did I don't like that?
They changed it.
Why did they do that?
And then you kind of step back and you're like, like whoa you're that guy that suddenly doesn't like change
and and so you try not to be but i i really wanted to like black ops 3 and then i kind of was like
but i really so liked advanced warfare why can't this be exactly like advanced warfare and just
call it black ops 3 but now it's kind of growing on me.
Yeah.
So,
uh,
I think the key takeaway here is if you voted for call of duty,
you were right.
Yes.
Yeah.
You,
you were totally,
you were totally right.
And,
uh,
so then there was the,
um,
episode 35 poll,
which again,
we didn't have a survey for it.
So it must have been somebody's fault so your
choices were it's alan's fault it's joe's fault or it's michael's fault it was definitely michael's
fault really yeah absolutely all right what do you think joe uh i i'm gonna say michael's only
because sometimes people seem to confuse me with michael what were we right so okay he's not
gonna answer this so i want to have a talk with you dear listener right now that means we were
right because more than 46 percent picked me then it was my fault that there wasn't a survey and you know the funny thing is is like
at first as the survey when the survey was out and the votes were coming in like i i was kind
of like chuckling to myself because i was the one that put the survey out there and initially they
were coming in as either like all alan or all joe and i was like oh this is kind of funny none of them have been
for me yet and then they all started coming in for me well that was because nobody had listened
yet they'd only download oh whatever i'm like wait a minute why why me like uh who do you think came
in last then out of that one me really you you think? No, it's Joe. Joe's a nice guy.
I'm going to say just me because whenever something is wrong, they tend to blame my wrongness on you somehow.
On me?
Yeah.
I think it was actually Joe.
If my levels are bad, it gets attributed to you for some reason.
Joe's like the nice guy.
I think Joe needs to say his name right now.
This is Joe. I am Joe. Hi, my name like right now this is Joe I am Joe hi my name's Joe Zach I think I think
before before Joe says anything from now on for the remainder of the episode every time that he's
about to say something he should say this is Joe this is Joe yeah yeah so so Joe was uh only 23%
he was he was in last oh that means I wasn't too far above him. I was like 26. Yeah, you were in the middle.
Yeah, yeah.
I didn't like that I had such a commanding lead.
Yeah, I was going to say, like, you doubled us up, man.
That, that.
I was like, wait a minute.
That's amazing.
Thank you, listeners.
Yeah, I really appreciate that, guys.
Thanks.
So, you're welcome.
All right. I really appreciate that, guys. Thanks. So you're welcome.
All right. So now let's get into the last chapter of the 12-Factor app, which is admin processes.
All right.
And basically the deal here is to run admin or management tasks as one-off processes.
And what they're really talking about here is basically keeping these associated with the application
and keeping it in line with that dev prod parity,
or I guess it's kind of like a prod broad parity,
but basically keeping this stuff with your application
so that it stays in sync.
If you've ever been somewhere that had a shared code
deployed to like a separate server for tasks,
then you know the pain that they're addressing here.
And it's basically like you put out a new version of your site, but you forget to update
the tasks or vice versa.
These things just get out of sync if you don't take great care to keep them together.
But if you're running these tasks as kind of like little, you know, maybe scripts or
something in the directory of your web route, then you can kind of keep this stuff all together and this stuff can be a website
or be used to run these little one-off processes.
Yeah, I mean, a true story behind this,
like what you were talking about,
having a shared environment
where you just have these things run,
it is so easy for something
to have been running perfectly for a year.
Your app is now umpteen versions
later and now you need to update this thing. Basically that code base that was there a year
ago no longer exists. And so now it's a major effort, right? Like you have to go update this
thing again. You have to go, it can become a bit of a pain. So like this whole thing running it off,
running it off the same code base
as what you've got out there now and keeping it with the app,
that actually makes a lot of sense.
Yep, so if you've got something like, say, you've got a search engine
or something, you've got a process that generates a feed every so often,
then you want this process to be in sync with the shared code
for your, say, website.
And if you've ever been in a situation where you update the website
and the feed breaks or vice versa, then, yeah, it sucks.
Yep.
I think the one part that I got maybe stuck on in this chapter, though,
was that there's this line where they say that the 12-factor
app strongly favors languages which provide a read-eval-print loop. And I was like, well,
that's kind of an unfortunate statement. Like, why does it need to favor that in order for
all of these other great chapters to adhere to all these other great chapters to be a 12-factor app, why is that necessary?
And I still don't know that I ever came up with an answer for that, at least in my own head.
To me, I understand why it would be nice to have a shell right there that you can interact with your shared code kind of, you know, in real
time. And I understand why you, you know, what's like a traditional static language like Java or
C sharp, why you wouldn't want like an executable or a jar there that you'd have to, you know,
build and interact with. But yeah, I don't like this. To me, you know, I don't know of any static
languages that have a REPL really, at least not a useful one um so yeah it's it seems kind of like a hacky thing to say like why should i be interacting
with a repl in production yeah i mean and that's another good point too i feel like if you're in
production you probably you know especially if you're if you've gone the way of the 12-factor app, then chances are all of these boxes being spun up should be automated.
You're not even touching these.
So the fact that why would you even be logged into a box to be in one of these, you know, read about print loop shells at all, right?
Yeah. I do get that it's faster to be able to say just in a little script file, you know, import the libraries I need and do these three actions compared to C Sharp where you have to create an executable and there's going to be an app config and, you know, stuff like that.
It's just kind of annoying to deal with.
But, yeah, I'm not crazy about this one.
I think they're kind of the website biases showing through again.
Well, and the language choice.
Right.
Right.
Yeah.
I mean, I did like that.
I think I read it somewhere on one of these where it was saying that in this section, too, that these scripts would be deployed along.
They would be part of the code base and deployed along with it so like every box you know if you had one of these uh admin scripts right for example then you know every deployment
got that script right so they're all at parity with one another right yep yeah and it's true
even by saying repl i definitely feel like i hear that a lot more for ruby like python you know i
hear like interactiveactive Shell.
And even for JavaScript, you don't really hear people talking about REPL.
And that's why I keep referring to it spelled out rather than saying it like that, right?
Right.
Like a read-avow print loop so that for those that aren't familiar with it, that have never experienced it.
But basically, okay, so I guess in fairness,
if you haven't, what we're talking about there with a redevelop print loop is, let's say that
you were to just type in, let's say you're a Perl developer, and you would normally type in Perl and
whatever your script name is to execute it. Unless you're on a Linux environment, which we'll forget.
Maybe you have at the top of the script you have the
interpreter listed there but let's forget about that for a moment you might just say like pearl
and then your script name and to execute it but in a read eval print loop you would just type in
pearl and then it would enter into a pearl shell environment where you could enter in, you know,
Perl language constructs and it would execute them there. Right.
You could do Python the same way, right? Like there's,
there's several of these and, but languages like C sharp,
for example, are not going to be one of them. Java is not going to be one of them. Right.
Yep. And I mean, there's, there's there's hacks in place you know there's tools
that you can use to kind of have repl like environments and i know there's like c sharp
script and um you know sources stuff like that but that stuff isn't really common it's not the
kind of stuff that you're going to have hanging around in production yeah but i just thought that
the repl thing was interesting and uh yeah not too fond of that
sentiment yeah like i said it i it may have just been me i don't know about you know for youtube
but it definitely like once i read that part i was like just sidetracked i'm like wait what
yeah lost all train of thought squirrel
so yep um and clearly tech.com uh they had a nice little snippet here i was going to read Squirrel. you know, from a local environment or something like that. And an example here, I think, is like something like clearing the cache.
You know, these are developer-oriented tasks,
things that you might want to do just kind of, you know, right now
or if there's some sort of problem or something.
And so I like the idea that I can kind of, you know,
SSH into production and, you know, kick off a script.
And, you know, so it's cool.
And I like that you don't have to worry
about the code being out of date
like you do if you have separate deployments.
And I like that there's basically one code base
instead of like separate installation types
for things that do tasks or things that run websites.
Yeah, again, I guess it's like the frame of mind
that you're in as you're reading it.
Because like I said, that one section or, you're reading it because like i said that that
one section or you know that one mention about the the repl definitely threw me off
and then there was also like i said to this other frame of thought that i was in where it's like
if i'm thinking about this from the point of view of a app that is let's think about like a cloud-based app right if you're thinking about a cloud-based
app that's going to uh scale up or down based on demand right then that should be completely
automated right no one is going to be ssaching into any one of these boxes right they shouldn't
you know that access shouldn't exist for them.
They shouldn't even know, you know, what boxes.
Like, that's not even something that should be happening
if you're in that kind of environment.
So then why do I need these admin processes there
that I'm going to be SSHing into to execute,
that I need this read-eval-print loop for?
So I guess where I'm going with that is that in the clearly tech from an importance point of view like i kind of ranked this one as
low yep same here yeah yeah the biggest issue for me is basically the prod prod parity issue
where you have different um different uh install locations
and therefore different versions of code that are possibly running your tasks but aside from that
you know i feel like if you if you do have a separate kind of install location for tasks and
separate locations for your website so you will get bit but um maybe not so often and maybe it
won't matter that much so i think this one's a low to medium.
That's where I fell on this one.
Because to what Outlaw said,
if you've got 50 of these things spun up,
should a developer really be logging in and running these scripts?
I could see if you had some sort of chef thing
to where it kicked them off when it got spun up,
but that's not the whole point of this repl loop right like
the the whole point of that was so you could get user feedback and then that doesn't really make
sense so yeah i would say this one's a low to a medium yeah so i'll buy that with it especially
with the chef from puppet kind of example where you know you're you're wanting to script out you
know what the what the configuration of the system is, and you want some tasks that will be executed as part of maybe that
that you want to coincide with the version.
So they should all be deployed to every instance
and be part of the code base.
I agree with that.
So I'll stand by low to medium.
Well, they give it a high.
Yeah, man. it a high.
Yeah, man.
Yeah.
But their reasoning... That's it, we're done.
No, like literally.
Yeah, I feel like this last step is kind of a fizzle.
I wish logging was the last one.
Oh.
We should have swapped it.
We should have swapped it.
We should have swapped it around.
So, their reasoning, though, is basically saying having console access to a production system is a critical administrative and debugging tool.
And every major language and framework provides it.
So no excuse for sloppiness here.
I disagree.
Having console access to a production system is a critical administrative and debugging.
Like, no.
Especially with REPL repl you can really
mess stuff up you
know if you
accidentally you
know run a delete
operation or
something well
that's the greatest
chance of where
you're going to
have a security
hole yeah if
you're allowing
like you know
production access
console access to
your production
system there's your
greatest chance for
for being hacked
like that should
be locked down
yep so and yeah so yeah i actually
consider logging into production and uh modifying things via repl i consider that kind of sloppy so
yeah i'm not crazy about their definition here but i'm not really crazy about this whole
factor all right so we're down to 10 factors yes we've chopped them i think there actually
might have been a couple others that we didn't quite agree with but that's true but um we uh
have gone through all of them so that's it uh tonight we went over um dev prod parity logs and
admin processes so do you guys have a favorite of the 12 oh good question mine was probably the
config one i really like
the whole idea of having configs or environment variable setup that like that the whole i forget
i don't even think it was part of the 12 factor thing but the whole don't commit anything you
wouldn't want to accidentally get open sourced like that that is so like crucial to making sure that you don't have major security gaps.
But I do like the whole deploy an app that you can change things on the fly without redeploying an app.
That is huge to me.
I like code base too, keeping each application separate in its own separate repository.
Yeah, I a good one too
actually what i was gonna say was like the the first three chapters started off very strong
yep you know and then and then you know the fizzle kind of came and went you know depending on the
chapter yeah code base dependencies and config um i also uh definitely was not like port binding
concurrency and disposability were were probably my least favorite.
Yeah, but then I did like 10 and 11 a lot, so that's dev, prod, parity, and logs.
Yeah, those are both good.
Very good.
Yeah.
It was definitely interesting, though, and I definitely am thankful that they took the time to put that out there. I mean, they're coming from a particular mindset, but a lot of experience in one particular realm of app development, right?
So it was interesting to see what their thoughts were on what made for a good app.
And I mean, honestly, again, a lot of this stuff translates.
Maybe not one-to-one for any kind of development environment but there's
a lot of good practices in here or things to think about at least while you're doing your development
so yeah yeah and i don't care what they say a lot of these chapters apply to any kind of app
development yep yeah and uh we hope you like this series so uh if you did like it uh please leave us
review and if you didn't uh send us an email email at comments at codingblocks.net. Right.
That's where the rants go.
Yeah.
Yeah.
Yeah. So,
uh,
in the resources that we like,
obviously we'll be mentioning the,
uh,
clearly tech article again.
And,
the 12 factor.net site will obviously be in there.
Yeah.
And,
um,
the,
uh,
wanted to mention the Phoenix project again,
which is basically a book with a it's
a nice fictional narrative around like a kind of a devops transformation that's uh it's really fun
to read um and i don't say that often uh also i wanted to mention the high scalability blog but
we didn't really mention this but if you want to read some like um some really great articles
about applications that for the most part uh kind of
follow this um this methodology then high scalability.com is a great place to go they've
got fantastic teardowns of like you know pinterest and netflix and they talk to the guys in charge of
those environments and talk about you know their high scalability issues and there's just a lot of fantastic write-ups there all right so let's get
into alan's favorite section of the show this is the tip of the week the tip of the week hey you
know what i decided something like i just made an executive decision for myself here oh my god um
you know it's the holiday season i'm giving two tips this time because I couldn't figure out which one I wanted to do.
So if you're ever cloning from a Git repo and you need a specific branch and it takes, you know, as long as it does for Outlaw to set up his character class in Advanced Warfare, then you don't want to wait around to pull master and then have to switch over to a branch, right?
There is a way that you can actually have it just grab that branch.
You can do a git clone and then whatever the URL is,
then dash B for a specific branch that you're looking for,
then a space and then the branch name,
and then do another space, two dasheses and then single dash branch and it will pull just that one branch down so that you don't have to clone the repo and then switch over to a new branch
because there are situations to where like if there are major divergent or like the branch has
diverged quite a bit from the master branch it can take forever for it to do those deltas and
especially on a big repo.
So I love this one.
I used it the other day.
It made me smile.
Whoa, whoa, whoa.
How are you going to maintain dev prod parity, then,
if you're dealing with multiple different versions of code bases that you're supporting?
This whole thing that we just did with the 12-factor,
that's all fictitional.
That's right.
No one ever does that.
Or fictitious so that's right oh no one ever fictitious i should say uh so depending on
your you know if you are writing a high scalable website like facebook.com then this stuff is
going to apply if you have uh just any other kind of apps then you can only really use part of these
like if you've got separate installs uh on premises of uh websites or if you're doing desktop software
then uh you know this stuff is just
kind of food for thought. Yeah, definitely. That went into the whole multiple versions of things
and all that. So the other tip I want to give, and I wanted to point this one out because I've
known this one for a while, but the first time that I set up an Angular app and I did it for a team of people, I didn't really totally understand the
npm install stuff. And I figured this might help because I know Node's very popular and so is npm
and you know, the 5 billion different packages out there. One of the things you can do when you do
an npm install is a lot of people just they'll show on the directions or in the an npm install, is a lot of people will just,
they'll show on the directions or in the tutorial,
npm install dash g,
and then whatever the library is,
whether it be gulp, grunt, something like that.
Well, what they fail to mention is,
okay, if you're setting this up for a team of people
that are coming behind you,
and they're going to need to be able
to get their environment set up pretty quick,
that does nothing for them and they're going to need to be able to get their environment set up pretty quick that does nothing for them what you need to do when you're setting up your app if you are doing npm installs in your in your application needs this library to be able to run
the application on your development machine or to be able to run it when it's deployed somewhere
you do an npm install and then dash dash save. That will make
it a dependency for your project. So the next person that comes in, they can just, as long as
they have node installed, they can say npm install, and it will go and get all the dependencies,
bring them down, and then you can run it. Now, if it's a development dependency, something that you
actually need to be able to do your development, you need to be able to get into the code, then you do an npm install dash dash save dash dev. And then that
will put it into a different place. So these all go into your packages.json. If you don't push
put dash dash save or dash dash save dash dev, then the next developer that comes they have to
actually know to go out and get all these
different packages that you did as opposed to being able to just say npm install and then
everything being done so if you're setting something up to where a team of people are
going to be working on something and you want to make it painless for them make sure you use the
dash dash save or the dash dash save you mean you're not going to take the approach that you had to suffer through that pain and so should they i try not to do that okay you're a
nice guy yeah like i said i feel i feel kind of giving right now awesome um and uh i uh speaking
of giving um i'm more of a taker and so i'm going to steal a tip from one of our listeners and we've mentioned him before Jeff Felina he's awesome there's a lot about SQL and he turned me
on to SQL Sentry Plan Explorer and Plan Explorer is free unlike the rest of SQL Sentry's tools
which cost a small fortune but it's basically like it lets you do a lot of things but how I've been using it or starting to use it is basically for execution plans.
It's just got a really nice explorer.
It highlights the trouble spots.
It lets you see CPU and IO numbers.
You can zoom in and out.
You can share plans with other people.
But just the color coding is really nice because I don't know a lot about uh you know execution plan and um basically soon sql tuning so it's nice to have something that kind of points
me in the right direction a little bit better than your normal kind of uh sql server execution plan
hey in all fairness i will say though he said sql century like all the tools cost a small fortune
i don't know of any database tools that don't like red gates up there.
SQL centuries up there.
Like I don't know any that,
that you basically don't have to mortgage a child for.
So,
you know,
you know,
my SQL,
all the things,
right?
There you go.
All right.
So,
uh,
I will in the spirit of the star Wars season, also give you two tips.
And the first one is a WebStorm-specific one.
So I found myself in a situation where I was going through a manual refactoring effort? Uh, where instead of, you know, for whatever
reason, I needed to do the chain, the name changes, um, myself rather than allowing the tool
to do it. I don't remember why, but once, once I was done, I was like, you know, I really wanted
a nice way to verify that I was done or, um, and so initially I guess the, the Unix side of me was like, oh, yeah, no problem, man.
I'll just hop over to my console over here, do a little find action, pipe that over to an XRX, do a grep on that and search for all instances of this particular string.
Only I was on Windows.
Sigwin.
So, yeah, uh,
yeah,
you know,
there was totally that option and,
and being a true,
um,
get bash lover that I am.
Of course I had get bash,
which could do similar things,
but even in a segment environment,
you know,
um,
if you like me have tried to do these types of situations where you're, you're going to, uh, pipe all the find results out to XRGs and, and, uh, pass that over to grep, then sometimes the spaces in the directories will throw off, um, XRGs and it'll start piping it'll start passing off like each uh different token uh space
delimited token as a as a separate argument to uh whatever you're trying to execute so it becomes
a problem but what i noticed which was fantastic is that in webstorm let's say whatever your
directory path is you can right click on the path okay and there is a find in path option
right and you can give it whatever you're trying to search for in that path and it'll just go and
find if there's any instances of it and if you want to do a replace right then and there you
could also do a replace in path so you could search an entire directory tree and find or replace within that directory
tree within your ide so you didn't have to install like a beyond compare or uh whatever
to do that right you didn't have to do that you're staying within your ide and for the keyboard
levers ctrl shift f or ctrl shift r and you can do your find or your find and replace from within WebStorm.
So I thought that was a pretty cool option. Yep. And then as the bonus one, uh, when Alan
mentioned web API earlier, it, uh, it reminded me of a problem that Web API has. So what I'll describe is, let's say you have two controllers, and both controllers have a similar route, right?
So in this contrived example, let's say you have a person controller and a company controller, and each one of these things has a name.
So you're going to have a method called get name, right?
And so what you ultimately want the path,
the URL path to look like might be something like API slash controller slash
get name, right?
And typically in web API style development,
you would specify the controller in curly braces and let it automatically
figure it out for you.
Right.
But this is where it,
it falls to its knees because it's like,
well,
wait a minute.
These both have get name.
How do I know which one is for the person controller and which one's for the company controller?
Which, for the love of, it's right in the file.
It's inside the person controller.
Why can't you figure out that I meant this get name belongs to the person controller?
To the person.
Right.
Right.
Because ultimately what you're looking for is a path that would be like slash api slash person slash get name or slash company slash get name but unfortunately it won't it won't figure that out web api won't
figure that out and more frustrating than that is it's not a compile time error no it's not even a
runtime error well kind of a runtime error it'll be a 404 when you try to access it but but you won't get
like does it 404 does it 500 no it's a 404 it gives you a path not found right it won't find
the path at all because they're like i don't know what that is so so it's totally frustrating so in
that case what you have to do is manually name both you can't just name one you have to name both
so you can't use that little curly brace controller trick instead you have to say in your
route you had to manually specify you know like if again you wanted it in an API path, API slash person slash get name or API slash company slash get name.
You have to manually type that in rather than saying controller and letting the compiler figure it out.
Now, one thing we do need to point out with this, though, this is if you're using the action approach to Web API as opposed to like the RESTful methods that I guess Web API is kind of intended for.
So this is using action
routing so like when he says get name um you know that would be as if you had an action to find
called get name but yeah it's uh yeah i didn't mean that like get as in the verb and the name
i mean the name of the path was get name yep but but okay so fine so if you don't like
that example another case where people have run into this before is let's say you were trying to
make a versionable copy of your api right so you release version one so it's slash api slash v1
slash whatever your controller is slash get name right and now
you're like hey you know what we've released version two and version two has some amazing
features but we want to be fully backwards compatible so if you want to use version two
you just go to api slash v2 slash person slash get name same thing you got a name on both you
would have to name the controller you'd have to fully name that path in order and this is an attribute right if i remember right it is an attribute it's
an attribute to the method but this is a web api kind of issue yeah and it will make you tear your
hair out yes it's uh it's aggravating yeah you'll be like why it's right there i don't understand why you're not worried why it's not working now if you want to see okay so it's not a compile time issue unless you are
using uh swagger oh will it pick it up if you are using swagger um which is a way to document
all of your web api calls um and it's pretty cool and and there's a counterpart to that which is a way to document all of your web API calls. And it's pretty cool.
And there's a counterpart to that, which is SwatchBuckle,
which will automatically do all that for you.
So if you were using Swagger and or SwatchBuckle,
then what will happen is that will throw a compile time error
because it won't know how to, or was it runtime error? Actually, I may be mistaken. It would probably be runtime because it wouldn't know how to... Or was it runtime error?
Actually, I may be mistaken.
It would probably be runtime because it wouldn't know how to pick it up, right?
Yeah, it doesn't know how to interpret that.
I think that's just a runtime, now that I think about it.
Yeah.
So, at any rate, manually name them.
That was, sadly, the answer.
Not all things in C Sharp and.NET are glorious. That was sadly the answer. Not all things in C-Sharp and.NET are glorious.
That's definitely one.
Yeah.
All right.
So with that,
like we said,
that was the last chapters of the 12 Factor app.
Chapters 10, 11, and 12.
Dev, prod, parody, logs, and admin processes.
And we hope you have enjoyed them.
Uh,
you can check out the previous,
uh,
episodes 32,
33 and 35,
where we talk about the first nine chapters of the 12 factor app.
Uh,
be sure to subscribe to us on iTunes,
Stitcher and more using your favorite podcast app.
And be sure to leave us a review on iTunes or Stitcher or wherever you choose to find your podcast. Uh, Stitcher, and more using your favorite podcast app. And be sure to leave us a review on iTunes or Stitcher
wherever you choose to find your podcast.
And let us know what that outlet is because we'd like to know.
Yep, and contact us with any questions or topics.
Seriously, we love getting them and we love answering them.
Sometimes we have to do some research and everybody benefits.
And it might be a month later.
It may be a little bit while later but
you know hey we do what we can
leave your name any preferred method
of shout out you have whether it's website Twitter
whatever we'll mention you in the podcast
and definitely please do leave us
a review visit us at
codingblocks.net where you can find all our show
notes examples discussions and more
yep and send your feedback
questions and rants to comments at codingblocks.net and more. Yep, and send your feedback, questions, and rants to comments
at codingblocks.net and
follow us on Twitter and Facebook and
Instagram and Vine and everywhere else.
Is there anywhere else?
Pinterest. Flickr.
Do we have any Pinterest codes?
Nope. Tumblr?
We got the name though.
We need a Slack channel, don't we?
We should do a Slack channel.