docs: Add comprehensive project documentation covering architecture, development, and APIs, and update AGENTS.md.
This commit is contained in:
275
docs/DEVELOPMENT.md
Normal file
275
docs/DEVELOPMENT.md
Normal file
@@ -0,0 +1,275 @@
|
||||
# 🛠 Руководство для разработчиков
|
||||
|
||||
## Локальный запуск
|
||||
|
||||
### Предварительные требования
|
||||
|
||||
- Docker и Docker Compose
|
||||
- Git
|
||||
- (Опционально) Java 17 + Maven 3.9+ для запуска backend вне Docker
|
||||
|
||||
### Первый запуск
|
||||
|
||||
```bash
|
||||
# Создать Docker-сеть
|
||||
docker network create proxy
|
||||
|
||||
# Собрать и запустить
|
||||
docker compose up -d --build
|
||||
|
||||
# Убедиться, что всё работает
|
||||
docker compose logs -f
|
||||
```
|
||||
|
||||
Приложение доступно: **http://localhost:80**
|
||||
|
||||
### Пересборка после изменений
|
||||
|
||||
```bash
|
||||
# Пересобрать только backend
|
||||
docker compose up -d --build backend
|
||||
|
||||
# Пересобрать только frontend
|
||||
docker compose up -d --build frontend
|
||||
```
|
||||
|
||||
### Полный сброс данных
|
||||
|
||||
```bash
|
||||
docker compose down -v # Удаляет БД
|
||||
docker compose up -d # Пересоздаёт с нуля
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Соглашения о коде
|
||||
|
||||
### Java (Backend)
|
||||
|
||||
#### Именование
|
||||
|
||||
| Категория | Стиль | Пример |
|
||||
|-----------|-------|--------|
|
||||
| Классы | PascalCase | `LessonsController`, `LessonResponse` |
|
||||
| Методы и переменные | camelCase | `getAllLessons()`, `teacherId` |
|
||||
| Константы | UPPER_SNAKE_CASE | `ROLE_REDIRECTS` |
|
||||
| Пакеты | lowercase | `com.magistr.app.controller` |
|
||||
|
||||
#### Архитектурные правила
|
||||
|
||||
- **Constructor Injection** — все зависимости через конструктор (не `@Autowired` на поля)
|
||||
- **Controller → Repository** — контроллеры работают напрямую с репозиториями (без слоя service)
|
||||
- **Префикс `/api/`** — все REST-эндпоинты
|
||||
- **`ResponseEntity<?>`** — все мутирующие методы возвращают `ResponseEntity` с HTTP-статусом
|
||||
- **Сообщения на русском** — все ошибки и уведомления на русском языке
|
||||
|
||||
#### Логирование
|
||||
|
||||
Используйте SLF4J:
|
||||
|
||||
```java
|
||||
private static final Logger logger = LoggerFactory.getLogger(MyController.class);
|
||||
|
||||
// Информационные сообщения
|
||||
logger.info("Запрос на получение всех занятий");
|
||||
|
||||
// Ошибки с полным стектрейсом
|
||||
logger.error("Ошибка при сохранении: {}", e.getMessage(), e);
|
||||
```
|
||||
|
||||
#### Валидация
|
||||
|
||||
- Для сложных правил — отдельные классы-валидаторы (`DayAndWeekValidator`, `TypeAndFormatLessonValidator`)
|
||||
- Для простых — inline-проверки в контроллере с `ResponseEntity.badRequest()`
|
||||
|
||||
#### Импорты
|
||||
|
||||
```java
|
||||
// 1. Static imports
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
// 2. Java/Jakarta
|
||||
import java.util.*;
|
||||
import jakarta.persistence.*;
|
||||
|
||||
// 3. External libraries
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
// 4. Internal packages (wildcard для того же модуля)
|
||||
import com.magistr.app.model.*;
|
||||
import com.magistr.app.repository.*;
|
||||
```
|
||||
|
||||
#### Форматирование
|
||||
|
||||
- **Отступы:** 4 пробела
|
||||
- **Скобки:** K&R style (открывающая на той же строке)
|
||||
- **Длина строки:** до 120 символов
|
||||
- **Фигурные скобки** обязательны для `if`/`for`/`while`
|
||||
|
||||
### JavaScript (Frontend)
|
||||
|
||||
#### Именование
|
||||
|
||||
| Категория | Стиль | Пример |
|
||||
|-----------|-------|--------|
|
||||
| Файлы | kebab-case | `main.js`, `schedule-view.js` |
|
||||
| Функции и переменные | camelCase | `loadUsers()`, `pageTitle` |
|
||||
| Константы | UPPER_SNAKE_CASE | `API_BASE_URL` |
|
||||
|
||||
#### Модули
|
||||
|
||||
- ES6 Modules с `import`/`export`
|
||||
- **Всегда указывать расширение:** `import { api } from './api.js';`
|
||||
|
||||
#### Лучшие практики
|
||||
|
||||
```javascript
|
||||
// ✅ Предпочитайте const
|
||||
const token = localStorage.getItem('token');
|
||||
|
||||
// ✅ Async/await вместо .then()
|
||||
async function loadData() {
|
||||
try {
|
||||
const data = await api.get('/api/users');
|
||||
} catch (e) {
|
||||
console.error('Ошибка:', e.message);
|
||||
}
|
||||
}
|
||||
|
||||
// ✅ Template literals
|
||||
const msg = `Найдено ${items.length} записей`;
|
||||
|
||||
// ✅ Деструктуризация
|
||||
const { id, name, role } = user;
|
||||
```
|
||||
|
||||
#### Форматирование
|
||||
|
||||
- **Отступы:** 4 пробела
|
||||
- **Кавычки:** одинарные `'`
|
||||
- **Точки с запятой:** обязательны
|
||||
|
||||
---
|
||||
|
||||
## Создание нового эндпоинта (пошагово)
|
||||
|
||||
### 1. Модель (если нужна новая таблица)
|
||||
|
||||
Создайте Flyway миграцию `V{N}__{description}.sql`:
|
||||
|
||||
```sql
|
||||
-- backend/src/main/resources/db/migration/V3__add_absences.sql
|
||||
CREATE TABLE IF NOT EXISTS absences (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
teacher_id BIGINT NOT NULL REFERENCES users(id),
|
||||
reason VARCHAR(255) NOT NULL,
|
||||
start_date DATE NOT NULL,
|
||||
end_date DATE NOT NULL
|
||||
);
|
||||
```
|
||||
|
||||
Создайте JPA-сущность:
|
||||
|
||||
```java
|
||||
@Entity
|
||||
@Table(name = "absences")
|
||||
public class Absence {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Репозиторий
|
||||
|
||||
```java
|
||||
public interface AbsenceRepository extends JpaRepository<Absence, Long> {
|
||||
List<Absence> findByTeacherId(Long teacherId);
|
||||
}
|
||||
```
|
||||
|
||||
### 3. DTO (опционально)
|
||||
|
||||
```java
|
||||
public record AbsenceResponse(Long id, String teacherName, String reason) {}
|
||||
```
|
||||
|
||||
### 4. Контроллер
|
||||
|
||||
```java
|
||||
@RestController
|
||||
@RequestMapping("/api/absences")
|
||||
public class AbsenceController {
|
||||
private final AbsenceRepository absenceRepository;
|
||||
|
||||
public AbsenceController(AbsenceRepository absenceRepository) {
|
||||
this.absenceRepository = absenceRepository;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public List<Absence> getAll() {
|
||||
return absenceRepository.findAll();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Работа с миграциями Flyway
|
||||
|
||||
### Правила
|
||||
|
||||
1. **Никогда** не изменяйте уже закоммиченные файлы миграций
|
||||
2. Имя файла: `V{номер}__{описание}.sql` (два подчёркивания!)
|
||||
3. Нумерация строго инкрементальная: `V1`, `V2`, `V3`, ...
|
||||
4. После добавления — перезапустите backend для применения
|
||||
|
||||
### Применение
|
||||
|
||||
```bash
|
||||
# Локально — сброс и повтор всех миграций
|
||||
docker compose down -v && docker compose up -d
|
||||
|
||||
# Продакшн — применить к существующим тенантам
|
||||
kubectl rollout restart deployment backend -n magistr
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Структура пакетов (Backend)
|
||||
|
||||
```
|
||||
com.magistr.app/
|
||||
├── Application.java # Точка входа
|
||||
├── config/
|
||||
│ ├── AppConfig.java # Бины (BCryptPasswordEncoder)
|
||||
│ ├── DataInitializer.java # Инициализация данных
|
||||
│ └── tenant/ # Мультитенантность
|
||||
│ ├── TenantConfig.java # POJO конфигурации тенанта
|
||||
│ ├── TenantContext.java # ThreadLocal текущего тенанта
|
||||
│ ├── TenantInterceptor.java # Определение тенанта из Host
|
||||
│ ├── TenantRoutingDataSource.java # Маршрутизация к БД
|
||||
│ ├── TenantDataSourceConfig.java # Spring-конфигурация
|
||||
│ ├── TenantConfigWatcher.java # Периодическая синхронизация
|
||||
│ └── ConfigMapUpdater.java # Обновление K8s ConfigMap
|
||||
├── controller/ # REST-контроллеры
|
||||
│ ├── AuthController.java
|
||||
│ ├── LessonsController.java
|
||||
│ ├── ClassroomController.java
|
||||
│ ├── DatabaseController.java
|
||||
│ ├── UserController.java
|
||||
│ ├── GroupController.java
|
||||
│ ├── SubjectController.java
|
||||
│ ├── EquipmentController.java
|
||||
│ ├── EducationFormController.java
|
||||
│ └── TeacherSubjectController.java
|
||||
├── dto/ # Data Transfer Objects
|
||||
├── model/ # JPA-сущности
|
||||
├── repository/ # Spring Data JPA
|
||||
└── utils/ # Валидаторы
|
||||
├── DayAndWeekValidator.java
|
||||
└── TypeAndFormatLessonValidator.java
|
||||
```
|
||||
Reference in New Issue
Block a user