Simplifying Frontend Structure: A Pragmatic Approach
Taisuke J
Posted on August 17, 2024
Recently, I embarked on a journey to refactor the frontend code of a personal React Native project. Along the way, I found myself constantly thinking about how I could streamline the structure to make future refactoring easier and improve maintainability. After much consideration, I distilled my approach into two key principles:
- Avoiding Premature DRY
- Thoughtful Simplicity
Avoiding Premature DRY
It's tempting to apply the DRY (Don't Repeat Yourself) principle early in a project by establishing rigid rules around:
- File organization
- Directory structure
- Function extraction
If there’s little uncertainty and you can create a well-defined structure, it’s often best to go with that approach and refine it as necessary.
That said, development rarely unfolds exactly as planned. You might start with one idea in mind but soon discover:
- A component initially placed under a specific domain (
domains/xxx/
) ends up being reused across multiple domains. - Functions, initially separated into individual files, proliferate without a clear grouping, leading to a cluttered codebase.
Rather than imposing strict rules for abstractions from the outset, it can be more effective to start with broader, more flexible structures. For example:
- Begin with a larger directory (
user/
, etc.) and only split it into sub-groups (auth/
,profile/
, etc.) when there's a clear need. - Start with a single file (
index.ts
, etc.) and continue adding functions until the need to split becomes evident.
If there’s a lot of uncertainty and you’re unsure where to start, you can begin with an ultra-simple structure:
app/ # File-based routing
components/
|__ComponentA.tsx
models/
|__user.ts
|__request.ts
# Initially, group everything outside of `components` under `models` and gradually introduce new layers or directories as the project evolves.
This approach allows the codebase to grow organically, with abstractions emerging naturally rather than being forced prematurely.
Thoughtful Simplicity
Simplicity in code isn’t just about reducing lines or avoiding complexity for its own sake. It’s about considering the problem from multiple angles and choosing the most straightforward solution that effectively addresses the needs of the project. The goal is to think critically and make simplicity a deliberate choice.
To achieve this, it’s also crucial to establish some basic guidelines early on (with the flexibility to adjust as the project progresses):
- Separate database models from frontend/end-user models.
- Define state management strategies (which library to use and when).
- Design for replaceability (using ports and adapters, etc.).
While this article focuses on frontend development, the principles discussed here can also be applied to backend development. Thoughtful simplicity and a measured approach to DRY can enhance maintainability and ease future development across the entire stack.
Posted on August 17, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.