Skip to content

Latest commit

 

History

History
322 lines (238 loc) · 22.5 KB

GENERICS.md

File metadata and controls

322 lines (238 loc) · 22.5 KB

Домашнее задание к занятию «Интерфейсы для организации малой связности. Обобщённое программирование (Generics)»

Инструкция к выполнению домашнего задания

Перед тем как отправить своё решение на проверку преподавателю, сверьтесь с чеклистом.

1. В решении выполнены все требования задания

Убедитесь, что все требования задания выполнены. Для этого перед отправкой внимательно прочтите весь текст условия задания и соотнесите сказанное в нём с вашим решением. Навык самопроверки работы перед ревью пригодится вам как при обучении, так и на работе.


2. Правильно настроен Maven-проект, тесты проходят

Репозиторий должен быть папкой вашего Мавен-проекта. Обратите внимание, что репозиторием не должна быть папка, в которой лежит папка Мавен-проекта, он сам должен быть папкой проекта. В нём должны быть соответствующие файлы и папки — pom.xml, src и другие.

Не забудьте создать .gitignore-файл в корне проекта и добавить туда в игнорирование автогенерируемую папку target.

Общая схема вашего pom.xml-файла:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>ru.netology</groupId>
  <artifactId>НАЗВАНИЕ-ВАШЕГО-ПРОЕКТА-БЕЗ-ПРОБЕЛОВ</artifactId>
  <version>1.0-SNAPSHOT</version>

  <properties>
      <maven.compiler.source>11</maven.compiler.source>
      <maven.compiler.target>11</maven.compiler.target>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>


  <dependencies>
      <dependency>
          ...
      </dependency>
      ...
  </dependencies>


  <build>
      <plugins>
          <plugin>
            ...
          </plugin>

          <plugin>
            ...
            <executions>
              <execution>
                ...
              </execution>
              ...
            </executions>
          </plugin>
          ...
      </plugins>
  </build>

</project>

JUnit

Обратите внимание, что у артефакта нет -api на конце. Если у вас автоматически добавилась зависимость вида <artifactId>junit-jupiter-api</artifactId>, то лучше поменять артефакт на тот, что ниже, иначе будут сюрпризы в работе.

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.7.0</version>
            <scope>test</scope>
        </dependency>

Surefire

Без этого плагина тесты могут Мавеном не запускаться, хоть в идее через кнопки они и будут проходить. Чтобы лишний раз убедиться, что всё работает, нажмите Ctrl+Ctrl и затем mvn clean test.

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.2</version>
                <configuration>
                    <failIfNoTests>true</failIfNoTests>
                </configuration>
            </plugin>

3. Что делать, если возникли сложности

Это здорово. Если их преодолевать правильно, то можно получить большую образовательную пользу для себя. Периодическое возникновение вопросов, недопонимание пройденного материала — нормальная и неотъемлемая часть обучения. А мы здесь, чтобы помочь вам пройти этот путь.

Что делать, если непонятна теория

  1. Если подобный вопрос разбирался на лекции, посмотрите ещё раз раздел с этой темой в видеозаписи.
  2. Если вопрос не решился, попробуйте поискать ответ самостоятельно в интернете, этот навык пригодится вам в работе.
  3. Если самостоятельно разобраться не удалось, задайте вопрос в общем чате, мы обязательно поможем.

Что делать, если непонятно условие задания

  1. Прежде чем задать вопрос по условию задачи, перечитайте его ещё раз и убедитесь, что в тексте условия нет прямого ответа на этот вопрос. Умение работать с текстом — важный навык работы с информацией.
  2. Если ответа на свой вопрос в тексте условия не увидели, задайте его в общем чате, мы раскроем детали условия.

Что делать, если не получается задача

