« All Episodes

Refactoring Based on Code Responsibility

Published 4/20/2016

In today's episode, I give you some tips for refactoring based on the responsibility of your code.

Mentioned or relevant to today's episode


Today's episode is sponsored by FreshBooks! Get paid faster, and get control of your business cash flow. Head over to FreshBooks.com/DeveloperTea today to get started with a free month. Don't forget to enter “Developer Tea” in the “how Did you Hear About Us?” Section when you sign up. Thanks again to FreshBooks for sponsoring the show!

Transcript (Generated by OpenAI Whisper)

Welcome to Developer Tea. My name is Jonathan Cottrell. And in today's episode, I'm going to be talking to you about refactoring tips. Specifically, we're going to be talking about refactoring tips for determining responsibility. Today's episode is sponsored by FreshBooks. FreshBooks is the ridiculously easy to use online accounting software designed to help creative entrepreneurs get organized, save time, and get paid faster. We will talk more about what FreshBooks has to offer to Developer Tea listeners later on in today's episode. But first, I want to talk about these refactoring tips. And we're going to frame this through the lens of difficulty. Different places where responsibility of code can go haywire. Code should call out what it is responsible for. And I have four times when the responsibility of code can be basically impossible to determine or incredibly difficult to determine. And really, here's why it's important. If a new developer comes to the project, right? Let's say the developer has never seen the code for that particular project. And they come to the project. And they realize that they need to work on this one particular piece of code. But it's impossible to determine what pieces are doing what. Now, this episode is certainly inspired by a recent example at my work. I was working on some code and it was difficult to determine exactly what that code was doing. And I couldn't determine what was responsible for what was happening in the interface. I was working on some JavaScript. And so, I want to... I want to point out a few things that can fix this problem before it occurs in your code. This is a huge maintainability issue. Because if I come to the code as a new developer. And I don't know what that code is responsible for. I could introduce brand new bugs that you never necessarily saw coming. Because that code may be responsible for something that's totally outside of the context of where that code shows up. So, let's talk about these four things. Four times when code can go haywire. When the responsibility of your code can go haywire. And the first one, this shouldn't surprise you, is poor variable naming. And when I say variable, I mean poor function naming, poor class naming, poor variable naming, of course. Poor constant... Anything that you name as the developer. Your responsibility is incredibly high here. Incredibly high. Incredibly high. Incredibly high. Incredibly high. There's a huge amount of talent that is necessary to be able to name things properly. Now, we've talked about naming being a difficult problem on the show. And it can't be stated enough. Learning how to label things well is absolutely essential to writing good, maintainable code. You can't write good code without proper labels. Code is really doing two things. All right? This is why labels are important. Code is really doing two things. It's processing something, whether that is input. Maybe it's some data that exists elsewhere. Maybe it is just time, for example. There's something that it's processing. Right? It's doing something. And it's explaining to the developer how that processing is occurring. Okay? So, it's a two-way communication. It's communicating with the computer. And it's communicating with a user. In this case, the developer. Okay? So, it's a two-way communication. So, it's a two-way communication. So, it's a two-way communication. So, it's a two-way communication. For example, it can model behavior and characteristics. But ultimately, what code does is it creates some set of pathways or actions. And it provides a way for humans to read and manipulate those pathways. So, when we talk about responsibility, it's incredibly important to name things well so that the responsibility of that particular reference, that particular object, is determined easily by someone new coming in. easily by someone new coming in. into the project. If you labeled something one-letter variable name, for example, this is a really common thing that you'll see. And a practical tip for those of you who are writing code today and you're looking for a very simple practical tip, stop using one-letter variable names. And the reason is, it's kind of difficult to know what that one letter is actually implying, what it refers to. We see these all the time when we look at generic algorithms. And that's probably the reason why we use them in our code. We may also think that it makes our code a little bit smaller and therefore a little bit more efficient. And this is true to a certain extent, but not to a reasonable extent. In other words, you're going to get much more out of naming your variable a few letters longer, just a few bytes more. You're going to get so much more value out of that than you gain by keeping your variable names short. So, go ahead and name it something significantly more. Descriptive. Most of the time, any of the issues that you would have experienced as a result of that name being too long will be resolved by either a compiler or a compressor or a minifier. It typically is going to be resolved. And most of the time, it's not even that much of an overhead anyway. So, go ahead and name your things much more descriptively. But imagine that you come into a project and you have something that is named really broadly or something. really non-descriptively. Well, how do you find out what that thing is doing? You have to go in and read every single line of code and determine, okay, what is this particular function, this foo function that I'm seeing? What is it actually performing? What are the effects? What are the side effects? What are the inputs and outputs? What should I expect from this code? And you as the programmer, you have the opportunity to point programmers in the future in the right direction if you name things well. Okay, don't miss this. You have the opportunity as a developer to point future developers, that includes you, by the way, if you come back to the project after a few years, I promise you, you're not going to remember what that abstractly named function is supposedly doing. You have the opportunity to point those developers in the right direction if you simply name things well. Okay, so that's number one. Number one, poor variable naming can cause a massive problem in your code. Name things well and you can help your future self, other developers, you can help them out significantly. Number two is what I like to call tag-along code. Tag-along code. Go open a piece of code you wrote in a hurry and you're likely to see this poor practice. You have a really well-written function that runs and it does a few things. Maybe, let's say you're writing JavaScript and it creates some HTML to inject into your page and everything is looking great, but then you need to add one little unrelated thing to the page. Now, you could go and create another function and create tests for that function and you could rename everything and go through that whole process or in your hurry, what is more likely is that you added that little bit of code to the end of that function. You've tagged it on. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. the same problem that you had in the first point, which is the name suddenly is invalid, right? You could possibly rename that function, you know, foo and bar, right? Whatever foo is and whatever bar is, hopefully you're not using those names specifically, but you know, maybe you're creating HTML. So you could name it create HTML if it was named that initially, and then you added something else like add a class to the header, create HTML and add class to header. But now you run into issues of that code just being terrible to look at. And your responsibilities are getting mixed up with each other. This is the problem that tag along code can create, you're much better off if you go ahead and take that code out of that function and create a new function or a method, whatever you need to do, create a new container with a new name for that particular job. Okay, so tips one and two, or times when your code will go haywire. Number one was when you name things poorly. And number two is when you add tag along code. Now I have two more for you. But first, I want to talk about today's sponsor, FreshBooks. This is FreshBooks first episode of developer tea. So thank you so much FreshBooks for joining spec and sponsoring developer tea. FreshBooks is the ridiculously easy to use online app. And if you're new to FreshBooks, you can find it on the web page. And if you're new to FreshBooks, you can find it on the web page. And if you're new to FreshBooks, you can find it on the web page. It's an online accounting software designed to help creative entrepreneurs get organized, save time and get paid faster. How do you get paid faster? Well, your clients can pay you online, you create your invoice, it literally takes about 30 seconds. And your clients can pay you online, this is so much faster than them trying to send you a check, or whatever it is that your clients normally do. Paying online is just a few clicks away, right? If a client forgets to pay you on time, FreshBooks will pay you back. So if you're new to FreshBooks, you can find it on the web page. Handles the awkwardness of reminding them, you can send customizable late payment reminders automatically through FreshBooks. So you don't have to give them a call and ask them to pay you since they're late. On top of this, FreshBooks has a mobile app, which will let you take pictures of your receipts, and then it organizes them for you to go through later. Beyond that, FreshBooks can also automatically import expenses directly from your bank account. So you have no excuse when you're tracking expenses anymore. It makes it so easy to just go and get those expenses directly either from the pictures you take of your receipts, or directly from your bank account. FreshBooks will also handle your time tracking. So when it comes time to create that invoice, you'll know what you did, and when you did it. All the little details about cash flow are kept in one place. So FreshBooks knows exactly what invoices you sent, when you sent them, who's paid you, and when you sent them, you'll know what you did, and when you did it. And perhaps most importantly, who owes you what? So to claim your free month, this is what FreshBooks is giving Developer T listeners, a free month on FreshBooks, go to freshbooks.com slash developer T and enter developer T in the how did you hear about us section when you sign up. If you've been putting off your bookkeeping, this is tax season, if you've been putting it off, then today is the day to start getting that stuff, cleaned up. Go to freshbooks.com slash developer T. Of course, that link can be found in the show notes at spec.fm. Thanks again to FreshBooks for sponsoring Developer T. Okay, so we've been talking about refactoring, and we're talking about determining the responsibility of different parts of your code. And I'm outlining a few times when your code may go haywire, where it becomes incredibly difficult to determine the responsibility of a particular piece of code. Now, hopefully, this will help you avoid that situation in the future. Because the refactoring process, when things are poorly named, for example, is very difficult. You have to go back and forth with whatever the product is that front end and the back end to determine whatever it is that this particular method or function is trying to do. It's really hard, it's really expensive. And it's much better to just go ahead and avoid it on the front end. So we talked about number one, poor variable naming. And number two, you have to be careful when you're naming your stuff properly. Because if you're naming your stuff properly, you're going to have a lot of problems. And that's going to be a huge issue. Especially when you're first starting out, and you're wanting to move through things very quickly, and there's not a lot of code. It's easy to name things very short variable names when there's not a lot of code. When the code gets longer, those short variable names that you have, you kind of go to that same variable name over and over, that's going to come up over and over in your code. And then it's going to be hard to discern one function from another one method from here. At the last evolution, you may have taken the name from the name of your name, and you may have taken the name from the name of your name from the name of your name from the name of your name, and you may have taken the name from the name of your name from the name of your name from the name of your name from the name of your name from your name from your name from your name from your name from your name from your name from your name from your name from your name from your name from your name from your name from your name from your name from your name from your name from your name from your name from your name from your name from your name from your name from your name from your name from if you're looking for it in the future. So make sure you don't add tag along code into methods where it doesn't belong. A good rule of thumb here is just create a method, create a new function. If you are in doubt, go ahead and create a new function. This is so much easier than actually trying to discern, you know, where, where these things came from. Why does this method have this thing that's totally unrelated in it? Just avoid that altogether. Create an extra method that gives it a name, that gives it something for you to describe it by. Okay, so that's number one and two. Number three, container functions, or you might hear this term God objects or God classes, God models. And the idea here is the model is too powerful. It has too much stuff in it. It has too many methods attached to it. Or for example, an initialization method. This happens most often in initialization or cleanup methods, these hooks that we you know, we hook into these things that are happening maybe in the back end, we're hooking into them into the front end, or maybe there's an API for this. This happens all the time. For example, in WordPress programming, you have initialization functions, and cleanup methods, and they collect a bunch of actions into one big string of stuff. It's one big method that just holds all of these actions that are one after the other one operation after the other. And really, this isn't a method that's going to work. It's going to work. It's going to work. It's going to work. It's going to work. It's going to work. It's going to work. It's going to work. It's going to work. It's going to work. It's going to work. It's going to work. It's going to work. It's going to much different than putting those methods, or those declarations, or those actions at the top level, like you might see in a utility script. The reason this is similar is because if you were to just take out the function name, the initialization function, which really doesn't tell you a lot about what's happening, then all you have is a bunch of unorganized imperative code. And this is what we're trying to avoid when we create these functions, or when we containerize these ideas into their own methods. We're trying to avoid this top level kind of global dirty space where everything is happening in parallel to each other and there's no particular organization. And that's what we get when we create these initialization functions or cleanup functions or whatever you want to call those things. Those things that collect a bunch of different actions into an event. And the problem is not only that they have multiple responsibilities, which is already a problem, but they also are very unpredictable. They're very unpredictable and often end up having a bunch of really poor patterns like nested logical branching, multiple return statements, side effects all over the code. On top of this, container functions can be incredibly difficult to test and just as difficult to document. An acceptable alternative is to create a container function that can be used to test and test a container is to create functions outside of those container functions that perform the individual routines or actions or the individual pieces of imperative code that end up showing up in the initialization. This allows initialization functions to exist because it's important to have these event-driven type functions and you read them more like a checklist rather than a long detailed imperative routine. Okay, so what you want to do is avoid these container functions. Avoid these god objects. These things that have far too many methods that are contained in one big object because you didn't know where else to put it. So we want to avoid these massive functions that are just filled with imperative code. And finally, number four. So number one, poor variable naming. Number two, tag along code. Number three, container functions or god functions, god objects. And number four, container functions. So we want to avoid these massive functions that are just filled with imperative code. And number four, mixing presentation with your logic. Hopefully you're not surprised by this. Hopefully you've heard this before. This has been around for a very long time. Separating your presentation from your logic is not a new idea. Of course, there's a whole set of refactoring patterns and software design patterns that recommend separating your presentation from your logic. But this particular space is even more important than it has been in recent years as we have a lot of people who are using this as a tool to do a lot of work. And so we want to avoid these powerful and interesting libraries and tools that allow and sometimes even encourage these two things to be mixed. React is a great example of this, as you could return markup inside of the same function where your logic is. And in fact, you can intersperse some logic in that markup. They've gone a little bit to the point where it's a little bit more difficult to do that, but it is possible. And we want to avoid this issue by simply separating those methods, from one another and using templates for presentation when possible. This doesn't necessarily mean that you have to separate these responsibilities into different files. This is the common misconception. You don't have to separate them into different files, but rather it means that the logical method or function you are writing should be agnostic to how the presentation will use the output. Let me say that again. You want to create two methods, one method and one method. And you want to separate them into different files. You want to separate them into different methods, one that does your presentation and one that does your logic. And your logic method should not care about how you wrote your presentation method. Your logic method should not care about how you wrote your presentation method. Now, if you can grasp this, it's going to change the way you write code forever. It's an incredibly powerful concept. And I highly recommend that you at least try to write code this way and see what it does. And if you can grasp this, it's going to change the way your workflow. See what it does to the maintainability of that code. I think you're going to be surprised. Thank you so much for listening to Developer Tea today. And I hope you enjoyed today's episode. By the way, Developer Tea was just launched. I'm recording on the day that it was launched in Google Play. If you are an Android user, and you've been waiting on a good Android app, or a good place to pick up the podcast on Android, this is your perfect time to do so. I'm recording on the day that it was launched in Google Play. If you are an Android user, and you've been waiting on a good Android app, or a good place to pick up the podcast on Android, this is your perfect opportunity. Google Play, they have the podcast directly available. Of course, that will be in the show notes at spec.fm. Thank you again to FreshBooks for sponsoring today's episode of Developer Tea. If you want to get your invoices paid faster, if you want them to be paid online, if you want someone to handle the awkwardness of sending late payment notices for you, go and check it out. There's a free month at freshbooks.com slash developer tea. Make sure when you sign up for the free month, you get a free month of free money. If you sign up that you put developer tea in the how did you hear about us section. And of course, all of those details will be found in the show notes at spec.fm. If you're enjoying the show, make sure you leave a review in iTunes. This is the best way to help other developers find developer tea. Once I know exactly how Google Play system works, I will tell you how to leave a review or how to help us out on Google Play as well. Thank you so much for listening. And until next time, enjoy your tea. Thank you.