Реализация хранилища

Реализация хранилища #

Доработайте приложение для работы с треугольниками так, чтобы оно использовало хранилище для хранения данных. Хранилищу следует использовать структурированный формат хранения, JSON или другой стандарт, при сохранении их на жёсткий диск.

Для сохранении информации о конкретном треугольнике следует сохранять только стороны треугольника, т.е. минимально необходимую информацию.

Краткий подход к реализации #

Создание хранилища #

  1. Убедитесь, что в конфигурации сборки приложения, build.gradle, указана зависимость от модуля сериализации данных в JSON. implementation group: "org.http4k", name: "http4k-format-jackson", version: "4.25.8.0". Версия зависимости должна совпадать с версиями других компонентов http4k.
  2. Создайте класс хранилища, Store. Он определяется путём к JSON-документу на жёстком диске.
  3. В классе определите метод для сохранения данных. Метод должен формировать JSON-строку и записывать её в файл. В настоящий момент добавьте туда корневой элемент — пустой JSON-объект.
  4. В классе Store создайте поле saveStore, в котором разместите объект потока Thread. Используйте метод thread, предоставляемый стандартной библиотекой языка Kotlin.
    1. Данный поток не должен запускаться автоматически.
    2. Внутри блока, определяющего работу потока, вызовите метод сохранения.
  5. Создайте объект класса Store в функции main. Добавьте вызов потока сохранения хранилища с помощью метода addShutdownHook класса Runtime.
  6. Запустите и остановите приложение. Если вы всё сделали корректно, то при остановке приложения JSON-документ на жёстком диске должен быть создан.

Описание репозитория треугольников #

  1. Создайте класс TriangleRepository в рамках пакета domain. Данный класс должен:
    1. Инициализироваться списком треугольников.
    2. Предоставлять метод asJsonObject или toJson, которые будут предоставлять данные в формате классов, описывающих узлы JsonNode.
  2. Метод JsonNode должен возвращать следующую структуру данных в виде Json элементов:
    {
     "counter": 1,
     "triangles": []
    }
  3. Создайте объект репозитория треугольников в качестве свойства класса хранилища.
  4. Используйте созданный метод по преобразованию репозитория треугольника в объект JsonNode. Сохраните результат внутри объекта с ключом triangles.
  5. Запустите и остановите приложение.
  6. В выходном файле должен быть сохранён документ со следующим содержимым:
    {
     "triangles": {
         "counter": 1,
         "triangles": []
     }
    }

Сериализация треугольника #

  1. В классе треугольник добавьте метод по его преобразованию в объект JsonNode.
  2. Данный метод должен сохранять длины всех сторон. Предлагается следующая структура:
    {
     "sideA": 15.5,
     "sideB": 10.0,
     "sideC": 13.5
    }
  3. Используйте данный метод при формировании JSON-документа, описывающего состояние репозитория. Сохраняйте узлы, описывающие треугольники, внутри массива triangles.
  4. Инициализируйте репозиторий при создании списком треугольников. Достаточно добавить пару треугольников.
  5. Выполните запуск и остановку приложения.
  6. В выходном файле, описывающим состояние, должно быть следующая структура:
    {
     "triangles": {
         "counter": 1,
         "triangles": [
             { "sideA": 3, "sideB": 4, "sideC": 5 },
             { "sideA": 10, "sideB": 10, "sideC": 3 }
         ]
     }
    }

Уникальная идентификация треугольника #

  1. В классе треугольник добавьте поле id: Int, которое должно быть уникальным среди всех треугольников внутри репозитория.
  2. Внутри репозитория треугольников организуйте хранение данных в изменяемом словаре (MutableMap), в котором ключами являются идентификаторы треугольников, а значением являются объекты треугольника. Изначальный список можно преобразовать к словарю с помощью функции associateBy.
  3. В рамках репозитория необходимо обеспечить инициализацию поля counter таким образом, чтобы оно содержало следующее значение идентификатора. Возможно реализовать стратегию двумя способами:
    1. Передать корректное значение в качестве аргумента репозиторию.
    2. Вычислить на основании переданных данных.
  4. При добавлении нового элемента в репозиторий необходимо обеспечить проверку уникальности добавляемых элементов по идентификатору. Возможны следующие стратегии:
    1. Выбрасывание исключения при добавлении элемента.
    2. Установление уникального идентификатора при добавлении нового элемента. В рамках данного подхода необходимо взять очередное значение из счётчика, поля counter, и использовать его при добавлении в словарь треугольников.
  5. Реализуйте функцию по добавлению нового элемента в репозиторий треугольников.

Выполнение запроса к репозиторию #

  1. В репозитории реализуйте метод для получения подмножества треугольников в зависимости от страницы. Функция должна принимать в качестве аргумента номер страницы и возвращать список из треугольников, удовлетворяющий запросу.
    1. Если номер страницы не входит в допустимые границы, то необходимо возвращать пустой список.
    2. Обратите внимание на последнюю страницу - в ней скорее всего недостаточно элементов для заполнения всей страницы.
  2. В репозитории реализуйте метод для получения треугольника по идентификатору.
  3. Используйте созданные методы репозитория в обработчиках запроса от пользователя.
  4. Удостоверьтесь, что после завершения работы приложения в JSON-документе сохраняются все данные из хранилища.

Инициализация хранилища из JSON-документа #

  1. В рамках хранилища реализуйте функцию, которая будет производить загрузку данных из JSON-документа на файловой системе. Данная функция должна считывать весь текст из документа и преобразовывать его к объектам JsonNode с помощью метода parse.
  2. Полученный объект верхнего уровня необходимо разобрать внутри хранилища и передать извлечённое значение поля triangles в функцию-инициализатор репозитория.
  3. У репозитория следует объявить вспомогательный объект, companion object, который будет содержать функцию инициализации из JSON-объекта.
  4. Такую же функцию следует реализовать и во вспомогательном объекте класса треугольника.
  5. Вызовите функцию инициализации хранилища при создании объекта хранилища или из функции main.
  6. Убедитесь, что при запуске приложения происходит чтение данных из JSON-объекта.

Соответствие кода статическому анализу #

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

© A. M. Васильев, 2022, CC BY-SA 4.0, andrey@crafted.su