1

I would like to hear some improvement suggestions for mobile development (Android/iOS) project architectures. I would like to go for a "safe" design, modular and that can be easily maintained in time.

As far as I know Android and also iOS platforms are built on MVC, at least have the Activities and UIViewControllers that are a sort of controller part from MVC(as many stated out there on the internet).

Also I know two approaches so far for a basic project(Android/*iOS*):

1. My favorite (a sort of MVC)

Model - I have here the models, only simple getter/setter classes
shaping the project entities

View - the Activities, UIViewController and custom views, only display, get data from the user interface here, usually gets the data from the Controller, never directly from the Acess

Controller - some singletons (not necessary but usual) that manage each entity data, usually are doing business jobs, loading data from the Access layer and don't have access to the view layer.

Access - Database and Web Service managers, serves data back to Controller layer, can't have contact to any other layers.

2. Commonly seen (also a sort of MVC)

Model - the models, only simple getter/setter classes shaping the project entities, I usually saw also some business jobs here too.

View-Controller -(Activities and UIViewController) that manage entity data, usually are doing business jobs and also take care of displaying data to the user. Also make calls through some web service classes to get the data.

So far I am using the first variant as I consider it more decoupled and I can see the difference between who is making business jobs, user interface communication and data providers. This making it more maintainable than the second one.

The drawback for the first one is that has 2 more layers than the second one, this means more classes(but less code in each class) and at the start of a project, this can take a bit longer to develop than the second one.

What approach do you use or which do you think it is better and why?

  • 1
    -1: It's tempting to to try to generalize Android programming into a neat and tidy pattern (like MVC) but I don't think it's possible. For instance, you should dispatch web service calls to a service that executes web service calls on a background thread. That has nothing to do with MVC. – Jim G. Dec 30 '13 at 0:50
  • I didn't said that one should go with one of those options, I asked others opinion only, also I wanted to see what others think of what I am doing :) – Cata Dec 30 '13 at 2:06
3

I don’t think either of them represent classical MVC.

Model

The model is the data and the business logic. A model contains the state of the running application. It should report data and state. It should validate input. It should update data and state based on input.

  1. The model should be independent of use. In iOS, this generally means it should derive from core Objective-C classes and use only core Objective-C objects. A good test for this would be to see if the model would work for other compilers like GCC Objective-C, or if it will work in other environments like OS X.

  2. The model should be externally controllable. The model should be able to be driven by unit-tests or driven by a completely separate set of controllers.

View

A view is anything that is displayed to a user. In iOS, this generally means anything derived from UIView (UILabel, UIButton, …) Views are dumb: meaning that they know nothing of the model, business logic, or context in which they are created.

Controller

The controller binds model data to views so it can be displayed to users, provides context to views so they are shown correctly (disabled, highlighted, …), and handles user input to update the model. In iOS, this generally means anything derived from UIViewController. A controller may need to process model data in some small way to get it into a view. A controller may need to process user input in some small way to make it suitable for the model.

Data Store

The data store is the permanent repository for model data. This can be a database or a web service. Usually, data stores stand outside of MVC or are attached to the model.

My Answer

Now that I got that out of the way, my answer to your question: the MVC described above is the approach I use. This has implications, some of which are difficult to deal with.

  1. A view must know nothing of the model. If you have a property in your view named price or total, then you’re doing it wrong.

  2. A controller must not contain business logic. If you have a controller calculate sales tax, then you’re doing it wrong.


Addressing concerns in the comments

Warning: I'm not an Android developer and have limited understanding of how Android works.

Services

Like data stores, long running async processing sits outside of MVC. If you need a service that updates the model, then think of it as method of the model. If you have a service that transforms data to show it to a user, then think of it as a method of a controller.

Novel Input

Like all input, broadcast receivers, orientation changes and task switching are tasks that should be handled by a controller. I think of iOS’s application delegate as a controller for the whole application: handling input which effects the whole application (like system notifications and application lifecycle changes).

Business Logic and Model Data

I see the Model composed of two parts, model data and business logic. I've learned it’s best to keep them separate. In practice, this means I wrap model data with business logic or add business logic on as a category of the model data.

Who I Am

To put it bluntly, it doesn’t matter who I am. I don’t think I’ve had a good original thought in my whole life. I’ve based my work on understanding patterns that other developers have created and applying them as best I can to the work I need to get done.

Since you asked, I’ve never worked in academia. I’ve been a software developer for the past 14 years. I’ve worked on code at all levels from drivers and debuggers to shiny custom views and silly apps. I’ve worked on iOS for the past 2½ years and have written many apps which have been released in the app store. I use my understanding of patterns to get my work done on time and on budget.


Update More questions in comments.

Models

I try to keep my data models as clean as possible. Usually they are mostly properties, sometimes conforming to NSCopying, NSCoding, and/or a JSON mapping. More and more, I include Key-Value Validation. This can be part of the data model or in a business logic category.

- (BOOL)validateValue:(inout MyValue **)value error:(out NSError **)error
{
    if (![self complexTestWithValue:*value]) {
        if (error != NULL) {
            // Report error to caller.
            *error = [self errorInValidation];
        }

        return NO;
    }

    return YES;
}

Business Logic

In the past, I've written lots of code which looks like

[dataSource fetchObjectsWithInput:input completion:^(NSArray *objects, NSError *error) {
    // Model objects are in objects
}];

or

[dataSource fetchObjectsWithInput:input completion:^(MyClassResult *result, NSError *error) {
    // Model objects are in result.objects
}];

Recently, I've gotten into promises (I'm using PromiseKit).

[dataSource fetchObjectsWithInput:input].then(^(MyClassResult *result) {
    // Model objects are in result.objects
});

This has been a good general purpose factory pattern for Objective C.

I tend to write business logic computations in categories.

@interface MyClass (BusinessLogic)

- (NSString *)textForValue; // A string to be used as label text.
- (MyResult *)computeOperationWithInput:(MyInput *)input error:(out NSError **error);
- (MyOtherClass *)otherObjectByTransformingValues;

@end
  • 1
    -1: In theory this makes sense. It practice it doesn't; at least on the Android side of things. For instance, where do services and broadcast receivers come into the mix? How do you save state when the phone's orientation changes or when the user switches to another task? Are you really going to shoehorn all of that logic into a model so that it remains device-agnostic? And are you preaching from an ivory tower or have you actually shipped iOS and Android apps? If you haven't actually shipped any apps, then you really shouldn't be recommending best practices. – Jim G. Dec 30 '13 at 2:35
  • I agree with you Jim regarding the business that is put in the model but I would also like to see what is your general approach on this? I don't want to see some sort of miracle code that fits with all the mobile projects, but I do consider that a low level architecture pattern should still be available for most of the projects. Thank you! – Cata Dec 30 '13 at 9:47
  • 2
    @JimG. I’ve updated my answer. I hope I’ve addressed your concerns. – Jeffery Thomas Dec 30 '13 at 16:00
  • @JefferyThomas can you please elaborate little more on how to achieve your approach on this Model data and Business Logic?As you have said, Model must be able to encapsulate data related to an entity of the application we build, plus be able to validate data when it's used to contain data or transport data. In code level how to do this? Do you do the data validation within the model and passes the errors to the view if the validation failed? I can agree with you, but the question for me is how to achieve this in the code level when it's on iOS! Please guide! – Randika Vishman Mar 16 '15 at 18:30
  • @Vishman I hope my Objective C examples helps. – Jeffery Thomas Mar 17 '15 at 11:12

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.