Click here to Skip to main content
Click here to Skip to main content

Applying MVC Architecture to Titanium Mobile Apps

, 6 Dec 2012
Rate this:
Please Sign up or sign in to vote.
Applying MVC architecture to Titanium mobile apps.

Appcelerator's Titanium Mobile is a great tool for cross-platform mobile development. Appcelerator publishes documentation and guides, the Kitchen Sink project gives a view into some best practices, and project templates can get you started quickly. However overall application architecture is left to the developer, and designing any substantial app can be a daunting task. This article describes my approach for implementing the Model-View-Controller (MVC) architecture within Titanium Mobile Apps. Note: I'm assuming the use of CommonJS for everything.

Project Layout

Here's the basic structure I like to use for projects.

  • application - Contains application-specific code. This keeps the folders containing actual code from being separated by those containing images or other general components.
  • images - Contains all the image files for the project
  • lib - Contains reusable, general purpose libraries. For me this is usually underscore.js, underscore.string.js, and internal libraries that I extend as I go.
Then, within the application folder components are organized into the MVC structure.

  • controller - Contains the business logic components which access data via model components and present information to the user via the user interface components.
  • model - Contains components that provide data access. That means remote data as well as local data, which might include application properties. Ideally you could change the underlying data source used by you model components without changing any of your other code.
  • ui - Contains our application-specific user interface components.

Example

I generally like to setup each controller and data entity with corresponding function calls. My recent work has been on a Customer Relations Management app that involves a fair amount of standard database maintenance functions. So, many of the controllers have functions for list, detail, create, edit, and delete. Their corresponding data entities then have the same or similar functions. The consistency makes maintenance straightforward.

If we were implementing an app that allows users to maintain a list of customers we might have these components:

Controller

  • customerController - Provides access to list, detail, edit, create, and deleteRecord functions. ("delete" is a keyword so I usually use deleteRecord.) I've found that controllers are often non-instantiable libraries, so they are named with an initial lowercase.

Model

  • customerEntity - Used by the customerController to access data. It might implement list, detail, create, and deleteRecord functions. This example is named for non-instantiable library.

View

  • CustomerListView - Used by customerController to display a list of customers. User interface components are generally instantiable, so they are usually named with an initial uppercase.
  • CustomerDetailView - Used by customerController to display details for a single record. (Instantiable)
  • CustomerEditView - Used by customerController to edit existing records and to create new records. (Instantiable)
Here's what it would look like within the project. Note that the user interface elements are further organized into folders named for their controller. I've also added a model.js library which would contain application-specific functions common to multiple data entities.

If you want to apply this structure to everything, you could add an application controller which might handle your bootstrap logic and open your application window. Perhaps you'd have an application entity that would manage access to configuration settings.

Now as we add more and more functionality the structure stays very organized.

Why Bother?

If you don't currently separate business logic from user interface code, you might think, "That's all very nice, but why bother doing this? I'm still writing the same code. It's just in different places now. If I want to add a field to a screen I'll have to edit two or three files instead of one!" Well, consider this: What if during the design phase you notice that the views which list records are pretty much the same. You might write a single component that you instantiate with the data and callback functions that it needs to function. Part of a customer controller that uses this generic list view might look something like this:
var ListView = require('/lib/ui/ListView'),
    customerEntity = require('/application/model/customerEntity');
.
.
.
var create = function(args){
    //Some code to display the edit view with what it needs for a new record.
}; 

var detail = function(args){
    //Some code to display record detail.
}; 

var list = function(args){
				
// Define the fields which the list view is supposed to display var fieldDefinitions = [
    
    {fieldName: 'company_name', type:'text', ....},
	{fieldName: 'address', type:'text', ....},
	{fieldName: 'referral_source', type:'text', ....},
																
	{fieldName: 'initial_contact', type:'date', ....} 
												
								
],
listData = customerEntity.list(),
customerListView = new ListView({

    fieldDefs : fieldDefinitions ,
	data : listData
	onRowClick : detail 
																
	onNewClick : create 
								
}); .
.
.
};

At this point you've replaced a bunch of potentially mind-numbing UI code with a reusable component that you can add to your personal library, you've guaranteed consistency across all the listing type views, and now you have a only single object to maintain for all of your lists.

What if you can do the same thing for the detail and edit views? Now, to add a field to your detail view you just need to adjust your data entity to include the field, and define it's attributes in the fieldDefinition object for the generic detail view. This type of code reuse is one of the benefits of separating business logic from user interface.

Additionally, from a maintenance perspective it's nice to have the components separated. You can address changes to business logic without wading through lines of display logic. Having data access encapsulated provides you some extra flexibility that you may need as your app matures. You may need to change one aspect of your app that has always used live remote data to something that can now function offline with a local database. Under this type of architecture you should be able to make that change without ever touching your controller or the associated user interface.

Wrap-Up

OK, I started with a nice overview of how to structure an app according to MVC, and provided some nice conceptual examples. Then I had to go and include a potentially confusing code snippet! If the code doesn't make sense to you, just set it aside for now. Take another look when you need to do something similar. I think it's a powerful approach which I've implemented, but it can make the head spin if you haven't done something like this before. Perhaps a topic for another day!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Phil Sweeney
Architect Produce Pro Software
United States United States
Hands-on problem solver who uses software development and project management skills to deliver corporate and departmental solutions. Guides clients in defining requirements. Identifies appropriate technologies for the solution. Builds functional and technical specifications. Prepares cost estimates and schedules. Leads development teams. Manages client expectations. Actively participates in all aspects of development including design, implementation, documentation, training, and support.
 
Specialties
Mobile application development; Web application development; Project Management; software concept exploration; database application design, development, documentation, and deployment; User Interface design; database replication; data modeling; Unified Modeling Language (UML); end-user training and support.
 
Java, Titanium Mobile, C#, SQL, HTML, XML, JavaScript, AJAX, PowerBuilder, Tomcat, Apache, MS SQL Server, Sybase SQL Anywhere, MS Access, MySQL, PostgreSQL, ERWin, PowerDesigner, Objecteering UML Modeler, MS Project
Follow on   Twitter   Google+

Comments and Discussions

 
GeneralMy vote of 3 PinmemberMember 939401213-Dec-12 6:33 
GeneralRe: My vote of 3 PinmemberPhil Sweeney13-Dec-12 6:50 
GeneralRe: My vote of 3 PinmemberMember 939401213-Dec-12 17:23 
Thanks for your response.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140721.1 | Last Updated 6 Dec 2012
Article Copyright 2012 by Phil Sweeney
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid