В качестве результата пришлите ссылки на ваши GitHub-проекты в личном кабинете студента на сайте netology.ru.
Все задачи этого занятия можно делать в одном репозитории.
Важно: если у вас что-то не получилось, то оформляйте Issue по установленным правилам.
Вы можете делать все задачи этого занятия в одном репозитории (если делаете их в разных ветках).
- Ознакомьтесь с особенностями Lombok при использовании наследования
- Ознакомьтесь с доп.материалами о
static
иreflection
- Инициализируйте на своём компьютере пустой Git-репозиторий
- Добавьте в него готовый файл .gitignore
- Добавьте в этот же каталог необходимые файлы (
pom.xml
) - Сделайте ветки для первой задачи (после того, как сделаете первую задачу, на её основе создайте ветку для второй задачи)
- Создайте публичный репозиторий на GitHub и свяжите свой локальный репозиторий с удалённым
- Сделайте пуш (удостоверьтесь, что ваш код и обе ветки появились на GitHub)
- Ссылку на ваш проект отправьте в личном кабинете на сайте netology.ru
- Задачи, отмеченные как необязательные, можно не сдавать, это не повлияет на получение зачета (в этом ДЗ все задачи являются обязательными)
На основании проекта из лекции необходимо реализовать менеджер товаров, который умеет:
- Добавлять товары в репозиторий
- Искать товары (репозиторий должен отдать все товары, а менеджер уже потом по ним ищет*)
Примечание*: это не самый эффективный способ. Когда мы будем проходить базы данных, поговорим, что это лучше делать там (ещё лучше - воспользоваться специализированным решением).
Что нужно сделать:
- Разработайте базовый класс
Product
, содержащийid
, название, стоимость - Разработать два унаследованных от
Product
класса:Book
(с полями название* и автор) иSmartphone
(с полями название* и производитель) - Разработайте репозиторий, позволяющий сохранять
Product
'ы, получать все сохранённыеProduct
'ы и удалять поid
- Разработайте менеджера, который умеет добавлять
Product
'ы в репозиторий и осуществлять поиск по ним
Примечание*: надеемся, вы догадались, что название итак уже есть в классе Product
У менеджера должен быть метод searchBy(String text)
, который возвращает массив найденных товаров
public class ProductManager {
// добавьте необходимые поля, конструкторы и методы
public Product[] searchBy(String text) {
// ваш код
}
public boolean matches(Product product, String search) {
// ваш код
}
}
Менеджер при переборе всех продуктов, хранящихся в репозитории, должен для каждого продукта вызывать собственный метод matches
, который проверяет, соответствует ли продукт поисковому запросу.
Проверку соответствия проводится с помощью instanceof
- для книги по полям название и автор, для смартфона по полям название и производитель.
Пример того, как это можно сделать:
if (product instanceof Book) {
Book book = (Book) product;
if (book.getName().equalsIgnoreCase(search)) {
return true;
}
if (book.getAuthor().equalsIgnoreCase(search)) {
return true;
}
return false;
}
Q: Откуда взять информацию о методе equalsIgnoreCase
?
A: Вам нужно посмотреть документацию на класс String
* (ведь book.getName()
возвращает объект класса String
) и подобрать необходимые методы (на ваше усмотрение). Это очень важно: знать какие классы есть в стандартной библиотеки и какие методы они предоставляют!
Примечание*: воспринимайте пока CharSequence
как String
.
Подсказка
public class ProductManager {
// добавьте необходимые поля, конструкторы и методы
public Product[] searcyBy(String text) {
Product[] result = new Product[0];
for (Product product: repository.findAll()) {
if (matches(product, text)) {
Product[] tmp = new Product[result.length + 1];
// используйте System.arraycopy, чтобы скопировать всё из result в tmp
tmp[tmp.length - 1] = product;
result = tmp;
}
}
return result;
}
public boolean matches(Product product, String search) {
// ваш код
}
}
Требования к проекту:
- Создайте ветку (не делайте ДЗ в
master
!) - Подключите плагин Surefire так, чтобы сборка падала в случае отсутсвия тестов
- Подключите плагин JaCoCo в режиме генерации отчётов (обрушать сборку по покрытию не нужно)
- Реализуйте нужные классы и методы
- Напишите автотесты на метод поиска (только на метод поиска в менеджере), добившись 100% покрытия по branch'ам* (вспомните, что мы говорили про тестирование методов, возвращающих набор значений)
- Подключите CI на базе Github Actions и выложите всё на Github
Примечание*: использовать Mockito или нет, мы оставляем на ваше усмотрение.
Итого: у вас должен быть репозиторий на GitHub, в котором расположен ваш Java-код в ветке (в master
должен быть только pom.xml
).
Достаточно часто объекты, моделирующие предметную область, называют моделями. Достаточно часто модели делают "глупыми", т.е. не содержащими никакой логики.
Но есть и другой подход, который позволяет делать "умные" или "богатые" модели (Rich Model), которые могут уже содержать определённую логику.
Что нужно сделать:
- Создайте новую ветку на базе ветки, в которой вы решали первую задачу
- Реализуйте в классе
Product
методpublic boolean matches(String search)
, который определяет, подходит ли продукт поисковому запросу исходя из названия - Переопределите этот метод в дочерних классах, чтобы они сначала вызывали родительский метод и только если родительский метод вернул
false
, тогда проводили доп.проверки (Book
- по автору,Smartphone
- по производителю). - Уберите из менеджера все
instanceof
и методmatches
, т.к. теперь у вас "умные" модели и благодаря переопределению методов вам этот код больше не нужен - Зато теперь вам нужны unit-тесты на методы ваших умных моделей (напишите их)
- Удостоверьтесь, что ранее написанные тесты на менеджера (из решения задачи 1) проходят
Итого: у вас должен быть репозиторий на GitHub, в котором расположен ваш Java-код в двух ветках (в master
должен быть только pom.xml
).
Подсказка №1
public class ProductManager {
// добавьте необходимые поля, конструкторы и методы
public Product[] searcyBy(String text) {
Product[] result = new Product[0];
for (Product product: repository.findAll()) {
if (product.matches(text)) {
Product[] tmp = new Product[result.length + 1];
// используйте System.arraycopy, чтобы скопировать всё из result в tmp
tmp[tmp.length - 1] = product;
result = tmp;
}
}
return result;
}
}
Подсказка №2 (про оператор ||)
У нас есть замечательный логический оператор ||
, который работает следующим образом: вычисляет правую часть выражения только в случае, если левая равна false
public class Book {
// ваши поля, конструкторы, методы
public boolean matches(String search) {
return super.matches(search) || ... ваше выражение ...;
}
}
Никто не говорит, что этот вариант лучше вот этого (наоборт, этот легче тестировать и отлаживать):
public class Book {
// ваши поля, конструкторы, методы
public boolean matches(String search) {
if (super.matches(search)) {
return true;
}
return ... ваше выражение ...;
}
}
Но вы должны знать оба варианта.