vsklamm / CppQuiz

Android app for cppquiz.org with the offline mode and other features
http://cppquiz.org/
GNU General Public License v3.0
6 stars 2 forks source link

Add Quiz Mode #5

Open vsklamm opened 5 years ago

vsklamm commented 5 years ago

Как без плохого кода добавить Quiz mode? Сейчас логика игры в singleton-классе GameLogic.

Для получения следующего вопроса, ответа пользователя, подсказки вызываются методы GameLogic, которые вызывают соответствующие(возможно, несколько) callbacks

В Quiz mode эти методы должны иметь несколько другой функционал ввиду другой логики "игры". Отличаются также изменения активити(callbacks). Кнопочки все те же

Пока представляю смену mode как переключатель-метод. Вызовы GameLogic методов остаются на месте, но меняется их функционал в зависимости от режима игры. В общем хз((

Какой паттерн проектирования нужен? И обязателен ли Dagger для синглтона GameLogic?

vsklamm commented 5 years ago

От Лёни

Звучит так, как будто тебе нужен общий интерфейс GameLogic и две его релизации: Training и Quiz mode. Активити может имплементить оба их лиснера, но логичней будет сделать например два активити/фрагмента (опять же, с общим предком, раз там много общего UI). В общем, наследование – твой друг.

Где у тебя в проекте Dagger, я пока не нашёл. Если ты хочешь его подключить, то он конечно такую проблему решает, при чём умеет выбирать инстансы интерфейса по квалифаеру и автоматически поддерживать инвариант того, что они синглтон. Но это можно решить и без него, хотя бы тупо сделав два разных .getInstance() или сделав фабрику.

По коду: у тебя все синглтоны имплементят Serializable. Зачем?... я не нашёл, где ты их сохраняешь/восстанавливаешь, они всё равно теряются при выгрузке приложения из памяти (но переживают поворот за счёт того что они синглтоны, ага). Вообще логика на синглтонах с состоянием может быть хрупкой, но тебе везёт и у тебя они работают только в UI треде, судя по всему. Вообще то что у тебя сейчас написано на коллбеках отдалённо напоминает правильный MVP, но там состояние гоняется по каналам (например, реактивным из Rx) и хранится только в активити.

listener = new WeakReference<>((GameLogic.GameLogicCallbacks) context); // TODO: zabotat'

Зачем принимать Context, если единственное применение – сразу скастить вниз, да ещё и заигнорить эксепшон. Почему не получать сразу Listener?

Ещё кажется ты используешь два json парсера: android.util.JsonParser и Gson. Можешь посмотреть в сторону Retrofit с Moshi конвертером

vsklamm commented 5 years ago

Пока отвечу только про логику на синглтонах. Получаю сбои в Play, что в этих синглтон-классах поля null. Как иначе организовать логику?

vsklamm commented 5 years ago

От Лёни

null видимо из-за того, что где-то у тебя они не инициализируются. Для логики может подойти MVP, он был популярным что-то около года назад, но и сейчас вполне ничего.

Идея в чём: MVP = Model - View - Presenter

Model – это сами данные или то, что знает, как их получить, например интерфейс к базе данных или к WebApi. Presenter – то, что умеет делать какую-то логику с данными, но само их не хранит. Например, логика игры View (не com.android.View) – то, что меняется под действием презентера. Довольно часто этот интерфейс имплементит Activity.

Идея в следующем: Presenter не имеет состояния, поэтому нам не нужно его нигде сохранять. Activity может его создать и подсунуть какую-то модель, которая может была там сохранена, а может это просто интерфейс к локальному кешу. После этого все обработчики кнопочек обычно вызывают просто методы presenter. Presenter смотрит на действие, смотрит на модель, решает что делать и вызывает соответствующим образом View.

На самом деле, у тебя навёрнуто что-то отдалённо похожее, только презентер (GameLogic) не должен быть синглтоном и не должен пытаться сохранять в себе данные, это нарушение принципа одной ответственности.

Почитать можно вроде как здесь https://antonioleiva.com/mvp-android/ и здесь https://hackernoon.com/basics-of-mvp-the-android-way-f75da407019d , а ещё ссылка на "эталонный" (нет) семпл гугла: https://github.com/googlesamples/android-architecture/tree/todo-mvp