docs: replace data source task with csv student io task
This commit is contained in:
@@ -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
|
||||
```
|
||||
Reference in New Issue
Block a user