3

I have an application architectured by: View -> ViewModel -> Repository -> Datasource.

My DataSource is consuming a webservice and then receiving a Soap object, which I want to transform to a custom Pojo object. So, by using RxJava I am calling the DataSource method by following this flow:

ViewModel

    repository.webserviceCall(data)...
            .subscribe();

Repository

public Single<SoapObject> webserviceCall(String data) {
    return dataSource.webserviceCall(data);
}

Datasource

public Single<SoapObject> webserviceCall(String data) {
    WSSoapDAO soapDAO = new WSSoapDAO("webserviceMethodName");
    soapDAO.addProperty("data", data);
    return soapDAO.call();
}

and then I would like to know where should I transform the SoapObject received in the DataSource call, either in the Repository class, in the ViewModel class or in thee DataSource class itself?

Onik
  • 19,396
  • 14
  • 68
  • 91
mantc_sdr
  • 451
  • 3
  • 17

3 Answers3

3

In addition to Onik's answer, I'd like to expand it with a few things.

  1. This is close to opinion based facts, so be careful where you walk. :)

  2. I agree this is normally a Repository problem (there's a "but"). In general, if the data you're receiving from your remote service needs to be transformed, then you want to abstract this away from the consumers of said data (A ViewModel, and even your local database).

  3. If the data is to be differently transformed for different usages, then perhaps you need to re-think your architecture (or rather, your remote services!); in any case, the viewModel should only do (in my opinion) things related to modifying your local domain objects/models/entities into something different for the purpose of the views that need it. In other words, if a specific "screen" needs to transform the data (for e.g. to flatten a few models into a single List<Things> to simplify a Recyclerview, then that could belong on a ViewModel, assuming you inject a "mapper" object (transformer, mapper, whateverDelegate, youNameIt) so the ViewModel delegates this transformation (and therefore simplifies testing).

  4. In any case, keep in mind this is very opinion based, and domain specific, but in the end, you want a clean repository that gives you data, and data for which you don't want to think (or know) where it came from, other than it's in the format you care, every time.

Martin Marconcini
  • 26,875
  • 19
  • 106
  • 144
1

In terms of your architecture I'd say the transformation should go to the repository. Let's call the entity that is to do the transformation Mapper. The mapper is supposed to transform a DTO object, SoapObject, to a model object, PojoObject.

For example

public interface Mapper {
    public PojoObject map(SoapObject dto)
}

Now the presentation layer (View and ViewModel) knows nothing about DTO objects exposed by the Datasources.

Onik
  • 19,396
  • 14
  • 68
  • 91
  • Thank you very much, what about this repository calls differnt WS methods? shall the 'map' method from the interface be the one in charge of checking what method is coming from and then decide how to transformate, or shall I have differnt methods in that interface? – mantc_sdr Apr 08 '21 at 15:49
  • 1
    @mantc_sdr, in most cases each repository should call only one data source. Following the approach, and in terms of your architecture, each repository should use only one mapper. By doing this you'd follow the Separation-of-Concern principle, making your code concise. – Onik Apr 08 '21 at 17:27
0

The architecture design is based on viewpoints. It is not always what works best for you.

Repository modules handle data operations. They provide a clean API so that the rest of the app can retrieve this data easily. They know where to get the data from and what API calls to make when data is updated. You can consider repositories to be mediators between different data sources, such as persistent models, web services, and caches.

This is Google's view of the role of the repository: querying data from different data-sources and assembling them, then making them available to different components.

There is a simple way to think about it: Is the data in the same format needed by different views, activities, services?

  • If so, it is generic data and should be generated in the repository.
  • If not, it is view-specific data. It should be converted in the view-model.
  • If this data is used by only one component, then it is fine wherever it is converted.
    Even there is no need to do so many layers of abstraction, you can treat the data-source as a repository. Abstraction is only used to solve complex problems.