Introduction
To become a hirable and sought-after web developer in today’s competitive job market, you must elevate your coding skills to a professional level to stand out from other candidates, significantly increasing your chances of being hired.
In this article, tech industry experts Matt Lawrence and Mike Karan explain the importance of code quality and how learning to improve yours can significantly enhance your career prospects! They discuss the necessity of maintaining consistent coding styles, effective refactoring, writing comprehensive tests, and utilizing tools like Prettier for formatting and linting to ensure your code is clean, safe, and maintainable.
Topics covered in this article include:
- Code Quality: Highlights the importance of maintaining clean, maintainable, and efficient code through consistent coding standards and practices, enhancing collaboration and reducing bugs.
- Testing: This section explains why unit and end-to-end tests are essential for preventing bugs and ensuring the code works well and is reliable.
- Prettier Formatting: Discuss how Prettier makes code styles consistent, improves readability, and cuts down on picky review comments by automatically formatting the code.
- Linting and Refactoring: These sections examine how linting helps find errors, enforce coding standards, and focus on refactoring to keep the code clean and efficient.
Article Concept Overview
Problem:
Poor code quality can cause crashes and unexpected errors, making it difficult for a team to read, review, and improve the code. This can disrupt project development and make maintenance difficult.
Solution:
The solution is to improve code quality by keeping coding styles consistent, refactoring code, writing tests, using tools like Prettier for formatting, and implementing linting to ensure the code is cleaner, safer, and easier to maintain.
Code Quality
To stand out in the competitive job market, you need to raise the quality of your code to a professional level, which will set you apart from other developers. It's not just about your programming skills; it's about how well you can adapt to working on a team that follows strict coding practices.
Raising the quality of your code includes:
- Ensuring your code conforms to the system's design.
- Testing your code thoroughly.
- Formatting your code correctly.
- Using linting tools to catch errors and enforce coding standards.
- Regularly refactoring your code to improve its structure and readability.
Achieving professional-level code quality involves how effectively you can adhere to a codebase's established standards, how proficiently you can write code that functions reliably and is easy to maintain, and how well you can document your code and its readability. Following these guidelines will improve team collaboration, reduce bugs, and improve the software's functionality. These skills will set you apart from other prospective developers and are essential for long-term career success.
Junior developers often struggle on a team because they fail to review the documentation and example patterns and need to perform linting properly. Their programming capabilities are not the issue; they must adhere to the codebase's standards and principles, which the rest of the team follows.
Although writing functional code quickly is a common objective when on a team, hiring managers may be concerned if the code needs more readability and maintainability. This is why writing better, cleaner, and safer code is crucial. Consistent coding styles are essential, particularly in larger teams, as they facilitate understanding and maintaining each other's code. So, mastering code quality goes beyond programming; it's about ensuring your work is reliable and manageable.
Improving your code quality is a technical skill and a crucial aspect of your career that can enhance your professional reputation! By consistently writing clean, easy-to-maintain, and efficient code, you demonstrate your ability to collaborate effectively in a team and meet industry standards. This emphasis on quality will help you stand out in the job market and earn the trust of your coworkers and supervisors.
The following sections will explore essential practices to help you write better code and strengthen your reputation as a skilled and reliable developer.
Testing
What is testing? Testing is a crucial process in software development that involves evaluating and verifying that a software application or system meets the specified requirements and functions correctly.
Writing comprehensive tests is important because it ensures that your application functions correctly and reliably. Comprehensive tests help identify and prevent bugs before they reach production, reducing the risk of errors affecting users. They also provide a safety net for developers, allowing them to confidently make changes to the codebase, knowing that existing functionality is protected. Additionally, comprehensive tests improve code quality by encouraging better design and documentation, facilitate easier maintenance, and enhance collaboration among team members by providing clear expectations of how the application should behave. Although there are many types of testing, we will focus on the main two discussed in the Podcast episode: Unit Testing and End-to-End (E2E) Testing.
Types of Software Testing and Their Definitions:
- Unit Testing: Tests individual components or functions in isolation to ensure they work as expected.
- Integration Testing: Tests the interaction between different components or systems to verify they work together correctly.
- End-to-End (E2E) Testing: Simulates real user scenarios to test the complete functionality of an application from start to finish.
- Functional Testing: Verifies that specific functions of the application work according to requirements.
- Regression Testing: Ensures that new code changes do not adversely affect existing functionality.
- Performance Testing: Assesses the speed, responsiveness, and stability of an application under various conditions.
- Load Testing: Evaluates how an application performs under heavy loads, such as high user traffic.
- Stress Testing: Determines the application's robustness by testing it beyond normal operational capacity.
- Usability Testing: Examines how easy and user-friendly the application is for end-users.
- Security Testing: Identifies vulnerabilities and ensures the application is protected against threats.
- Acceptance Testing: Validates the application against business requirements to ensure it meets the needs of the end-users.
Now that we understand the importance of testing let's explore the steps to run them effectively, commonly utilizing tools like the React Testing Library and Jest.
The React Testing Library is a tool for testing React components in a way that closely resembles user interaction. It focuses on testing the behavior of components rather than their implementation details, making tests more reliable and easier to maintain. Simulating user actions like clicking buttons or typing text ensures that the components work as expected in real-world scenarios.
On the other hand, Jest is a testing framework that provides a robust environment for running tests. It includes a test runner that executes your tests and an assertion library that helps you check if your code behaves as expected. Jest also offers features like mocking, which allows you to simulate parts of your application during testing. When used with the React Testing Library, Jest helps you write and run tests that ensure your React components function correctly, providing confidence in your code's quality.
Jest is a popular testing framework often used with the React Testing Library to test React components. Here's how it works together with the React Testing Library:
- Setup:
- Jest is typically configured in your project when you set up a React application, especially if you use Create React App. It provides a test runner, assertion library, and built-in mocking capabilities.
- Writing Tests:
- You write test files with a
.test.js
or.spec.js
extension. These files contain test suites and test cases. - Use
describe
to group related tests andit
ortest
to define individual test cases.
- You write test files with a
- Rendering Components:
- Use the
render
function from the React Testing Library to render your React components in a test environment. This function returns utility methods to interact with the rendered component.
- Use the
- Querying the DOM:
- Use methods like
screen.getByTestId
,screen.getByText
, orscreen.getByRole
to query the DOM and find elements. These methods help simulate how a user would interact with the application.
- Use methods like
- Assertions:
- Use Jest's built-in assertion methods like
expect
to verify that the component behaves as expected. For example, you can check if an element is in the document or if it contains specific text.
- Use Jest's built-in assertion methods like
- Running Tests:
- Run your tests using the command
jest
ornpm test
(orpnpm test
if using pnpm). Jest will automatically find and execute all test files in your project.
- Run your tests using the command
- Viewing Results:
- Test results are displayed in the terminal, showing which tests passed or failed. Jest provides detailed output for any failed tests, including the expected and received values, to help with debugging.
By combining Jest with the React Testing Library, you can write tests that focus on the behavior of your components from the user's perspective, ensuring they work correctly in your application.
Unit Testing
Now that we understand how the React Testing Library and Jest work together, let's explore a real-world example. Below is a unit test written by Ryan Furrer for the EntryStatus component, part of the Gridiron Survivor project. I and other junior developers in our apprenticeship program are participating in this project.
The following file is a test suite for a React component called EntryStatus
. It uses the React Testing Library to verify that the component renders correctly under different conditions. Here's a breakdown of how it works:
- Imports:
EntryStatus
is imported from a local file, which is the component being tested.render
andscreen
are imported from@testing-library/react
, which are utilities used to render the component and query the DOM.React
is imported to use JSX syntax.
- Test Suite:
- The
describe
block groups related tests for theEntryStatus
component.
- The
- Test Cases:
- The first
it
block tests that theEntryStatus
component renders correctly when the user is not eliminated. It renders the component and checks if an element with the test IDentry-status
is present in the document and contains the text 'alive'. - The second
it
block tests the component's behavior when the user is eliminated. It renders the component with theisEliminated
prop set totrue
and checks if theentry-status
element contains the text 'eliminated'.
- The first
The tests ensure that the EntryStatus
component displays the correct status based on the isEliminated
prop.
import { EntryStatus } from './EntryStatus';
import { render, screen } from '@testing-library/react';
import React from 'react';
describe('EntryStatus', () => {
it('renders correctly if user is not eliminated', () => {
render(<EntryStatus />);
const entryStatus = screen.getByTestId('entry-status');
expect(entryStatus).toBeInTheDocument();
expect(entryStatus).toHaveTextContent('alive');
});
it('renders correctly if user is eliminated', () => {
render(<EntryStatus isEliminated={true} />);
const entryStatus = screen.getByTestId('entry-status');
expect(entryStatus).toBeInTheDocument();
expect(entryStatus).toHaveTextContent('eliminated');
});
});
Below are the results of running the test:
$ pnpm test EntryStatus.test.tsx
> @0.4.4 test C:\Users\larocca\Desktop\vscode\GIS\GIS-10-25-2024\gridiron-survivor
> jest --passWithNoTests "EntryStatus.test.tsx"
PASS components/EntryStatus/EntryStatus.test.tsx
EntryStatus
√ renders correctly if user is not eliminated (31 ms)
√ renders correctly if user is eliminated (3 ms)
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0
totalTime: 1.54 sRan all test suites matching /EntryStatus.test.tsx/i.
End-to-End (E2E) Testing
End-to-end testing is a crucial aspect of software testing that simulates real user scenarios to ensure the entire application functions as expected from start to finish. This type of testing verifies the integration and interaction of various components within the application, providing confidence that the system works seamlessly in a production-like environment. By mimicking user actions, E2E tests help identify issues that may not be apparent in isolated unit tests, ensuring a smooth and reliable user experience.
Incorporating comprehensive tests into your development process is essential for ensuring robust, reliable software that meets user expectations and withstands the demands of real-world use.
Prettier Formatting
Prettier is essential for maintaining visual consistency in your code without altering its functionality. It automatically formats your code, addressing common stylistic issues such as tabs versus spaces, semicolons, and trailing commas. By defining a standard code style, Prettier ensures that all team members adhere to the same formatting rules, eliminating the need for manual checks before submitting a pull request. This automation reduces the likelihood of nitpicky code review comments related to formatting, such as requests to add a comma or a semicolon, allowing developers to focus on more critical aspects of the code.
Prettier is a versatile tool that can be configured to format code automatically upon saving or even during commits, ensuring a consistent code style throughout your project. You can enhance your workflow by adding specific settings to your configuration files. Some of Prettier's default settings include:
- Using spaces for indentation
- Adding semicolons at the end of statements
- Using single quotes for strings
Modifying the Prettier configuration file allows you to customize these defaults to match your team's preferences. Additionally, Prettier supports various programming languages and integrates seamlessly with many editors and version control systems, making it a valuable asset for maintaining code quality and consistency.
Richard Choi, a fellow member of the Gridiron Survivor project, wrote the Gridiron Survivor onboarding documentation which includes instructions for setting up Prettier for team collaboration, which includes instructions on how to set up Prettier properly for team collaboration:
Search for and opensettings.json
by pressingcmd+shift+p
on MacOS orctrl+shift+p
on Windows.
[!IMPORTANT] There may be multiple options. Ensure you select the option that says "Open User Settings (JSON)"
Add the following lines to your settings.json
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
Open a file and save it. You should see formatting changes made as soon as you save it!
Incorporating Prettier into your development workflow is essential for improving code readability and consistency and streamlining collaboration among team members. By automating code formatting, teams can concentrate on more critical development tasks, boosting productivity and code quality. Using this tool helps you write more efficient and effective code.
Linting
Linting is an essential process in software development that involves analyzing code to identify potential errors, enforce coding standards, and improve overall code quality. Tools like ESLint automatically detects syntax errors, unused variables, and inconsistent coding styles, helping maintain a clean and efficient codebase. This enhances team collaboration by ensuring all members adhere to the same coding conventions.
While TypeScript can handle some checks, linting remains crucial for enforcing a consistent code style across the project. It operates based on predefined rules, which can sometimes feel restrictive but are essential for maintaining code quality. Standard rules include prohibiting unused variables, disallowing console logs, and enforcing strict equality checks. It is advisable to start with a basic configuration, such as Airbnb's, and customize it as you become more familiar with your project's needs.
The screenshot below illustrates a real-world example of a linter in action. My recent Gridiron Survivor project pull request resulted in a Vercel deployment error due to an issue identified by the linter.
To determine the issue, my fellow team members Alex and Danielle instructed me to run a build using the “run pnpm build” command in the bash terminal. When I did, I saw the following error:
My first instinct was correct. Adding the copyright remark at the top of the file might be the “missing header“ that the linter expected.
// Copyright (c) Gridiron Survivor.
// Licensed under the MIT License.
Once I added the copyright remark, I committed the updated file, pushed it to the repo, and successfully created a pull request with the error resolved. As shown in the screenshot of the pull request, I now only need to wait on two approved reviews.
Incorporating linting into your development workflow streamlines the coding process and fosters a culture of quality and consistency within your team. By catching errors early and enforcing coding standards, linting reduces the likelihood of bugs making it to production, ultimately saving time and resources. As projects become complex, maintaining a high standard of code quality becomes increasingly crucial, and linting is a foundational tool in achieving this goal. Embracing linting practices ensures your codebase remains robust, scalable, and easier to manage over time.
Refactoring
Let's face it: We often draft code quickly to get it to work, with code quality as an afterthought. Once the code works, we usually move on without taking the time to refactor it.
Refactoring is a crucial practice in software development that involves rewriting code to make it cleaner and more maintainable after its initial creation. This process is essential for improving your codebase's overall quality and efficiency. You can enhance the code's readability and maintainability by simplifying functions, reducing redundancy, and breaking down large functions into smaller, more manageable pieces.
It's essential to recognize that the first version of any application could be better! Accepting this reality allows you to embrace refactoring as an integral part of the development process. By scheduling regular refactoring sprints, such as quarterly reviews for team projects, or committing to refactor after each release of a personal app, you can ensure the code remains robust and adaptable to future changes.
Incorporating refactoring into your workflow improves code quality and encourages a culture of continuous improvement and adaptability. This proactive approach to code maintenance is essential for long-term success in software development, enabling you and your team to deliver more reliable and efficient applications.
I highly recommend watching our Sprint Demos October YouTube Livestream to see firsthand how writing code, conducting reviews, and refactoring come together. Specifically, watch Alex Appleget’s fetch data function that gets every Gridiron Survivor League entry the user is part of (Timestamp: 31:30). You will see Microsoft Engineer Shashi Lo provide a constructive criticism code review, applauding Alex for first getting the code to work and then pointing out that he can refactor the code to use one API call instead of two. Shashi explained how his current code would cause performance issues as the data sets increase, and during the Livestream, when he ran the code, the lag was noticeable.
Shashi explains that Alex’s approach was correct in first getting the code to work, ideally within our two-week Sprint, and that we can add tickets for code reviews to optimize the fetch data function.
Sprint Demos October - Gridiron Survivor
Be sure to listen to the Podcast episode!
🎙 Why Code Quality Matters: Testing, Linting, Refactoring
Be sure to check out HTML All The Things on socials!
Episode Sponsor - Wix Studio
We want to thank this episode's sponsor for their support!
Wix Studio: The Web Platform for Agencies and Enterprises
Wix Studio is the new web platform tailored to designers, developers, and marketers who build websites for others or large organizations. The magic of Wix Studio is its advanced design capabilities, which make website creation efficient and intuitive.
Check out Wix Studio today.
How to support the show
Patreon
Prices are subject to change and are listed in USD
- Support the show from as little as ~$1/month
- Get a shoutout at the end of the episode (while supplies last) for just ~$3/month
- Help support the HTML All The Things Podcast: Click Here
Learn with Scrimba!
Learn to code using Scrimba with their interactive follow-along code editor.
Join their exclusive discord communities and network to find your first job!
Use our affiliate link for a 10% discount!! (Discount valid until the end of 2024)
- Click the link and take a look around at the new Scrimba 2.0!
- Make an account
- You'll then have the option to upgrade to pro content (and you should see our 20% discount listed!)
- Discount is for new accounts only
This article contains affiliate links, which means we may receive a commission on any purchases made through these links at no additional cost to you. This helps support our work and allows us to continue providing valuable content. Thank you for your support!
Sponsored content: The original publisher kindly sponsored this article, allowing me to share my expertise and knowledge on this topic.
My other related articles
- Bridging the Skills Gap: Empowering Junior Developers Through Apprenticeship Programs
- Expert Advice for Developers Beginning Their Tech Careers
- From Skillset to Networking: Tactics for Standing Out in a Challenging Job Market
- What to Expect When You’re Expecting a Developer Job
- How to Transition from JR Dev to an In-Demand Developer: Your Path to Getting Hired
Conclusion
Elevating your coding skills is essential for standing out in a competitive job market. This requires focusing on code quality and adhering to professional practices. It is crucial to maintain clean, maintainable, and efficient code. Consistent coding standards, thorough testing, and regular refactoring can help achieve this.
Unit and end-to-end tests are vital for preventing bugs and ensuring code reliability. Tools like React Testing Library and Jest are commonly used for these testing purposes.
Tools such as Prettier help maintain a consistent code style, which enhances readability and reduces the need for manual formatting checks. Linting aids in identifying errors and enforcing coding standards. At the same time, refactoring improves the overall structure and maintainability of the code.
Rewriting code regularly for clarity and efficiency is essential. By incorporating refactoring into the development process, developers can create robust and adaptable code.
Adopting these practices will improve your code quality, coding skills, and professional reputation, ultimately helping you stand out in the competitive job market!