DEV Community

Cover image for Fewer Files, More Lines vs. More Files, Fewer Lines of Code
Anmoldeep Singh
Anmoldeep Singh

Posted on

Fewer Files, More Lines vs. More Files, Fewer Lines of Code

Ah, the classic developer debate: **"Fewer files with more lines" vs. "More files with fewer lines." It’s like choosing pizza toppings—everyone has their preference, and no one’s ever fully satisfied.

When organising code for a pull request (PR), some prefer the simplicity of keeping things in one place, while others favour breaking it into smaller, focused files.

Ultimately, it’s not just about you—it’s about saving future-you and your team from untangling a messy codebase later.

Let's delve into a practical scenario. Imagine a developer is tasked with rendering a list of widgets on a dashboard page. Here's the initial implementation:

// Dashboard.js
export default function Dashboard() {
 const widgets = getWidgets();

  // Handles widget deletion
  const handleDelete = (id) => {};

  // Handles widget title update
  const handleUpdate = (id, newTitle) => {};

  return (
    <div>
      <h1>Dashboard</h1>
      <div className="widget-container">
        {widgets.map((widget) => (
          <div className="widget">
                  <h2>{widget.title}</h2>
                  <p>{widget.description}</p>
                  <span onClick={handleDelete}>🗑️</span>
                  <span onClick={handleUpdate}>✎</span>
          </div>
        ))}
      </div>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

During a review, someone suggests separating the logic for rendering individual widgets into their own components. The developer refactors the code as follows:

// Dashboard.js
export default function Dashboard() {
  const widgets = getWidgets();

  // Handles widget deletion
  const handleDelete = (id) => {};

  // Handles widget title update
  const handleUpdate = (id, newTitle) => {};

  return (
    <div>
      <h1>Dashboard</h1>
      <div className="widget-container">
        {widgets.map((widget) => (
          <Widget
            key={widget.id}
            widget={widget}
            onDelete={handleDelete}
            onUpdate={handleUpdate}
          />
        ))}
      </div>
    </div>
  );
}

// Widget component for individual widget
function Widget({ widget, onDelete, onUpdate }) {
  return (
    <div className="widget">
      <h2>{widget.title}</h2>
      <p>{widget.description}</p>
      <button onClick={() => onDelete(widget.id)}>🗑️</button>
      <button onClick={() => onUpdate(widget.id, "New Title")}>✏️</button>
    </div>
  );
}

// Can be even further moved to a separate file
// Widget.js
export default function Widget({ widget, onDelete, onUpdate }) {
  return (
    <div className="widget">
      <h2>{widget.title}</h2>
      <p>{widget.description}</p>
      <button onClick={() => onDelete(widget.id)}>🗑️</button>
      <button onClick={() => onUpdate(widget.id, "New Title")}>✏️</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Didn't the initial implementation seem simpler and more straightforward, particularly when additional logic—such as handling analytics—is closely tied to the widget, leading to increased props and context switching? 👀 This raises an important question: which approach should the Dashboard component take? Should it retain the inline implementation, adopt the refactored structure, or opt for a hybrid approach? 🤔


When to Keep Components in the Same File

  1. Small Project or Single Responsibility:
    • If the DashBoard component is tightly coupled to the Widget component and your project is small, keeping them together reduces unnecessary complexity.
  2. Reusability is Unlikely:
    • When the Widget component won't be reused elsewhere, separating it provides little benefit.
  3. Readability:
    • For smaller components, a single file makes it easier to understand the relationship between components without context switching.
  4. Avoiding Overhead:
    • Inline components eliminate additional import/export statements, reducing boilerplate code in simple setups.

When to Use Separate Files

  1. Reusability:
    • If the Widget component might be used elsewhere, a separate file makes it more accessible and manageable.
  2. Code Readability and Organisation:
    • As files grow larger, breaking them into smaller, logical pieces improves navigation and reduces cognitive load, particularly in larger projects.
  3. Testing and Maintenance:
    • Isolated components in separate files are easier to unit test, leading to better test coverage and maintainability.
  4. Separation of Concerns:
    • Following the single responsibility principle, separate files ensure each component has a clear, distinct purpose—crucial for long-term maintainability.
  5. Scalability:
    • Breaking components into separate files ensures the codebase remains manageable as the project grows, enabling seamless addition of new features without disrupting existing functionality

Making the Decision

For this DashBoard example, your choice depends on the project's scale and the component's intended role. As this is a small example where Widget won't be reused, a single file works well:

// Dashboard.js
export default function Dashboard() {
 const widgets = getWidgets();

  const handleDelete = (id) => {};

  const handleUpdate = (id, newTitle) => {};

  return (
    <div>
      <h1>Dashboard</h1>
      <div className="widget-container">
        {widgets.map((widget) => (
          <div className="widget">
                  <h2>{widget.title}</h2>
                  <p>{widget.description}</p>
                  <span onClick={handleDelete}>🗑️</span>
                  <span onClick={handleUpdate}>✎</span
          </div>
        ))}
      </div>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

For larger or growing projects, separating Widget will be beneficial in terms of flexibility and maintainability

Key Takeaways

Balancing “more lines in a single file” versus “more files with fewer lines” depends on your project’s scope, team size, and growth trajectory. Consider the following when deciding:

  • Is the component likely to be reused?
  • How complex is the parent file?
  • Does the project follow conventions or specific design patterns?
  • Will the codebase scale significantly over time?

If someone suggests moving a component to a separate file during a PR review, double-check whether the benefits align with these considerations.

Top comments (0)