
When the Grass was Green… and then Yellow
Let’s say as a developer for an organization, one of the given requirements is to display images and information about all the sponsors on the organization’s website. That is, for each sponsor, I need to show the sponsor’s image, name, and a short description of them. If we’re just starting with 1 or 2 sponsors, that should be pretty intuitive.
// App.js// import necessary dependenciesfunction App() {
return (
<section>
<article>
<figure>
<img src={sponsorA} alt="Sponsor A"/>
<h2>Sponsor A</h2>
<figcaption>This is what Sponsor A does.</figcaption>
</figure>
<figure>
<img src={sponsorB} alt="Sponsor B"/>
<h2>Sponsor B</h2>
<figcaption>This is what Sponsor B does.</figcaption>
</figure>
</article>
</section>
);
}
Simple right? In the above code snippet, each “sponsor” figure has the same structure ( img , h2 , and figcaption elements). Adding a 3rd new sponsor shouldn’t be any more difficult. We can just copy one of the figure blocks, modify it with Sponsor C’s information and paste it right below Sponsor B.
<figure>
<img src={sponsorC} alt="Sponsor C"/>
<h2>Sponsor C</h2>
<figcaption>This is what Sponsor C does.</figcaption>
</figure>
We can definitely do this over and over again as we get more sponsor data that we’d like to display because copying and pasting are simple to do. However, it’s easy to overlook the consequences of making changes to any part of the code when we’re focused on just adding more to our existing code.
What if we don’t want to have the h2 element anymore? That means we’d have to go through each figure and delete each corresponding h2 element (likewise if we wanted to add something). Imagine if we have 20 sponsors to display or even more! While this is just a simple example, things could be a lot worse if our application was way more complex as well.
We shouldn’t have to mess with code related to the view (ie. what the user will see) if we aren’t making any new, significant changes to the user interface. Doing so would create more room for error, which means possibly spending additional time debugging/making adjustments we didn’t have to make in the first place.
Refactor Time
Now that we see these issues, this is probably a good place where we can start refactoring! Let’s first see if we can isolate our static data.
// constants.js// import imagesexport const sponsorInfo = [
{
image: sponsorA,
name: "Sponsor A",
description: "This is what Sponsor A does."
},
{
image: sponsorB,
name: "Sponsor B",
description: "This is what Sponsor B does."
},
{
image: sponsorC,
name: "Sponsor C",
description: "This is what Sponsor C does."
}
];
Now that we’ve isolated our data into a different file called constants.js, if we have more data, we don’t have to touch any code directly related to the view. Instead, we can add more to the sponsorInfo array, which we need to import later in our application.
Next, we can introduce the concept of modularity to our main component by making another component that “generates” these elements. This allows for simply plugging in the new component wherever we need to instead of having to copy and paste. We’ll call this component Sponsor.
function Sponsor(props) {
const {image, name, description} = props;
return (
<figure>
<img src={image} alt={name}/>
<h2>{name}</h2>
<figcaption>{description}</figcaption>
</figure>
);
}
With the help of props in React, we can connect all the pieces together by using our Sponsor component in our original App component and passing in the sponsorInfo data we separately set aside (thanks to object destructuring).
// App.js// Import data we stored in 'constants.js'
import { sponsorInfo } from './constants';// Import the `Sponsor` component we just created
import Sponsor from './components/Sponsor';function App() {
return (
<section>
<article>
{sponsorInfo.map(data => <Sponsor {...data}/>)}
</article>
</section>
);
}
That’s it! With this approach, we’ve refactored our code to make it more modular while anticipating any new data we may receive. Also, if we ever need to make an API call to fetch data stored somewhere else (like in a database), we can just reuse the Sponsor component as we did for the static data, assuming the structure of the data stays the same. Here’s how the issues we addressed earlier are now resolved:
- If we ever want to make any changes to each “sponsor” figure element, we just need to change it in one place rather than multiple places. Not only does this save time, but also if we want to write tests for it, we can now independently test the Sponsor component.
- Adding more data doesn’t directly mess with the view anymore. Our Sponsor component is all set in stone, so the only thing we need to touch is the sponsorInfo array.
Now that we’ve successfully refactored our code, there are a couple of important tips that can be brought up about the process that I personally find can be helpful.
- Isolate independent data, variables, helper functions, etc into a separate file. This can help make our code more testable and plus, you never know if another component needs to use the same elements.
- Find ways to reduce the amount of unnecessary work. This could mean creating a component that does the work for you (like we did) or maybe a higher-order component that shares any duplicate logic. Either way, we shouldn’t need to reinvent something over and over again.
Refactoring can seem like an unpleasant process because you’re putting a brief hold on adding new features to instead explore how you can “move code around”. However, the latter shouldn’t be seen as a negative because there are a lot of positives to take out of it, such as making your code more scalable or testable. During my software engineering internship this past summer, I quickly learned that refactoring doesn’t just improve your own developer experience, but also for other developers because other team members might be working on the same code. Better yet, what if the codebase you’re working on gets handed off to a different team? There are certain tradeoffs when it comes to refactoring but in the end, I think it entirely depends on what the priorities are at the moment.
WRITTEN BY
No comments:
Post a Comment