21
Prefer duplication over code that depends on if-else
Back in 2018, when i had just begun coding, it was during the rise of JavaScript frameworks like React, Vue, and others like them. Those frameworks redefined frontend code and development as we know of, from the days of jquery.
One thing that stood out to me and really liked was the idea Components, the idea that you can nest some html code into a component and reuse it anywhere you liked, it stood out to me, i really liked to keep my code DRY. Not knowing of the other SOLID principle, the SRP(Single Responsibility principle) which states, an object, class, file, code needs to do one thing, and it needs to do it well. I was so fascinated by components that i tricked myself into violating the SRP while i was creating my components.
How? well, a component's purpose is to encapsulate some code and behaviour, and to be used on a location/s.
Let's illustrate that with an example, consider this Card
component
import React from "react"
const card = (props) => {
// return some html code here
}
export default card;
now this is really handy, we can use this in our Profile
page by simply doing these two lines
import Card from "./components/card"
<Card ...props />
Now, all logic and UI design of a card is enacpsulated in one single source of truth(file), which allows us to change only in one place and all Card
elements will be changed, really powerful, or is it?
Now, requirement's change, we need to display some UI from card depending on a state of it's Consumer(the place where it's rendered). We want to show an admin badge next to the user icon if they are an admin, pretty easy to add, let's update the code
const card = (props) => {
if(props.isAdmin) {
// render admin badge here
// other elements for admin
}
// return some html code here
}
export default card;
and we can simply pass it to the component where we need it
<Card isAdmin={admin value} />
Now, requirements change again, aside from supporting admin elements like badge, we need to set the border
of the element based if the user has been a long time user (they have been created more than one month ago). Let's update the code once more
const card = (props) => {
if(props.isAdmin) {
// render admin badge here
// other elements for admin
}
if(props.isUserActive) {
// change border of the card element
}
// return some html code here
}
export default card;
Yet again, requirement change, we need to render a different icon for a user type moderator, let's update the code once more
const card = (props) => {
if(props.isAdmin) {
// render admin badge here
// other elements for admin
}
if(props.isModerator) {
// update UI elements for moderator
// a border and specific icon
}
if(props.isUserActive) {
// change border of the card element
}
// return some html code here
}
export default card;
Now, you can see the pattern. whenever we want the card to support a specific use-case we need to add another if
statement. I've been guilty of this, i've had components perform multiple checks and multiple control props just to determine how i'm going to render the component.
you can break the if
statements by placing each if
in it's own file, we would end up with three components
//components/cards/admin.js
import React from "react"
const adminCard = (props) => {
// all admin properties
// admin icon
// admin badge
// returns html for an admin card.
}
export default adminCard;
//components/cards/moderator.js
import React from "react"
const moderatorCard = (props) => {
// all moderator properties
// moderator icon
// moderator badge
// returns html for an moderator card.
}
export default moderatorCard;
//components/cards/activeUser.js
import React from "react"
const activeUserCard = (props) => {
// all active user properties
// active user icon
// active user badge
// returns html for an moderator card.
}
export default activeUserCard;
we breaked the file into multiple files each with it's own properties, now we have three different card elements
<AdminCard isAdmin={admin value} />
<ActiveUserCard ...props />
<ModeratorCard ...props />
However, we have some code duplication here, some code from all three files are duplicated, it's all a matter of trade-offs here, we removed if
controlled code into a file with standalone purpose, but we ended up copy-pasting the code into three different files.
It's okay for a component to have a couple of if related code there, but if you see yourself passing more and more control variables, this is usually a sign that your component is attempting to do a-lot of stuff at once, your solution would be dividing the code into separated files.
Happy coding!.
Related links:
21