DEV Community

TJ Stifter
TJ Stifter

Posted on

Refactoring your code: Looking for Patterns

Introduction

Writing good clean code is a difficult skill to pick up and no one should feel expected to be great at it starting off. It's is something you acquire through practice of writing a lot of code. Refactoring is the process of restructuring code, while not changing its original functionality. The goal of refactoring is to improve internal code by making many small changes without altering the code's external behavior. It is important to practice refactoring and be diligent in looking for places to improve your code because it both helps you as you write and build your app as well as helps other developers who end up looking at your code. Let's talk a bit about how to go about refactoring your code.

Refactoring code to a new developer can seem incredibly overwhelming at first. It can be a struggle just to find a correct way to get your code to functionally work, and looking for ways to improve its efficiency or readability is just asking for a new developer to break their code. However, it is important to review your code on a regular basis looking for opportunities to refactor. First, cleaning up your code helps both you and others who may have to go over your code at a later date. Second, refactoring your code provides you an opportunity to reduce further complications by compartmentalizing code that can include making reusable pieces. Let's go over a strategy and some examples to help with practicing refactoring.

Looking For Patterns

Identifying patterns in your code is a great place to implement refactoring and can allow you to think about your code in a more compartmental way. We often repeat use of codes snippets throughout our code, and no one is expected to find every single repeat and devise a way to write some compartmentalized code to replace it. However, when blocks of code become larger and are all centered around a specific task that is then repeated somewhere else, the pattern becomes clear and finding a way to refactor that code makes everything much easier in the long run. Below is a simple example using React, without much content, but the concept provides a good example for looking to refactor your code. When writing out Components in React, we write our JSX to provide the structure for the component that is rendered. Depending on the complexity of your component, that return line of JSX can get rather large and complex very quickly. Here is just a simple example where a certain block of tags in JSX is repeated in our components return line.

return(

  <div>
    <div>
      <p></p>
      <p></p>
      <span></span>
    </div>
    <h2></h2>
    <div>
    <p></p>
      <p></p>
      <span></span>
    </div>
  </div>

)
Enter fullscreen mode Exit fullscreen mode

We can refactor this to improve both the readability of what our main components returns, and to create a new component that contains a piece of repetitive code, which we can implement in our main component. With our code factored out this way, we could also use this refactored piece in an entirely different component that may wish to utilize the same structure and content.

return(
  <div>
    <MyCard />
    <h2></h2>
    <MyCard />
  </div>
)

function MyCard () {
  return (
    <div>
    <p></p>
      <p></p>
      <span></span>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

For another exmaple, let's look at another commonly used piece of code wiritten in javascript, a patch request. Depending on the complexity of your app, you may be sending multiple patch requests to your backend from different components, for different pieces of data, and to different places on your backend. You may think because the information, or the route, or the object being changed is different you would need to write out the patch request each time in each place you needed it. By using refactoring and noticing the patterns in the patch requests, we can instead write a single general patch function that can then be called upon multiple times and provided the relevant information as arguments.

//patch request to our database
const update = {'username' : newUsername}
fetch (`/users/${user.id}`, {
    method: "PATCH",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(update),
}).then(r => {
    if (r.ok) {
        r.json().then(user => {
            setUser({...user, 'username' : user.username})
        })
    }
    else {
        r.json().then(data => console.log(data))
    }
})
Enter fullscreen mode Exit fullscreen mode

We can start by identifying the unique pieces of information to each patch. Once we know these item,update,and url, we can assign variables in their place and then to implement the patch, call the function patchItem(item, update, url) passing in those arguments.

const patchItem = (item, update, url) => {
    fetch(url, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(update),
    }).then(r => {
        if (r.ok) {
            r.json().then(data => {
                const keys = Object.keys(data)
                keys.forEach(key => item[key] = data[key])
            })
        }
        else {
            r.json().then(data => console.log(data))
        }
    })
    return item
}
Enter fullscreen mode Exit fullscreen mode

An important thing to note here, is that sometimes when refactoring your code, you may have to solve for different cases. In the example above for a patch request, because I cannot be sure how many attributes were modified; therefore, I need to properly handle the response object by looking through each of the keys and updating each one, rather than only updating the username in the first example. While not meant to be a perfect example, the above shows how to go about thinking of ways to refactor your code to a higher level of abstraction so that it can be used in multiple places.

Conclusion

Refactoring code is an important skill to have, but it is not one that comes easy and takes a lot of practice and experience from both writing your own code as well as reading others code. It can be useful try to identify patterns and blocks of code functionality that are either the same or very similar as places to implement refactoring. Some times it can be easier to look for the unique pieces of code in a code block to understand the key elements that need to be generalized so the code can be used in additional places. Finally, while refactoring can be intimidating to new coders who may feel overwhelmed or anxious about breaking code they got to function correctly, refactoring provides you a great chance to gain a better understanding of what the code does and why.

Top comments (0)