#233: The Masonite Python Web Framework Transcript
00:00 Michael Kennedy: Folks, it's not like the old days where there were just a couple of web frameworks for building applications with Python. These days, there are so many web frameworks to choose from! One of those is the Masonite Web Framework created by Joseph Mancuso. Joseph is here today to tell us all about Masonite, what makes it special, its core value proposition for web developers, and much more. This is Talk Python to Me, Episode 233, recorded September 11th, 2019. Welcome to Talk Python to Me, a weekly podcast on Python, the language, the libraries, the ecosystem, and the personalities. This is your host, Michael Kennedy. Follow me on Twitter where I'm @mkennedy, keep up with the show and listen to past episodes at talkpython.fm, and follow the show on Twitter via @talkpython. Joe, welcome to Talk Python to Me.
00:59 Joseph Mancuso: Thank you, thanks for having me.
01:00 Michael Kennedy: Yeah, it's great to have you here. I'm really excited to talk about Masonite and sort of do a quick survey and dive into these modern web frameworks. That's going to be a lot of fun. I think a thousand flowers are blooming these days on the Python web framework world. We've had some stalwart web frameworks, primarily Flask and Django, but Pyramid, and before them some others like Turbogears and whatnot, but those all had been around for a really long time and slowly growing or really slowly maturing and I fell just like every month, there's a new interesting framework.
01:33 Joseph Mancuso: Yeah yeah, I think that's exactly right. And when I started Masonite, I thought I was doing really, really good and then I guess it's because I got into the ecosystem and then also when I saw a whole bunch of other frameworks start blossoming from that, and it's probably because I just wasn't in it, in the ecosystem ones, so I just saw it more, but yeah, it seems like every couple of months, there's something new coming up.
01:54 Michael Kennedy: Yeah, it's is really positive, I think, but also creates some confusion. We'll talk about that in a bit. Before we get to it, though, let's start with your story. How'd you get into programming and into Python?
02:03 Joseph Mancuso: I always never know which story to tell, like the long story or the short story, but the medium story I guess would be that in high school, in ninth grade, I got kicked out of school for a bunch of stuff like fighting and stuff like that. I was a bad kid, and I was home schooled for eight months after that until the next school year, and I was very very bored and I didn't really know what to do and at the time, when I was 14, I was actually into Pokemon too, so I was like, "You know what? I'm going to just play this Pokemon game," and I got into, and I wanted to build websites, too, 'cause I had a lot of time on my hands, so then I got this website, I started learning C and then C++ and I didn't really like it, and then I was like, "You know what? I'm going to start trying to develop websites maybe." And then I got into PHP because I found really good documentation. I mean, good YouTube tutorials about PHP.
02:58 Michael Kennedy: Yeah, and it seems like PHP is a real quick and easy way into web development, like a lot of folks go that route and they kind of graduate to more formal languages, Python, and sort of intermediate level I guess there.
03:11 Joseph Mancuso: Yeah, formal languages, yeah sure. Yeah, so I got into PHP and I watched the New Boston. I don't know if you've ever...
03:19 Michael Kennedy: They did a ton of tutorials and stuff. I haven't seen a lot of stuff from them lately but yeah, they were all over YouTube for a while, weren't they?
03:26 Joseph Mancuso: He hasn't made a video in like for years, he sort of just dove off face there but at the time he was huge. He only had like maybe 40,000, 50,000 subscribers I think at the time and now he's probably like three or four million. But yeah, I went from there and then I took sort of this Pokemon thing and then I, I used that as my base of a project to build like this website. And then I built the website and I had people on Tumblr I think it was at the time start using it and I thought it was amazing that you could build something and have people use it. It was crazy. So I got into PHP and then from there I really just took off PHP. Like from like ninth grade to when I graduated high school, 18 years old, I just coded non-stop. I didn't do any homework, I didn't do anything else besides go to school, come home and then just start coding.
04:15 Michael Kennedy: That's pretty cool, it was just your deep passion, huh?
04:18 Joseph Mancuso: Yeah, it just clicked and I had this entrepreneurial spirit and I realized that I can create these websites and sort of make money from them, I can monetize them, I could put ads on them.
04:27 Michael Kennedy: Did you have friends who were working, like making like $4 an hour minimum wage and you're like, "You know what I'm doing?"
04:33 Joseph Mancuso: Oh my God, yes. I cut them checks, I cut them checks for like $1.25 and I gave it to them in class, yeah. How'd you know that? I feel like...
04:42 Michael Kennedy: No, no, no, I just mean they had other jobs, like minimum wage jobs and you had these businesses making real money, yeah, yeah. I didn't know they were actually working for you directly but I imagine that you probably in high school had, like I had friends, and even for a while I worked at like a pizza place, I think I made like $3.25 an hour. It was the minimum I could be paid to go there. I mean eventually I went and did some other really wild stuff that is like super funny and outrageous and not probably, it'd be too much of a diversion to cover now. But it's just really funny to probably contrast you in high school building these sites, running interesting things and folks going, "Well, I'm bagging groceries." Not that there's anything wrong with that but it's quite the contrast.
05:26 Joseph Mancuso: Yeah, that's so true, even my step-brother now, he does like marketing or something for a big corporate guy. And he's like, "Dude," he's like, "I wish when you were in the other room just coding non-stop," he's like, "I wish I did it with you and like we learned coding together cause you're off doing this job, doing this pretty big project that your job." And he's like, "I'm sort of sitting here in a cubicle just banging paperwork."
05:50 Michael Kennedy: You really got into and it sounds like you just really independently went after PHP and building sites and that's super cool. So where'd Python come from?
06:00 Joseph Mancuso: When I was 18, I joined the army and I came back and I was still sort of doing programming within the army, 'cause it's a passion of mine, it's a hobby. And then when I got out, I wanted to build a POS ordering system that you see like at a kiosk almost or like a pizza place. So I wanted to build that. So I wanted to learn something new and do it. So I picked up Python just 'cause it was just something new, it was cool, it seemed to be rising at the time with the whole data science thing and machine learning. So I thought it was cool to sort of pick it up. And then from there I built, I needed to pick a framework and the obvious one at the time seemed to be Django. So I picked up Python for about a month, I learned on like Codecademy, I did like all the basics. And then I picked up a framework and then I started building this thing out. And it took me about probably eight months or so to build this thing. And then I actually said all right, I'm going to start trying to sell this thing. In hindsight it was actually crap. But at the time I thought it was super cool and I wanted to create a company. One of my all-time goals in life is to have a 100-person software development company.
07:02 Michael Kennedy: Yeah, that's a good goal.
07:03 Joseph Mancuso: I put that in the same ballpark as like...
07:05 Michael Kennedy: It's nice and concrete.
07:06 Joseph Mancuso: Yeah, as like Gary Vaynerchuk's like want to buy The Jets sort of thing. So I sort of put it there. Like it probably never happened and even if you look like Basecamp, even they have like a couple of dozen employees I think and they're like a huge company. So a 100-person software development company is gigantic. But anyway I digress. So I built this thing and I even went door-to-door to like businesses to try to sell this thing.
07:26 Michael Kennedy: What was that experience like? Were they receptive or were they just like what are you doing here, like you're from the internet, why are you in my place, my pizza place or whatever?
07:34 Joseph Mancuso: That's exactly what it was. But actually my whole philosophy is that I'm really not afraid to fail and even if I fail I learn something from it. And it was super nerve-wracking to walk in, just cold walk into a business. But I figured even if I fail, I'll probably learn something from this guy. And what I actually learned which was interesting is that when I went in and I asked them if they, is your manager there? So I had like a whole pitch lined up and they basically said that, "Oh no, sorry, we've already tried some and it just doesn't fit us." And I thought that was interesting because I was walking into companies that didn't have it online. But it makes sense that they'd probably been around for five to 10 years. And if they don't have one they had to have tried one already. So I used that failure to sort of repitch into "Oh, I know you've tried something before, maybe you should try this instead."
08:27 Michael Kennedy: I see, it didn't work before and here's why it's going to work this time.
08:30 Joseph Mancuso: Right, something like that. Nobody really went for it and I'm not really a sales guy. I'm very introverted sometimes. I call myself an ambivert. So I'm like I'm sort of introverted but I'm extroverted in comfortable environments if that makes sense.
08:45 Michael Kennedy: I think that describes a lot of tech people honestly.
08:46 Joseph Mancuso: Yeah, I think it's far as most people in general. Very few people I think that I've experienced are really introverted. Once you get familiar with them and they get comfortable with you, they're just like off-the-wall.
08:58 Michael Kennedy: Yeah, for sure. This is a really cool way to get into Python, and where did you go from there?
09:03 Joseph Mancuso: So from there I learned a, I want to throw in a new technology. Each year I try to make it a theme. That year I wanted to learn frameworks. So I learned like Django and Python and then I wanted to, I already came from PHP so I wanted to learn Laravel 'cause I never learned Laravel at the time. So then I created a new site, us, we just have a bunch of side projects that we try to create businesses out of. I created a new side project which was basically like a textbook rental service. I built a whole business model out of it and how I was going to do it and then I built the site in Laravel and I used Google API and all that stuff to try to build this thing out. I actually really like Laravel. And then from there I worked with Laravel more and more. And then finally I got a job locally working with Laravel at the company I work with now and that's what I do right now.
09:55 Michael Kennedy: Oh yeah, what are you doing day to day? What kind of work, sounds like more web development?
09:58 Joseph Mancuso: I continued web development. Right now day-to-day I work for a wholesale military supply company. It's actually a pretty big company. It's like a 150-person company. The web team is probably about, mmm, probably six strong. And we run basically this multi-million dollar website that does all the wholesale processing and all that. I also am in charge of a four-person software development team that we're working on a large-scale ERP project to basically run this whole company.
10:29 Michael Kennedy: Yeah, cool.
10:29 Joseph Mancuso: So I'm taking a lot of those concepts and trying to come home and apply them to Masonite.
10:34 Michael Kennedy: Yeah, excellent. All right yeah, so let's dig into the Python web frameworks. So speaking of Masonite, if you go look at the usage stats, we've got 40% Django, 40% Flask, plus or minus a couple in there. A little bit down from there we've got like Pyramid, I think it's like 6% was the last usage I saw there. That rounds out a significant portion of what is Python and web frameworks. But we talked at the opening, it used to be well, Flask, Django, which are you? It's kind of what was the greeting or whatever amongst the Python web developers, right? The last two or three years, there have been so many different frameworks. We have Japronto, Sanic, Vibora, Starlette, FastAPI, Hug Falcon, it's not even a super clear connection, API star for example. So there's Starlette and there's FastAPI? So there's a handful of websites that actually use Starlette underneath. I think Responder from Kenneth Reitz for example is one of those. So there's just, there's like this layering on of what people's different ideas of the Python web world should look like. And how would you summarize that? Is that looking at trying to make type hints do interesting things? Is that Async? What are the trends that you're seeing in all of those or kind of in general there?
12:00 Joseph Mancuso: So this is mildly controversial and I actually argue a lot with the people inside the, well not argue, debate a lot with people inside the community of. The correct answer is that the trend is moving towards asynchronous frameworks itself, like the actual framework code is built around some kind of ASGI server or asynchronous server. That's the trend, I'm not entirely sure I agree with the trend because I feel like it forces a lot of people that are new to all of this to sort of see the trend and sort of prematurely optimize their application. So if their application is like a blog framework for example they're like yeah, this blog framework, I mean, sorry this blog application can handle 15,000 requests per second but does it need to? Does it really need to do that? I mean that is really cool, and especially if you try to load balance across two of these applications, you can handle like thousands and thousands of requests per second, but I feel like it's more of a premature optimization. And then when they use these frameworks like a lot of times, they have to start writing their code with the idea of it being also asynchronous as well. Like thread safe I believe it is and all that stuff. And they can't just take any ORM off the shell. They have to use a asynchronous compatible ORM. It basically narrows down a lot of your decision-making. If you need to create an API or something, some kind of small micro service, just hit API endpoints, get information from a database. That's 100% the way to go. If you're creating a bunch of micro services, maybe for a one monolithic application and that's 100% the way to go. But that's not the way I like to create my applications, right, yeah. So most people just want to create like a service, like a SaaS or something.
13:48 Michael Kennedy: It's an interesting point that you bring up. I would certainly say that there's a trend to see what the cool hot frameworks are doing or what the amazing web companies are doing, and try to emulate those way too early, right? You talked about these websites that you were creating, when you're let's say, if you're creating your textbook rental company, you're planning like well, we're going to have all the campuses around America, in September they're all going back to school and getting their books, it's going to be crazy, there's going to be all these orders and it's just, and the reality is probably one campus if you're lucky joins in and it starts real slow, right? And you've got all the time in the world to see the analytics, you scale your web server, potentially if you even have to. 'Cause a standard web app, it can take millions, millions of data driven requests per month on like a $10 server before you have to start worrying about all that stuff. It's definitely true that you can just not worry about it for a good long while. I mean if you build your app poorly and it's super slow, then you're going to want those features more, right? But if you build it well, right indexes on your database, things like that, it should fly and it should be able to go quite a long ways until you have to worry about that. That certainly seems like a reasonable philosophy to me. The other one is I do training and write courses and do other presentation to help people learn things like web programming and it's super overwhelming. As you know, I mean you learned when you were young so maybe it didn't feel as overwhelming, you just like this is what computers are, this is what I do, right?
15:25 Joseph Mancuso: Yeah, that's probably right.
15:26 Michael Kennedy: But there's HTML, there's CSS, there's databases, there's query syntax, there's Python, there's the templating language, there's Linux, there's deploy, I mean there's just so many things, right? And if you say oh, by the way while you're trying to learn all this for the first time, you need to learn asynchronous programming too so don't forget about that, I mean that's a tricky level...
15:45 Joseph Mancuso: Yeah, it's 100% right.
15:46 Michael Kennedy: It's a really great thing to have for a web framework but it is not necessarily a great starting point.
15:50 Joseph Mancuso: Right, yeah.
15:52 Michael Kennedy: That's what I was saying.
15:54 Joseph Mancuso: It's a tool that you should reach for if you need it, but it's not something that you should default to just because it handles more requests per second. That's my take on it.
16:01 Michael Kennedy: Cool, yeah so I do see a quite a number of those that I mentioned like Starlette and Sanic and whatnot focusing FastAPI or whatever, focusing on this Async aspect. But another aspect that I see being used a lot is things like type annotations and some of the other Python 3 features to try to make some of those features help with the web framework for example. Does Masonite do any of that?
16:25 Joseph Mancuso: We'll probably talk about more of this when we get into the Masonite part but Masonite has something called an inversion of control container, an IoC container or a service container which utilizes type hints and the short answer and we'll do the long answer later. The short answer is basically in the controller code and the controller method, you can type hint a class and Masonite will inject that class for you.
16:47 Michael Kennedy: Right, so this controller takes a database derived class or whatever and then you say that as a type hint and then the IoC container will push that in for you?
16:57 Joseph Mancuso: Exactly right. Yeah, if you do sort like a base class or something. So if it's an instance of a database base class, then inject the base class, the database driver that you have defaulted or something like that.
17:09 Michael Kennedy: Right, what if you've registered, yeah. Okay, cool, yeah. So I think this is kind of unique and new that so many of these like last couple years frameworks have really tried to embrace Python 3, right? Like Python 3 has been a struggle for Flask, they're not there anymore but like for a while they had a statement saying basically we don't work on Python 3. Well, we probably work on Python 3 but we don't guarantee it, something to that effect, like four years ago or something. That's pretty rough statement given the date that it was. And then Django as well just, and 2.0 dropped support for Python 2. So they've been kind of carrying that baggage around, they can't do things like this with their API, right? If you fundamentally said you must have type hints, well there goes your Python 2 support, right? Straight away. So all these new ones though, they seem to be coming along with like a fresh look. So I think that's pretty cool.
18:03 Joseph Mancuso: Masonite, I notice that a lot. It's pretty hard to support multiple versions of Python that don't work well with each other, so like for example 2.7 and 3.4 for example to support both of those. So what I wanted to do with Masonite was one, yeah, start with Python 3. But also only default to the latest four versions of Python. So currently we support 3.4, 3.5, 3.6, 3.7 and 3.8 is coming out soon. And so far the tests work for eight so that's good. But when eight comes out, we're going to drop support for 3.4.
18:40 Michael Kennedy: Yeah, that seems reasonable.
18:41 Joseph Mancuso: Yeah, my philosophy basically is if you really need to create something in 3.4, then you're going to have to use Masonite 2.2. And if you want to use the latest, this way we can sort of keep up with the trends as it goes on.
18:53 Michael Kennedy: Yeah, well for the moment, Python has released an 18-month release cycle. So that gives you like six years of backwards compatibility, that should be enough. Right, exactly. Should be enough I would think. There's actually a out, I forgot the number by Lukasz Langa to move to yearly releases. But that would still be four years, that should be good.
19:14 Joseph Mancuso: Yeah, yeah definitely.
19:17 Michael Kennedy: This portion of Talk Python to Me is brought to you by Linode. Are you looking for hosting that's fast, simple and incredibly affordable? Well, look past that bookstore and check out Linode at talkpython.fm/linode. That's L-I-N-O-D-E. Plans start at just $5 a month for a dedicated server with a gig of ram. They have 10 data centers across the globe. So no matter where you are or where your users are, there's a data center for you. Whether you want to run a Python web app, host a private Git server or just a file server, you'll get native SSDs on all the machines, a newly upgraded 200 gigabit network, 24/7 friendly support even on holidays and a seven day money-back guarantee. Need a little help with your infrastructure? They even offer professional services to help you with architecture, migrations and more. Do you want a dedicated server for free for the next four months? Just visit talkpython.fm/linode. I'm really excited about all these web frameworks, Masonite included. However I have this new problem, right? I could go and look and see Flask, Django, Pyramid, let me compare those and sort of see that things I like or don't like about them and then I can look at history and say well it's probably this much supported. So it's probably going to be about that much market share in the future. Flask is about 40%, there's a good chance Flask is going to be around next year. But I don't get that sense with these new frameworks, right? Responder is cool, I don't know if anything has even been done with Responder in the last little bit, right? Not a whole lot had been going on with...
20:49 Joseph Mancuso: It took off in like the first two months and then it sort of died out after.
20:53 Michael Kennedy: Exactly, I mean it is super cool and it's great that people are working with it but how do you think about going through these frameworks. I mean obviously you're just working on Masonite, you're just going forward and keeping things going but what would you say to people out there about how they should consider the stability of one of these projects? Is this like a super cool one-month idea or is this an actual thing?
21:14 Joseph Mancuso: Masonite in itself, oh yeah, it's definitely an actual thing. I always sort of think about what Masonite is going to, like Masonite is really really cool now but what is it going to look like in five years? What is that Masonite going to look like? And I sort of work towards what that's going to look like. And then maybe in five years, I'll look for another five years and do the same thing. But basically what I really like about the PHP ecosystem is that a lot of the time, these frameworks, like if you look at Symphony or Laravel, there's faces to them. There's people that you can, there's like leaders. Even Django is sort of like, I don't know if it's just me but it's sort of like this nameless faceless organization type thing that like, maybe like this Marvel type organization that controls Django. I think it has like a committee and stuff but there's not one specific person that I know like oh they own it or something that. And like with Laravel, the guy Taylor Otwell, he's all about Laravel and he works on it full-time obviously but I can look at him and I could look at his future and tell the future of Laravel. So me personally, Masonite is going to be around for a super super long time. This is basically, Masonite is going to turn into my side project that turns into that business. For example, maybe what that textbook rental service might have turned into. That's going to be what Masonite is. So know once Masonite becomes profitable either through sponsorships or partnerships or basically SaaS around it, it'll just take off from there. But I mean Masonite is going to be around for super long time.
22:44 Michael Kennedy: That's awesome, one of the metrics that you use is when I go to these projects, obviously I look at how many stars does it have but also maybe when was the last commit? Is that three years ago or is that two days ago or an hour ago, right? What does that look like? The other one is, probably the biggest one for me is open PRs that are not being addressed or barely are being addressed. That seems like a real big red flag to me, right? If you go there and there's like five people who have put a bunch of work in to add some new features and they're just, all you got to do is just verify this all right and then just accept it, and the people running the project can't be bothered to respond to it, as a contributor that's a crappy feeling. But also that's not a super good sign for the project I don't think. Yeah, so the reason I bring this up is when I go to Masonite there's zero open issues and there's zero open PRs which is pretty cool.
23:42 Joseph Mancuso: So here's the weird thing with Masonite and maybe in future versions this will be different. But Masonite has really broken up into two different repositories. So there's the Masonite repo that everybody goes to and they see has a thousand stars but people talked me into, actually did people talked me into this? I'm not sure, but at one point I extracted all of the framework itself logic out and I just created an application so people can basically, when people run their craft commands and they run craft new project and it creates this project down, it actually creates that, basically a copy of that repository down onto their computer. But if you look at, if you go to the Masonite organization, then you go to the core repository, you can see the actual core code.
24:23 Michael Kennedy: That's the actual real code. Okay, got it.
24:25 Joseph Mancuso: That's the actual, what's actually driving the Masonite application. Basically the Masonite that you see on the one with a thousand stars is basically just a shell of Masonite that I took all the, basically the framework code out and I made it its own repository and then I made that a package that this shell basically requires. So basically what I really wanted to do was take out as much. So when I first posted Masonite on Reddit, it was out like one version 1.3 and everybody hated it and they said it was crap and it was dumb. Typical Reddit stuff. But the weird thing is that they were right because the original version of Masonite was basically one function that did everything. So basically from there, I extracted all the logic out and I kept that repository up because I had so many stars already. I had like 100 at the time or something. And I basically created, it's a new package and tried to make it as modular as possible.
25:22 Michael Kennedy: Yeah, that makes a lot of sense, that sounds cool. It seems like there's at least activity on all the various items there which is pretty cool, right? It's not like three years ago, they're just hanging out there, that's good. All right, so maybe we could dig in to some of the features of Masonite. You talked a little bit about why you started it but maybe give a little bit of clarity on that. And then let's just talk about some of its major features like why would people choose it over the other frameworks and what were some of the goals there?
25:49 Joseph Mancuso: So I needed a winter project 'cause I was going, you know college. So I went to recess, I needed something to do 'cause I'm home all day, and programming is a passion, and I can't just sit home and not do anything. So I need to code something and I didn't really have anything to do. And I was going through my year of learning frameworks. So I was like let me learn how to build a framework. So I looked up how to build a Python framework 'cause that would be cool, 'cause Laravel, I mean the the PHP ecosystem seems, seemed to be too hard of a competition to penetrate. And I saw a lot of holes that I tried to fill with Masonite in the Python community so I thought it'd be good to build a Python framework. And getting a WSGI server takes maybe seven minutes to set up and running and getting some kind of response. You're having some kind of dynamic response, which is probably why so many pop-up.
26:37 Michael Kennedy: Right, so you're basically, there's like one function you implement. They pass you the request and you return the response or something along those lines?
26:45 Joseph Mancuso: Yeah, exactly, yeah. It's just a normal WSGI application that takes two variables and then you basically return, you use one to set the headers and then the other one to return a response, super simple. So from there I basically had it up and running and I was like okay well, I'm coming from Laravel so I think it would probably be cool to write my routes and something I'm familiar with if I'm going to start building this framework, 'cause I don't want to learn something new even though I'm building it. So I took what I'm familiar with and I made the routes look like the modern-day routes that they are now. And I added that feature in and I was like oh that's pretty cool. I mean I wonder if I could add controller logic too, that'd be cool. So I added the controller logic and the methods and swapping between different methods and calling certain classes. I was like that'd be cool. I was like what if I add something like super awesome, like like built-in email sending support. I built that in and then I tried to build it all modular. And it basically just went from there. Little bit by little bit, I just kept on putting more and more features in until just out of nowhere, people started joining the community and contributing actually. Basically we teamed up, me and a couple of early adopters and we built into something really really cool. And then we released 2.0 on June of 2018 I think. And then from there it just shot up. It went from like 80 stars to like 500 in a couple of days.
28:12 Michael Kennedy: Wow, that's cool. Featured in the right places, a lot of people came to check it out, huh?
28:16 Joseph Mancuso: Yeah, I think I put it on Reddit and I got like 20,000 views in three days and it was on the top of R/Python and it was on Hacker News I think and I got like a whole bunch of tweets and stuff like that and people talking about it. It basically shot up from there.
28:30 Michael Kennedy: Yeah, super. You started out this conversation by talking about routes and the routing mechanism and controllers. So let's maybe dig into the code story around that a little bit. Now talking about code in audio format, it's kind of not the easiest thing to do but if we keep it simple enough, I think we can give people an idea. So it looks like you have some pretty interesting ideas around creating routes and it looks like you are sort of embracing this HTTP verb type of world as well, right? So if I'm going to create some routes, I would go and create, import a get, is that a class that I'm creating or is that a function I'm calling?
29:10 Joseph Mancuso: No, that's a class.
29:11 Michael Kennedy: A class, so I would create like a list of classes and I would say Get().route('/url/here', 'WelcomeController@show'). So the WelcomeController is a class that is handling this request and shows a method within it, or maybe WelcomeController is just a module I don't know...
29:30 Joseph Mancuso: No, that's correct.
29:32 Michael Kennedy: So I can create these gets and posts and it seems like a really nice way to build up from sort of naturally understanding HTTP verbs in the way the internet and websites actually work.
29:43 Joseph Mancuso: Something early on in Masonite and really in my code in general, even when I create my method names, these method names are like, it seems like a whole sentence long 'cause when I read my code, I like to read it in English. I like to read it from left to right as if I'm thinking it and I want to show it to a little kid almost and have him understand it basically. It's like reading a book almost. So originally it was actually, normally it's get and then inside the get you have the URL that you want to send to like you said and then the controller method. But previously it was actually get.route. So when I read it, it was I want to get route and then I pass in the URL and stuff like that. And you can still do that actually but we basically shortened it down to yeah, just a list of get routes, post routes, option routes, put routes, delete routes, stuff like that.
30:33 Michael Kennedy: Thats super cool. How do you pass variables in through the URL here? So I don't see any examples of that. If I do this show, I probably want to show like slash some blog post with the URL or something like that.
30:48 Joseph Mancuso: Yep, so in your URL it would be, say you want to do like a slash blog post, slash maybe one or a two or you want that to be a dynamic.
30:55 Michael Kennedy: Sure, that'd be fine.
30:57 Joseph Mancuso: It would be slash dashboard and then you would do another slash and then @ symbol and then the name of the variable that you want to retrieve later. So maybe you would use blog ID, so it would be blog_id and then you'd put that there. And then that would be the dynamic part. Or you can add sort of what I call regex compilers which was basically, maybe I only want that to be an int. So it would be @blog_id:int so it'll only match integers or I could do strings or I could do some kind of super complex one where I do a website. And then I could actually pass a website in with slashes as well. It'll actually match that as well. You could do a lot of complex things with it.
31:38 Michael Kennedy: I love that simple way of doing constraints for types and stuff. You can create really nice things like on our website. You can say talkpython.fm/233 I think would be this episode, right? If I got the number right. That would actually only match for integers and then it'll go look that up and take you to the real location. So it's like a really nice way to create short sort of CLI almost feel to your web app.
32:03 Joseph Mancuso: Yeah, exactly, I try to write everything first. So actually when I created the routing engine, I actually wrote down on a piece of paper every single variation I could possibly write for a routing engine. And then I basically crossed out all the crappy ones that I thought looked ugly and I only went with the one that looked nice. And then I worked backwards to the actual implementation. I had no idea how I was going to create this thing but then I worked backwards to actually creating the class and creating all that stuff. That's how I actually write almost anything.
32:30 Michael Kennedy: I want to use it this way. I don't really know how though, we're going to make this happen somehow, that's cool. The other things you have here is you have classes and the classes capture the request object and then you have the methods that run for the view. And I actually really like this pattern. I use this pattern in some of my websites as well even though I have to kind of fight against the grain a tad bit to make it happen, I really like it. And you have the word controller, do you consider Masonite a Model View Controller framework, Model View Template, I don't really even understand why there's a distinction between those things but it seems to be in the Python space there is.
33:05 Joseph Mancuso: So I do consider Masonite an MVC but it's not, I try to make it not constrained to just controller logic. So I try to sort of assist the developer who's working with Masonite to sort of take a lot of that logic and add, extract it into like maybe like a mail class which is ejected into the controller and stuff like that. So it's not a strict MVC but it does use, basically the wording to sort of help you structure your code.
33:31 Michael Kennedy: I like the pattern, it's cool. You talked about the injection and stuff and I do want to cover that, that's fairly unique in the Python space. But before we get there, so the way that I would, if I was a Masonite developer and I was starting a new web app based on it, I would create a virtual environment and I would pip install some stuff, Masonite and whatnot, right? And then I would start issuing command line or CLI behavior commands to Masonite to help scaffold up and start building my app, right? So you could say, you have this utility called craft, tell us about craft and some of the commands and what's the story around that.
34:10 Joseph Mancuso: I think it's incredible actually, I think that's actually what makes or breaks the framework. So craft commands, so think of like Django 'cause a lot of your listeners are probably familiar with Django. So in Django you might have a class-based view and you might have that return a couple of templates, maybe some kind of context and stuff like that. And then you want to create another one, what you usually end up doing is you either maybe create a new file. And then instead of creating a whole class you probably sort of copy and paste that old one that you already created into the new one.
34:37 Michael Kennedy: Certainly a copy and paste is a solid start.
34:39 Joseph Mancuso: Yeah, exactly. So what craft does is it gets rid of all of that boilerplate. So in Masonite if you want to create a new controller with a couple of imports, maybe you want to import the request class, the view class, you want to create a method, what you do is you do craft controller and the controller name. So maybe craft controller blog. And it will actually create you a blog controller, it imports the request class, it imports the view class, it makes a default show method and it type hinits the view class, and it type hints the request, it creates all that boilerplate for you. And it does the same thing. Like if I want to create a middleware, cross controller middleware, it creates me a class, imports everything I need.
35:17 Michael Kennedy: What's an example of middleware? Why would I create one of these things? What does it do?
35:21 Joseph Mancuso: A middleware?
35:22 Michael Kennedy: Yeah, in the Masonite terminology.
35:23 Joseph Mancuso: So a middleware is basically a piece of functionality or code that runs in between the request class, in between the incoming requests and your controller method. So for example maybe you want to have some kind of authentication. So if the user is not logged in, I don't even want to hit the controller. I just want to redirect to the login page. So I might create that. Or maybe I want to create some kind of after middleware, like I want to take the HTML response and maybe minify it every time, something like that. So you create these middleware that run in between your controller, in between the incoming request and the controller and then in between the controller and the final response. And you sort of inject these things. That's actually really really simple to work with with Masonite. Yeah, you just use these craft commands, you can create migrations, you can create jobs, you can create listeners and tasks. And you can create all these things, all this boilerplate. So the objective really is that I don't want to focus on writing things that aren't crucial to my application. So if I have a thought that says all right, I need to start sending out an email, let me make a new controller or something like that, I just create the controller and I go to the controller and I'm still focused on sending out my email. I drop down to the method and I start coding sending out my email. I never break my train of thought with what I actually need to do to get my business logic set up.
36:43 Michael Kennedy: It's cool, and it seems like it follows some really nice conventions. So for example, you said maybe you want to create a blog controller, has a show method. So you would say craft controller blog but it actually creates the controller, controller class called BlogController, not just blog. It puts it in /app/http/controllers and it initializes it all correctly, right? Has an initializer which has a type, request object that has a type annotation of requests and things like that.
37:13 Joseph Mancuso: Yeah, exactly.
37:15 Michael Kennedy: This portion of Talk Python To Me is brought to you by Datadog. Datadog is a monitoring and analytics platform that unifies metrics, logs and distributed traces from your Python applications. Datadog's tracing client auto instruments popular frameworks and libraries such as Django, Flask, Postgres SQL and AsyncIO, so you can quickly get deep visibility into your applications. Trace requests across service boundaries, correlate traces with logs and metrics and plot your application architecture with the service map. Get started today, sign up for a free trial at talkpython.fm/datadog and Datadog will send you a free T-shirt. Yeah, one of my pet peeves around some of these projects is they give you zero guidance about any organization. And maybe even kicking it farther, sometimes they even accentuate their ability to not have any organization or any structure. Look, you don't even need that. Look, you don't even need that file, just put it in this file and you're good, this is where it goes, it all just goes in here and like no, it doesn't all go in there. You're going to have so many view files or controller files, you have 50 templates. You need organization and this like selling the lack of it as simplification seems to me like pushing, at least beginners down the wrong path, right? So I like that your craft commands take a natural structure and just say this is the convention we use and we're just putting it here.
38:43 Joseph Mancuso: Right, exactly and like you said it creates that file and then it puts that controller in it. But it's only that one class and that is opinionated, that is the way I like to work, mainly because in my view as code editor, if I need to go to my authentication middleware, in order to do that, I hit the command P thing and I go to authentication middleware and I click enter and I go to that specific class, that specific method. I'm not going to some kind of middleware.py file scrolling down a couple hundred lines so I could find that middleware class or anything like that. So it's just the way I code. I just hop around files all day until my app is done.
39:20 Michael Kennedy: Man, I'm with you, I love it. That's the way to do it. Having like these huge long files with everything crammed in there, it just means it's so hard to find. I think the choice of editor somewhat influences the granularity that you're comfortable with here. But I'm kind of, it sounds like you and I would have a similar style.
39:38 Joseph Mancuso: Yeah, exactly, I feel like it's almost like when give a kid like a guitar, and he grows up to be a rock star. Whatever that sound that guitar made is probably what kind of rock he's going to play. So like it's almost like that, whatever editor you use probably dictates what kind of applications you're going to build.
39:54 Michael Kennedy: Right, something like VS Code is very natural at handling many directories, many files and seeking between them really quickly. The other thing that you talked about when you talked about that flow there was injecting things. Now I definitely think dependency injection and the open-closed principle and all those things have some really interesting places in the Python world. But I also don't see them used very often. So this is kind of a unique aspect of it, of what you're doing. So for example, if I've got my show method from my blog and maybe in order to get my blog I have to go to my database and I want to work with MongoDB, so somewhere previously at the app startup I said, when I asked for a database give me the MongoDB implementation of my repository thing or my database service, whatever I called it, right? So I can go to that view method and say, show(self, view:view, DB:repository) or database class or database service. And then I'll just automatically just start getting my database instance passed into me by Masonite?
41:01 Joseph Mancuso: Yep, that's exactly right. Or what you can really do, where Masonite really shines is being able to basically swap out what I call interfaces or contracts. So like one of the other principles of interface segregation principle, right? Where you want to really code to an interface and not to a concretion.
41:19 Michael Kennedy: Yeah, we're going to hit all the solid principles.
41:20 Joseph Mancuso: Right, yep, so what you can do is you can, Python doesn't have like a implements keyword or anything but if you have like a base class, say you have a, what would be a good example, like a payment base class. You can type int that...
41:33 Michael Kennedy: Payment service, whatever, sure.
41:35 Joseph Mancuso: Right, yeah, payment service. So you type hint payment service and even though you have no classes called payment service, it'll find an instance of payment service and return that as well.
41:44 Michael Kennedy: Right, maybe you were at a class called Stripe payment service and payment service and it actually talks to the stripe API or something like that. And it'll just find that and then...
41:52 Joseph Mancuso: Yeah, exactly. And what's even better I think is that, and this might sound confusing to people who don't understand IoC but what also it does is when it resolves that payment service class, it'll resolve whatever is in the initializer of the payment service class as well. So basically it's sort of like, basically ties every single class that that payment service relies on, ties it all together, initializes everything and then returns everything as an object already set. So you no longer do you have to sort of import a class, maybe get some config variables, maybe pass it in, construct that thing and then pass that thing into something else that needs it. Everything just ties together sort of seamlessly. And then you could also swap out functionality as well. That's really what powers an IoC container. And the funny thing with Python and IoC is that even if you google why doesn't Python have an IoC implementation or something like that, I forget the Google question. But you go there and it says you don't need an IoC container I think it's like because Python is like duck typed or something. It almost made no sense, that's not really the reason for an IoC or anything like that, or even for like interfaces or anything. So it was very strange but I think IoC is more of a architectural decision that just you have to build applications. Like we're building this large-scale ERP system at work. There's probably going to be a two-year long project, probably thousands and thousands of classes. And if you didn't have an IoC, how do you manage all those dependencies between the classes? It's crazy.
43:28 Michael Kennedy: It gets tricky, that's for sure. I would say for sure that Python does not, as a general rule, the people in community and the libraries don't generally embrace IoC but yeah, I see it being really useful here so that makes a lot of sense. Like your payment service, your stripe line also takes a logging framework or logging service and it takes a database service or something like that, right? You just register them all and it all just, you just go to your view and say it takes a payment service and you get the Stripe service all set up.
43:58 Joseph Mancuso: Yeah, as long as they're all in the container, they all can communicate with each other.
44:01 Michael Kennedy: That's cool, and probably use that for testing as well, right? You could swap out the database with like a mock database and the logging with like a null logger that actually doesn't do anything or something like that, that you print.
44:13 Joseph Mancuso: Even Masonite itself is strictly based around this container. So if you want to change out the request class for example, you want to make it a different request class you could just do that and everything else will sort of follow. As long as you follow the contract of the class, you can sort of swap every single piece of functionality out of Masonite and inject your own.
44:32 Michael Kennedy: That's cool, one of the challenges I've had when working with IoC is I'll be somewhere in the middle of the system and I'll have all these dependencies that were put together by the IoC container and I'll be like all right, I have no idea what actual database I have or what logging thing I have or where it came from or any of that. Now I do see that as one of the drawbacks of IoC is it's kind of hard to see where it all gets started.
44:54 Joseph Mancuso: Yeah, if you sort of lose yourself then I guess you're sort of lost I guess. But as long as you have like a good file structure and you have like maybe good documentation on your project and stuff like that, you sort of, there are caveats I'll admit. It's definitely a pretty good architecture.
45:12 Michael Kennedy: Yeah, one of the things I like about your craft commands is, I'm a fan of things like cookiecutter and I think cookiecutter is a super way to get started. The right way is not create an empty .py file and start typing it out. I already talked about the structure but there's also, sounds a static file, it's just there's a lot of stuff that would be nice if you could start farther from let's enter character one and get going, right? And I think cookiecutter is a nice way to do that, right? You could say okay, I'm going to use, create a Flash project that's already using SQLAlchemy so it's got the requirements set up, it's already got a database structure, it's already got a connection string for a SQLite database for getting started, that kind of stuff, right? What falls apart with a lot of those systems is you get to run them once and that's it. Like I have a super cool...
46:03 Joseph Mancuso: I was just about to say that.
46:04 Michael Kennedy: Yeah, I have a cool cookiecutter template that will actually generate the final code from this course called Python for Entrepreneurs and it's super involved, there's so much stuff going on. And you can type in the name of your project and whatever and run the cookie cutter and it will just boom, out drops this really well-formed project that looks just like the final project of that course but with your data in it, right? The problem is that's great for getting my first controller or whatever is in there, but if I want the second one, cookiecutter's not going to help me. That's where copy and paste comes in, right? It seems like with your craft commands, you can start out building pieces of your app and continue kind of adding to the app with that CLI, what do you think?
46:44 Joseph Mancuso: Yeah, exactly, I mean every, when you try to reach for like a copy and paste, you're wasting so much time. And not only wasting time but now, that you've finally copied and pasted and I have to be like all right, wait what was I trying to do again? Oh yeah, right, okay, yeah sending email. And then you sort of go back into sending email, it takes your mind off it and it's just a massive time suck. And most people that use Masonite, not about most people but a lot of people that are in the Slack channel, they say man like, I built this thing in Masonite in three days, it would've took me three weeks in Django. So I actually get that a lot. It sort of gets to the point where you almost expect it when someone comes from Django or something. I basically just wait for it. And I think a lot of that is because all of that boilerplate code is done for you, we already created controllers. If you need to create a job, you create a job, you add your logic and then you just add it to a queue, it takes five seconds. Yeah, it's huge.
47:41 Michael Kennedy: Yeah, that's cool. So let's talk about some of the other things that you can make with these craft commands. You just talked about jobs, that sounds like an asynchronous thing, maybe kicking now to some kind of background worker process. You talked about email before, we've got views and templates, can create templates. So you've adopted the Jinja2 template system, is that right?
48:01 Joseph Mancuso: Yes.
48:02 Michael Kennedy: Do you have any other support like Chameleon? Hint hint Chameleon.
48:06 Joseph Mancuso: I don't currently. I know that one guy came to me and he said he wanted to write in Pug. I don't know if you've ever heard of Pug before?
48:13 Michael Kennedy: No, I only know it as a dog.
48:14 Joseph Mancuso: Yeah, I think it's called, oh no, maybe I just kept on calling it pug but maybe a pub or something. Anyway, it's basically, it looks like a markdown type style. And he wanted to write in that and it had a Jinja2 extension. And then from there I basically added extension support for the views and stuff, so you could write, you could basically write in any Jinja2 extension language. So it basically just compiles down into Jinja I guess and then gets rendered. But as far as swapping out that functionality for chameleon, it's possible but there's no documented way of doing it. But it definitely could be, you could open an issue.
48:49 Michael Kennedy: PRs are accepted, huh? Nice, background work, let's touch on that real quick. That's not something every framework decides to take on for itself.
48:58 Joseph Mancuso: Yeah, definitely. So a lot of the features of Masonite came by me needing it. I'll basically add it to my application and then I'll try to extract it into a framework feature. And one of the things I needed was sending an email and I wanted to send that asynchronously. So I created the concept of queues and jobs. So a job is basically just a normal simple class that extends queuable and you can add your logic of sending an email. Maybe it'll accept a parameter of an email. And then you could take that job and then you could pass it into any queue driver that you want. So if we want to run it asynchronously, we pass it in the asynchronous queue driver if we want to. And then when I deploy to Heroku, I didn't want to run things asynchronously. I wanted to run things through some kind of RabbitMQ server, so I coded that driver. And the cool thing is that in order to create a new driver, it's just a simple class that needs four methods. And then you take that and you register it to the container and then you have that functionality. So create an AMQP driver which is the protocol for RabbitMQ. Took like maybe a night and then actually last night, I actually created a database driver as well. So now it could take that same job, that email job, adds it to a database table, you have a worker that you run as a separate process, maybe on like a supervisor process. That will basically poll that database and then run the job. And the cool thing about that is that you can actually delay queued jobs as well. So you can delay it by 10 minutes, maybe after the user signs up, will send a welcome email in 10 minutes. And then you add that and it will basically wait 10 minutes and then it'll send the email out. That's the way I like to sort of counter the ASGI competition. So going to the next page might take one second or a half a second but sending that email might take two seconds. But if you send it to a queue job, it only takes that half a second and then it'll just run in the background or in your queue server or something like that. So I thought that was a really cool feature that I added in Masonite pretty early, and I use it all the time.
51:09 Michael Kennedy: That's cool, certainly synchronous queues and background work like that do solve a lot of the primary reasons that you need some sort of direct async behavior. I do you think the database stuff if you could have it Async once, and we talked about it not necessarily being a great place to start. But once you get advanced, it would be kind of cool but my sites don't have it either, right? Both my database access layer can't support it nor does the framework support it, and the thing is super super fast. Honestly I don't understand why most websites that I work with are so crappy and slow, because I didn't work that hard to get mine to go fast. Doesn't seem that hard, anyway.
51:51 Joseph Mancuso: But I bet you if it was simple enough, like if you just had to create a job and then add it to the queue which is already created for you, I bet you probably would do it. Creating some kind of queue background work, a lot of Django projects probably don't.
52:02 Michael Kennedy: I did end up creating this type of thing because certain types of operations might send thousands of emails than the click of a button, and you can't wait for that to happen, right? It's insane, right? For example, I have office hours for my courses. So people can come, they take the course, they get office hours for free. A bunch of people signed up for those, right? If I enter a new one I can't just wait, hit to send all those emails 'cause it'll timeout. But other things like putting people on mailing list, right? They signed up for the site, they said okay, you can put me on your mailing list but they don't need to wait for you to put them on the mail. There's no outcome from that that they need anything from.
52:36 Joseph Mancuso: Right, exactly.
52:37 Michael Kennedy: Right, so that's a perfect example of some kind of background work.
52:40 Joseph Mancuso: And adding background work to Masonite literally takes about maybe 10 seconds of code once you get comfortable with it. I tried to make every single thing as easy as, quick as possible just to make it this rapid application development tool that people reach for.
52:55 Michael Kennedy: Yeah, cool, one of the things that Django comes with is DjangoORM and that's been really popular. One of the things that Flask and Pyramid have eschewed, they've decided we're staying far away from is defining a database access layer at all. And it's like up to you. Typically the answer is go get SQLAlchemy or something like Mongo Engine if you're going to talk to MongoDB or something else, right? But it's up to you, there's no guidance. It sounds to me like with Masonite you decided to bring along an ORM, an active record style one which matches really well with DjangoORM in its style, not so much with SQLAlchemy which is a unit of work type of one. Why not just lean on SQLAlchemy?
53:35 Joseph Mancuso: So again it was what I wanted it to look like. So I wanted the ORM to look like something I was comfortable with using. And again Masonite is sort of like a framework for me, right? I knew I was going to use it, I didn't want to build it for somebody else. I used it, so I built it in a way that I would like it. And I came from Laravel, like I said, and Laravel has something called an Eloquent ORM which is another active record style. And then I found Orator which is pretty feature complete, there's a couple of things that can be added to it and it was basically influenced by Eloquent. So it was almost perfect to bring in because it is super sleek, you don't have to like do anything crazy. Like getting all records is like the modelname.all that's it, it's all you have to do. Getting where is .where and then, you can maybe change some wheres together. To get the first record is .first. It's very very sleek and I thought that was the same as Masonite's philosophy of doing something as quick as possible to get what I need done. And it also had the, what I wanted to do as well was the migrations. So the migrations are really important. So in Django you have these magic migrations that are basically, I don't even know how but they're somehow like taken from model changes. And it basically generates these things that run that you should never edit because that's probably bad and it's probably going to screw up something down the road.
54:55 Michael Kennedy: Something will get out of sync.
54:56 Joseph Mancuso: Yeah, in Laravel and Orator, you want to do the migrate. The migrations are much more explicit. So what you're doing is you generate this new migration and you add a couple of table columns. There's like an up method and a down method and the down method just reverses what you did in the up method which is usually it's defaulted to like a sensible default, like dropping the table which is usually what you need to do. And that's what I wanted and then Orator also had that too. So that saved like a whole lot of time. So it just made sense to go with Orator and I used it and I integrated the migrations process with it, and I just really really like Orator. I think it's a really great ORM, so then I just incorporated it and everybody else seems to like it so I guess something's good.
55:41 Michael Kennedy: It looks pretty interesting, I can certainly see how it goes with your philosophy of I want it to look like this, how do I make that happen? It's a little bit SQLAlchemy-esque in some ways but not in others, right? Like the way you define the model and the table names and stuff, that's pretty cool. One of the things I like about some of your philosophies or styles here is you could go and say get a user, you could say user.find and pass a user ID and that will give you back the user or maybe none, right?
56:12 Joseph Mancuso: Yeah, it's nice and quick.
56:13 Michael Kennedy: Or you could say user.find or fail, and you either get one back or I'm guessing get an exception if that didn't work, right? Yeah, so when I'm using, say SQLAlchemy, SQLAlchemy has a first and it has a one. Which one of those, he's going to throw an exception when it doesn't find it. I mean probably one, but is one just the way I get the first one or is first the way I get the first one? You know what I mean, it's just a little less...
56:39 Joseph Mancuso: It's very fluent, Orator is very fluent.
56:41 Michael Kennedy: Obviously once you get used to it, right? First just gives you the first or nine and so on but this name is super clear, and I really like the style of find or fail because...
56:51 Joseph Mancuso: Like I said, when I write my code, I didn't write Orator, I'll admit, it was already written. Almost written for me I felt like. But it reads like English and that's how I like to do it as well.
57:01 Michael Kennedy: Yeah, you also have an interesting way of setting up relationships with decorators and properties. How does that work?
57:07 Joseph Mancuso: Oh yeah, so I think this is actually really cool. So in Orator, if you have a user and in articles, a user has many articles and then an article belongs to a user. So what you can do is when you do like, maybe user equals, user.findone and you get your user, you can do user.articles and this is called a dynamic property. Even though you created a method called articles and you decorated it with a, has many relationship, you fetch it by using this dynamic property.
57:39 Michael Kennedy: Right, it basically is similar to the app properties syntax.
57:42 Joseph Mancuso: And it actually returns a collection of all the articles. Or what you could do is if maybe a user has one profile which has one address, which has one something else, you could actually, when you fetch your user, you could do user.address or user.profile.address. and you just keep on chaining these relationships and then eventually you get down to what you need. Or what you do is you do user with profile address, something else and then you actually what you call eager load. And that gets rid of the n plus one problem.
58:20 Michael Kennedy: That's a big problem with ORMs and I think some people don't know what that is, what the n plus one problem is. You want to take a shot at describing that for the audience because personally I am a huge fan of ORMs or in the Mongo world, ODMs for documents. But these classes that map back to your data, I think it's a huge benefit. But this is one of the problems that you need to be aware of and it can be one of the performance problems. So maybe tell people about this n plus one problem in ORMs.
58:46 Joseph Mancuso: So let's say you get a list of 50 users and you want to loop through all those 50 users, and you want to get the profile of each user, right?
58:56 Michael Kennedy: That first one where you get the list, that's probably a single query, right? Users.find state equals California or something like that and you get 50 results. So there's your one, there's your one in the n plus one.
59:07 Joseph Mancuso: Right, I'll explain the problem first and then I'll explain the solution. So the problem is if I did, if I loop through the user and I did user.profile, it's going to create or it's going to fire a query for each time I use user.profile and it's going to fire a query. So that's where the n comes in 'cause you're looping through all 50, now you have 50 plus 1 queries and now you have 51 queries.
59:29 Michael Kennedy: Probably is slow to do that, right? It's probably not good to do 50 queries when you could do one.
59:33 Joseph Mancuso: Right, so what you do is you do user with profile find one, and that eager loads what's called. So that's two queries and what that does is it gets the user ID and then it does a where in on the other table and it basically saves that information basically in memory on that object. So now whenever I do user.address, I already loaded that information so I just fetch it from some kind of dictionary or something or some kind of collection saved on that user object. So now it's only ever two queries that I'm doing it. So it gets rid of that n plus one problem.
01:00:08 Michael Kennedy: Yeah, that's perfect and it's super easy to tell if you just turn on logging. You could tell you have an n plus one problem because you're like whoa, why is, if you turn on logging to every time you do a query, show me what's happening, go into the database you're like I hit this one page and there's like 20 queries. Like why, this should be one or two, what is happening, right? That's probably an n plus one problem.
01:00:30 Joseph Mancuso: Yeah, I've gotten about 750 queries down to like 13 or something like that using the when statements. Yeah, it's pretty crazy.
01:00:38 Michael Kennedy: That's pretty sweet. Alright Joe, I think we're getting long on time here but this has been been really fun. It's clearly an opinionated framework but I also like that you can use these craft commands to kind of bring in bits and pieces as you want to or not. That's cool.
01:00:54 Joseph Mancuso: Yeah, thank you.
01:00:55 Michael Kennedy: Yeah, you bet. Alright, so let me just ask you one really quick question I guess around the project itself before we move off of it. So are you looking for contributors, people to take it for a run, people to add issues, add PRs? Where's it at?
01:01:12 Joseph Mancuso: Yeah, I mean we're looking for contributors all the time. I mean you could be a contributor by joining the Slack channel and saying like hey you should have this feature. And then I'll probably either code it that night or maybe a couple of days later or that weekend. That's even contributing. I mean you didn't code but you still contributed towards the development of the framework. And Masonite's in a really unique position because it sort of is opinionated and it is a Python framework, so it has a lot of people coming in from different ecosystems. People feel really comfortable coming from Ruby, people feel really comfortable coming from Laravel, people love it coming from Django. So when they come in, they have all these really really unique ideas. So if you're not even in the Python community, I think that's even better coming in 'cause you're coming with fresh ideas that maybe people from the Python community don't have yet or haven't seen. So yeah, just joining the Slack channel is huge to come in. If you know how to code and you go to a Python that's great too.
01:02:06 Michael Kennedy: Yeah, that's cool, how old is Masonite?
01:02:08 Joseph Mancuso: So Masonite was developed, started December of 2017 and then in six months later we came out with the main release which was June of 2018. So it's probably about what is that? About really only a year and a half old is really when it really started kicking off.
01:02:27 Michael Kennedy: Cool, the reason I ask is a lot of these other web projects in the Python space are very old, right? They've been around since 2005 or 2008 or something like that and as a contributor if you want to participate in that, you're walking up to a highly polished, careful delicate balance of features and things and so many people depending upon it. And if you want to make a change, it can be really hard to do minor things, right? So these newer frameworks I feel are maybe better opportunities for folks to contribute because it's somewhat newer, right? And it's a little more dynamic and flexible and it's not so set in stone.
01:03:02 Joseph Mancuso: Yeah, I think that's exactly right. And even the Masonite code in general was super super clean. Almost every single method has doc strings that explain where each variable comes from and stuff like that. So it's really really easy to contribute. And since it's fairly new, although it has like a crap ton of features and people actually are really really impressed that it's only a year and a half old and it has dozens and dozens of features, there's a lot of easy pickings still that can be coded up. So there's even, in the issues I usually put good first issue or a list of difficulty, easy, medium, hard. I haven't done that actually with their latest issues but normally I do that. So if you want to hop in and see what kind of difficulty you're at, then go there.
01:03:45 Michael Kennedy: Yeah, you can decide oh actually this might be more than I want to spend concerning this. The other thing that is interesting and I noticed about your project is you're participating in the GitHub sponsor program. I don't know if that's the right name for it but it's something to that effect, where folks can contribute through GitHub to Masonite right? Tell people about that.
01:04:06 Joseph Mancuso: So I think with that button that you see, that little sponsor button, it's really, I think it is called the GitHub sponsor button but it's really just a list of other links. It's really just a button and then you could post links to like a Patreon or some kind of like patronage service. So it's not anything crazy but if you click on it, it'll show you the link to the Patreon page where you can either sign up to be a contributor if you're a company and you want a sponsor. The documentation page gets I think around 10,000 page views a month. So if you want to go there, it's always good to contribute there as well.
01:04:39 Michael Kennedy: Very cool, alright, well let me ask you the two questions before I let you get out of here. Now I think astute listeners will already know the answer to this question but that's okay. I think we kind of touched on already but if you're going to write some Python code, what editor do you use?
01:04:54 Joseph Mancuso: VS Code, yeah.
01:04:55 Michael Kennedy: Yeah, that's a good one. That's definitely got a lot of momentum behind it right now. And then notable PyPI package that maybe you ran across or maybe Masonite depends upon, like this thing is awesome, it doesn't get enough attention. Maybe tell people about something like that. First of all, just say get out of the way, you can pip install Masonite as a thing, right? So there's one notable package.
01:05:16 Joseph Mancuso: Can I say my own package? Like a different package that I created?
01:05:18 Michael Kennedy: If you want.
01:05:19 Joseph Mancuso: Something that I created as sort of an extension is called Masonite validation. I needed again something extremely simple to create, to create validation and I didn't really see anything that was simple, I saw like, I think something's called pillow or marshmallow or something, it just wasn't what I wanted. So I created this validation package and you could see it in the Masonite organization on GitHub, that you could bring in. And it's not just for Masonite, it's for I think it's for Django or Slack or any thing, so you could pull it in, it'll only pull in the validation part of Masonite. And you can validate dictionaries, you can validate multi-dimensional dictionaries, you can validate JSON responses and stuff. It's a really really cool package.
01:05:58 Michael Kennedy: Okay, that sounds really nice. All right, final call to action, people are maybe interested in checking out Masonite, interested in getting started, what would you tell them?
01:06:02 Joseph Mancuso: So if you go to the main GitHub page, github/masoniteframework/masonite, you'll see a link to the Slack channel.
01:06:12 Michael Kennedy: Yeah, and I'll link to that in the show notes as well. I'll link that in the show notes.
01:06:16 Joseph Mancuso: Yeah, Slack channel which is, I'm really really responsive, it's about, it's almost 350 people in that Slack channel so far. Everybody's really really friendly so you can join there. And then on Twitter @MasoniteProject. I post news and tips and tricks and stuff like that on Twitter as well. So if you want to learn Masonite on Twitter, then you could join there.
01:06:38 Michael Kennedy: Alright, well it looks like a cool framework and it has a really unique way of working with it I think and yeah, congrats on it.
01:06:44 Joseph Mancuso: Yeah, thank you.
01:06:46 Michael Kennedy: You bet, thanks for being on the show. This has been another episode of Talk Python To Me. Our guest on this episode was Joseph Mancuso, and it's been brought to you by Linode and Datadog. Linode is your go-to hosting for whatever you're building with Python. Get four months free at talkpython.fm/linode. That's L-I-N-O-D-E. Datadog gives you visibility into the whole system running your code. Visit talkpython.fm/datadog and see what you've been missing. They'll throw in a free T-shirt. Want to level up your Python? If you're just getting started, try my Python Jumpstart by Building 10 Apps course. Or if you're looking for something more advanced check out our new Async course that digs into all the different types of Async programming you can do in Python. And of course, if you're interested in more than one of these, be sure to check out our Everything Bundle. It's like a subscription that never expires. Be sure to subscribe to the show. Open your favorite pod catcher and search for Python, we should be right at the top. You can also find the iTunes feed at /itunes, the Google Play feed at /play, and the direct RSS feed at /rss on talkpython.fm. This is your host, Michael Kennedy. Thanks so much for listening, I really appreciate it. Now get out there and write some Python code.