Если ваша проблема — это ошибка компиляции — подчёркивает красным, не даёт запустить программу, сборки проекта, CI и прочие подобные ошибки, то:

  1. Найдите и прочитайте текст ошибки, который вам подсвечивает идея или логи. «Подчёркивает красным» — это не описание ошибки.
  2. Попробуйте понять текст ошибки, при необходимости воспользуйтесь переводчиком. Не страшно, если вы переведёте неточно, тут главное — сам процесс: со временем и с нашей помощью вы будете это делать лучше и лучше, но, пропуская этот этап, вы не сможете научиться это делать.
  3. Если не получилось понять ошибку по её тексту, попробуйте её загуглить и изучить подобную ошибку у других людей. Попробуйте примерить решения их проблем на свой код. Соотнесите найденные описания ошибки с пройденной теорией.
  4. Если всё равно ваши трудности не разрешились, напишите в общий чат, обязательно указав:
    1. название задачи и ссылку на условие;
    2. ссылку на вашу работу;
    3. текст и скриншот, не фотографию, ошибки;
    4. ваши размышления и описание шагов, которые вы совершили для решения.

Если ваша проблема — это ошибка исполнения, программа умирает уже после запуска, или она отрабатывает неправильно, из-за чего ваши тесты не проходят, то:

  1. Воспользуйтесь отладчиком для пошагового анализа работы вашей программы. Так вы или убедитесь в неправильности придуманного вами алгоритма, или найдёте конкретное место, где ожидаемое поведение программы разошлось с фактическим.
  2. Если проблему найти не получилось, напишите в общий чат, обязательно указав:
    1. название задачи и ссылку на условие;
    2. ссылку на вашу работу;
    3. конкретное и подробное описание проблемы или затруднения при решении задачи. «Помогите, что-то не так» — это не описание;
    4. подробное описание вашего анализа программы с помощью отладчика вместе со скринами;
    5. ваши размышления и описание шагов, которые вы совершили для решения.

4. Отформатирован код

Кроме правил, нарушение которых приводит к ошибкам компиляции, есть ещё и правила форматирования кода, соблюдение которых обязательно при написании программ.

С большинством проблем может справиться автоформатирование в идее. Для этого выберите Code -> Reformat code в меню или используйте горячие сочетания клавиш. В меню будет показано актуальное сочетание для вашей операционной системы. Так, идея поправит неправильные отступы, пробелы и некоторые другие ошибки. Следите, чтобы у if-else, for, while всегда были {}.

Проблемы с именованием сущностей нужно решать самим. Так, все ячейки, кроме final-констант, и методы должны писаться камелкейсом с маленькой буквы, а классы и интерфейсы — камелкейсом с большой буквы.

Мы вам настоятельно советуем всегда держать код в отформатированном виде во время разработки, со временем глаз привыкнет, и вы почувствуете, насколько это облегчает поиск ошибок в коде и его анализ. В любом случае перед отправкой кода на проверку его обязательно нужно отформатировать, иначе он может быть отправлен на доработку без более глубокой проверки на этой итерации.

5. Настроен Github CI с verify-сборкой Maven и JaCoCo в режиме генерации отчётов с покрытием на 100% по бранчам методов с логикой [:warning:: в этом задании можно не покрывать на 100%]

CI

После связывания локального репозитория с удалённым и первого пуша в заготовки проекта, время настроить CI на основе GitHub Actions. Шаблон вашего maven.yml должен выглядеть вот так, убедитесь, что всё совпадает с вашим шаблоном, например, что вы указали фазу verify, а не package:

name: Java CI with Maven

on: [push, pull_request]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: Set up JDK 11
      uses: actions/setup-java@v2
      with:
        java-version: '11'
        distribution: 'adopt'
    - name: Build with Maven
      run: mvn -B -e verify

JaCoCo

            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>0.8.5</version>
                ...

Инициализация:

                    <execution>
                        <id>prepare-agent</id>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                    </execution>

В режиме генерации отчётов:

                    <execution>
                        <id>report</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>report</goal>
                        </goals>
                    </execution>

В режиме проверки и обрушения сборки по уровню покрытия:

                    <execution>
                        <id>check</id>
                        <goals>
                            <goal>check</goal>
                        </goals>
                        <configuration>
                            <rules>
                                <rule>
                                    <limits>
                                        <limit>
                                            <counter>LINE</counter>
                                            <value>COVEREDRATIO</value>
                                            <minimum>100%</minimum>
                                        </limit>
                                    </limits>
                                </rule>
                            </rules>
                        </configuration>
                    </execution>

Задание 1. Поиск билетов (обязательное к выполнению)

Вы работаете в сервисе по продаже авиабилетов онлайн.

