From 81afad5ecd8779fbfcd9743b1a08498d65509606 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BE=D0=BB=D0=BE=D0=B4=D0=B8=D0=BD=20=D0=93=D0=B5?= =?UTF-8?q?=D1=80=D0=BC=D0=B0=D0=BD?= Date: Fri, 28 Aug 2026 22:28:12 +0400 Subject: [PATCH] docs: add composite student search task --- docs/tasks/CompositeStudentSearch.md | 455 +++++++++++++++++++++++++++ 1 file changed, 455 insertions(+) create mode 100644 docs/tasks/CompositeStudentSearch.md diff --git a/docs/tasks/CompositeStudentSearch.md b/docs/tasks/CompositeStudentSearch.md new file mode 100644 index 0000000..8ab2a72 --- /dev/null +++ b/docs/tasks/CompositeStudentSearch.md @@ -0,0 +1,455 @@ +# Техническое задание: поиск студентов с использованием паттерна Компоновщик + +## Задача + +Реализовать механизм поиска студентов по диапазону значений с использованием паттерна **Компоновщик**. + +Должны поддерживаться следующие критерии поиска: + +- диапазон `groupNumber`; +- диапазон `averageGrade`; +- диапазон `recordBookNumber`. + +Критерии должны поддерживать объединение в составной критерий. + +Режим объединения критериев — **объединение (ИЛИ)** или **пересечение (И)** — задаётся в конструкторе основного класса. + +--- + +# Названия классов и интерфейсов + +## `StudentSearchCriteria` + +Интерфейс отдельного критерия поиска. + +### Контракт + +```java +boolean matches(Student student); +``` + +Метод возвращает `true`, если студент соответствует критерию. + +--- + +## `GroupNumberRangeCriteria` + +Критерий поиска по диапазону `groupNumber`. + +### Конструктор + +```java +GroupNumberRangeCriteria(String min, String max); +``` + +### Метод + +```java +boolean matches(Student student); +``` + +`groupNumber` имеет тип `String`, поэтому сравнение выполнять лексикографически. + +Границы диапазона включаются. + +--- + +## `AverageGradeRangeCriteria` + +Критерий поиска по диапазону `averageGrade`. + +### Конструктор + +```java +AverageGradeRangeCriteria(double min, double max); +``` + +### Метод + +```java +boolean matches(Student student); +``` + +Студент соответствует критерию, если: + +```text +min <= averageGrade <= max +``` + +--- + +## `RecordBookNumberRangeCriteria` + +Критерий поиска по диапазону `recordBookNumber`. + +### Конструктор + +```java +RecordBookNumberRangeCriteria(int min, int max); +``` + +### Метод + +```java +boolean matches(Student student); +``` + +Студент соответствует критерию, если: + +```text +min <= recordBookNumber <= max +``` + +--- + +# `CompositeStudentSearchCriteria` + +Компоновщик критериев поиска. + +Класс реализует: + +```java +StudentSearchCriteria +``` + +и содержит другие реализации `StudentSearchCriteria`. + +### Методы + +```java +void add(StudentSearchCriteria criteria); +``` + +```java +void remove(StudentSearchCriteria criteria); +``` + +```java +boolean matches(Student student); +``` + +### Логика + +`CompositeStudentSearchCriteria` должен поддерживать два режима: + +```text +UNION — объединение условий, ИЛИ +INTERSECTION — пересечение условий, И +``` + +Режим должен задаваться при создании компоновщика: + +```java +CompositeStudentSearchCriteria( + SearchOperation operation +); +``` + +где `SearchOperation` — перечисление: + +```java +public enum SearchOperation { + UNION, + INTERSECTION +} +``` + +Для `UNION` студент подходит, если выполняется **хотя бы один** вложенный критерий. + +Для `INTERSECTION` студент подходит, если выполняются **все** вложенные критерии. + +--- + +# `StudentSearchService` + +Основной класс поиска. + +Он должен принимать интерфейс `StudentSearchCriteria`, а не конкретную реализацию критерия. + +### Конструктор + +```java +StudentSearchService(StudentSearchCriteria criteria); +``` + +### Метод + +```java +MyList find(MyList students); +``` + +### Поведение + +Метод `find()` должен: + +1. Последовательно проверить студентов исходной коллекции. +2. Передать каждого студента в: + +```java +criteria.matches(student) +``` + +1. Добавить подходящих студентов в новую `MyList`. +2. Вернуть новую коллекцию. + +`StudentSearchService` не должен содержать логику конкретных диапазонов или объединения критериев. + +### Обработка отсутствующего критерия + +Если `StudentSearchService` создан без критерия: + +```java +new StudentSearchService(null); +``` + +необходимо выбросить: + +```java +IllegalArgumentException +``` + +Класс не должен выполнять поиск без заданного критерия. + +--- + +# Пример использования + +### Один критерий + +```java +StudentSearchCriteria criteria = + new AverageGradeRangeCriteria(4.0, 5.0); + +StudentSearchService service = + new StudentSearchService(criteria); + +MyList result = + service.find(students); +``` + +### Пересечение критериев + +Например, студент должен одновременно: + +- находиться в группе от `A10` до `C30`; +- иметь средний балл от `4.0` до `5.0`. + +```java +CompositeStudentSearchCriteria criteria = + new CompositeStudentSearchCriteria( + SearchOperation.INTERSECTION + ); + +criteria.add( + new GroupNumberRangeCriteria("A10", "C30") +); + +criteria.add( + new AverageGradeRangeCriteria(4.0, 5.0) +); + +StudentSearchService service = + new StudentSearchService(criteria); +``` + +### Объединение критериев + +Студент должен соответствовать хотя бы одному условию: + +```java +CompositeStudentSearchCriteria criteria = + new CompositeStudentSearchCriteria( + SearchOperation.UNION + ); + +criteria.add( + new AverageGradeRangeCriteria(4.5, 5.0) +); + +criteria.add( + new RecordBookNumberRangeCriteria(10000, 20000) +); + +StudentSearchService service = + new StudentSearchService(criteria); +``` + +--- + +# Общие требования + +1. `StudentSearchService` должен работать только через `StudentSearchCriteria`. +2. `StudentSearchService` не должен знать о конкретных критериях. +3. `CompositeStudentSearchCriteria` должен реализовывать тот же интерфейс `StudentSearchCriteria`. +4. Должна поддерживаться вложенность компоновщиков. + +Например: + +```text +Composite + ├── GroupNumberRangeCriteria + └── Composite + ├── AverageGradeRangeCriteria + └── RecordBookNumberRangeCriteria +``` + +1. Исходную `MyList` не изменять. +2. Результат возвращать в виде новой `MyList`. +3. Порядок найденных студентов должен сохраняться. +4. Стандартные `List`, `ArrayList`, `LinkedList` не использовать. +5. Готовые методы поиска не использовать. +6. При отсутствии совпадений возвращать пустую `MyList`. +7. Для диапазонов `min > max` выбрасывать `IllegalArgumentException`. + +--- + +# Примеры тестов + +## `GroupNumberRangeCriteria` + +Проверить: + +- значение внутри диапазона; +- значение равное нижней границе; +- значение равное верхней границе; +- значение вне диапазона. + +## `AverageGradeRangeCriteria` + +Проверить: + +```text +3.9 → false +4.0 → true +4.5 → true +5.0 → true +5.1 → false +``` + +## `RecordBookNumberRangeCriteria` + +Проверить значения внутри и вне диапазона, включая обе границы. + +## Некорректный диапазон + +Для каждого критерия проверить: + +```text +min > max +``` + +Ожидается: + +```java +IllegalArgumentException +``` + +## `INTERSECTION` + +Создать два критерия и проверить: + +```text +критерий A = true +критерий B = true +→ true +``` + +```text +критерий A = true +критерий B = false +→ false +``` + +## `UNION` + +Проверить: + +```text +A = true +B = false +→ true +``` + +```text +A = false +B = true +→ true +``` + +```text +A = false +B = false +→ false +``` + +## Компоновщик без критериев + +Проверить поведение: + +```java +new CompositeStudentSearchCriteria( + SearchOperation.INTERSECTION +); +``` + +и: + +```java +new CompositeStudentSearchCriteria( + SearchOperation.UNION +); +``` + +Поведение должно быть явно определено и закреплено тестами. + +Рекомендуется: + +- пустое `INTERSECTION` → `true`; +- пустое `UNION` → `false`. + +## `StudentSearchService` + +Проверить: + +- корректный поиск по одному критерию; +- пустой результат; +- пустую исходную коллекцию; +- сохранение порядка; +- неизменность исходной коллекции; +- работу с `CompositeStudentSearchCriteria`. + +## Проверка вложенного Компоновщика + +Создать компоновщик с вложенным компоновщиком и проверить корректность вычисления результата. + +## Проверка отсутствующего критерия + +Создать: + +```java +new StudentSearchService(null); +``` + +Проверить `IllegalArgumentException`. + +## Результат + +Реализовать: + +```text +StudentSearchCriteria.java +GroupNumberRangeCriteria.java +AverageGradeRangeCriteria.java +RecordBookNumberRangeCriteria.java +CompositeStudentSearchCriteria.java +SearchOperation.java +StudentSearchService.java +``` + +## Git + +Название ветки: + +```text +feature/composite-student-search +```