April 6th, 2020 × #abstraction#javascript#components
Hasty Treat - Abstraction
Wes and Scott discuss abstraction in programming - what it is, when to use it, benefits like reusability and testing, guidelines, examples of good abstraction, and differences between personal and public code.
Transcript
Announcer
Monday. Monday. Monday.
Announcer
Open wide dev fans. Get ready to stuff your face with JavaScript, CSS, Node modules, barbecue tips, get workflows, breakdancing, soft skill, web development, the hastiest, the craziest, the tastiest web development treats coming in hot. Here is Wes Barracuda Bos and Scott El Toro Loco Tolinski.
Scott Tolinski
Welcome to syntax in this Monday, hasty treat. We're gonna be talking all about abstraction.
Explaining what abstraction is
Scott Tolinski
And if you don't know what abstraction is, so Wes got an introduction to what it is. We're gonna be talking about it in the context of both React as well as just general JavaScript programming, in general, talking about how to make things more simple for ourself. This episode is sponsored by LogRocket, which is the perfect place to see how errors are happening on your website. And when I mean see, I don't mean see an error log. I mean, see visually what the heck the user did to cause your site to break. Because LogRocket gives you a session replay, which is a scrubbable video that gives you network Wes, Redux store, and it gives you console logs. It gives you everything you could possibly see, even like mouse tracking, what the user did to click to break the thing. So you get all that and more, with LogRocket. So head on over to logrocket.comforward/syntax.
Scott Tolinski
Sign up and get 14 days for free and just or be able to reproduce your bugs live in a video without having to ask your users what the heck they did to break the thing.
Scott Tolinski
Okay. My name is Scott Tolinski. I'm a developer from Denver, Colorado. With me, as always, is the Wes Bos.
Wes Bos
Hey, everybody.
Scott Tolinski
Hey, Wes. How's it going?
Wes Bos
I'm doing good. Excited to talk about abstractions.
Scott Tolinski
Abstractions.
Scott Tolinski
You know, abstraction is one of those words. It's one of those terms that gets thrown around. We get so many terms in in lingo and and stuff, and new programmers will look at this stuff and just say, oh, this seems scary, just because it's, some syntax. Right? It's some some word that Wes don't know about. But what is abstract in the most basic terms? So abstraction in its most basic form Bos hiding complexity, basically, by taking something and abstracting it, I'm using the word in its own definition, and into, something else that's much easier to understand. Right? Because in in programming, we often write these big old functions that do this thing. And maybe you've seen it before where you have, like, a 100 line function does this and this and this and this and this. Well, maybe it's worth it to take some of those steps and abstract them into smaller steps, things that make maybe a little bit more sense. Right? So basically, what abstraction is is taking complex things and encapsulating that into smaller ideas or smaller functions or smaller use cases.
Abstraction helps with reusability and testing
Scott Tolinski
And we've largely seen this as component developers by well, think about it. Right? We talk about this all the time with React and Vue and Svelte and whatever. You You have a component. This component's gotten to be, like, 200 lines or whatever. It's obviously a massive component. Maybe this component should be broken down into something smaller. Maybe we should abstract this into little tiny components, encapsulate it. I used to have this, programming language. It was a visual programming language called Max MSP for audio creation. I talk about it all the time. It's one of my first introductions to programming on here. And you create these little boxes, and you connect them via patch cables. One of my favorite things about Max MSP is because it was all visual and you had these little patch cables and boxes, you could click and drag and select and then click encapsulate. And it just took all of that complexity and just shrunk it down into 1 little box. So instead of having 20 boxes, you now have 1 little box, and it has its inputs and outputs, whatever.
Scott Tolinski
So that's really at its core what abstraction is. You're taking something that's big and complex and smooshing it down into something that is a little bit more usable, pushable, whatever. And we can think about this all the time in our components.
Guidelines for when to abstract something
Wes Bos
Yeah. Like, reusability is a huge benefit of, of abstraction because, like, certainly, I have written code before where I find myself doing something like formatting money or making a fetch request that we're only, like, 1 little 1 little piece is different. And I say, Like, I'm doing this kinda similar in a couple pieces of my application. Why don't I abstract this out into its own function, into its own library? And then when I wanna do this piece of functionality, I can just call this Node one nice clean line.
Wes Bos
Not to mention, you probably can test that thing really nicely Oh, yeah. In isolation
Scott Tolinski
without having to bring in the rest of the application into it. Totally. That those are all, like, key key points here. And, you know, I think the the main concepts here, it's like, when do you know to abstract something? Right? When does something become its own thing rather than this big hunk of thing? And this JS all comes down to, in my mind, personal preference. You'll often see people, tout, like, don't do this. Do this. Take okay. Components should be this high. And sometimes people even give, like, these, like, arbitrary line limits saying, no function should be greater than 5 lines. And, then you you just end up with splitting everything where Scott doesn't doesn't necessarily make sense, but it's it's more or less like based on some arbitrary rule. For me, I often think about this as, again, like you mentioned, smaller smaller things that are easier to test because it's much easier to test a function that checks the the currency or changes the currency or whatever. It's much easier to test that than to test the the entire order order thing at once, you know, processing the order or whatever. So if you have all these smaller little bits, you can test those little bits in isolation, make sure they work. And to me, that that makes the whole thing easier to test.
How to know when a component is too complex
Scott Tolinski
It often has this, like, feeling of, when you look at a component, it's too heavy. It's too much. It's too complex.
Scott Tolinski
And reading this thing, maybe I don't understand exactly what it's doing. And to me, Node should be readable.
Scott Tolinski
It should definitely you should have a good understanding of what it does. And one of the things recently that got me thinking about abstraction in these kind of ways was I was thinking about some animation stuff I was doing, and I've been getting into Framer Motion a lot lately. You know, I've done a course on it, and I had animated routes. I built animated routes. And to do animated routes, you have an animated animate presence component, then you have your React router switch, then you have your route component, then you have your motion Scott DIV to do the animation. That's 4 components. And what I did is I wrote 2 abstractions, Node of which combines the animate presence in the switch and one of which combines the route and the div. And they still accept the same props, and it has really smart defaults. So by by default, it automatically does an opacity change. And what you get is you get a much cleaner API. You can see that I have an animated route or an animate animated router and then an animated route, and that's it. And if you don't need to pass any props in there other than the the route path, then the whole thing just works. And not only that. It's just so much easier to read.
Animated routes example of good abstraction
Scott Tolinski
So to me, it comes down to is this thing difficult to parse? Is it difficult to test? Is it difficult to read? And should I think about breaking it into smaller pieces? That's beautiful. I like that that way of approaching it. Yeah. I I'm a big fan of this. I sometimes go a little bit overboard with it. I would definitely veer on the side of abstracting too much. But then, you know, the downsides are if you abstract too much, you could see that there's very minimal savings. Right? Like, maybe you're you're saving one line of code and having to write a whole bunch of extra files and extra things and have this call this call this call this call this whatever.
Scott Tolinski
And you get sort of a redux y kind of mess where that's just you don't know where the source of anything is because it's too far abstracted.
Scott Tolinski
So sometimes, you have to be cognizant if the savings are worth it.
Scott Tolinski
Is the juice worth the squeeze there?
Wes Bos
I I agree. Like, I I go on the other side of things where I don't abstract until I absolutely need to. Sometimes ahead of time, you can think about like, oh, yeah. Of course, I'm gonna need another function or reusable function to to do this, but, I might rather Scott to just write it, be able to see everything, see how it all works, and then quickly abstract it out into its own package or its own function or its own file or something like that, once I see the the need for something like that. To me, it all comes down to re reusability.
Evaluating if abstraction is worth it
Scott Tolinski
You Node? It all it all comes down to, like, whether or not this thing needs to exist.
Scott Tolinski
And I was thinking about it specifically with my animated routes thing. It's like, oh, I have this animated routes I'm using on this one section.
Scott Tolinski
But if I abstract it in this kimonos, I don't have to do any work to get animated routes throughout the rest of the entire site. Even if it's just a basic fade. I don't have to do any work. I just gotta change a component here or there. I just I'm just changing the import and the name of the component, and the whole thing just works. So to me, it's like, what is the benefit Vercel what's the cost? And you have to sort of look at that, and that comes with experience and that comes with, experimenting. So don't feel like you shouldn't, abstract, and don't feel like you should abstract when you're just learning. Just play around with it. Feel free. I've gotten really into much smaller single use functions lately just in terms of, like, that's, like, really functional programming. A function should do one thing, and it spits out something. And that's how you work. Right? Yeah. So for me, personally, I I've been thinking a lot about them and breaking things up into smaller things. And and sometimes, abstraction is just a pointless layer, but sometimes it's really helpful.
Scott Tolinski
And I think there's also a difference between your personal code Vercel consumable libraries. Right? Because if you think about it, a library that you're releasing off into the world, something that other people are using, needs to really fit so many more use cases than your own. Right? For me, with my animated routes, all you have to do is pass the routes prop, and then it works. But some people will be like, well, how do you get the route to fly in from the right? Well, with my particular abstraction, you can't. But if I was publishing this as a package, that would be a huge downside of the package that you couldn't do all that stuff. So what you end up having is when you when you have packages that are publicly and don't have these, like, really strong opinions, they have a whole ton of inputs. And the more pnpm you add to something, the more complex and difficult it is to understand. So, I think there's a little bit of a trade off there in terms of, like, who's using this thing, what it needs to do, and and how that all works.
Difference between personal and public code
Scott Tolinski
Have you seen, Chakra UI? It's a chakra hyphen ui.com.
Wes Bos
Let me check it out. I heard of it. It's one of these
Scott Tolinski
component libraries. I think it's built in Yes. Yes. I've seen this. Motion. And it's really nice. There's a ton of components, and they all look great.
Scott Tolinski
In my mind, these things are fantastic, but I would much rather write my own version of this if I have the opportunity.
Scott Tolinski
Because what this has to do is it has to accept so many different use cases and so many different configurations that you end up having, like, a set of 5 or 6 props on something that to change the way something looks, where I would personally write my own or even take this and abstract it into my own components that have, like, these smart defaults.
Scott Tolinski
Because when you start adding inputs and you start adding props, it can get out of hand really quick in terms of usability, readability, and, I don't know. The the less choice you give developers when doing design system stuff like this Mhmm. Probably the better because the more cohesive the whole thing's going to be. You don't want you don't want people to be able to goof it up. Absolutely.
Scott Tolinski
So if you are writing components for your team and your use cases that aren't going to be made publicly available or even if they are going to be publicly available, like, don't worry about accommodating every particular use case. People ask us about our design system all the time and how we do things, And, let me look at my some of my components here. I have some layout components, and I have a couple of layout components, and they're very opinionated. And, for instance, my layout, component itself is a singular style div, and it only accepts 1 prop. And that prop is a string, which is either title or wide. That's it. Those are the only options to use the layout. I also have a columns 1, columns component named calls, and calls accepts 1 component, and that's whether or not it's reversed. And our calls component gives us 2 evenly spaced columns, one that's like 30 per 65%, and one's a fraction of that using CSS grid.
Scott Tolinski
And it that's it's whether or not the big one is on the right or the big one's on the left. That's the only prop it takes. And because we have these, like, secure, solid defaults, we just know that you can drop these things in and you don't need to configure them and you don't need to anything else. Again, our container prop one or our container component 1 prop.
Scott Tolinski
Our flex component, we have a flex component anytime we wanted to use, like, a flexbox container.
Scott Tolinski
The only thing that we accept in this is a prop for our justify content, and we do that as a prop rather than a style thing just to to keep it all in. But that's the only thing. Otherwise, it's just flex. Right? You wanna flex some items. It just works.
Scott Tolinski
And same with our grid component. Our grid component just takes an array of, how many columns we want, how many equal columns.
Wes Bos
So it's just very simple and keeping your I'm glad that you you say that because, like, a lot of my components are very similar in that, like, I think sometimes people ask me to open source parts of my code base. I'm like, it's so so specific Yeah. To what I'm doing, and it's it only does what I need. Like, I don't I'm not writing this thing where it's gonna every single person in the world that that ever wants to use it will have have the ability to do so. It's just for my use case. And if I need if I need to, I'd be able to add 3 columns, then I'll I'll modify that component and and add it in. I think that especially for people who maybe haven't worked in in code bases like that, they may be thinking that that's how they how people approach it. But, honestly, it just adds more complexity
Scott Tolinski
to the the function or to the component to do more than you need it to do. And that's 100% the reason why I don't use frameworks. Because if you have a framework, there's just too many options and too many variables and too much learning and too many things to distract that's like a very specific learning too. Like, it's it's 2020.
Scott Tolinski
How many people are still using that Bootstrap knowledge that they they spent all that time in to figure out specifically how bootstrap works? Are you gonna have the negative margin? You Scott have the container? Like, that stuff, I don't I don't even think about that stuff anymore, and and that's, like, almost wasted time learning that when I have my own component system that, just works. And since I wrote it, you know, I didn't have to learn it.
Scott Tolinski
So for me, that I guess it's an argument in in writing your own things for your own use cases, and it's all dependent on time. But to me, this saves a lot of time because I don't have to learn these things. It took 2 seconds to write a flex component. So, for me, it's it's all about knowing when things need to be buttoned up and and pulled into to their own thing and when to maybe look at this as being it's too complex.
Scott Tolinski
Mhmm. And a funny a funny example, I've been doing a lot of custom hooks. And so one of the things I've been doing is moving some of my GraphQL calls into their own custom hooks, which is actually which is actually really kinda interesting because I haven't done this before, but I was thinking about it. I use this particular user query to grab the user all the time, and so I have to import the user query from the GraphQL file warp even worse, copy and paste the user query into each file depending on how you do that. Then you have to do the the whole Apollo ESLint, use query pass, query, whatever, do all the exact same things every time.
Scott Tolinski
Whereas if I were to abstract that into a custom hook, that's just use user, that all happens behind the scenes. I only do 1 import. There's only one source of what it's grabbing, whatever. I don't have to import all those things. I just import use user, pop it in there, and I got the user. So, for me, React Hooks JS specifically custom React Hooks has really changed my viewpoint on when to abstract things and how simple some things can get, and, I just love it. Love it. Love it. Love it.
Wes Bos
Alright. I think that's a good way to end it. Thanks, Scott, for leading this one off on abstraction.
Wes Bos
It's funny. A topic we've never covered before. I saw it, and I was like, we must have covered that, but certainly, we haven't. So, that was a good one. Thanks for tuning in, and we will catch you on Wednesday.
Scott Tolinski
Peace.
Scott Tolinski
Peace.
Scott Tolinski
Head on over to syntax.f m for a full archive of all of our shows, and don't forget to subscribe in your podcast player or drop a review if you like this show.