Applying Martin Fowler Principles in React
Martin Fowler is a software architect and author who emphasizes clean, maintainable, and scalable software design. Some key concepts:
1. Key Principles
a) Layered Architecture
-
Separates the app into:
- Presentation/UI Layer → React pages/components
- Business Logic Layer → hooks, state, domain rules
- Data/API Layer → API services, Supabase, backend calls
-
Each layer has a single responsibility.
b) Separation of Concerns
- UI components do not contain business logic.
- Business logic does not directly render UI.
-
Data layer only communicates with backend APIs.
-
Keep UI, business rules, and data access separate.
-
Example in React:
- UI →
Transactions.jsxpage - Business Logic →
useTransactions.jshook - Data →
transactionService.jscalling backend APIs
- UI →
c) Single Source of Truth
- Backend APIs or services provide authoritative data.
- Frontend state mirrors backend data when needed.
d) Dependency Inversion
- High-level modules (UI) depend on abstractions (hooks/services) rather than low-level modules (API).
e) Patterns Applied in React
| Pattern | React Example |
|---|---|
| Layered Architecture | ui/, business-logic/, data/ folders |
| Service Layer | transactionService.js for API calls |
| Repository Pattern | Abstracts data fetching logic (Supabase client, REST API) |
| Dependency Injection | Hooks or context providing services to components |
| Single Responsibility | Components only render, hooks handle logic, services handle data |
2. React Implementation Example
src/
├── ui/ # UI Layer
│ └── pages/Transactions.jsx
├── business-logic/
│ └── transactions/useTransactions.js
├── data/
│ └── api/transactionService.js
Data Flow:
- UI calls a hook from the Business Logic Layer.
- Hook calls API service from Data Layer.
- API service fetches backend data and returns it.
- Business Logic Layer processes data.
- UI renders the result.
3. File Naming Conventions
| Layer | Naming Convention |
|---|---|
| UI Layer | Component.jsx or Page.jsx |
| Business Logic Layer | useFeature.js, featureHelpers.js |
| Data/API Layer | featureService.js, apiRoutes.js |
4. Benefits in Large Applications
- Clear separation reduces coupling.
- Easier testing and mocking.
- Supports scalability and team collaboration.
- Makes future backend or frontend changes safer.