Too many objects to separate UI, domain, and data layers - android

I am designing my Android app to create model/entity classes separately for web service, database, domain, and UI.
I would be transforming my web service objects into domain objects. Then where I have recycler view, I create UI model objects for each row from my domain which would be a subset.
https://developer.android.com/training/articles/perf-tips.html#ObjectCreation
I have also come across https://github.com/PaNaVTEC/Clean-Contacts which is one sample codebase that strictly separates each layer.
I know it's a trade-off between performance and design, but what is recommended? I really like the design, but my concern is the number of objects instantiated.

My take on this is that it is fine to share entities between different layers of your application as long as doing so does not leak implementation details between the layers.
I would happily share a class such as:
public class Product {
private String name;
private BigDecimal price;
private boolean isInStock;
//..
}
But would not share a class such as:
public class MyNetworkLibraryResponse<T> {
private int status;
private Throwable error;
private T data;
//...
}
If you ever decided to swap MyNetworkLibrary for ShineyNewNetworkLibrary you'd soon come unstuck.
Product however would be an integral part of your Domain. Unless you have a need to re-use View code across business domains you'll likely be better off sharing it than causing increased complexity creating a ProductViewModel

Related

Does model of MVP belongs to presentation layer or domain layer?

I understand the MVP. However i do not understand model belongs to presentation layer or domain layer. It is said in some resources, mvp only models the presentation layer, in other words model is in presentation layer. https://antonioleiva.com/mvp-android/
However, in other resources https://proandroiddev.com/clean-architecture-data-flow-dependency-rule-615ffdd79e29 , model belongs to domain layer. Which one is correct? Thanks in advance.
You can have different types of models. You can have a DomainModel, a PresentationModel an ApplicationModel etc.
You can use each kind of model in an MVP application if you need to. for example if you have a complex application with multiple Presenters that need to communicate with each other it may be usefull to add an additional ApplicationModel to simplify these communications by adding a Model that has Application specific data and behavior. If you don't have that you can just use a pure DomainModel.
In this article, Martin Fowler says:
Supervising Controller decomposes presentation functionality into two
parts: a controller (often called presenter) and view. The domain data
that needs to be displayed is separate, and following rough MVC
terminology I'll refer to it as a model, although it need not be a
Domain Model.
It's a tricky one, but the basic distintion is that a pure DomainModel usually models some domain (math, banking etc.) and has no presentation or application specific data and/or behavior. You can mix different types of models in your application.
If your application has some complex logic, say that when one thing is selected another thing need to be deselected. you can capture this in a specific Model let's say ApplicationState that is not a DomainModel.
Here's an example. Let's say that we have an application that has Keywords and Tags and displays them to the user. The user can select only a Keyword or a Tag. He can't select both at the same time. Here's a way to do this by sing a Model that captures this application specific logic that is not part of our Domain. We are using the observer pattern here. When this Model changes we raise events.
class ApplicationSate : Subject {
private Tag mSelectedTag;
private Keyword mSelectedKeyword;
public Tag getSelectedTag() { return mSelectedTag; }
public Keyword getSelectedKeyword() { return mSelectedKeyword; }
public Tag HasSelectedTag() { return mSelectedTag != null; }
public Tag HasSelectedKeyword() { return mSelectedKeyword != null; }
public void selectKeyword(Keyword keyword) {
if(hasSelectedTag()) {
mSelectedTag = null;
}
mSelectedKeyword = keyword;
raiseChangedEvent();
}
public void selectTag(Tag tag) {
if(hasSelectedKeyword()){
mSelectedKeyword = null;
}
mSelectedTag = tag;
raiseChangedEvent();
}
}
Here is a good article on GUI architectures.

How to pass data from parent view's presenter to child view's presenter?

