Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

README.md

Домашнее задание к занятию «Наследование и расширяемость систем. Проблемы наследования»

‼️ Вниманию студентов, обучающихся на QA, QAMID - 29, 31, 33, 35! Вам следует выполнять обновленное домашнее задание из репозитория по ссылке

В качестве результата пришлите ссылки на ваши GitHub-проекты в личном кабинете студента на сайте netology.ru.

Все задачи этого занятия можно делать в одном репозитории.

Важно: если у вас что-то не получилось, то оформляйте Issue по установленным правилам.

Вы можете делать все задачи этого занятия в одном репозитории (если делаете их в разных ветках).

Напоминалку по некоторым теоретическим моментам в джаве вы можете найти здесь.

Как сдавать задачи

  1. Ознакомьтесь с особенностями Lombok при использовании наследования
  2. Ознакомьтесь с доп.материалами о static и reflection
  3. Инициализируйте на своём компьютере пустой Git-репозиторий
  4. Добавьте в него готовый файл .gitignore
  5. Добавьте в этот же каталог необходимые файлы (pom.xml)
  6. Сделайте ветки для первой задачи (после того, как сделаете первую задачу, на её основе создайте ветку для второй задачи)
  7. Создайте публичный репозиторий на GitHub и свяжите свой локальный репозиторий с удалённым
  8. Сделайте пуш (удостоверьтесь, что ваш код и обе ветки появились на GitHub)
  9. Ссылку на ваш проект отправьте в личном кабинете на сайте netology.ru
  10. Задачи, отмеченные как необязательные, можно не сдавать, это не повлияет на получение зачета

Задача №1 - "Менеджер Товаров"

На основании проекта из лекции необходимо реализовать менеджер товаров, который умеет:

  1. Добавлять товары в репозиторий
  2. Искать товары

Что нужно сделать:

  1. Разработайте базовый класс Product, содержащий id, название, стоимость
  2. Разработать два унаследованных от Product класса: Book (с полями название* и автор) и Smartphone (с полями название* и производитель)
  3. Разработайте репозиторий, позволяющий сохранять Product'ы, получать все сохранённые Product'ы и удалять по id. Для этого репозиторий будет хранить у себя поле с типом Product[] (массив товаров).
  4. Разработайте менеджера, который умеет добавлять Product'ы в репозиторий и осуществлять поиск по ним. Для этого вам нужно создать класс, конструктор которого будет принимать параметром репозиторий, а также с методом publiс void add(Product product) и методом поиска (см. ниже).

Примечание*: надеемся, вы догадались, что название итак уже есть в классе Product и будет наследовано от него в классах Book и Smartphone

Как осуществлять поиск

У менеджера должен быть метод searchBy(String text), который возвращает массив найденных товаров

public class ProductManager {
  // добавьте необходимые поля, конструкторы и методы

  public Product[] searchBy(String text) {
    // ваш код
  }

  public boolean matches(Product product, String search) {
    if (product instanceof Book) { // если в параметре product лежит объект класса Book
      Book book = (Book) product; // положем его в переменную типа Book чтобы пользоваться методами класса Book
      if (book.getAuthor().contains(search)) { // проверим есть ли поисковое слово в данных об авторе
        return true;
      }
      if (book.getTitle().contains(search)) {
        return true;
      }
      return false;
    }
    ...
    return false;
  }
}

Менеджер при переборе всех продуктов, хранящихся в массиве (или в репозитории, если вы в предыдущих ДЗ сделали репозиторий)*, должен для каждого продукта вызывать определённый в классе менеджера же метод matches, который проверяет, соответствует ли продукт поисковому запросу.

Примечание*: если вы сделали репозиторий, то пусть менеджер забирает из репозитория все товары и сам уже по ним ищет.

При проверке на соответствие запросу книги мы проверяем по полям названия и автора, для смартфона по полям названия и производителя.

Подсказка
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) {
    // ваш код
  }
}

Требования к проекту:

  1. Создайте ветку (не делайте ДЗ в master!)
  2. Подключите плагин Surefire так, чтобы сборка падала в случае отсутсвия тестов
  3. Подключите плагин JaCoCo в режиме генерации отчётов (обрушать сборку по покрытию не нужно)
  4. Реализуйте нужные классы и методы
  5. Напишите автотесты на метод поиска (только на метод поиска в менеджере), добившись 100% покрытия по branch'ам* (вспомните, что мы говорили про тестирование методов, возвращающих набор значений)
  6. Подключите CI на базе Github Actions и выложите всё на Github

Примечание*: использовать Mockito или нет, мы оставляем на ваше усмотрение.

Итого: у вас должен быть репозиторий на GitHub, в котором расположен ваш Java-код в ветке (в master должен быть только pom.xml).

Задача №2 - "Менеджер Товаров" (Rich Model)*

Важно: это необязательная задача. Её (не)выполнение не влияет на получение зачёта по ДЗ.

Легенда

Достаточно часто объекты, моделирующие предметную область, называют моделями. Достаточно часто модели делают "глупыми", т.е. не содержащими никакой логики.

Но есть и другой подход, который позволяет делать "умные" или "богатые" модели (Rich Model), которые могут уже содержать определённую логику.

Что нужно сделать:

  1. Создайте новую ветку на базе ветки, в которой вы решали первую задачу
  2. Реализуйте в классе Product метод public boolean matches(String search), который определяет, подходит ли продукт поисковому запросу исходя из названия
  3. Переопределите этот метод в дочерних классах, чтобы они сначала вызывали родительский метод и только если родительский метод вернул false, тогда проводили доп.проверки (Book - по автору, Smartphone - по производителю).
  4. Уберите из менеджера все instanceof и метод matches, т.к. теперь у вас "умные" модели и благодаря переопределению методов вам этот код больше не нужен
  5. Зато теперь вам нужны unit-тесты на методы ваших умных моделей (напишите их)
  6. Удостоверьтесь, что ранее написанные тесты на менеджера (из решения задачи 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 ... ваше выражение ...;
  }
}

Но вы должны знать оба варианта.