Minimal Frontend Self-Review

Minimal Frontend Self-Review

Background

When I was a junior developer, I was fortunate enough to start developing in an environment where I could receive code reviews. At first, I did not even have a clear idea of what the review criteria were. I thought development was complete as long as the functionality worked properly, and the issues pointed out in reviews initially seemed trivial.

I would often receive questions about areas that did not appear to be directly related to functionality, such as the order of import statements or variable names.

  • "Is this state value really necessary?"

  • "You handled this with watch, but wouldn't it be more appropriate to handle it with an event?"

  • "Doesn't this component have too many responsibilities?"

  • "Are null, undefined, and empty arrays being handled properly?"

At first, making each correction one by one was sometimes tedious. However, after experiencing team-based development and services running in production firsthand, my perspective gradually changed. Instead of stopping at "Does the functionality work right now?" I began asking myself, "If someone else had to modify this code later, would they be able to understand it easily?"

In a production environment, it is difficult to work with the mindset that "another developer will fix it if a problem occurs later." Even when developing as a team, someone else may modify the code I wrote, or I may have to look at that code again several months later.

As I repeated these experiences, I naturally began checking the items I had previously looked for during code reviews at least once during the development process as well.

Of course, it is still practically difficult to review every piece of code thoroughly. This is especially true when the development schedule is tight. Therefore, by "self code review," I mean a minimal verification process that is closer to quickly checking once more for issues that are easy to overlook while developing quickly than to performing a detailed analysis.

1. Why Self Code Review Is Necessary

When developing quickly, it is easy to move on to the next task after implementing a feature and confirming that it works properly. If you consider only development speed, this may be an efficient approach. However, the faster you develop, the fewer opportunities you have to view the code objectively. Since you understand the overall context when writing the code, it is easy to naturally overlook unnecessary code or ambiguous structures.

2. A Review Is Not Finished Just Because the Functionality Works

If the screen appears normally and clicking a button produces the desired result, development may appear to be complete. However, real-world services do not consist only of normal situations (the Happy Path). Even for a single API request, various situations must be considered.

  • Successful response → Display the data

  • API failure → Handle the error

  • No response data → Empty state

  • undefined / null → Check whether data exists and handle it safely

  • Repeated clicks → Prevent duplicate requests or state inconsistencies

In a self-review, I do not stop at simply asking "Does it work properly?" I also examine "How does it behave in abnormal situations?"

3. First Review: Finding Unnecessary Code

The first thing I look at is surprisingly simple: "Is this code really necessary?"

① Unused variables and import statements

Check whether there are console.log() statements left behind for testing, variables that are no longer used, or imported modules that are no longer needed. It is a good idea to automate this with the help of static analysis tools such as ESLint.

② Duplicate code

If the same API calls and error handling are repeated across multiple screens, review whether they need to be shared. However, blindly making everything common is not always the right answer. Make the decision based on the question, "Will maintenance actually become easier if this code is made common?"

③ Excessive state values

// ❌ AS-IS
const dataList = ref([]);
const isEmpty = ref(false);
const hasData = ref(false);
// ⭕ TO-BE
const dataList = ref([]);
const isEmpty = computed(() => dataList.value.length === 0);한 상태값

As shown above, you can first review whether values such as isEmpty or hasData, which can be calculated from dataList alone, really need to be managed as separate state (ref) values.

If the state is managed separately, the values of isEmpty or hasData must also be manually updated whenever the data is updated. If even one piece of the state update logic is omitted, a bug may occur in which the actual data exists but the screen displays "No data." Using computed to make the logic depend on the original data reduces the need to manually synchronize state values and lowers the likelihood that a developer will omit a state update.

4. Second Review: Checking Component Responsibilities

Even a component that was simple at first can take on numerous responsibilities as development progresses, such as user lookup, authentication, form validation, modals, and pagination.

When I see a large component, I divide it into areas by functionality and review whether any of them can be separated independently. However, splitting code indiscriminately just because it is long only increases the cost of navigating files. The important thing is not to "make it smaller," but to "make the responsibilities clear."

Props and Emits: Check whether the parent is directly controlling too much state and whether the behavior can be inferred just by looking at the event name.

5. Third Review: Checking State and Exceptional Situations

Personally, this is what I consider most important in a self-review. Screens are much more likely to break in exceptional situations than in normal ones.

Loading and Error States

  • Is an appropriate state displayed to the user while the data is loading?

  • When the API fails, is it handled in a state that allows the user to take the next action?

