docs: replace data source task with csv student io task

This commit is contained in:
2026-08-28 21:10:13 +04:00
parent 1fe77ef1b3
commit c8c9c05a65
3 changed files with 324 additions and 480 deletions
+324
View File
@@ -0,0 +1,324 @@
# Техническое задание: чтение и дозапись `Student` в CSV
## Задача
Реализовать два независимых класса для работы с объектами `Student` в формате CSV:
- `StudentCsvWriter` — дозапись студентов в файл;
- `StudentCsvReader` — последовательное чтение студентов из файла.
Для работы с форматом CSV использовать готовую библиотеку для работы с CSV. Самостоятельно реализовывать парсинг CSV запрещено.
Оба класса должны принимать **абсолютный путь к файлу**.
Исключения `Student` и `StudentBuilder` не обрабатывать.
---
# Формат CSV-файла
Первая строка файла должна содержать заголовок:
```text
groupNumber,averageGrade,recordBookNumber
```
Каждая следующая строка содержит данные одного студента:
```text
groupNumber,averageGrade,recordBookNumber
```
Пример:
```text
groupNumber,averageGrade,recordBookNumber
A12,4.5,10001
B07,3.8,10002
C25,4.9,10003
```
Для формирования и чтения CSV использовать стандартную библиотеку для работы с форматом CSV.
---
# `StudentCsvWriter`
## Назначение
Дозаписывать одного студента в указанный CSV-файл.
## Контракт
Конструктор:
```java
public StudentCsvWriter(String absoluteFilePath)
```
Метод:
```java
public void write(Student student) throws IOException
```
### Требования
1. Метод принимает одного `Student`.
2. Запись выполняется в режиме добавления.
3. Существующие записи не изменяются.
4. Если файл существует, заголовок повторно не записывается.
5. Если файл не существует, необходимо создать файл.
6. При создании нового файла имя должно соответствовать формату:
```text
students-yyyy-MM-dd-HH-mm.csv
```
Например:
```text
students-2026-08-28-20-45.csv
```
1. Новый файл создаётся в директории, указанной абсолютным путём.
2. При создании нового файла сначала записывается заголовок.
3. При успешной записи метод завершается без исключения.
4. Метод не возвращает значение.
5. Исключения, связанные с записью файла, не обрабатывать внутри метода — они должны передаваться вызывающему коду.
6. Исключения `Student` и `StudentBuilder` также не обрабатывать.
## Невозможность записи
Если студент не может быть записан, например:
- отсутствуют права на запись;
- невозможно создать файл;
- файл недоступен;
- произошла ошибка файловой системы;
метод должен выбросить соответствующее исключение, например `IOException`.
Запись не должна возвращать специальное значение вроде `0` для обозначения ошибки.
---
# `StudentCsvReader`
## Назначение
Последовательно читать студентов из CSV-файла.
## Контракт
Класс должен реализовывать:
```java
Iterator<Student>
```
Конструктор:
```java
public StudentCsvReader(String absoluteFilePath)
```
Методы:
```java
@Override
public boolean hasNext()
```
```java
@Override
public Student next()
```
### Требования к `hasNext()`
1. Проверяет наличие следующей записи `Student`.
2. Заголовок CSV не считается записью.
3. Повторный вызов `hasNext()` не должен пропускать следующую запись.
4. После окончания файла метод возвращает `false`.
### Требования к `next()`
1. Возвращает следующего `Student`.
2. `Student` создаётся через существующий `StudentBuilder`.
3. При отсутствии следующего элемента выбрасывается:
```text
NoSuchElementException
```
1. Весь файл не должен предварительно загружаться в коллекцию.
## Невозможность прочитать студента
Если следующую запись невозможно прочитать или преобразовать в `Student`, например:
- некорректный формат CSV;
- отсутствует обязательное поле;
- значение невозможно преобразовать в нужный тип;
- данные не проходят валидацию `Student`;
исключение должно передаваться вызывающему коду.
Исключения `Student` и `StudentBuilder` **не перехватывать и не обрабатывать**.
Некорректные записи не должны молча пропускаться.
---
# Общие требования
1. Оба класса принимают абсолютный путь к файлу.
2. Использовать готовую библиотеку для работы с CSV.
3. Не реализовывать собственный CSV-парсер.
4. Не использовать стандартные коллекции Java как основное хранилище студентов.
5. Не дублировать в этих классах валидацию `Student`.
6. Не дублировать логику создания `Student` вне `StudentBuilder`.
7. `StudentCsvWriter` отвечает только за запись.
8. `StudentCsvReader` отвечает только за чтение.
---
# Примеры тестов
## `StudentCsvWriter`
### Создание нового файла
Передать путь к несуществующему файлу и вызвать:
```java
writer.write(student);
```
Проверить:
- файл создан;
- имя соответствует `students-yyyy-MM-dd-HH-mm.csv`;
- присутствует заголовок;
- студент записан;
- метод завершился без исключения.
### Дозапись
Создать файл с одним студентом и выполнить:
```java
writer.write(student2);
```
Проверить, что:
- первая запись сохранилась;
- `student2` добавлен в конец;
- заголовок присутствует только один раз.
### Несколько последовательных записей
```java
writer.write(student1);
writer.write(student2);
writer.write(student3);
```
Проверить наличие трёх записей в правильном порядке.
### Невозможность записи
Передать путь, по которому невозможно создать или открыть файл для записи.
Проверить, что `write()` выбрасывает `IOException`.
Не проверять специальное возвращаемое значение — метод ничего не возвращает.
---
## `StudentCsvReader`
### Чтение корректного файла
Для файла:
```text
groupNumber,averageGrade,recordBookNumber
A12,4.5,10001
B07,3.8,10002
C25,4.9,10003
```
Проверить:
- `hasNext()` возвращает `true` до последнего студента;
- `next()` возвращает студентов в правильном порядке;
- после последнего студента `hasNext()` возвращает `false`.
### Повторный вызов `hasNext()`
```java
reader.hasNext();
reader.hasNext();
Student student = reader.next();
```
Проверить, что первый студент не был пропущен.
### `next()` после окончания файла
После чтения всех студентов вызвать:
```java
reader.next();
```
Проверить выброс:
```text
NoSuchElementException
```
### Некорректная запись
Передать файл:
```text
groupNumber,averageGrade,recordBookNumber
A12,4.5,10001
INVALID
C25,4.9,10003
```
Проверить, что ошибка при чтении некорректной записи передаётся вызывающему коду.
### Некорректные данные `Student`
Передать данные, нарушающие ограничения `Student`.
Проверить, что исключение от `Student` или `StudentBuilder` выходит наружу и не перехватывается `StudentCsvReader`.
---
# Названия файлов
```text
StudentCsvWriter.java
StudentCsvReader.java
```
# Git
Название ветки:
```text
feature/csv-student-io
```
Conventional Commit:
```text
feat: add csv student reader and writer
```