Архитектура приложения. Вся связано делегированием, как избавиться?


#1

Здравствуйте, разрабатываю приложение диагностики автомобилей.
Вот краткая последовательность работы:

  1. Пользователь выбирает тип подключения: Bluetooth/Wi-Fi
  2. Приложение подключается к машине
  3. Приложение отправляет несколько тестовых запросов, чтобы определить протоколы общения KWP2000/UDS
  4. Протоколы общения сохраняются в Singleton
  5. Есть 4 разных экрана на которых отображаются данные автомобиля
  6. Каждый экран может получать данные по разным протоколам KWP2000/UDS

Приложение работает. Графическая часть никак не связана с кодом реализации протоколов. Я в любой момент могу добавить новый протокол или новый экран ничего не сломав. Но архитектура получилась вся на основе шаблона делегирования и протоколов.

  1. Класс EngineViewController делегирует получение данных классам EngineKWP2000 или EngineUDS.
  2. Классы EngineKWP2000 и EngineUDS занимаются только расшифровкой данных, а получение данных делегируют классам KWP2000 или UDS.
  1. Классы KWP2000 и UDS занимаются только составлением правильных команд для отправки в машину, а делегируют получение данных классу Networking.
  2. К сожалению Networking приходится делать глобальным, чтобы один объект можно было использовать на разных экранах с разными протоколами.
  3. Класс Networking создает 2 объекта: wifiCommunication или bluetoothCommunication и уже через них общается с машиной.

Получается, что в цепочке делегирования находятся 4 класса: EngineViewController -> EngineKWP2000 -> KWP2000 -> Networking

Промежуточные классы EngineKWP2000 и KWP2000 и делегируют и сами являются делегатами. Мне не нравится эта сложность, можно ли как-то упростить архитектуру?


#2

Можно


#3

С RxSwift все становится лучше. Но проект нужно будет полностью переписать. Я думал можно немного скорректировать архитектуру, а не полностью перейти на новую парадигму.


#4

Тут варианта два, или изначально закладываешь архитектуру, или переписываешь всё заново. Если у вас всё на делегатах, а переписывать вы не хотите, ну хз, пусть останется как есть, зачем напрягаться :slight_smile:


#5

Было бы очень интересно почитать про ваш опыт работы создания такого приложения. Если у вас найдется время на это.
Документацию по работе с протоколами собирали из разных мест или есть хорошая одна?


#6

Смотри, на мой взгляд следует сделать так:

  1. Пользователь собирается перейти на экран EngineVC
  2. Он обращается роутеру (Router)
  3. В Router у тебя есть Assembly
  4. Ты говоришь роутеру перейдут на 1-й, 2-й, 3-й или 4-й экран
  5. Router говорит Assembly сделай мне такой-то экран
  6. В Assembly есть методы для подготовки соответствующего экрана
  7. В этом методе подготовки экрана создаются:
  • Сервис для подготовки команд (Comands), он у тебя содержит логику подготовки команд KWP200 или UDS
  • Сервис для получения данных от машины (Networking) - Interactor
  • Presenter для взаимодействия со View - в данном случае с EngineVC
    лучше эти View закрыть протоколом и ты сможешь пользоваться одним презентером для всех 4-х экранов
  • и соответсвенно создается сам EngineVC
    Получается примерно следующее:

func makeEngineVC() -> ViewProtocol {
let comands = Comands()
let interactor = Networking(comands)
let presenter = Presenter(interactor)
let engineVC = EngineVC(presenter)
return engineVC
}

Это тебе позволяет гибко в любой момент поменять любой сервис на другой
8) Router переходит на подготовленный экран


#7

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


#8

Это же Viper? Я о нем читал, но диаграммы оставляют впечатления, что он нужен для сложных и больших проектов. Возможно у меня такой и есть.


#9

Да. Архитектуру можно строить внутри приложения разную. Все зависит от сложности реализации.
Если у Вас один экран со слайдером и вычисление чего-то в лейбл, то нет смысла городить Viper, MVVM, или еще что-то. Стандартного MVC достаточно.


#10