Моделирование DataSource. Часть 2.

Некоторое время назад была опубликована статья на тему моделирования DataSource.
Ниже представлено продолжение, а если быть точнее, то развитие идеи, исключение недостатков, присущих предыдущему варианту, и в конечном итоге будет предложен подход, имеющий место в реальной практике разработки приложений для iOS.
Упаковка в библиотеку
Решение, предложенное ранее не представлялось возможным переиспользовать. Другими словами, разработчику приходилось копировать довольно объемную часть кода каждый раз, когда нужно было моделировать dataSource. Единственная причина существования такого недостатка — это использование перечислений Section.Kind и Row.Kind, поскольку swift не позволяет добавлять case’ы к перечислению из extension.
Также нужно обратить внимание на еще один недостаток — полностью одинаковая реализация Section.Kind и Row.Kind. А дублирование кода следует избегать.
Решением будет использование структуры Kind и статических констант вместо перечисления Kind и case'ов. Также при выводе в консоль необходим читаемый текст, описывающий константу. Поэтому требуется реализовать протоколы RawRepresentable, ExpressibleByStringLiteral, CustomStringConvertible.
В результате, по необходимости можно создавать любое количество констант, используя контроль доступа.
Моделирование секции UITableView и UICollectionView
Структура IndexPath содержит вспомогательные свойства для того, чтобы синтаксис был читаемым как в случае UITableView (indexPath.row), так и в случае UICollectionView (indexPath.item). Поэтому структуру Section следует проектировать с учетом моделирования данных UICollectionView.
Не стоит забывать о выводимом тексте в консоль. Разработчику незачем знать UUID секции, в то время как тип (kind) и элементы секции (rows/items) являются более ценной информацией.
Редактирование элементов секции
В повседневной практике наверняка потребуется удалять, добавлять, менять местами и т.д. элементы секции. Те же самые операции применимы и в отношении самих секций. И поскольку модель — это массив секций, а секция — это массив элементов секции, требуется полный набор методов редактирования, который предоставляет стандартная библиотека для массива.
Одним из возможных решений является объявление структуры Items, которая реализует RandomAccessCollection, MutableCollection, RangeReplaceableCollection, и по-сути является массивом элементов секции — структур Item.
Важно отметить, что DiffableDataSource использует значение hash для оперирования и при неуникальности этого значения приложение успешно crash’ится. Это главная причина, по которой объявлена структура Item, а свойство data объявлено с уровнем доступа private(set).
Создание DiffableDataSource.
Редактирование модели.
Редактирование сеций
В коде, представленном выше можно заметить конструкции вида
1. sections[.contacts]...2. ...firstIndex(of: .addContact)
- Subscript, который возвращает Section структуру, с указанным типом (kind). Естественно, если такая есть в массиве.
- Метод, который возвращает индекс секции, с указанным типом. Также, если такая есть в массиве.
Все это, конечно, синтаксический сахар, однако его наличие упрощает процесс разработки.
Заключение
В итоге у разработчика под рукой библиотека под названием DataSource, включающая Kind, Section, SectionItem и SectionProtocol, представленные выше.
Очевидно, что код становится намного понятнее. А если сравнивать с хардкодированными данными — небо и змеля.
К сожалению, в настоящий момент Swift не предлагает решений для кастомизации вывода в лог коллекций,
поэтому отступы получились не самыми лучшими. Тем не менее вывод читаемый.

Итак, весь API, разработанный и предложенный в предыдущей статье сохранен и даже расширен. Значительно сокращено дублирование кода, появилась возможность распространения решения в виде отдельного модуля, будь то package, pod или framework.
Желаю вам прекрасного настроения. На этом у меня все.