3
\$\begingroup\$

I'm working on an Android (Java) project which utilizes different analytic metrics (sum of x group by date, sum of x group by id, etc) and I am projecting the data sets into different charts using MPAndroidChart.

For the backend, I'm following the MVP architecture and applying a Repository pattern for querying from Realm database. Mind you, I haven't had enough experience in applying Repository pattern into a project, so this might be my early trial and error.


Right now, I have a base Repository which contains all the generic queries:

public interface Repository<T> {

    Observable<T> find();

    Observable<List<T>> findAll();

    Observable<T> add(T model);

    Observable<Iterable<T>> add(Iterable<T> items);

    Observable<String> update(T model);

    Observable<String> remove(T model);

    Observable<List<T>> query(Specification specification);

}

Specification is an empty marker class which being extended by more specific Specification interfaces, for example ChartSpecification extends Specification.

In my ChartSpecification interface has one method called mapToChart

public interface ChartSpecification<To, From extends RealmModel> extends Specification {

    List<To> mapToChart(RealmResults<From> results);

}

This is how I implement the concrete method for mapToChart inside MyModelCountPerMonth. Why I do it this way is to make sure I create one class per unique query. For example:

public class MyModelCountPerMonth implements RealmSpecification<MyModel>, ChartSpecification<Charting, MyModel> {

    @Override
    public RealmResults<MyModel> toRealmResults(Realm realm) {
        return realm.where(MyModel.class)
                .findAll();
    }

    @Override
    public List<Charting> mapToChart(RealmResults<MyModel> results) {

        // do MyModel model mapping to Charting model

        // X and Y coordinates are set here into Charting model


        return mappedChartData;
    }
}

So, the query is done by MyModelRepositoryImpl class:

public class MyModelRepositoryImpl implements Repository<MyModel> {

    // some initialization and other method overriding

    @Override
    public Observable<List<MyModel>> query(Specification specification) {

        if (specification instanceof MyModelCountPerMonth) {
            return Observable.create((Subscriber<? super List<MyModel>> subscriber) -> {
                try {
                    final MyModelCountPerMonth realmSpecification = (MyModelCountPerMonth) specification;

                    final Realm realm = Realm.getDefaultInstance();
                    final RealmResults<MyModel> realmResults = realmSpecification.toRealmResults(realm);

                    realm.close();
                    final List<Charting> chartData = realmSpecification.mapToChart(realmResults);

                    subscriber.onNext(chartData); // this gives error because Observable returns List<MyModel> instead
                    subscriber.onCompleted();
                } catch (Exception e) {
                    subscriber.onError(e);
                }
            });
        }

        // there may be more if statements here if required

        return null;
    }

}

From here, I could just call this Repository and subscribe on the query data and return it to the View.

myModelRepo.query(new MyModelCountPerMonth())
        .subscribe(chartingList -> 
            if (chartingList.size() > 0) {
                mView.onRequestDatasetSuccess(chartingList);
            } else {
                mView.showEmpty();
            }
        );

So, back to my question. Referring to MyModelRepositoryImpl, the error I'm getting is at onNext since the Observable from Repository only returns List<MyModel>, instead I want it to return List<Charting>. But by doing that, doesn't it violates the SRP rule because it has side-effects (toRealmResults and mapToChart)?

How do I make it so that the MyModel Specification can do both RealmResult and mapping of the data into Charting model?

Do I need to separate the ChartSpecification and just do it in the Presenter after retrieving data from repository?

Thanks!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.