I am using MVP patterns in Android. And structure looks like below.
Activity - Presenter
|
Fragment
|
CustomView
|
views
So when the presenter gets data from the network, it directly passes data to fragment, and fragment pass data to a custom view and custom view pass data to views.
I am not sure how I can pass data used in views from activity with MVP patterns. If I make presenters for each fragments, custom views, and views, then how can I pass data from activity's presenter to other presenters?
Anyone can help me out with examples?
In order to give a more specific answer to your question you need to give a concrete example. Every solution is valid in a context. I'll give couple of ways you can do this. Choose the one that suits your problem.
Very important part of the MVP is the Model. As far as I'm aware the term Model became popular in programing with the release of the paper Thing Model View Editor which was later refined and renamed to MVC.
The definition of the concept of a Model from this paper is:
A Model is an active representation of an abstraction in the form of
data in a computing system
The Models are represented in the computer as a collection of data
together with the methods necessary to process these data.
With time and experience, people have discovered and specified different types of models.
Here are some of them:
Domain Model
Application Model (read this article for more information)
Presentation Model
MVP, since it derives from MVC, makes two major divisions of responsibilities: Model (the abstraction that represent concepts) and Presentation (View and Presenter to visualize the Model).
Because we have divided the Model from the Presentation, we can have multipe Views that show the same Model different ways. An example of that is a Model that represents Statistical Data that can be shown different ways: a Pie chart, a Bar chart etc. In this example the Statistical Data Model is a Domain Model.
In the example above, the Model will probably be shared between the two View-Presenter pairs , The PieChart and the BarChart. If you use the Observer pattern, when one of the View-Presenter pairs update the StatisticalModel, it will raise changed events, and both View-Presenter pairs will receive notifications for this change and update.
Sometimes an application needs an ApplicationModel. This model can be shared between different View-Presentation pairs. Let's take a look at a verfy simplified example.
Let's say we have a File Browser application like Windows Explorer. This GUI of the application has two major parts: The left panel that shows a Tree of the folders and the middle File-Folder panel. When a folder is selected in the left folders tree panel, files and folders from the selected folder must be shown in the middle panel. We can do this by defining an ApplicationModel that will capture and represent the above logic and be shared between both View-Presentation pairs for the left and middle panels.
Note: I'll omit details to simply the example and write less code
public class ApplicationState {
// singleton, it's evil I know,
// but it's the simplest way without DI or ServiceLocator
private static ApplicationState mInstance = new ApplicationState();
public static ApplicationState getInstance() { return mInstance; }
private Folder mSelectedFolder;
public bool hasSelectedFolder() { return mSelectedFolder != null; }
public Folder getSelectedFolder() { return mSelectedFolder; }
public Folder setSelectedFolder(Folder f) {
mSelectedFolder = f;
RaiseSelectedFolderChangedEvent();
}
// method for registering listeners, raising events etc.
}
public class FoldersTreeViewPresenter {
private ApplicationState mApplicationState;
public void onSelectFolder(FolderView view) {
// select the folder in the view
mApplicationState.setSelectedFolder(view.Folder);
}
}
public class FilesFoldersViewPresenter : ApplicationStateListener {
private ApplicationState mApplicationState;
public FilesFoldersViewPresenter() {
// you can use service locator, dependency injection, whatever
mApplicationState = ApplicationState.getInstance();
mApplicationState.addEventListener(this);
}
private void getFilesAndFoldersFromFileSystem(Folder folder) {
// get from fs
// fill views with them etc.
}
private void clearView() {
// clear the panel
}
public void onApplicationStateChanged() {
if(mApplicationState.hasSelectedFolder()){
getFilesAndFoldersFromFileSystem(mApplicationState.getSelectedFolder());
}
else {
clearView();
}
}
}
In this example we created a shared object that represent the application state and the logic, that our application has a selection that can be changed. In this case the ApplicationState class is part of the Model and is an Application Model. Because it is shared and it's life time is the same as the application (it exists as long as the application is running) it will hold the state. Views and Presenters are created and destroyed, but this class will exist and hold the state, so that when a new View and/or Presenter is created it can check this state and do something.
In my experince people do concentrate on Views and Presenters more, while they should work on their Models. Peronally I use Models alot as it makes things cleaner and the application easier to understand.
Of course, using Models doesn't always work, so when they don't you can use messaging, having one Presenter sending messages to others. Here's an example with the same File Browser app.
public class MessageBus {
// static this time, you can use DI or ServiceLocator with interface
public static void sendMessage(object m) { }
public static void registerListener(MessageListener listener) { }
}
public class FoldersTreeViewPresenter {
public void onSelectFolder(FolderView view) {
// select the folder in the view
MessageBus.sendMessage(new FolderSelected(view.Folder));
}
}
public class FilesFoldersViewPresenter : MessageListener {
public FilesFoldersViewPresenter() {
MessageBus.addListener(this);
}
private void getFilesAndFoldersFromFileSystem(Folder folder) {
// get from fs
// fill views with them etc.
}
public void onMessage(object m) {
if(m instanceof FolderSelected) {
FolderSelected folderSelectedMessage = (FolderSelected)m;
getFilesAndFoldersFromFileSystem(folderSelectedMessage.Folder);
}
}
}
Depending on your specific case, if you can create a nice Model, either a Domain, Application or Presentation, do it. Share this Model thus creating a dependency on the Model from the Presenters instead of creating a dependency between Presenters. This way you have loose coupling between Presenters and you can change them much easier
If you can't use a Model, use a Messages. It's a nice way to decouple Presenters by creating a protocol of messages that are used for communication.
Check this article on using messages for collaboration between components.
Also here are some good articles on GUI architectures:
https://martinfowler.com/eaaDev/uiArchs.html
http://aspiringcraftsman.com/2007/08/25/interactive-application-architecture/