image

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

  1. Спроектируйте класс для информации о билете.
  2. Реализуйте репозиторий для хранения информации о билетах: добавить, удалить, получить набор билетов.
  3. Реализуйте менеджера поиска по аэропорту вылета и аэропорту прилёта, даты не учитывайте.

Информация о билете

Класс информации о билете — это data-класс, который должен содержать:

  1. ID.
  2. Стоимость, для упрощения будем считать стоимость единой для всех продавцов.
  3. Аэропорт вылета, вы можете использовать IATA-коды.
  4. Аэропорт прилёта, вы можете использовать IATA-коды.
  5. Время в пути в минутах.

Других данных не нужно.

Этот класс должен реализовывать интерфейс Comparable<...> так, чтобы по умолчанию сортировка происходила по цене, самый дешёвый — самый первый. Для этого шапка вашего дата-класса должна выглядеть как-то так:

public class Ticket implements Comparable<Ticket> {

После чего идея подсветит вам её красным, нажмите на подсказку и выберите «Implement methods» — «Реализовать методы». Идея сама сгенерирует заглушку для нужного метода из этого интерфейса, которая всегда возвращает 0. Вам надо переписать тело сгенерированного метода, чтобы если билет, у которого вызвали метод compareTo, стоит дешевле, чем тот, который передали через параметр, то возвращалось бы число меньше нуля. Если же билет, наоборот, дороже, то число больше нуля, а если стоимость одинакова, то 0. Дав верную реализацию этому методу, вы научите Java сравнивать объекты этого класса.

Репозиторий

Репозиторий для хранения билетов ничем не отличается от тех репозиториев, что мы проходили раньше.

Менеджер

В менеджере методов findAll должен претерпеть некоторые изменения — он должен принимать два параметра:

  • from — аэропорта вылета,
  • to — аэропорт прилёта.

Значит, в результате поиска возвращается массив только с теми билетами, что соответствуют условиям поиска. Методы поиска вы уже делать умеете.

Кроме того, результаты должны быть отсортированы по цене от меньшей к большей.

Автотесты

Напишите автотесты на поиск, удостоверившись, что он удовлетворяет условиям задачи. Количество тестов и тестируемые сценарии мы оставляем на ваше усмотрение.

Итого: у вас должен быть репозиторий на GitHub, в котором расположен ваш Java-код и автотесты к нему, GitHub Actions и т. д. — всё как обычно.

Отправьте на проверку ссылку на репозиторий GitHub с вашим проектом.

Задание 2*. Самый быстрый (необязательная задача)

Иногда необходима сортировка не только по цене, но и, например, по времени — люди хотят найти самый быстрый перелёт.

Естественно, ваш сервис идёт навстречу пожеланиям клиентов и решает добавить такую возможность.

Но как мы это сделаем, ведь наши билеты уже сортируются по цене.

Comparator

Помимо интерфейса Comparable, который определяет порядок сортировки объектов данного класса по умолчанию, у нас есть интерфейс Comparator, который позволяет создавать объекты, определяющие порядок сортировки других объектов.

Как это выглядит, мы покажем на примере сортировки по цене по возрастанию — аналог, который реализован вами в первой задаче:

public class TicketByPriceAscComparator implements Comparator<Ticket> {
  public int compare(Ticket o1, Ticket o2) {
    return o1.getPrice() - o2.getPrice();
  }
}

Обратите внимание: это отдельный специальный класс, который умеет сравнивать два объекта типа «Билет».

Логика интерпретации возвращаемого из метода compare значения аналогична логике compareTo.

В отдельной ветке fast того же репозитория улучшите сервис, создав метод findAll(String from, String to, Comparator<Ticket> comparator).

Этот метод делает всё то же самое, что и обычный findAll из первой задачи, но сортирует не методом Arrays.sort(result), а Arrays.sort(result, comparator).

Таким образом, вы сможете передавать в этот метод объект любого класса, реализующего интерфейс Comparator<Ticket>.

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

Если автотесты в ветке проходят — делаете Pull Request на слияние в основную ветку. Сливать не нужно.

Результат

При отправке решения в личном кабинете прикрепите ссылку на ваш публичный репозиторий GitHub с вашим проектом.