While conducting a code review for a project, I once discovered a problem in which an exception was not handled when a specific error occurred during authentication, causing the entire screen to turn white and preventing the subsequent process from continuing. Since there was no problem in the normal authentication flow, this error would have been easy to miss if only the normal case had been checked. Since then, whenever I look at API call code, I check not only the result when it succeeds but also ask, "If it fails here, what screen will the user see?"

Empty and Null / Undefined

A situation in which the data is an empty array ([]) (Empty State) is different from a situation in which the API has failed. Also, if you do not consider the possibility that profile may not exist in a reference such as user.profile.name, a runtime error may occur and prevent the screen from rendering properly.

6. Fourth Review: Checking Asynchronous Operations and API Calls

Duplicate calls: Check whether the same API is being called unnecessarily when entering a page, when watch runs, or when a user event occurs.

Order of asynchronous processing (Race Condition): Check whether, when a user performs an action twice quickly, the data from the later request could arrive first and then the data from the earlier request could arrive later and overwrite the latest state.

7. Fifth Review: Reexamining from a Maintenance Perspective

Finally, I summarize everything from the perspective of someone seeing the code for the first time.

Naming and HTML Semantics: Use names that reveal the role instead of const temp, and check whether <button> is used instead of <div> for buttons that require click events.

Comments and Unused Code: It is better to clean up unused code rather than leave it commented out. Past code can be checked in Git's change history. When comments are necessary, leave explanations of why something is difficult to understand from the code alone or anything that requires special attention.

Structural Consistency: Check whether the placement and style of import, props, state, methods, and so on differ significantly from the project's existing code. However, rather than blindly following the existing approach, also consider whether there is a more appropriate approach for the current code.

If the project already has a common API-handling approach, utilities, or UI components, check the existing implementations first before creating a new approach.

You may be able to use the existing approach as is, but depending on the situation, you may also choose a new approach. The important thing is to first examine why the existing approach is being used and then determine which method is more appropriate for the current code.

For example, if API calls and error handling have already been standardized, first check whether the existing approach can be used. Conversely, if the existing approach works only in specific situations or needs improvement, consider applying a new approach.

8. Self-Review Based on the Actual Changes

Checking all of these things in the middle of writing code can actually slow down development. I prefer to finish implementing the functionality first and then review it again on a screen where I can see only the code that was actually modified, such as the Git diff or the changes in a PR.

While writing, I focus on “How should I implement this?” During review, I shift my perspective to “If I were seeing this code for the first time, would I be able to understand it?”

[Minimal Self-Review Checklist]

-Functionality

  • Does it work as intended with valid input?

  • Are Loading / Error / Empty states handled?

  • Have you checked for possible null / undefined values?

  • Does it avoid affecting existing functionality?

-Code

  • Are there any unused variables / imports / console.log statements?

  • Have you created any unnecessary state values?

  • Have you checked for duplicated logic?

  • Is the component's responsibility excessively large?

-API / Asynchronous Operations

  • Is the same API being called redundantly?

  • Is API error handling consistent?

  • Is there a possibility that consecutive requests could cause the state to become inconsistent?

-Maintainability

  • Can you understand the roles of variables and functions just by looking at their names?

  • Is there any unused code or outdated comments?

  • If you used an approach different from the existing pattern, is there a reason for it?

  • Can a developer seeing the code for the first time follow it?

9. Real-World Review Experience and Practical Compromises

What I learned from receiving reviews as a junior developer continued to help me when I later took on code reviews myself. Rather than simply looking for problems in the code, I also began considering how they might affect subsequent modifications and maintenance. In practice, examining code from this perspective has sometimes helped me discover and fix errors that are easy to overlook during development.

However, it is not possible to apply perfect standards to every project. I experienced this while supporting a project with a tight schedule. Since I was also responsible for developing functionality, I did not have the realistic time to clean up all of the existing code. In that situation, I set priorities and improved the necessary areas first.

  1. Critical issues that affect functionality

  2. Areas that directly hinder maintainability

  3. Areas where standardization would provide clear benefits

  4. Simple code-style cleanup (removing console statements, organizing comments, and so on, while keeping it to a minimum)

Ignoring every problem because the schedule is tight will eventually come back as technical debt, but trying to achieve perfection all at once and missing the deadline is also a problem. Therefore, I set priorities according to the situation and try to improve the necessary areas first.

Conclusion

Self-code review does not have to be an elaborate architecture review. This is especially true when rapid development is required. To me, self-code review ultimately means “taking one more skeptical look at the code after functionality has been implemented.”

As a junior developer, I learned by addressing the points raised in code reviews one by one. Even now, I try to recall the questions I was asked in those reviews whenever I encounter similar situations.

When you need to develop quickly, instead of trying to review every part perfectly, you can start by spending even five minutes taking one more look to see whether you missed anything.

Code_Latte

Site footer