Android, Do I use ViewModel to perform insertion or update?

I understand that ViewModel in the Architecture component is for storage and managing data so it will not be lost during config changes.
For example, my activity has nothing do with LiveData or using storage Data. Should I still go through ViewModel? or directly instantiate the Repo Class and call the insertion method? I hope that make sense
An Example of my usage of ViewModel
public class MainViewModel extends AndroidViewModel {
private DataRepo dataRepo;
private LiveData<List<Group>> groupList;
private LiveData<List<Bill>> billList;
public MainViewModel(Application application) {
super(application);
dataRepo = new DataRepo(this.getApplication));
groupList = dataRepo.getGroup();
billList = dataRepo.getBill();
}
public LiveData<List<Group>> getGroupList() {
return groupList:
}
public LiveData<List<Bill>> getBillList() {
return billList:
}
public void insertGroupAndMember(Group group) {
dataRepo.insertGroupAndMember(group);
}
public void insertBills(List<Bill> bills) {
dataRepo.insertBills(bills);
}
public List<Member> getMemberList(Group group) {
return dataRepo.getMembers(group);
}
}
I think you want to use a ViewModel to keep your UI controller as clean as possible. Your viewmodel should call the repo to do simple CRUD operations.
See below snippet from documentation:
Requiring UI controllers
to also be responsible for loading data from a database or network
adds bloat to the class. Assigning excessive responsibility to UI
controllers can result in a single class that tries to handle all of
an app's work by itself, instead of delegating work to other classes.
Assigning excessive responsibility to the UI controllers in this way
also makes testing a lot harder.
Here are some points I would advice you to consider:
MVVM as a pattern has it's roots back in 2000-th, for example, here is Martin Fowler's article about the concept, and in 2005 John Gossman announced the pattern in his blog. Yes, it solves the problem with rotation in android's implementation of the pattern, but this problem could be solved without it. MVVM is actualy needen for separation of presentation state from views that are seen to the end user. As Wiki says -
The view model is an abstraction of the view exposing public properties and commands. Instead of the controller of the MVC pattern, or the presenter of the MVP pattern, MVVM has a binder, which automates communication between the view and its bound properties in the view model. The view model has been described as a state of the data in the model.
So, primarily it is (like all other GUI architectural patterns in their root) about abstraction between view and domain parts of the application, so that they can vary independently and subsequent changes to the system will be cheap.
Instantiating domain objects in the view scope and their subsequent use by the view leads to tight coupling between the view and domain objects, which is a bad characteristic of any system. Also, it is one more reason to change view's internals, because if construction logic of the domain object changes - view will have to be changed too.
If ViewModel is exessive for you (as I can see, its benefits are not relevant for you in this particular case, because the UI is not very complex and it's state is lightweight), consider using a less heavy-weight abstraction, such as MVP. Thus, you will be able to preserve abstraction between view and model in your application (no unwanted coupling) and you won't have to support the code that you don't benefit from.

Handling Entities and Pojos

Still new to Room and while most of the tutorials I've found are related to simple table and CRUD operations I am stuck on evolving this.
Let's take this sample structures.
Users entity
#Entity(tableName = "users")
public class UsersEntity{
#PrimaryKey(autoGenerate = true)
private long id;
#NonNull
private String name;
#NonNull
private long roleId;
}
Roles entity
#Entity(tableName = "roles")
public class RolesEntity{
#PrimaryKey(autoGenerate = true)
private long id;
#NonNull
private String name;
}
First question: Should Entity objects be extended to also replace POJO? Or have Entities and POJO as separate classes?
Extending from the Room setup, the way I would see User POJO is:
public class User{
private long id;
private Role role;
}
Basically this setup should work both if the User would come as a json response from a web service or entered by the user in the app's input fields.
However, this raises the second question: how to insert and retrieve user info?.
Inserting seems possible as there could be something like
userDAO.insertRole(userId)
But how can I get the Role object of User by using Room and the userDAO?
I find inappropriate to do something like:
user = userDao.getUser(userId)
user.setRole(roleDao.getRole(user.getRoleId)
Third question: it seems to be a good practice to have the table columns with _ (eg. role_id) but in java roleId is recommended as class property. If the result of a #Query for instance select role_id from... and the the POJO with roleId field, will fail so the query needs to be select role_id as roleId... to get it work. Is it a good practice to use camel case in table/column names in sqlite?
What you intend as POJO, probably can be seen as a kind of a view model. In general it is a bad idea to unify/link entities and pojos because you are just making a long wider visibilty/scope for the entity, where it is not necessary and can lead to potential problems.
Say you have some client which requires some different visualization of the data, for instance imagine you have a website which exposes a vehicle data and you have implemented everything using metric system, so for distance you have km, for speed km/h and so on. Now your company gains a huge client from UK, and they want you to provide them the data in imperial format. What to do now? Probably implement a deserilization/conversion process which takes the values and converts them according to the context of the user (whether they are using metric or imperial system). What could possibly go wrong if your entity and view model objects are basically the same? Really bad stuff. You have really tight coupling of things, you should implement different getters for serialization for client, for db..it can become a mess.
Instead if you separate the two, you will have your entity which takes care of working with the database, which is standard procedure with small coefficient of variability, and on the other side you will have the view model which is very likely to require frequent modification, after all it is expected, since it is the interface to the final user.

Windows Phone 8 Equivalent for Android's StartActivityForResult

I am from an Android background and am progressing into Windows Phone 8.
I have a Page that uses the camera to decode a QR code and this works fine. In Android I would start this Activity using the Intent StartActivityForResult, which would then give me the decoded value back to the original Activity.
I have searched but could not find an obvious equivalent in Windows Phone 8. My thought at the moment is to navigate to the calling page with a query string containing the decoded value and alter the back stack, but this seems a little messy.
The Question
Is there an equivalent to the process in android, and if so can someone outline the methodology so I may see it in action?
First, there's no such thing in WP8, so you'll need a workaround. Workarounds could be different, and the linked question (and answer) is one of the potential approaches. I personally do this a bit differently. I'll describe my current project's architecture here, though it may not be applicable to your situation, since my app is quite big and has a complex structure. But I'll try to explain how it could be applied to your situation.
Particularly, my current app consists of so called services (just my name, not a standard one). Those have different scope (some are used by 1 page, some are global for the app), different lifetime, and so on. Essentially, every service is a class implementing a well-defined interface, so that other services could use that.
Next, services could depend on each other. I'm using Ninject framework for dependency injection. Essentially, if service A depends on service B, it leads to a code like this:
public class B : IB
{
...
}
public class A
{
IB b;
public A(IB b)
{
this.b = b;
}
}
where IB is an interface, which service B implements.
Then I have view models (yes, I'm using MVVM and you probably should too, if you want to build a reasonably big WP8 app). View models are using services to perform app functions. Some of the services are used by several view models. For example, I have one service that fetches some data from the web, and keep it up to date with periodic polling. That web data is used in several pages of the application, so it should be shared between different view models. It is achieved by dependency injection again, so that all interested view models accept this service instance as a constructor parameter.
public class MainPageViewModel : INotifyPropertChanged
{
private string webData;
public MainPageViewModel(IWebDataService service)
{
webData = service.CurrentWebData;
service.WebDataChanged += (o, e) => webData = service.CurrentWebData;
}
...
}
public class DetailPageViewModel : INotifyPropertChanged
{
private string webData;
public DetailPageViewModel(IWebDataService service)
{
webData = service.CurrentWebData;
service.WebDataChanged += (o, e) => webData = service.CurrentWebData;
}
...
}
public class WebDataService : IWebDataService
{
public string CurrentWebData;
public event EventHandler WebDataUpdated;
...
}
Ninject allows me to have a single instance of IWebDataService instantiated, so that main and details page share the same instance of it. When the web data is updated, an event is fired, so that both view models can update their instances of web data, and push this new data to the views.
So here's how I do it. You could potentially reuse some part of this architecture, like having a singleton instance of some class accessible by different pages. One page puts some new data to that singleton instance, and, when data is updated (event fired or during construction, if garbage collector had enough time to kill existing page and/or view model instance), another page reads the updated data. That's how they share.
If you want me to go deeper into details on some topic, please feel free to ask in comments. Android developers are more than welcomed to the Windows Phone. :)

Categories

Resources