← Назад к вопросам
Какую архитектуру выберешь при написании проекта с нуля?
2.0 Middle🔥 151 комментариев
#Архитектура и паттерны
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Какую архитектуру выберешь при написании проекта с нуля?
Я выбрал бы модульную архитектуру на основе признаков приложения (Feature-based Architecture) с послойной организацией (Layered Architecture). Это оптимальный баланс между масштабируемостью, поддерживаемостью и простотой на ранних этапах.
Рекомендуемая структура проекта
src/
app/ # Точка входа, App-уровень
App.tsx
root.tsx
features/ # Признаки приложения
auth/
components/
LoginForm.tsx
SignupForm.tsx
hooks/
useAuth.ts
useLogin.ts
services/
authService.ts
types/
auth.ts
pages/
LoginPage.tsx
SignupPage.tsx
posts/
components/
PostCard.tsx
PostList.tsx
hooks/
usePosts.ts
services/
postService.ts
types/
post.ts
pages/
PostsPage.tsx
comments/
components/
CommentForm.tsx
hooks/
useComments.ts
services/
commentService.ts
types/
comment.ts
shared/ # Переиспользуемый код
components/
Button.tsx
Card.tsx
Modal.tsx
hooks/
useApi.ts
useLocalStorage.ts
utils/
formatDate.ts
cn.ts
types/
index.ts
constants/
api.ts
lib/ # Низкоуровневые утилиты
api.ts
store.ts
logger.ts
Почему Feature-based архитектура
Плюсы:
- Масштабируемость: легко добавлять новые фичи
- Инкапсуляция: всё связанное в одной папке
- Параллельная работа: разные команды работают над разными фичами
- Легче удалять: удаляешь папку фичи — всё готово
- Организованно: ясная структура и иерархия
Минусы:
- Может быть оверинжиниринг для маленьких приложений
- Требует дисциплины в организации кода
Послойная организация внутри фичи
feature-name/
types/ # TypeScript типы (domain слой)
index.ts
services/ # Бизнес-логика (application слой)
featureService.ts
hooks/ # React логика (infrastructure слой)
useFeature.ts
components/ # UI (presentation слой)
FeatureComponent.tsx
pages/ # Страницы (presentation слой)
FeaturePage.tsx
Зависимости только вниз (типы -> сервисы -> компоненты):
- Компоненты -> Хуки -> Сервисы -> Типы
- Никогда: Типы -> Компоненты (это плохо)
Практический пример: фича постов
// types/post.ts (domain слой)
export interface Post {
id: string;
title: string;
content: string;
authorId: string;
createdAt: Date;
updatedAt: Date;
}
export interface CreatePostDto {
title: string;
content: string;
}
// services/postService.ts (application слой)
import { Post, CreatePostDto } from '../types/post';
export class PostService {
async getPosts(): Promise<Post[]> {
const response = await fetch('/api/posts');
return response.json();
}
async createPost(data: CreatePostDto): Promise<Post> {
const response = await fetch('/api/posts', {
method: 'POST',
body: JSON.stringify(data)
});
return response.json();
}
async updatePost(id: string, data: Partial<Post>): Promise<Post> {
const response = await fetch(`/api/posts/${id}`, {
method: 'PUT',
body: JSON.stringify(data)
});
return response.json();
}
async deletePost(id: string): Promise<void> {
await fetch(`/api/posts/${id}`, {
method: 'DELETE'
});
}
}
// hooks/usePosts.ts (infrastructure слой)
import { useState, useEffect } from 'react';
import { PostService } from '../services/postService';
import { Post } from '../types/post';
const postService = new PostService();
export function usePosts() {
const [posts, setPosts] = useState<Post[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
const fetchPosts = async () => {
setLoading(true);
try {
const data = await postService.getPosts();
setPosts(data);
} catch (err) {
setError(err instanceof Error ? err : new Error('Unknown error'));
} finally {
setLoading(false);
}
};
fetchPosts();
}, []);
return { posts, loading, error };
}
// components/PostList.tsx (presentation слой)
import { usePosts } from '../hooks/usePosts';
export function PostList() {
const { posts, loading, error } = usePosts();
if (loading) return <div>Загружается...</div>;
if (error) return <div>Ошибка: {error.message}</div>;
return (
<ul>
{posts.map(post => (
<li key={post.id}>
<h2>{post.title}</h2>
<p>{post.content}</p>
</li>
))}
</ul>
);
}
// pages/PostsPage.tsx
import { PostList } from '../components/PostList';
export default function PostsPage() {
return (
<main>
<h1>Посты</h1>
<PostList />
</main>
);
}
Общая структура приложения
// app/App.tsx
import { Outlet } from 'react-router-dom';
import { Header } from '@/shared/components/Header';
import { Footer } from '@/shared/components/Footer';
export default function App() {
return (
<div className="app">
<Header />
<main>
<Outlet /> {/* Роуты здесь */}
</main>
<Footer />
</div>
);
}
// Маршруты
const routes = [
{
path: '/',
element: <App />,
children: [
{
path: '/posts',
lazy: () => import('@/features/posts/pages/PostsPage')
},
{
path: '/posts/:id',
lazy: () => import('@/features/posts/pages/PostDetailPage')
},
{
path: '/login',
lazy: () => import('@/features/auth/pages/LoginPage')
}
]
}
];
Когда масштабируется
Если проект растёт, добавляй слои:
- Domain слой: бизнес-правила, domain модели
- Application слой: use cases, сервисы
- Infrastructure слой: API, БД, кеширование
- Presentation слой: компоненты, страницы
Альтернативы и когда их использовать
1. Плоская структура (для очень маленьких проектов):
src/
components/
pages/
hooks/
styles/
Простая, но быстро становится хаотичной.
2. Слоевая архитектура (для сложных приложений):
src/
domain/ # Бизнес-логика
application/ # Use cases
infrastructure/ # API, БД
presentation/ # UI
Мощная, но может быть оверинжиниринг для новых проектов.
3. Модули по функциям (my choice):
src/
features/ # Фичи
shared/ # Переиспользуемое
app/ # Конфиг
Оптимальный баланс.
Ключевые принципы архитектуры
- SOLID: один класс — одна ответственность
- DRY: не повторяй код
- Инкапсуляция: каждый модуль независим
- Зависимости вниз: никогда вверх
- Легко тестировать: юнит-тесты без моков
Ключевые выводы
- Feature-based архитектура — лучший выбор для роста
- Послойная организация — контролирует сложность
- Типы -> Сервисы -> Компоненты — правильное направление зависимостей
- Shared и lib — для переиспользуемого кода
- Масштабируется — легко добавлять фичи и разработчиков
Эта архитектура оптимальна для 90% проектов и растёт вместе с приложением.